UNPKG

@azure-utils/storybooks

Version:

Utils to upload and manage Storybooks via Azure Functions and storage.

1 lines 7.89 kB
{"version":3,"file":"index.mjs","names":["options: RegisterStorybooksRouterOptions","name: string","options: HttpFunctionOptions","options"],"sources":["../src/index.ts"],"sourcesContent":["/**\n * Module exports a single function to register\n * the Storybooks management endpoints.\n *\n * @module\n */\n\nimport { app, type HttpFunctionOptions } from \"@azure/functions\";\nimport z from \"zod\";\nimport { timerPurgeHandler } from \"./handlers/timer-purge-handler\";\nimport { registerProjectsRouter } from \"./routers/projects-router\";\nimport { registerBuildsRouter } from \"./routers/builds-router\";\nimport { registerLabelsRouter } from \"./routers/labels-router\";\nimport { registerWebUIRouter } from \"./routers/web-ui-router\";\nimport { registerStorybookRouter } from \"./routers/storybook-router\";\nimport {\n DEFAULT_CHECK_PERMISSIONS_CALLBACK,\n DEFAULT_PURGE_SCHEDULE_CRON,\n DEFAULT_STORAGE_CONN_STR_ENV_VAR,\n DEFAULT_SERVICE_NAME,\n} from \"./utils/constants\";\nimport type { CheckPermissionsCallback, OpenAPIOptions } from \"./utils/types\";\nimport { joinUrl } from \"./utils/url-utils\";\nimport { wrapHttpHandlerWithStore } from \"./utils/store\";\nimport { EmptyObjectSchema, ProjectIdSchema } from \"./models/shared\";\n\nexport type { CheckPermissionsCallback, OpenAPIOptions };\n\n/**\n * Options to register the storybooks router\n */\nexport type RegisterStorybooksRouterOptions = {\n /**\n * Name of the service. @default \"storybooks\"\n */\n serviceName?: string;\n\n /**\n * Define the route on which all router is placed.\n * Can be a sub-path of the main API route.\n *\n * @default ''\n */\n baseRoute?: string;\n\n /**\n * Set the Azure Functions authentication level for all routes.\n *\n * This is a good option to set if the service is used in\n * Headless mode and requires single token authentication\n * for all the requests.\n *\n * This setting does not affect health-check route.\n */\n authLevel?: \"admin\";\n\n /**\n * Name of the Environment variable which stores\n * the connection string to the Azure Storage resource.\n * @default 'AzureWebJobsStorage'\n */\n storageConnectionStringEnvVar?: string;\n\n /**\n * Modify the cron-schedule of timer function\n * which purge outdated storybooks.\n *\n * Pass `null` to disable auto-purge functionality.\n *\n * @default \"0 0 0 * * *\" // Every midnight\n */\n purgeScheduleCron?: string | null;\n\n /**\n * Options to configure OpenAPI schema\n */\n openapi?: OpenAPIOptions;\n\n /**\n * Directories to serve static files from relative to project root (package.json)\n * @default './public'\n */\n staticDirs?: string[];\n\n /**\n * Callback function to check permissions. The function receives following params\n * @param permission - object containing resource and action to permit\n * @param context - Invocation context of Azure Function\n * @param request - the HTTP request object\n *\n * @return `true` to allow access, or following to deny:\n * - `false` - returns 403 response\n * - `HttpResponse` - returns the specified HTTP response\n */\n checkPermissions?: CheckPermissionsCallback;\n};\n\n/**\n * Function to register all routes required to manage the Storybooks including\n * GET, POST and DELETE methods.\n *\n * @returns a function to register additional HTTP handlers for the service.\n */\nexport function registerStorybooksRouter(\n options: RegisterStorybooksRouterOptions = {}\n): (name: string, options: HttpFunctionOptions) => void {\n const {\n serviceName = DEFAULT_SERVICE_NAME,\n baseRoute = \"\",\n authLevel,\n storageConnectionStringEnvVar = DEFAULT_STORAGE_CONN_STR_ENV_VAR,\n purgeScheduleCron,\n openapi,\n checkPermissions = DEFAULT_CHECK_PERMISSIONS_CALLBACK,\n } = options;\n\n const storageConnectionString = process.env[storageConnectionStringEnvVar];\n\n if (!storageConnectionString) {\n throw new Error(\n \"Missing env-var '${storageConnectionStringEnvVar}' value.\\n\" +\n \"It is required to connect with Azure Storage resource.\"\n );\n }\n\n console.log(\"Registering Storybooks Router\");\n\n const openAPIEnabled = !openapi?.disabled;\n\n app.setup({ enableHttpStream: true });\n\n const handlerWrapper = wrapHttpHandlerWithStore.bind(null, {\n serviceName,\n baseRoute,\n authLevel,\n connectionString: storageConnectionString,\n openapi,\n staticDirs: options.staticDirs || [\"./public\"],\n checkPermissions,\n });\n\n const normalisedServiceName = serviceName.toLowerCase().replace(/\\s+/g, \"_\");\n registerProjectsRouter({\n serviceName: normalisedServiceName,\n baseRoute: joinUrl(baseRoute, \"projects\"),\n basePathParamsSchema: EmptyObjectSchema,\n openAPIEnabled,\n handlerWrapper,\n });\n\n registerBuildsRouter({\n serviceName: normalisedServiceName,\n baseRoute: joinUrl(baseRoute, \"projects\", \"{projectId}\", \"builds\"),\n basePathParamsSchema: z.object({ projectId: ProjectIdSchema }),\n openAPIEnabled,\n handlerWrapper,\n });\n\n registerLabelsRouter({\n serviceName: normalisedServiceName,\n baseRoute: joinUrl(baseRoute, \"projects\", \"{projectId}\", \"labels\"),\n basePathParamsSchema: z.object({ projectId: ProjectIdSchema }),\n openAPIEnabled,\n handlerWrapper,\n });\n\n registerStorybookRouter({\n serviceName: normalisedServiceName,\n baseRoute: joinUrl(baseRoute, \"_\"),\n basePathParamsSchema: EmptyObjectSchema,\n openAPIEnabled,\n handlerWrapper,\n });\n\n registerWebUIRouter({\n serviceName: normalisedServiceName,\n baseRoute,\n basePathParamsSchema: EmptyObjectSchema,\n openAPIEnabled,\n handlerWrapper,\n });\n\n if (purgeScheduleCron !== null) {\n app.timer(`${normalisedServiceName}-timer_purge`, {\n schedule: purgeScheduleCron || DEFAULT_PURGE_SCHEDULE_CRON,\n handler: timerPurgeHandler(storageConnectionString),\n });\n }\n\n /**\n * Register an HTTP function.\n *\n * The baseRoute and authLevel is inherited.\n *\n * @param name unique name for the HTTP function\n * @param options Options for Azure HTTP function\n */\n function registerRoute(name: string, options: HttpFunctionOptions) {\n app.http(`${normalisedServiceName}-${name}`, {\n authLevel,\n ...options,\n route: joinUrl(baseRoute, options.route || name),\n handler: handlerWrapper(options.handler, []),\n methods: options.methods || [\"GET\"],\n });\n }\n\n return registerRoute;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuGA,SAAgB,yBACdA,UAA2C,CAAE,GACS;CACtD,MAAM,EACJ,cAAc,sBACd,YAAY,IACZ,WACA,gCAAgC,kCAChC,mBACA,SACA,mBAAmB,oCACpB,GAAG;CAEJ,MAAM,0BAA0B,QAAQ,IAAI;AAE5C,KAAI,CAAC,wBACH,OAAM,IAAI,MACR;CAKJ,QAAQ,IAAI,gCAAgC;CAE5C,MAAM,iBAAiB,CAAC,SAAS;CAEjC,IAAI,MAAM,EAAE,kBAAkB,KAAM,EAAC;CAErC,MAAM,iBAAiB,yBAAyB,KAAK,MAAM;EACzD;EACA;EACA;EACA,kBAAkB;EAClB;EACA,YAAY,QAAQ,cAAc,CAAC,UAAW;EAC9C;CACD,EAAC;CAEF,MAAM,wBAAwB,YAAY,aAAa,CAAC,QAAQ,QAAQ,IAAI;CAC5E,uBAAuB;EACrB,aAAa;EACb,WAAW,QAAQ,WAAW,WAAW;EACzC,sBAAsB;EACtB;EACA;CACD,EAAC;CAEF,qBAAqB;EACnB,aAAa;EACb,WAAW,QAAQ,WAAW,YAAY,eAAe,SAAS;EAClE,sBAAsB,EAAE,OAAO,EAAE,WAAW,gBAAiB,EAAC;EAC9D;EACA;CACD,EAAC;CAEF,qBAAqB;EACnB,aAAa;EACb,WAAW,QAAQ,WAAW,YAAY,eAAe,SAAS;EAClE,sBAAsB,EAAE,OAAO,EAAE,WAAW,gBAAiB,EAAC;EAC9D;EACA;CACD,EAAC;CAEF,wBAAwB;EACtB,aAAa;EACb,WAAW,QAAQ,WAAW,IAAI;EAClC,sBAAsB;EACtB;EACA;CACD,EAAC;CAEF,oBAAoB;EAClB,aAAa;EACb;EACA,sBAAsB;EACtB;EACA;CACD,EAAC;AAEF,KAAI,sBAAsB,MACxB,IAAI,MAAM,GAAG,sBAAsB,YAAY,CAAC,EAAE;EAChD,UAAU,qBAAqB;EAC/B,SAAS,kBAAkB,wBAAwB;CACpD,EAAC;;;;;;;;;CAWJ,SAAS,cAAcC,MAAcC,WAA8B;EACjE,IAAI,KAAK,GAAG,sBAAsB,CAAC,EAAE,MAAM,EAAE;GAC3C;GACA,GAAGC;GACH,OAAO,QAAQ,WAAWA,UAAQ,SAAS,KAAK;GAChD,SAAS,eAAeA,UAAQ,SAAS,CAAE,EAAC;GAC5C,SAASA,UAAQ,WAAW,CAAC,KAAM;EACpC,EAAC;CACH;AAED,QAAO;AACR"}