UNPKG

hypertune

Version:

[Hypertune](https://www.hypertune.com/) is the most flexible platform for feature flags, A/B testing, analytics and app configuration. Built with full end-to-end type-safety, Git-style version control and local, synchronous, in-memory flag evaluation. Opt

172 lines 9.39 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.generate = exports.generateOptionsSchema = exports.defaultOptions = void 0; exports.registerGenerateCommand = registerGenerateCommand; const node_fs_1 = __importDefault(require("node:fs")); const node_path_1 = __importDefault(require("node:path")); const cross_fetch_1 = __importDefault(require("cross-fetch")); const edge_1 = require("../../lib/edge"); const shared_1 = require("../../shared"); const helpers_1 = require("../helpers"); const defaultLocalLogger_1 = __importDefault(require("../../shared/helpers/defaultLocalLogger")); exports.defaultOptions = { queryFilePath: "hypertune.graphql", outputDirectoryPath: "generated", includeToken: false, includeInitData: false, includeToolbar: false, language: "ts", }; exports.generateOptionsSchema = { token: "string", branchName: "string", framework: "string", platform: "string", queryFilePath: "string", outputFilePath: "string", outputDirectoryPath: "string", includeToken: "boolean", includeInitData: "boolean", includeToolbar: "boolean", language: "string", edgeBaseUrl: "string", getHypertuneImportPath: "string", }; function registerGenerateCommand(cli) { cli // TODO: make generate a sub command, after https://github.com/cacjs/cac/pull/152 // .command("generate", "Generate Hypertune files for your project", { allowUnknownOptions: true }) // .alias("!") .command("", "Generate Hypertune files for your project", { allowUnknownOptions: true, ignoreOptionDefaultValue: true, }) .example((bin) => `${bin} --token U2FsdGVkX1abcdef`) .action((0, helpers_1.withOtherOptionSources)(exports.generate, exports.generateOptionsSchema)) .option("--token [value]", "Project token") .option("--branchName [value]", "Project branch to use") .option("--queryFilePath [value]", "File path to the GraphQL initialization query", { default: exports.defaultOptions.queryFilePath }) .option("--outputFilePath [value]", "(Deprecated) The path to write the generated file to") .option("--outputDirectoryPath [value]", "The directory to write the generated files to", { default: exports.defaultOptions.outputDirectoryPath }) .option("--includeToken", "Include the project token in the generated code", { default: exports.defaultOptions.includeToken, }) .option("--includeInitData", "Embed a static snapshot of your flag logic in the generated code so the SDK can reliably, locally and instantly initialize first, before fetching the latest logic from the server, and can function even if the server is unreachable", { default: exports.defaultOptions.includeInitData, }) .option("--includeToolbar", "Generate code for Hypertune toolbar. Only available on paid plans.", { default: exports.defaultOptions.includeToolbar, }) .option("--language [value]", "Target language (ts, js (uses ESM), mjs or cjs)", { default: exports.defaultOptions.language, }) .option("--framework [value]", "Framework (nextApp, nextPages, react, vue, remix or gatsby)") .option("--platform [value]", "Platform (vercel)") .option("--getHypertuneImportPath [value]", "Relative import path for a file with a default export of the `getHypertune` function, which takes a single object argument containing readonly `headers` and `cookies`; only used for the nextApp framework and vercel platform"); } exports.generate = (0, helpers_1.withValidation)(exports.generateOptionsSchema, (options) => __awaiter(void 0, void 0, void 0, function* () { var _a, _b, _c, _d, _e, _f, _g, _h, _j; console.log("Starting Hypertune code generation..."); if (options.outputFilePath) { console.warn("Warning: --outputFilePath option is deprecated, please use --outputDirectoryPath instead"); } try { const language = (_a = options.language) !== null && _a !== void 0 ? _a : exports.defaultOptions.language; const outputFilePath = node_path_1.default.join((_b = options.outputDirectoryPath) !== null && _b !== void 0 ? _b : exports.defaultOptions.outputDirectoryPath, `hypertune.${language}`); yield generateCode({ token: (0, helpers_1.throwIfOptionIsUndefined)("token", options.token), branchName: (_c = options.branchName) !== null && _c !== void 0 ? _c : null, queryCode: getQueryCode((_d = options.queryFilePath) !== null && _d !== void 0 ? _d : exports.defaultOptions.queryFilePath, /* throwIfNotExists */ !!options.queryFilePath), outputFilePath: options.outputDirectoryPath ? outputFilePath : ((_e = options.outputFilePath) !== null && _e !== void 0 ? _e : outputFilePath), includeToken: (_f = options.includeToken) !== null && _f !== void 0 ? _f : exports.defaultOptions.includeToken, includeFallback: (_g = options.includeInitData) !== null && _g !== void 0 ? _g : exports.defaultOptions.includeInitData, includeToolbar: (_h = options.includeToolbar) !== null && _h !== void 0 ? _h : exports.defaultOptions.includeToolbar, language, edgeBaseUrl: (_j = options.edgeBaseUrl) !== null && _j !== void 0 ? _j : shared_1.prodEdgeCdnBaseUrl, framework: options.framework, platform: options.platform, getHypertuneImportPath: options.getHypertuneImportPath, }); console.log("Done"); } catch (error) { console.error(error instanceof Error ? `Error: ${error.message}` : String(error)); process.exit(1); } })); function generateCode(_a) { return __awaiter(this, arguments, void 0, function* ({ token, branchName, queryCode, outputFilePath, includeToken, includeFallback, includeToolbar, edgeBaseUrl, language, framework, platform, getHypertuneImportPath, }) { if (framework === "nextApp" && platform === "vercel" && !getHypertuneImportPath) { console.log(`Not generating Vercel flag definitions. To enable generation, set the "getHypertuneImportPath" option.`); } if (framework && language !== "js" && language !== "ts") { console.warn(`Warning: framework option is not supported for language: ${language}`); } const extension = node_path_1.default.extname(outputFilePath); const clientFileName = node_path_1.default.basename(outputFilePath.slice(0, outputFilePath.length - extension.length)); const codegenResponse = yield (0, edge_1.codegenRequest)({ traceId: (0, shared_1.uniqueId)(), token, branchName, body: { framework: framework, platform: platform, clientFileName, query: queryCode, includeToken, includeFallback, includeToolbar, getHypertuneImportPath, }, language, edgeBaseUrl, tracedFetch: (_, url, init) => { return (0, cross_fetch_1.default)(url, init); }, }); const outputDirectoryPath = node_path_1.default.dirname(outputFilePath); if (!node_fs_1.default.existsSync(outputDirectoryPath)) { node_fs_1.default.mkdirSync(outputDirectoryPath, { recursive: true }); } codegenResponse.messages.forEach(({ level, message, metadata }) => { (0, defaultLocalLogger_1.default)(level, message, metadata); }); codegenResponse.files.forEach(({ name, content }) => { writeFile(node_path_1.default.join(outputDirectoryPath, name), content); }); }); } function getQueryCode(filePath, throwIfNotExists) { const queryFilePath = node_path_1.default.join("./", filePath); if (!node_fs_1.default.existsSync(queryFilePath)) { if (throwIfNotExists) { throw new Error(`Query file does not exist at the provided path: "${queryFilePath}"`); } return null; } const queryCode = node_fs_1.default.readFileSync(queryFilePath).toString(); console.log(`Loaded query code from file: "${queryFilePath}"`); return queryCode; } function writeFile(filePath, contents) { node_fs_1.default.writeFileSync(filePath, contents, { flag: "w" }); console.log("Generated file:", filePath); } //# sourceMappingURL=index.js.map