@backstage/plugin-scaffolder-backend 1.31.0-next.2 → 1.32.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/dist/ScaffolderPlugin.cjs.js.map +1 -1
  3. package/dist/index.d.ts +1 -1
  4. package/dist/lib/templating/filters/createDefaultFilters.cjs.js +16 -0
  5. package/dist/lib/templating/filters/createDefaultFilters.cjs.js.map +1 -0
  6. package/dist/lib/templating/filters/parseEntityRef/examples.cjs.js +32 -0
  7. package/dist/lib/templating/filters/parseEntityRef/examples.cjs.js.map +1 -0
  8. package/dist/lib/templating/filters/parseEntityRef/filter.cjs.js +37 -0
  9. package/dist/lib/templating/filters/parseEntityRef/filter.cjs.js.map +1 -0
  10. package/dist/lib/templating/filters/parseRepoUrl/examples.cjs.js +17 -0
  11. package/dist/lib/templating/filters/parseRepoUrl/examples.cjs.js.map +1 -0
  12. package/dist/lib/templating/filters/parseRepoUrl/filter.cjs.js +30 -0
  13. package/dist/lib/templating/filters/parseRepoUrl/filter.cjs.js.map +1 -0
  14. package/dist/lib/templating/filters/pick/examples.cjs.js +17 -0
  15. package/dist/lib/templating/filters/pick/examples.cjs.js.map +1 -0
  16. package/dist/lib/templating/filters/pick/filter.cjs.js +16 -0
  17. package/dist/lib/templating/filters/pick/filter.cjs.js.map +1 -0
  18. package/dist/lib/templating/filters/projectSlug/examples.cjs.js +18 -0
  19. package/dist/lib/templating/filters/projectSlug/examples.cjs.js.map +1 -0
  20. package/dist/lib/templating/filters/projectSlug/filter.cjs.js +21 -0
  21. package/dist/lib/templating/filters/projectSlug/filter.cjs.js.map +1 -0
  22. package/dist/scaffolder/actions/builtin/fetch/template.cjs.js +2 -2
  23. package/dist/scaffolder/actions/builtin/fetch/template.cjs.js.map +1 -1
  24. package/dist/scaffolder/actions/builtin/fetch/templateFile.cjs.js +2 -2
  25. package/dist/scaffolder/actions/builtin/fetch/templateFile.cjs.js.map +1 -1
  26. package/dist/scaffolder/dryrun/DecoratedActionsRegistry.cjs.js +3 -1
  27. package/dist/scaffolder/dryrun/DecoratedActionsRegistry.cjs.js.map +1 -1
  28. package/dist/scaffolder/tasks/NunjucksWorkflowRunner.cjs.js +2 -2
  29. package/dist/scaffolder/tasks/NunjucksWorkflowRunner.cjs.js.map +1 -1
  30. package/dist/service/router.cjs.js +12 -1
  31. package/dist/service/router.cjs.js.map +1 -1
  32. package/dist/util/templating.cjs.js +132 -2
  33. package/dist/util/templating.cjs.js.map +1 -1
  34. package/package.json +25 -25
  35. package/dist/lib/templating/filters.cjs.js +0 -28
  36. package/dist/lib/templating/filters.cjs.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,81 @@
1
1
  # @backstage/plugin-scaffolder-backend
2
2
 
3
+ ## 1.32.0-next.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 75e4db4: add template-extensions scaffolder service endpoint
8
+
9
+ ### Patch Changes
10
+
11
+ - 497d47a: Document the internal built-in filters, and ensure that the types are validated when using `createTemplateFilter` and `createTemplateGlobalFunction` from the `zod` schema.
12
+ - Updated dependencies
13
+ - @backstage/backend-defaults@0.9.0-next.0
14
+ - @backstage/plugin-scaffolder-backend-module-azure@0.2.8-next.0
15
+ - @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.9-next.0
16
+ - @backstage/plugin-scaffolder-backend-module-github@0.6.2-next.0
17
+ - @backstage/plugin-scaffolder-node@0.8.1-next.0
18
+ - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.8-next.0
19
+ - @backstage/plugin-auth-node@0.6.1
20
+ - @backstage/plugin-permission-node@0.9.0
21
+ - @backstage/backend-plugin-api@1.2.1
22
+ - @backstage/catalog-client@1.9.1
23
+ - @backstage/catalog-model@1.7.3
24
+ - @backstage/config@1.3.2
25
+ - @backstage/errors@1.2.7
26
+ - @backstage/integration@1.16.2
27
+ - @backstage/types@1.2.1
28
+ - @backstage/plugin-bitbucket-cloud-common@0.2.28
29
+ - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.6
30
+ - @backstage/plugin-catalog-node@1.16.1
31
+ - @backstage/plugin-events-node@0.4.9
32
+ - @backstage/plugin-permission-common@0.8.4
33
+ - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.8-next.0
34
+ - @backstage/plugin-scaffolder-backend-module-gerrit@0.2.8-next.0
35
+ - @backstage/plugin-scaffolder-backend-module-gitea@0.2.8-next.0
36
+ - @backstage/plugin-scaffolder-backend-module-gitlab@0.8.2-next.0
37
+ - @backstage/plugin-scaffolder-common@1.5.10
38
+
39
+ ## 1.31.0
40
+
41
+ ### Minor Changes
42
+
43
+ - 36677bb: Support new `createTemplateAction` type, and convert `catalog:fetch` action to new way of defining actions.
44
+ - 2b1e50d: use CreatedTemplate[Filter|Global*] as canonical template extensions in scaffolder plugin
45
+
46
+ ### Patch Changes
47
+
48
+ - e0b226b: build(deps): bump `esbuild` from 0.24.2 to 0.25.0
49
+ - 09cf038: Got rid of most `@backstage/backend-common` usages
50
+ - 4f8b5b6: Allow signing git commits using configured private PGP key in scaffolder
51
+ - 59dcf37: Fixed bug in fs:delete causing no files to be deleted on windows machines
52
+ - Updated dependencies
53
+ - @backstage/plugin-scaffolder-backend-module-gitlab@0.8.1
54
+ - @backstage/integration@1.16.2
55
+ - @backstage/backend-defaults@0.8.2
56
+ - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.7
57
+ - @backstage/plugin-scaffolder-backend-module-github@0.6.1
58
+ - @backstage/plugin-scaffolder-node@0.8.0
59
+ - @backstage/plugin-permission-node@0.9.0
60
+ - @backstage/plugin-auth-node@0.6.1
61
+ - @backstage/plugin-scaffolder-common@1.5.10
62
+ - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.7
63
+ - @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.8
64
+ - @backstage/plugin-scaffolder-backend-module-gerrit@0.2.7
65
+ - @backstage/plugin-scaffolder-backend-module-azure@0.2.7
66
+ - @backstage/plugin-scaffolder-backend-module-gitea@0.2.7
67
+ - @backstage/plugin-events-node@0.4.9
68
+ - @backstage/backend-plugin-api@1.2.1
69
+ - @backstage/catalog-client@1.9.1
70
+ - @backstage/catalog-model@1.7.3
71
+ - @backstage/config@1.3.2
72
+ - @backstage/errors@1.2.7
73
+ - @backstage/types@1.2.1
74
+ - @backstage/plugin-bitbucket-cloud-common@0.2.28
75
+ - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.6
76
+ - @backstage/plugin-catalog-node@1.16.1
77
+ - @backstage/plugin-permission-common@0.8.4
78
+
3
79
  ## 1.31.0-next.2
4
80
 
5
81
  ### Minor Changes
@@ -1 +1 @@
1
- {"version":3,"file":"ScaffolderPlugin.cjs.js","sources":["../src/ScaffolderPlugin.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha';\nimport { eventsServiceRef } from '@backstage/plugin-events-node';\nimport { TaskBroker, TemplateAction } from '@backstage/plugin-scaffolder-node';\nimport {\n AutocompleteHandler,\n CreatedTemplateFilter,\n CreatedTemplateGlobal,\n createTemplateFilter,\n createTemplateGlobalFunction,\n createTemplateGlobalValue,\n scaffolderActionsExtensionPoint,\n scaffolderAutocompleteExtensionPoint,\n scaffolderTaskBrokerExtensionPoint,\n scaffolderTemplatingExtensionPoint,\n scaffolderWorkspaceProviderExtensionPoint,\n WorkspaceProvider,\n} from '@backstage/plugin-scaffolder-node/alpha';\nimport {\n createCatalogRegisterAction,\n createCatalogWriteAction,\n createDebugLogAction,\n createFetchCatalogEntityAction,\n createFetchPlainAction,\n createFetchPlainFileAction,\n createFetchTemplateAction,\n createFetchTemplateFileAction,\n createFilesystemDeleteAction,\n createFilesystemReadDirAction,\n createFilesystemRenameAction,\n createWaitAction,\n} from './scaffolder';\nimport { createRouter } from './service/router';\nimport { loggerToWinstonLogger } from './util/loggerToWinstonLogger';\nimport {\n convertFiltersToRecord,\n convertGlobalsToRecord,\n} from './util/templating';\n\n/**\n * Scaffolder plugin\n *\n * @public\n */\nexport const scaffolderPlugin = createBackendPlugin({\n pluginId: 'scaffolder',\n register(env) {\n const addedActions = new Array<TemplateAction<any, any>>();\n env.registerExtensionPoint(scaffolderActionsExtensionPoint, {\n addActions(...newActions: TemplateAction<any>[]) {\n addedActions.push(...newActions);\n },\n });\n\n let taskBroker: TaskBroker | undefined;\n env.registerExtensionPoint(scaffolderTaskBrokerExtensionPoint, {\n setTaskBroker(newTaskBroker) {\n if (taskBroker) {\n throw new Error('Task broker may only be set once');\n }\n taskBroker = newTaskBroker;\n },\n });\n\n const additionalTemplateFilters: CreatedTemplateFilter[] = [];\n const additionalTemplateGlobals: CreatedTemplateGlobal[] = [];\n\n env.registerExtensionPoint(scaffolderTemplatingExtensionPoint, {\n addTemplateFilters(newFilters) {\n additionalTemplateFilters.push(\n ...(Array.isArray(newFilters)\n ? newFilters\n : Object.entries(newFilters).map(([id, filter]) =>\n createTemplateFilter({\n id,\n filter,\n }),\n )),\n );\n },\n addTemplateGlobals(newGlobals) {\n additionalTemplateGlobals.push(\n ...(Array.isArray(newGlobals)\n ? newGlobals\n : Object.entries(newGlobals).map(([id, global]) =>\n typeof global === 'function'\n ? createTemplateGlobalFunction({ id, fn: global })\n : createTemplateGlobalValue({ id, value: global }),\n )),\n );\n },\n });\n\n const autocompleteHandlers: Record<string, AutocompleteHandler> = {};\n env.registerExtensionPoint(scaffolderAutocompleteExtensionPoint, {\n addAutocompleteProvider(provider) {\n autocompleteHandlers[provider.id] = provider.handler;\n },\n });\n\n const additionalWorkspaceProviders: Record<string, WorkspaceProvider> = {};\n env.registerExtensionPoint(scaffolderWorkspaceProviderExtensionPoint, {\n addProviders(provider) {\n Object.assign(additionalWorkspaceProviders, provider);\n },\n });\n\n env.registerInit({\n deps: {\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n lifecycle: coreServices.rootLifecycle,\n reader: coreServices.urlReader,\n permissions: coreServices.permissions,\n database: coreServices.database,\n auth: coreServices.auth,\n discovery: coreServices.discovery,\n httpRouter: coreServices.httpRouter,\n httpAuth: coreServices.httpAuth,\n auditor: coreServices.auditor,\n catalogClient: catalogServiceRef,\n events: eventsServiceRef,\n },\n async init({\n logger,\n config,\n lifecycle,\n reader,\n database,\n auth,\n discovery,\n httpRouter,\n httpAuth,\n catalogClient,\n permissions,\n events,\n auditor,\n }) {\n const log = loggerToWinstonLogger(logger);\n const integrations = ScmIntegrations.fromConfig(config);\n\n const templateExtensions = {\n additionalTemplateFilters: convertFiltersToRecord(\n additionalTemplateFilters,\n ),\n additionalTemplateGlobals: convertGlobalsToRecord(\n additionalTemplateGlobals,\n ),\n };\n const actions = [\n // actions provided from other modules\n ...addedActions,\n\n // built-in actions for the scaffolder\n createFetchPlainAction({\n reader,\n integrations,\n }),\n createFetchPlainFileAction({\n reader,\n integrations,\n }),\n createFetchTemplateAction({\n integrations,\n reader,\n ...templateExtensions,\n }),\n createFetchTemplateFileAction({\n integrations,\n reader,\n ...templateExtensions,\n }),\n createDebugLogAction(),\n createWaitAction(),\n // todo(blam): maybe these should be a -catalog module?\n createCatalogRegisterAction({ catalogClient, integrations, auth }),\n createFetchCatalogEntityAction({ catalogClient, auth }),\n createCatalogWriteAction(),\n createFilesystemDeleteAction(),\n createFilesystemRenameAction(),\n createFilesystemReadDirAction(),\n ];\n\n const actionIds = actions.map(action => action.id).join(', ');\n\n log.info(\n `Starting scaffolder with the following actions enabled ${actionIds}`,\n );\n\n const router = await createRouter({\n logger: log,\n config,\n database,\n catalogClient,\n reader,\n lifecycle,\n actions,\n taskBroker,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n auth,\n httpAuth,\n discovery,\n permissions,\n autocompleteHandlers,\n additionalWorkspaceProviders,\n events,\n auditor,\n });\n httpRouter.use(router);\n },\n });\n },\n});\n"],"names":["createBackendPlugin","scaffolderActionsExtensionPoint","scaffolderTaskBrokerExtensionPoint","scaffolderTemplatingExtensionPoint","createTemplateFilter","createTemplateGlobalFunction","createTemplateGlobalValue","scaffolderAutocompleteExtensionPoint","scaffolderWorkspaceProviderExtensionPoint","coreServices","catalogServiceRef","eventsServiceRef","log","loggerToWinstonLogger","ScmIntegrations","convertFiltersToRecord","convertGlobalsToRecord","createFetchPlainAction","createFetchPlainFileAction","createFetchTemplateAction","createFetchTemplateFileAction","createDebugLogAction","createWaitAction","createCatalogRegisterAction","createFetchCatalogEntityAction","createCatalogWriteAction","createFilesystemDeleteAction","createFilesystemRenameAction","createFilesystemReadDirAction","router","createRouter"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgEO,MAAM,mBAAmBA,oCAAoB,CAAA;AAAA,EAClD,QAAU,EAAA,YAAA;AAAA,EACV,SAAS,GAAK,EAAA;AACZ,IAAM,MAAA,YAAA,GAAe,IAAI,KAAgC,EAAA;AACzD,IAAA,GAAA,CAAI,uBAAuBC,qCAAiC,EAAA;AAAA,MAC1D,cAAc,UAAmC,EAAA;AAC/C,QAAa,YAAA,CAAA,IAAA,CAAK,GAAG,UAAU,CAAA;AAAA;AACjC,KACD,CAAA;AAED,IAAI,IAAA,UAAA;AACJ,IAAA,GAAA,CAAI,uBAAuBC,wCAAoC,EAAA;AAAA,MAC7D,cAAc,aAAe,EAAA;AAC3B,QAAA,IAAI,UAAY,EAAA;AACd,UAAM,MAAA,IAAI,MAAM,kCAAkC,CAAA;AAAA;AAEpD,QAAa,UAAA,GAAA,aAAA;AAAA;AACf,KACD,CAAA;AAED,IAAA,MAAM,4BAAqD,EAAC;AAC5D,IAAA,MAAM,4BAAqD,EAAC;AAE5D,IAAA,GAAA,CAAI,uBAAuBC,wCAAoC,EAAA;AAAA,MAC7D,mBAAmB,UAAY,EAAA;AAC7B,QAA0B,yBAAA,CAAA,IAAA;AAAA,UACxB,GAAI,MAAM,OAAQ,CAAA,UAAU,IACxB,UACA,GAAA,MAAA,CAAO,OAAQ,CAAA,UAAU,CAAE,CAAA,GAAA;AAAA,YAAI,CAAC,CAAC,EAAI,EAAA,MAAM,MACzCC,0BAAqB,CAAA;AAAA,cACnB,EAAA;AAAA,cACA;AAAA,aACD;AAAA;AACH,SACN;AAAA,OACF;AAAA,MACA,mBAAmB,UAAY,EAAA;AAC7B,QAA0B,yBAAA,CAAA,IAAA;AAAA,UACxB,GAAI,MAAM,OAAQ,CAAA,UAAU,IACxB,UACA,GAAA,MAAA,CAAO,OAAQ,CAAA,UAAU,CAAE,CAAA,GAAA;AAAA,YAAI,CAAC,CAAC,EAAI,EAAA,MAAM,MACzC,OAAO,MAAA,KAAW,aACdC,kCAA6B,CAAA,EAAE,IAAI,EAAI,EAAA,MAAA,EAAQ,CAC/C,GAAAC,+BAAA,CAA0B,EAAE,EAAI,EAAA,KAAA,EAAO,QAAQ;AAAA;AACrD,SACN;AAAA;AACF,KACD,CAAA;AAED,IAAA,MAAM,uBAA4D,EAAC;AACnE,IAAA,GAAA,CAAI,uBAAuBC,0CAAsC,EAAA;AAAA,MAC/D,wBAAwB,QAAU,EAAA;AAChC,QAAqB,oBAAA,CAAA,QAAA,CAAS,EAAE,CAAA,GAAI,QAAS,CAAA,OAAA;AAAA;AAC/C,KACD,CAAA;AAED,IAAA,MAAM,+BAAkE,EAAC;AACzE,IAAA,GAAA,CAAI,uBAAuBC,+CAA2C,EAAA;AAAA,MACpE,aAAa,QAAU,EAAA;AACrB,QAAO,MAAA,CAAA,MAAA,CAAO,8BAA8B,QAAQ,CAAA;AAAA;AACtD,KACD,CAAA;AAED,IAAA,GAAA,CAAI,YAAa,CAAA;AAAA,MACf,IAAM,EAAA;AAAA,QACJ,QAAQC,6BAAa,CAAA,MAAA;AAAA,QACrB,QAAQA,6BAAa,CAAA,UAAA;AAAA,QACrB,WAAWA,6BAAa,CAAA,aAAA;AAAA,QACxB,QAAQA,6BAAa,CAAA,SAAA;AAAA,QACrB,aAAaA,6BAAa,CAAA,WAAA;AAAA,QAC1B,UAAUA,6BAAa,CAAA,QAAA;AAAA,QACvB,MAAMA,6BAAa,CAAA,IAAA;AAAA,QACnB,WAAWA,6BAAa,CAAA,SAAA;AAAA,QACxB,YAAYA,6BAAa,CAAA,UAAA;AAAA,QACzB,UAAUA,6BAAa,CAAA,QAAA;AAAA,QACvB,SAASA,6BAAa,CAAA,OAAA;AAAA,QACtB,aAAe,EAAAC,yBAAA;AAAA,QACf,MAAQ,EAAAC;AAAA,OACV;AAAA,MACA,MAAM,IAAK,CAAA;AAAA,QACT,MAAA;AAAA,QACA,MAAA;AAAA,QACA,SAAA;AAAA,QACA,MAAA;AAAA,QACA,QAAA;AAAA,QACA,IAAA;AAAA,QACA,SAAA;AAAA,QACA,UAAA;AAAA,QACA,QAAA;AAAA,QACA,aAAA;AAAA,QACA,WAAA;AAAA,QACA,MAAA;AAAA,QACA;AAAA,OACC,EAAA;AACD,QAAM,MAAAC,KAAA,GAAMC,4CAAsB,MAAM,CAAA;AACxC,QAAM,MAAA,YAAA,GAAeC,2BAAgB,CAAA,UAAA,CAAW,MAAM,CAAA;AAEtD,QAAA,MAAM,kBAAqB,GAAA;AAAA,UACzB,yBAA2B,EAAAC,iCAAA;AAAA,YACzB;AAAA,WACF;AAAA,UACA,yBAA2B,EAAAC,iCAAA;AAAA,YACzB;AAAA;AACF,SACF;AACA,QAAA,MAAM,OAAU,GAAA;AAAA;AAAA,UAEd,GAAG,YAAA;AAAA;AAAA,UAGHC,4BAAuB,CAAA;AAAA,YACrB,MAAA;AAAA,YACA;AAAA,WACD,CAAA;AAAA,UACDC,oCAA2B,CAAA;AAAA,YACzB,MAAA;AAAA,YACA;AAAA,WACD,CAAA;AAAA,UACDC,kCAA0B,CAAA;AAAA,YACxB,YAAA;AAAA,YACA,MAAA;AAAA,YACA,GAAG;AAAA,WACJ,CAAA;AAAA,UACDC,0CAA8B,CAAA;AAAA,YAC5B,YAAA;AAAA,YACA,MAAA;AAAA,YACA,GAAG;AAAA,WACJ,CAAA;AAAA,UACDC,wBAAqB,EAAA;AAAA,UACrBC,qBAAiB,EAAA;AAAA;AAAA,UAEjBC,oCAA4B,CAAA,EAAE,aAAe,EAAA,YAAA,EAAc,MAAM,CAAA;AAAA,UACjEC,oCAA+B,CAAA,EAAE,aAAe,EAAA,IAAA,EAAM,CAAA;AAAA,UACtDC,8BAAyB,EAAA;AAAA,UACzBC,oCAA6B,EAAA;AAAA,UAC7BC,mCAA6B,EAAA;AAAA,UAC7BC,kCAA8B;AAAA,SAChC;AAEA,QAAM,MAAA,SAAA,GAAY,QAAQ,GAAI,CAAA,CAAA,MAAA,KAAU,OAAO,EAAE,CAAA,CAAE,KAAK,IAAI,CAAA;AAE5D,QAAIhB,KAAA,CAAA,IAAA;AAAA,UACF,0DAA0D,SAAS,CAAA;AAAA,SACrE;AAEA,QAAM,MAAAiB,QAAA,GAAS,MAAMC,mBAAa,CAAA;AAAA,UAChC,MAAQ,EAAAlB,KAAA;AAAA,UACR,MAAA;AAAA,UACA,QAAA;AAAA,UACA,aAAA;AAAA,UACA,MAAA;AAAA,UACA,SAAA;AAAA,UACA,OAAA;AAAA,UACA,UAAA;AAAA,UACA,yBAAA;AAAA,UACA,yBAAA;AAAA,UACA,IAAA;AAAA,UACA,QAAA;AAAA,UACA,SAAA;AAAA,UACA,WAAA;AAAA,UACA,oBAAA;AAAA,UACA,4BAAA;AAAA,UACA,MAAA;AAAA,UACA;AAAA,SACD,CAAA;AACD,QAAA,UAAA,CAAW,IAAIiB,QAAM,CAAA;AAAA;AACvB,KACD,CAAA;AAAA;AAEL,CAAC;;;;"}
1
+ {"version":3,"file":"ScaffolderPlugin.cjs.js","sources":["../src/ScaffolderPlugin.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha';\nimport { eventsServiceRef } from '@backstage/plugin-events-node';\nimport { TaskBroker, TemplateAction } from '@backstage/plugin-scaffolder-node';\nimport {\n AutocompleteHandler,\n CreatedTemplateFilter,\n CreatedTemplateGlobal,\n createTemplateFilter,\n createTemplateGlobalFunction,\n createTemplateGlobalValue,\n scaffolderActionsExtensionPoint,\n scaffolderAutocompleteExtensionPoint,\n scaffolderTaskBrokerExtensionPoint,\n scaffolderTemplatingExtensionPoint,\n scaffolderWorkspaceProviderExtensionPoint,\n WorkspaceProvider,\n} from '@backstage/plugin-scaffolder-node/alpha';\nimport {\n createCatalogRegisterAction,\n createCatalogWriteAction,\n createDebugLogAction,\n createFetchCatalogEntityAction,\n createFetchPlainAction,\n createFetchPlainFileAction,\n createFetchTemplateAction,\n createFetchTemplateFileAction,\n createFilesystemDeleteAction,\n createFilesystemReadDirAction,\n createFilesystemRenameAction,\n createWaitAction,\n} from './scaffolder';\nimport { createRouter } from './service/router';\nimport { loggerToWinstonLogger } from './util/loggerToWinstonLogger';\nimport {\n convertFiltersToRecord,\n convertGlobalsToRecord,\n} from './util/templating';\n\n/**\n * Scaffolder plugin\n *\n * @public\n */\nexport const scaffolderPlugin = createBackendPlugin({\n pluginId: 'scaffolder',\n register(env) {\n const addedActions = new Array<TemplateAction<any, any>>();\n env.registerExtensionPoint(scaffolderActionsExtensionPoint, {\n addActions(...newActions: TemplateAction<any>[]) {\n addedActions.push(...newActions);\n },\n });\n\n let taskBroker: TaskBroker | undefined;\n env.registerExtensionPoint(scaffolderTaskBrokerExtensionPoint, {\n setTaskBroker(newTaskBroker) {\n if (taskBroker) {\n throw new Error('Task broker may only be set once');\n }\n taskBroker = newTaskBroker;\n },\n });\n\n const additionalTemplateFilters: CreatedTemplateFilter<any, any>[] = [];\n const additionalTemplateGlobals: CreatedTemplateGlobal[] = [];\n\n env.registerExtensionPoint(scaffolderTemplatingExtensionPoint, {\n addTemplateFilters(newFilters) {\n additionalTemplateFilters.push(\n ...(Array.isArray(newFilters)\n ? newFilters\n : Object.entries(newFilters).map(([id, filter]) =>\n createTemplateFilter({\n id,\n filter,\n }),\n )),\n );\n },\n addTemplateGlobals(newGlobals) {\n additionalTemplateGlobals.push(\n ...(Array.isArray(newGlobals)\n ? newGlobals\n : Object.entries(newGlobals).map(([id, global]) =>\n typeof global === 'function'\n ? createTemplateGlobalFunction({ id, fn: global })\n : createTemplateGlobalValue({ id, value: global }),\n )),\n );\n },\n });\n\n const autocompleteHandlers: Record<string, AutocompleteHandler> = {};\n env.registerExtensionPoint(scaffolderAutocompleteExtensionPoint, {\n addAutocompleteProvider(provider) {\n autocompleteHandlers[provider.id] = provider.handler;\n },\n });\n\n const additionalWorkspaceProviders: Record<string, WorkspaceProvider> = {};\n env.registerExtensionPoint(scaffolderWorkspaceProviderExtensionPoint, {\n addProviders(provider) {\n Object.assign(additionalWorkspaceProviders, provider);\n },\n });\n\n env.registerInit({\n deps: {\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n lifecycle: coreServices.rootLifecycle,\n reader: coreServices.urlReader,\n permissions: coreServices.permissions,\n database: coreServices.database,\n auth: coreServices.auth,\n discovery: coreServices.discovery,\n httpRouter: coreServices.httpRouter,\n httpAuth: coreServices.httpAuth,\n auditor: coreServices.auditor,\n catalogClient: catalogServiceRef,\n events: eventsServiceRef,\n },\n async init({\n logger,\n config,\n lifecycle,\n reader,\n database,\n auth,\n discovery,\n httpRouter,\n httpAuth,\n catalogClient,\n permissions,\n events,\n auditor,\n }) {\n const log = loggerToWinstonLogger(logger);\n const integrations = ScmIntegrations.fromConfig(config);\n\n const templateExtensions = {\n additionalTemplateFilters: convertFiltersToRecord(\n additionalTemplateFilters,\n ),\n additionalTemplateGlobals: convertGlobalsToRecord(\n additionalTemplateGlobals,\n ),\n };\n const actions = [\n // actions provided from other modules\n ...addedActions,\n\n // built-in actions for the scaffolder\n createFetchPlainAction({\n reader,\n integrations,\n }),\n createFetchPlainFileAction({\n reader,\n integrations,\n }),\n createFetchTemplateAction({\n integrations,\n reader,\n ...templateExtensions,\n }),\n createFetchTemplateFileAction({\n integrations,\n reader,\n ...templateExtensions,\n }),\n createDebugLogAction(),\n createWaitAction(),\n // todo(blam): maybe these should be a -catalog module?\n createCatalogRegisterAction({ catalogClient, integrations, auth }),\n createFetchCatalogEntityAction({ catalogClient, auth }),\n createCatalogWriteAction(),\n createFilesystemDeleteAction(),\n createFilesystemRenameAction(),\n createFilesystemReadDirAction(),\n ];\n\n const actionIds = actions.map(action => action.id).join(', ');\n\n log.info(\n `Starting scaffolder with the following actions enabled ${actionIds}`,\n );\n\n const router = await createRouter({\n logger: log,\n config,\n database,\n catalogClient,\n reader,\n lifecycle,\n actions,\n taskBroker,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n auth,\n httpAuth,\n discovery,\n permissions,\n autocompleteHandlers,\n additionalWorkspaceProviders,\n events,\n auditor,\n });\n httpRouter.use(router);\n },\n });\n },\n});\n"],"names":["createBackendPlugin","scaffolderActionsExtensionPoint","scaffolderTaskBrokerExtensionPoint","scaffolderTemplatingExtensionPoint","createTemplateFilter","createTemplateGlobalFunction","createTemplateGlobalValue","scaffolderAutocompleteExtensionPoint","scaffolderWorkspaceProviderExtensionPoint","coreServices","catalogServiceRef","eventsServiceRef","log","loggerToWinstonLogger","ScmIntegrations","convertFiltersToRecord","convertGlobalsToRecord","createFetchPlainAction","createFetchPlainFileAction","createFetchTemplateAction","createFetchTemplateFileAction","createDebugLogAction","createWaitAction","createCatalogRegisterAction","createFetchCatalogEntityAction","createCatalogWriteAction","createFilesystemDeleteAction","createFilesystemRenameAction","createFilesystemReadDirAction","router","createRouter"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -885,7 +885,7 @@ interface RouterOptions {
885
885
  */
886
886
  concurrentTasksLimit?: number;
887
887
  taskBroker?: TaskBroker$1;
888
- additionalTemplateFilters?: Record<string, TemplateFilter$1> | CreatedTemplateFilter[];
888
+ additionalTemplateFilters?: Record<string, TemplateFilter$1> | CreatedTemplateFilter<any, any>[];
889
889
  additionalTemplateGlobals?: Record<string, TemplateGlobal$1> | CreatedTemplateGlobal[];
890
890
  additionalWorkspaceProviders?: Record<string, WorkspaceProvider>;
891
891
  permissions?: PermissionsService;
@@ -0,0 +1,16 @@
1
+ 'use strict';
2
+
3
+ var filter = require('./parseRepoUrl/filter.cjs.js');
4
+ var filter$1 = require('./parseEntityRef/filter.cjs.js');
5
+ var filter$2 = require('./pick/filter.cjs.js');
6
+ var filter$3 = require('./projectSlug/filter.cjs.js');
7
+
8
+ const createDefaultFilters = (options) => [
9
+ filter.createParseRepoUrl(options.integrations),
10
+ filter$1.parseEntityRef,
11
+ filter$2.pick,
12
+ filter$3.createProjectSlug(options.integrations)
13
+ ];
14
+
15
+ exports.createDefaultFilters = createDefaultFilters;
16
+ //# sourceMappingURL=createDefaultFilters.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createDefaultFilters.cjs.js","sources":["../../../../src/lib/templating/filters/createDefaultFilters.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { ScmIntegrations } from '@backstage/integration';\nimport { createParseRepoUrl } from './parseRepoUrl';\nimport { parseEntityRef } from './parseEntityRef';\nimport { pick } from './pick';\nimport { createProjectSlug } from './projectSlug';\n\nexport const createDefaultFilters = (options: {\n integrations: ScmIntegrations;\n}) => [\n createParseRepoUrl(options.integrations),\n parseEntityRef,\n pick,\n createProjectSlug(options.integrations),\n];\n"],"names":["createParseRepoUrl","parseEntityRef","pick","createProjectSlug"],"mappings":";;;;;;;AAqBa,MAAA,oBAAA,GAAuB,CAAC,OAE/B,KAAA;AAAA,EACJA,yBAAA,CAAmB,QAAQ,YAAY,CAAA;AAAA,EACvCC,uBAAA;AAAA,EACAC,aAAA;AAAA,EACAC,0BAAA,CAAkB,QAAQ,YAAY;AACxC;;;;"}
@@ -0,0 +1,32 @@
1
+ 'use strict';
2
+
3
+ const examples = [
4
+ {
5
+ description: "Without context",
6
+ example: `- id: log
7
+ name: Parse Entity Reference
8
+ action: debug:log
9
+ input:
10
+ message: \${{ parameters.owner | parseEntityRef }}
11
+ `,
12
+ notes: `- **Input**: \`group:techdocs\`
13
+ - **Output**: \`{"kind": "group", "namespace": "default", "name": "techdocs"}\`
14
+ `
15
+ },
16
+ {
17
+ description: "With context",
18
+ example: `- id: log
19
+ name: Parse Entity Reference
20
+ action: debug:log
21
+ input:
22
+ message: \${{ parameters.owner | parseEntityRef({ defaultKind:"group", defaultNamespace:"another-namespace" }) }}
23
+ `,
24
+ notes: `- **Input**: \`techdocs\`
25
+ - **Arguments:**: \`[{ "defaultKind": "group", "defaultNamespace": "another-namespace" }]\`
26
+ - **Output**: \`{"kind": "group", "namespace": "another-namespace", "name": "techdocs"}\`
27
+ `
28
+ }
29
+ ];
30
+
31
+ exports.examples = examples;
32
+ //# sourceMappingURL=examples.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"examples.cjs.js","sources":["../../../../../src/lib/templating/filters/parseEntityRef/examples.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { TemplateFilterExample } from '@backstage/plugin-scaffolder-node/alpha';\n\nexport const examples: TemplateFilterExample[] = [\n {\n description: 'Without context',\n example: `\\\n- id: log\n name: Parse Entity Reference\n action: debug:log\n input:\n message: \\${{ parameters.owner | parseEntityRef }}\n`,\n notes: `\\\n- **Input**: \\`group:techdocs\\`\n- **Output**: \\`{\"kind\": \"group\", \"namespace\": \"default\", \"name\": \"techdocs\"}\\`\n`,\n },\n {\n description: 'With context',\n example: `\\\n- id: log\n name: Parse Entity Reference\n action: debug:log\n input:\n message: \\${{ parameters.owner | parseEntityRef({ defaultKind:\"group\", defaultNamespace:\"another-namespace\" }) }}\n`,\n notes: `\\\n- **Input**: \\`techdocs\\`\n- **Arguments:**: \\`[{ \"defaultKind\": \"group\", \"defaultNamespace\": \"another-namespace\" }]\\`\n- **Output**: \\`{\"kind\": \"group\", \"namespace\": \"another-namespace\", \"name\": \"techdocs\"}\\`\n`,\n },\n];\n"],"names":[],"mappings":";;AAiBO,MAAM,QAAoC,GAAA;AAAA,EAC/C;AAAA,IACE,WAAa,EAAA,iBAAA;AAAA,IACb,OAAS,EAAA,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAAA,IAOT,KAAO,EAAA,CAAA;AAAA;AAAA;AAAA,GAIT;AAAA,EACA;AAAA,IACE,WAAa,EAAA,cAAA;AAAA,IACb,OAAS,EAAA,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAAA,IAOT,KAAO,EAAA,CAAA;AAAA;AAAA;AAAA;AAAA;AAMX;;;;"}
@@ -0,0 +1,37 @@
1
+ 'use strict';
2
+
3
+ var catalogModel = require('@backstage/catalog-model');
4
+ var alpha = require('@backstage/plugin-scaffolder-node/alpha');
5
+ var examples = require('./examples.cjs.js');
6
+
7
+ const parseEntityRef = alpha.createTemplateFilter({
8
+ id: "parseEntityRef",
9
+ description: "Extracts the parts of an entity reference, such as the kind, namespace, and name.",
10
+ schema: (z) => z.function().args(
11
+ z.union([
12
+ z.string().describe("compact entity reference"),
13
+ z.object({
14
+ kind: z.string().optional(),
15
+ namespace: z.string().optional(),
16
+ name: z.string()
17
+ }).describe("`CompoundEntityRef`")
18
+ ]),
19
+ z.object({
20
+ defaultKind: z.string().describe("The default kind, if none is given in the reference"),
21
+ defaultNamespace: z.string().describe(
22
+ "The default namespace, if none is given in the reference"
23
+ )
24
+ }).partial().optional()
25
+ ).returns(
26
+ z.object({
27
+ kind: z.string(),
28
+ namespace: z.string(),
29
+ name: z.string()
30
+ }).describe("`CompoundEntityRef`")
31
+ ),
32
+ examples: examples.examples,
33
+ filter: catalogModel.parseEntityRef
34
+ });
35
+
36
+ exports.parseEntityRef = parseEntityRef;
37
+ //# sourceMappingURL=filter.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter.cjs.js","sources":["../../../../../src/lib/templating/filters/parseEntityRef/filter.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { parseEntityRef as filter } from '@backstage/catalog-model';\nimport { createTemplateFilter } from '@backstage/plugin-scaffolder-node/alpha';\nimport { examples } from './examples';\n\nexport const parseEntityRef = createTemplateFilter({\n id: 'parseEntityRef',\n description:\n 'Extracts the parts of an entity reference, such as the kind, namespace, and name.',\n schema: z =>\n z\n .function()\n .args(\n z.union([\n z.string().describe('compact entity reference'),\n z\n .object({\n kind: z.string().optional(),\n namespace: z.string().optional(),\n name: z.string(),\n })\n .describe('`CompoundEntityRef`'),\n ]),\n z\n .object({\n defaultKind: z\n .string()\n .describe('The default kind, if none is given in the reference'),\n defaultNamespace: z\n .string()\n .describe(\n 'The default namespace, if none is given in the reference',\n ),\n })\n .partial()\n .optional(),\n )\n .returns(\n z\n .object({\n kind: z.string(),\n namespace: z.string(),\n name: z.string(),\n })\n .describe('`CompoundEntityRef`'),\n ),\n examples,\n filter,\n});\n"],"names":["createTemplateFilter","examples","filter"],"mappings":";;;;;;AAmBO,MAAM,iBAAiBA,0BAAqB,CAAA;AAAA,EACjD,EAAI,EAAA,gBAAA;AAAA,EACJ,WACE,EAAA,mFAAA;AAAA,EACF,MAAQ,EAAA,CAAA,CAAA,KACN,CACG,CAAA,QAAA,EACA,CAAA,IAAA;AAAA,IACC,EAAE,KAAM,CAAA;AAAA,MACN,CAAE,CAAA,MAAA,EAAS,CAAA,QAAA,CAAS,0BAA0B,CAAA;AAAA,MAC9C,EACG,MAAO,CAAA;AAAA,QACN,IAAM,EAAA,CAAA,CAAE,MAAO,EAAA,CAAE,QAAS,EAAA;AAAA,QAC1B,SAAW,EAAA,CAAA,CAAE,MAAO,EAAA,CAAE,QAAS,EAAA;AAAA,QAC/B,IAAA,EAAM,EAAE,MAAO;AAAA,OAChB,CACA,CAAA,QAAA,CAAS,qBAAqB;AAAA,KAClC,CAAA;AAAA,IACD,EACG,MAAO,CAAA;AAAA,MACN,WAAa,EAAA,CAAA,CACV,MAAO,EAAA,CACP,SAAS,qDAAqD,CAAA;AAAA,MACjE,gBAAA,EAAkB,CACf,CAAA,MAAA,EACA,CAAA,QAAA;AAAA,QACC;AAAA;AACF,KACH,CAAA,CACA,OAAQ,EAAA,CACR,QAAS;AAAA,GAEb,CAAA,OAAA;AAAA,IACC,EACG,MAAO,CAAA;AAAA,MACN,IAAA,EAAM,EAAE,MAAO,EAAA;AAAA,MACf,SAAA,EAAW,EAAE,MAAO,EAAA;AAAA,MACpB,IAAA,EAAM,EAAE,MAAO;AAAA,KAChB,CACA,CAAA,QAAA,CAAS,qBAAqB;AAAA,GACnC;AAAA,YACJC,iBAAA;AAAA,UACAC;AACF,CAAC;;;;"}
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ const examples = [
4
+ {
5
+ example: `- id: log
6
+ name: Parse Repo URL
7
+ action: debug:log
8
+ input:
9
+ message: \${{ parameters.repoUrl | parseRepoUrl }}`,
10
+ notes: ` - **Input**: \`github.com?repo=backstage&owner=backstage\`
11
+ - **Output**: \`{"host":"github.com","owner":"backstage","repo":"backstage"}\`
12
+ `
13
+ }
14
+ ];
15
+
16
+ exports.examples = examples;
17
+ //# sourceMappingURL=examples.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"examples.cjs.js","sources":["../../../../../src/lib/templating/filters/parseRepoUrl/examples.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { TemplateFilterExample } from '@backstage/plugin-scaffolder-node/alpha';\n\nexport const examples: TemplateFilterExample[] = [\n {\n example: `\\\n- id: log\n name: Parse Repo URL\n action: debug:log\n input:\n message: \\${{ parameters.repoUrl | parseRepoUrl }}`,\n notes: ` - **Input**: \\`github.com?repo=backstage&owner=backstage\\`\n - **Output**: \\`{\"host\":\"github.com\",\"owner\":\"backstage\",\"repo\":\"backstage\"}\\`\n`,\n },\n];\n"],"names":[],"mappings":";;AAkBO,MAAM,QAAoC,GAAA;AAAA,EAC/C;AAAA,IACE,OAAS,EAAA,CAAA;AAAA;AAAA;AAAA;AAAA,sDAAA,CAAA;AAAA,IAMT,KAAO,EAAA,CAAA;AAAA;AAAA;AAAA;AAIX;;;;"}
@@ -0,0 +1,30 @@
1
+ 'use strict';
2
+
3
+ var pluginScaffolderNode = require('@backstage/plugin-scaffolder-node');
4
+ var alpha = require('@backstage/plugin-scaffolder-node/alpha');
5
+ var examples = require('./examples.cjs.js');
6
+
7
+ const createParseRepoUrl = (integrations) => alpha.createTemplateFilter({
8
+ id: "parseRepoUrl",
9
+ description: "Parses a repository URL into its constituent parts: owner, repository name, etc.",
10
+ schema: (z) => z.function().args(
11
+ z.string().describe("repo URL as collected from repository picker")
12
+ ).returns(
13
+ z.object({
14
+ repo: z.string(),
15
+ host: z.string()
16
+ }).merge(
17
+ z.object({
18
+ owner: z.string(),
19
+ organization: z.string(),
20
+ workspace: z.string(),
21
+ project: z.string()
22
+ }).partial()
23
+ ).describe("`RepoSpec`")
24
+ ),
25
+ examples: examples.examples,
26
+ filter: (url) => pluginScaffolderNode.parseRepoUrl(url, integrations)
27
+ });
28
+
29
+ exports.createParseRepoUrl = createParseRepoUrl;
30
+ //# sourceMappingURL=filter.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter.cjs.js","sources":["../../../../../src/lib/templating/filters/parseRepoUrl/filter.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { ScmIntegrations } from '@backstage/integration';\nimport { parseRepoUrl } from '@backstage/plugin-scaffolder-node';\nimport { createTemplateFilter } from '@backstage/plugin-scaffolder-node/alpha';\nimport { examples } from './examples';\n\nexport const createParseRepoUrl = (integrations: ScmIntegrations) =>\n createTemplateFilter({\n id: 'parseRepoUrl',\n description:\n 'Parses a repository URL into its constituent parts: owner, repository name, etc.',\n schema: z =>\n z\n .function()\n .args(\n z.string().describe('repo URL as collected from repository picker'),\n )\n .returns(\n z\n .object({\n repo: z.string(),\n host: z.string(),\n })\n .merge(\n z\n .object({\n owner: z.string(),\n organization: z.string(),\n workspace: z.string(),\n project: z.string(),\n })\n .partial(),\n )\n .describe('`RepoSpec`'),\n ),\n examples,\n filter: url => parseRepoUrl(url, integrations),\n });\n"],"names":["createTemplateFilter","examples","parseRepoUrl"],"mappings":";;;;;;AAoBa,MAAA,kBAAA,GAAqB,CAAC,YAAA,KACjCA,0BAAqB,CAAA;AAAA,EACnB,EAAI,EAAA,cAAA;AAAA,EACJ,WACE,EAAA,kFAAA;AAAA,EACF,MAAQ,EAAA,CAAA,CAAA,KACN,CACG,CAAA,QAAA,EACA,CAAA,IAAA;AAAA,IACC,CAAE,CAAA,MAAA,EAAS,CAAA,QAAA,CAAS,8CAA8C;AAAA,GAEnE,CAAA,OAAA;AAAA,IACC,EACG,MAAO,CAAA;AAAA,MACN,IAAA,EAAM,EAAE,MAAO,EAAA;AAAA,MACf,IAAA,EAAM,EAAE,MAAO;AAAA,KAChB,CACA,CAAA,KAAA;AAAA,MACC,EACG,MAAO,CAAA;AAAA,QACN,KAAA,EAAO,EAAE,MAAO,EAAA;AAAA,QAChB,YAAA,EAAc,EAAE,MAAO,EAAA;AAAA,QACvB,SAAA,EAAW,EAAE,MAAO,EAAA;AAAA,QACpB,OAAA,EAAS,EAAE,MAAO;AAAA,OACnB,EACA,OAAQ;AAAA,KACb,CACC,SAAS,YAAY;AAAA,GAC1B;AAAA,YACJC,iBAAA;AAAA,EACA,MAAQ,EAAA,CAAA,GAAA,KAAOC,iCAAa,CAAA,GAAA,EAAK,YAAY;AAC/C,CAAC;;;;"}
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ const examples = [
4
+ {
5
+ example: `- id: log
6
+ name: Pick
7
+ action: debug:log
8
+ input:
9
+ message: \${{ parameters.owner | parseEntityRef | pick('name') }}`,
10
+ notes: `- **Input**: \`{ kind: 'Group', namespace: 'default', name: 'techdocs'\` }
11
+ - **Output**: \`techdocs\`
12
+ `
13
+ }
14
+ ];
15
+
16
+ exports.examples = examples;
17
+ //# sourceMappingURL=examples.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"examples.cjs.js","sources":["../../../../../src/lib/templating/filters/pick/examples.ts"],"sourcesContent":["import { TemplateFilterExample } from '@backstage/plugin-scaffolder-node/alpha';\n\n/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nexport const examples: TemplateFilterExample[] = [\n {\n example: `\\\n- id: log\n name: Pick\n action: debug:log\n input:\n message: \\${{ parameters.owner | parseEntityRef | pick('name') }}`,\n notes: `\\\n- **Input**: \\`{ kind: 'Group', namespace: 'default', name: 'techdocs'\\` }\n- **Output**: \\`techdocs\\`\n`,\n },\n];\n"],"names":[],"mappings":";;AAiBO,MAAM,QAAoC,GAAA;AAAA,EAC/C;AAAA,IACE,OAAS,EAAA,CAAA;AAAA;AAAA;AAAA;AAAA,qEAAA,CAAA;AAAA,IAMT,KAAO,EAAA,CAAA;AAAA;AAAA;AAAA;AAKX;;;;"}
@@ -0,0 +1,16 @@
1
+ 'use strict';
2
+
3
+ var alpha = require('@backstage/plugin-scaffolder-node/alpha');
4
+ var lodash = require('lodash');
5
+ var examples = require('./examples.cjs.js');
6
+
7
+ const pick = alpha.createTemplateFilter({
8
+ id: "pick",
9
+ description: "Selects a specific property (e.g. kind, namespace, name) from an object.",
10
+ schema: (z) => z.function().args(z.any(), z.string().describe("Property")).returns(z.any().describe("Selected property")),
11
+ examples: examples.examples,
12
+ filter: lodash.get
13
+ });
14
+
15
+ exports.pick = pick;
16
+ //# sourceMappingURL=filter.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter.cjs.js","sources":["../../../../../src/lib/templating/filters/pick/filter.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { createTemplateFilter } from '@backstage/plugin-scaffolder-node/alpha';\nimport { get as filter } from 'lodash';\nimport { examples } from './examples';\n\nexport const pick = createTemplateFilter({\n id: 'pick',\n description:\n 'Selects a specific property (e.g. kind, namespace, name) from an object.',\n schema: z =>\n z\n .function()\n .args(z.any(), z.string().describe('Property'))\n .returns(z.any().describe('Selected property')),\n examples,\n filter,\n});\n"],"names":["createTemplateFilter","examples","filter"],"mappings":";;;;;;AAmBO,MAAM,OAAOA,0BAAqB,CAAA;AAAA,EACvC,EAAI,EAAA,MAAA;AAAA,EACJ,WACE,EAAA,0EAAA;AAAA,EACF,MAAA,EAAQ,OACN,CACG,CAAA,QAAA,GACA,IAAK,CAAA,CAAA,CAAE,GAAI,EAAA,EAAG,CAAE,CAAA,MAAA,GAAS,QAAS,CAAA,UAAU,CAAC,CAC7C,CAAA,OAAA,CAAQ,EAAE,GAAI,EAAA,CAAE,QAAS,CAAA,mBAAmB,CAAC,CAAA;AAAA,YAClDC,iBAAA;AAAA,UACAC;AACF,CAAC;;;;"}
@@ -0,0 +1,18 @@
1
+ 'use strict';
2
+
3
+ const examples = [
4
+ {
5
+ example: `- id: log
6
+ name: Project Slug
7
+ action: debug:log
8
+ input:
9
+ message: \${{ parameters.repoUrl | projectSlug }}
10
+ `,
11
+ notes: `- **Input**: \`github.com?repo=backstage&owner=backstage\`
12
+ - **Output**: backstage/backstage
13
+ `
14
+ }
15
+ ];
16
+
17
+ exports.examples = examples;
18
+ //# sourceMappingURL=examples.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"examples.cjs.js","sources":["../../../../../src/lib/templating/filters/projectSlug/examples.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { TemplateFilterExample } from '@backstage/plugin-scaffolder-node/alpha';\n\nexport const examples: TemplateFilterExample[] = [\n {\n example: `\\\n- id: log\n name: Project Slug\n action: debug:log\n input:\n message: \\${{ parameters.repoUrl | projectSlug }}\n`,\n notes: `\\\n- **Input**: \\`github.com?repo=backstage&owner=backstage\\`\n- **Output**: backstage/backstage\n`,\n },\n];\n"],"names":[],"mappings":";;AAiBO,MAAM,QAAoC,GAAA;AAAA,EAC/C;AAAA,IACE,OAAS,EAAA,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAAA,IAOT,KAAO,EAAA,CAAA;AAAA;AAAA;AAAA;AAKX;;;;"}
@@ -0,0 +1,21 @@
1
+ 'use strict';
2
+
3
+ var pluginScaffolderNode = require('@backstage/plugin-scaffolder-node');
4
+ var alpha = require('@backstage/plugin-scaffolder-node/alpha');
5
+ var examples = require('./examples.cjs.js');
6
+
7
+ const createProjectSlug = (integrations) => alpha.createTemplateFilter({
8
+ id: "projectSlug",
9
+ description: "Generates a project slug from a repository URL.",
10
+ schema: (z) => z.function().args(
11
+ z.string().describe("repo URL as collected from repository picker")
12
+ ).returns(z.string()),
13
+ examples: examples.examples,
14
+ filter: (repoUrl) => {
15
+ const { owner, repo } = pluginScaffolderNode.parseRepoUrl(repoUrl, integrations);
16
+ return `${owner}/${repo}`;
17
+ }
18
+ });
19
+
20
+ exports.createProjectSlug = createProjectSlug;
21
+ //# sourceMappingURL=filter.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter.cjs.js","sources":["../../../../../src/lib/templating/filters/projectSlug/filter.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { ScmIntegrations } from '@backstage/integration';\nimport { parseRepoUrl } from '@backstage/plugin-scaffolder-node';\nimport { createTemplateFilter } from '@backstage/plugin-scaffolder-node/alpha';\nimport { examples } from './examples';\n\nexport const createProjectSlug = (integrations: ScmIntegrations) =>\n createTemplateFilter({\n id: 'projectSlug',\n description: 'Generates a project slug from a repository URL.',\n schema: z =>\n z\n .function()\n .args(\n z.string().describe('repo URL as collected from repository picker'),\n )\n .returns(z.string()),\n examples,\n filter: repoUrl => {\n const { owner, repo } = parseRepoUrl(repoUrl, integrations);\n return `${owner}/${repo}`;\n },\n });\n"],"names":["createTemplateFilter","examples","parseRepoUrl"],"mappings":";;;;;;AAoBa,MAAA,iBAAA,GAAoB,CAAC,YAAA,KAChCA,0BAAqB,CAAA;AAAA,EACnB,EAAI,EAAA,aAAA;AAAA,EACJ,WAAa,EAAA,iDAAA;AAAA,EACb,MAAQ,EAAA,CAAA,CAAA,KACN,CACG,CAAA,QAAA,EACA,CAAA,IAAA;AAAA,IACC,CAAE,CAAA,MAAA,EAAS,CAAA,QAAA,CAAS,8CAA8C;AAAA,GAEnE,CAAA,OAAA,CAAQ,CAAE,CAAA,MAAA,EAAQ,CAAA;AAAA,YACvBC,iBAAA;AAAA,EACA,QAAQ,CAAW,OAAA,KAAA;AACjB,IAAA,MAAM,EAAE,KAAO,EAAA,IAAA,EAAS,GAAAC,iCAAA,CAAa,SAAS,YAAY,CAAA;AAC1D,IAAO,OAAA,CAAA,EAAG,KAAK,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA;AAAA;AAE3B,CAAC;;;;"}
@@ -8,7 +8,7 @@ var globby = require('globby');
8
8
  var fs = require('fs-extra');
9
9
  var isbinaryfile = require('isbinaryfile');
10
10
  var SecureTemplater = require('../../../../lib/templating/SecureTemplater.cjs.js');
11
- var filters = require('../../../../lib/templating/filters.cjs.js');
11
+ var createDefaultFilters = require('../../../../lib/templating/filters/createDefaultFilters.cjs.js');
12
12
  var template_examples = require('./template.examples.cjs.js');
13
13
  var templating = require('../../../../util/templating.cjs.js');
14
14
 
@@ -25,7 +25,7 @@ function createFetchTemplateAction(options) {
25
25
  additionalTemplateGlobals
26
26
  } = options;
27
27
  const defaultTemplateFilters = templating.convertFiltersToRecord(
28
- filters.default({ integrations })
28
+ createDefaultFilters.createDefaultFilters({ integrations })
29
29
  );
30
30
  return pluginScaffolderNode.createTemplateAction({
31
31
  id: "fetch:template",
@@ -1 +1 @@
1
- {"version":3,"file":"template.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/fetch/template.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { extname } from 'path';\nimport { UrlReaderService } from '@backstage/backend-plugin-api';\nimport { resolveSafeChildPath } from '@backstage/backend-plugin-api';\nimport { InputError } from '@backstage/errors';\nimport { ScmIntegrations } from '@backstage/integration';\nimport {\n createTemplateAction,\n fetchContents,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport globby from 'globby';\nimport fs from 'fs-extra';\nimport { isBinaryFile } from 'isbinaryfile';\nimport { SecureTemplater } from '../../../../lib/templating/SecureTemplater';\nimport createDefaultFilters from '../../../../lib/templating/filters';\nimport { examples } from './template.examples';\nimport { convertFiltersToRecord } from '../../../../util/templating';\n\n/**\n * Downloads a skeleton, templates variables into file and directory names and content.\n * Then places the result in the workspace, or optionally in a subdirectory\n * specified by the 'targetPath' input option.\n *\n * @public\n */\nexport function createFetchTemplateAction(options: {\n reader: UrlReaderService;\n integrations: ScmIntegrations;\n additionalTemplateFilters?: Record<string, TemplateFilter>;\n additionalTemplateGlobals?: Record<string, TemplateGlobal>;\n}) {\n const {\n reader,\n integrations,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n } = options;\n\n const defaultTemplateFilters = convertFiltersToRecord(\n createDefaultFilters({ integrations }),\n );\n\n return createTemplateAction<{\n url: string;\n targetPath?: string;\n values: any;\n templateFileExtension?: string | boolean;\n\n // Cookiecutter compat options\n /**\n * @deprecated This field is deprecated in favor of copyWithoutTemplating.\n */\n copyWithoutRender?: string[];\n copyWithoutTemplating?: string[];\n cookiecutterCompat?: boolean;\n replace?: boolean;\n trimBlocks?: boolean;\n lstripBlocks?: boolean;\n token?: string;\n }>({\n id: 'fetch:template',\n description:\n 'Downloads a skeleton, templates variables into file and directory names and content, and places the result in the workspace, or optionally in a subdirectory specified by the `targetPath` input option.',\n examples,\n schema: {\n input: {\n type: 'object',\n required: ['url'],\n properties: {\n url: {\n title: 'Fetch URL',\n description:\n 'Relative path or absolute URL pointing to the directory tree to fetch',\n type: 'string',\n },\n targetPath: {\n title: 'Target Path',\n description:\n 'Target path within the working directory to download the contents to. Defaults to the working directory root.',\n type: 'string',\n },\n values: {\n title: 'Template Values',\n description: 'Values to pass on to the templating engine',\n type: 'object',\n },\n copyWithoutRender: {\n title: '[Deprecated] Copy Without Render',\n description:\n 'An array of glob patterns. Any files or directories which match are copied without being processed as templates.',\n type: 'array',\n items: {\n type: 'string',\n },\n },\n copyWithoutTemplating: {\n title: 'Copy Without Templating',\n description:\n 'An array of glob patterns. Contents of matched files or directories are copied without being processed, but paths are subject to rendering.',\n type: 'array',\n items: {\n type: 'string',\n },\n },\n cookiecutterCompat: {\n title: 'Cookiecutter compatibility mode',\n description:\n 'Enable features to maximise compatibility with templates built for fetch:cookiecutter',\n type: 'boolean',\n },\n templateFileExtension: {\n title: 'Template File Extension',\n description:\n 'If set, only files with the given extension will be templated. If set to `true`, the default extension `.njk` is used.',\n type: ['string', 'boolean'],\n },\n replace: {\n title: 'Replace files',\n description:\n 'If set, replace files in targetPath instead of skipping existing ones.',\n type: 'boolean',\n },\n token: {\n title: 'Token',\n description:\n 'An optional token to use for authentication when reading the resources.',\n type: 'string',\n },\n },\n },\n },\n supportsDryRun: true,\n async handler(ctx) {\n ctx.logger.info('Fetching template content from remote URL');\n\n const workDir = await ctx.createTemporaryDirectory();\n const templateDir = resolveSafeChildPath(workDir, 'template');\n\n const targetPath = ctx.input.targetPath ?? './';\n const outputDir = resolveSafeChildPath(ctx.workspacePath, targetPath);\n if (ctx.input.copyWithoutRender && ctx.input.copyWithoutTemplating) {\n throw new InputError(\n 'Fetch action input copyWithoutRender and copyWithoutTemplating can not be used at the same time',\n );\n }\n\n let copyOnlyPatterns: string[] | undefined;\n let renderFilename: boolean;\n if (ctx.input.copyWithoutRender) {\n ctx.logger.warn(\n '[Deprecated] copyWithoutRender is deprecated Please use copyWithoutTemplating instead.',\n );\n copyOnlyPatterns = ctx.input.copyWithoutRender;\n renderFilename = false;\n } else {\n copyOnlyPatterns = ctx.input.copyWithoutTemplating;\n renderFilename = true;\n }\n\n if (copyOnlyPatterns && !Array.isArray(copyOnlyPatterns)) {\n throw new InputError(\n 'Fetch action input copyWithoutRender/copyWithoutTemplating must be an Array',\n );\n }\n\n if (\n ctx.input.templateFileExtension &&\n (copyOnlyPatterns || ctx.input.cookiecutterCompat)\n ) {\n throw new InputError(\n 'Fetch action input extension incompatible with copyWithoutRender/copyWithoutTemplating and cookiecutterCompat',\n );\n }\n\n let extension: string | false = false;\n if (ctx.input.templateFileExtension) {\n extension =\n ctx.input.templateFileExtension === true\n ? '.njk'\n : ctx.input.templateFileExtension;\n if (!extension.startsWith('.')) {\n extension = `.${extension}`;\n }\n }\n\n await fetchContents({\n reader,\n integrations,\n baseUrl: ctx.templateInfo?.baseUrl,\n fetchUrl: ctx.input.url,\n outputPath: templateDir,\n token: ctx.input.token,\n });\n\n ctx.logger.info('Listing files and directories in template');\n const allEntriesInTemplate = await globby(`**/*`, {\n cwd: templateDir,\n dot: true,\n onlyFiles: false,\n markDirectories: true,\n followSymbolicLinks: false,\n });\n\n const nonTemplatedEntries = new Set(\n await globby(copyOnlyPatterns || [], {\n cwd: templateDir,\n dot: true,\n onlyFiles: false,\n markDirectories: true,\n followSymbolicLinks: false,\n }),\n );\n\n // Cookiecutter prefixes all parameters in templates with\n // `cookiecutter.`. To replicate this, we wrap our parameters\n // in an object with a `cookiecutter` property when compat\n // mode is enabled.\n const { cookiecutterCompat, values } = ctx.input;\n const context = {\n [cookiecutterCompat ? 'cookiecutter' : 'values']: values,\n };\n\n ctx.logger.info(\n `Processing ${allEntriesInTemplate.length} template files/directories with input values`,\n ctx.input.values,\n );\n\n const renderTemplate = await SecureTemplater.loadRenderer({\n cookiecutterCompat: ctx.input.cookiecutterCompat,\n templateFilters: {\n ...defaultTemplateFilters,\n ...(additionalTemplateFilters ?? {}),\n },\n templateGlobals: additionalTemplateGlobals,\n nunjucksConfigs: {\n trimBlocks: ctx.input.trimBlocks,\n lstripBlocks: ctx.input.lstripBlocks,\n },\n });\n\n for (const location of allEntriesInTemplate) {\n let renderContents: boolean;\n\n let localOutputPath = location;\n if (extension) {\n renderContents = extname(localOutputPath) === extension;\n if (renderContents) {\n localOutputPath = localOutputPath.slice(0, -extension.length);\n }\n // extension is mutual exclusive with copyWithoutRender/copyWithoutTemplating,\n // therefore the output path is always rendered.\n localOutputPath = renderTemplate(localOutputPath, context);\n } else {\n renderContents = !nonTemplatedEntries.has(location);\n // The logic here is a bit tangled because it depends on two variables.\n // If renderFilename is true, which means copyWithoutTemplating is used,\n // then the path is always rendered.\n // If renderFilename is false, which means copyWithoutRender is used,\n // then matched file/directory won't be processed, same as before.\n if (renderFilename) {\n localOutputPath = renderTemplate(localOutputPath, context);\n } else {\n localOutputPath = renderContents\n ? renderTemplate(localOutputPath, context)\n : localOutputPath;\n }\n }\n\n if (containsSkippedContent(localOutputPath)) {\n continue;\n }\n\n const outputPath = resolveSafeChildPath(outputDir, localOutputPath);\n if (fs.existsSync(outputPath) && !ctx.input.replace) {\n continue;\n }\n\n if (!renderContents && !extension) {\n ctx.logger.info(\n `Copying file/directory ${location} without processing.`,\n );\n }\n\n if (location.endsWith('/')) {\n ctx.logger.info(\n `Writing directory ${location} to template output path.`,\n );\n await fs.ensureDir(outputPath);\n } else {\n const inputFilePath = resolveSafeChildPath(templateDir, location);\n const stats = await fs.promises.lstat(inputFilePath);\n\n if (stats.isSymbolicLink() || (await isBinaryFile(inputFilePath))) {\n ctx.logger.info(\n `Copying file binary or symbolic link at ${location}, to template output path.`,\n );\n await fs.copy(inputFilePath, outputPath);\n } else {\n const statsObj = await fs.stat(inputFilePath);\n ctx.logger.info(\n `Writing file ${location} to template output path with mode ${statsObj.mode}.`,\n );\n const inputFileContents = await fs.readFile(inputFilePath, 'utf-8');\n await fs.outputFile(\n outputPath,\n renderContents\n ? renderTemplate(inputFileContents, context)\n : inputFileContents,\n { mode: statsObj.mode },\n );\n }\n }\n }\n\n ctx.logger.info(`Template result written to ${outputDir}`);\n },\n });\n}\n\nfunction containsSkippedContent(localOutputPath: string): boolean {\n // if the path is empty means that there is a file skipped in the root\n // if the path starts with a separator it means that the root directory has been skipped\n // if the path includes // means that there is a subdirectory skipped\n // All paths returned are considered with / separator because of globby returning the linux separator for all os'.\n return (\n localOutputPath === '' ||\n localOutputPath.startsWith('/') ||\n localOutputPath.includes('//')\n );\n}\n"],"names":["convertFiltersToRecord","createDefaultFilters","createTemplateAction","examples","resolveSafeChildPath","InputError","fetchContents","globby","SecureTemplater","extname","fs","isBinaryFile"],"mappings":"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"}
1
+ {"version":3,"file":"template.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/fetch/template.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { extname } from 'path';\nimport { UrlReaderService } from '@backstage/backend-plugin-api';\nimport { resolveSafeChildPath } from '@backstage/backend-plugin-api';\nimport { InputError } from '@backstage/errors';\nimport { ScmIntegrations } from '@backstage/integration';\nimport {\n createTemplateAction,\n fetchContents,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport globby from 'globby';\nimport fs from 'fs-extra';\nimport { isBinaryFile } from 'isbinaryfile';\nimport { SecureTemplater } from '../../../../lib/templating/SecureTemplater';\nimport { createDefaultFilters } from '../../../../lib/templating/filters/createDefaultFilters';\nimport { examples } from './template.examples';\nimport { convertFiltersToRecord } from '../../../../util/templating';\n\n/**\n * Downloads a skeleton, templates variables into file and directory names and content.\n * Then places the result in the workspace, or optionally in a subdirectory\n * specified by the 'targetPath' input option.\n *\n * @public\n */\nexport function createFetchTemplateAction(options: {\n reader: UrlReaderService;\n integrations: ScmIntegrations;\n additionalTemplateFilters?: Record<string, TemplateFilter>;\n additionalTemplateGlobals?: Record<string, TemplateGlobal>;\n}) {\n const {\n reader,\n integrations,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n } = options;\n\n const defaultTemplateFilters = convertFiltersToRecord(\n createDefaultFilters({ integrations }),\n );\n\n return createTemplateAction<{\n url: string;\n targetPath?: string;\n values: any;\n templateFileExtension?: string | boolean;\n\n // Cookiecutter compat options\n /**\n * @deprecated This field is deprecated in favor of copyWithoutTemplating.\n */\n copyWithoutRender?: string[];\n copyWithoutTemplating?: string[];\n cookiecutterCompat?: boolean;\n replace?: boolean;\n trimBlocks?: boolean;\n lstripBlocks?: boolean;\n token?: string;\n }>({\n id: 'fetch:template',\n description:\n 'Downloads a skeleton, templates variables into file and directory names and content, and places the result in the workspace, or optionally in a subdirectory specified by the `targetPath` input option.',\n examples,\n schema: {\n input: {\n type: 'object',\n required: ['url'],\n properties: {\n url: {\n title: 'Fetch URL',\n description:\n 'Relative path or absolute URL pointing to the directory tree to fetch',\n type: 'string',\n },\n targetPath: {\n title: 'Target Path',\n description:\n 'Target path within the working directory to download the contents to. Defaults to the working directory root.',\n type: 'string',\n },\n values: {\n title: 'Template Values',\n description: 'Values to pass on to the templating engine',\n type: 'object',\n },\n copyWithoutRender: {\n title: '[Deprecated] Copy Without Render',\n description:\n 'An array of glob patterns. Any files or directories which match are copied without being processed as templates.',\n type: 'array',\n items: {\n type: 'string',\n },\n },\n copyWithoutTemplating: {\n title: 'Copy Without Templating',\n description:\n 'An array of glob patterns. Contents of matched files or directories are copied without being processed, but paths are subject to rendering.',\n type: 'array',\n items: {\n type: 'string',\n },\n },\n cookiecutterCompat: {\n title: 'Cookiecutter compatibility mode',\n description:\n 'Enable features to maximise compatibility with templates built for fetch:cookiecutter',\n type: 'boolean',\n },\n templateFileExtension: {\n title: 'Template File Extension',\n description:\n 'If set, only files with the given extension will be templated. If set to `true`, the default extension `.njk` is used.',\n type: ['string', 'boolean'],\n },\n replace: {\n title: 'Replace files',\n description:\n 'If set, replace files in targetPath instead of skipping existing ones.',\n type: 'boolean',\n },\n token: {\n title: 'Token',\n description:\n 'An optional token to use for authentication when reading the resources.',\n type: 'string',\n },\n },\n },\n },\n supportsDryRun: true,\n async handler(ctx) {\n ctx.logger.info('Fetching template content from remote URL');\n\n const workDir = await ctx.createTemporaryDirectory();\n const templateDir = resolveSafeChildPath(workDir, 'template');\n\n const targetPath = ctx.input.targetPath ?? './';\n const outputDir = resolveSafeChildPath(ctx.workspacePath, targetPath);\n if (ctx.input.copyWithoutRender && ctx.input.copyWithoutTemplating) {\n throw new InputError(\n 'Fetch action input copyWithoutRender and copyWithoutTemplating can not be used at the same time',\n );\n }\n\n let copyOnlyPatterns: string[] | undefined;\n let renderFilename: boolean;\n if (ctx.input.copyWithoutRender) {\n ctx.logger.warn(\n '[Deprecated] copyWithoutRender is deprecated Please use copyWithoutTemplating instead.',\n );\n copyOnlyPatterns = ctx.input.copyWithoutRender;\n renderFilename = false;\n } else {\n copyOnlyPatterns = ctx.input.copyWithoutTemplating;\n renderFilename = true;\n }\n\n if (copyOnlyPatterns && !Array.isArray(copyOnlyPatterns)) {\n throw new InputError(\n 'Fetch action input copyWithoutRender/copyWithoutTemplating must be an Array',\n );\n }\n\n if (\n ctx.input.templateFileExtension &&\n (copyOnlyPatterns || ctx.input.cookiecutterCompat)\n ) {\n throw new InputError(\n 'Fetch action input extension incompatible with copyWithoutRender/copyWithoutTemplating and cookiecutterCompat',\n );\n }\n\n let extension: string | false = false;\n if (ctx.input.templateFileExtension) {\n extension =\n ctx.input.templateFileExtension === true\n ? '.njk'\n : ctx.input.templateFileExtension;\n if (!extension.startsWith('.')) {\n extension = `.${extension}`;\n }\n }\n\n await fetchContents({\n reader,\n integrations,\n baseUrl: ctx.templateInfo?.baseUrl,\n fetchUrl: ctx.input.url,\n outputPath: templateDir,\n token: ctx.input.token,\n });\n\n ctx.logger.info('Listing files and directories in template');\n const allEntriesInTemplate = await globby(`**/*`, {\n cwd: templateDir,\n dot: true,\n onlyFiles: false,\n markDirectories: true,\n followSymbolicLinks: false,\n });\n\n const nonTemplatedEntries = new Set(\n await globby(copyOnlyPatterns || [], {\n cwd: templateDir,\n dot: true,\n onlyFiles: false,\n markDirectories: true,\n followSymbolicLinks: false,\n }),\n );\n\n // Cookiecutter prefixes all parameters in templates with\n // `cookiecutter.`. To replicate this, we wrap our parameters\n // in an object with a `cookiecutter` property when compat\n // mode is enabled.\n const { cookiecutterCompat, values } = ctx.input;\n const context = {\n [cookiecutterCompat ? 'cookiecutter' : 'values']: values,\n };\n\n ctx.logger.info(\n `Processing ${allEntriesInTemplate.length} template files/directories with input values`,\n ctx.input.values,\n );\n\n const renderTemplate = await SecureTemplater.loadRenderer({\n cookiecutterCompat: ctx.input.cookiecutterCompat,\n templateFilters: {\n ...defaultTemplateFilters,\n ...(additionalTemplateFilters ?? {}),\n },\n templateGlobals: additionalTemplateGlobals,\n nunjucksConfigs: {\n trimBlocks: ctx.input.trimBlocks,\n lstripBlocks: ctx.input.lstripBlocks,\n },\n });\n\n for (const location of allEntriesInTemplate) {\n let renderContents: boolean;\n\n let localOutputPath = location;\n if (extension) {\n renderContents = extname(localOutputPath) === extension;\n if (renderContents) {\n localOutputPath = localOutputPath.slice(0, -extension.length);\n }\n // extension is mutual exclusive with copyWithoutRender/copyWithoutTemplating,\n // therefore the output path is always rendered.\n localOutputPath = renderTemplate(localOutputPath, context);\n } else {\n renderContents = !nonTemplatedEntries.has(location);\n // The logic here is a bit tangled because it depends on two variables.\n // If renderFilename is true, which means copyWithoutTemplating is used,\n // then the path is always rendered.\n // If renderFilename is false, which means copyWithoutRender is used,\n // then matched file/directory won't be processed, same as before.\n if (renderFilename) {\n localOutputPath = renderTemplate(localOutputPath, context);\n } else {\n localOutputPath = renderContents\n ? renderTemplate(localOutputPath, context)\n : localOutputPath;\n }\n }\n\n if (containsSkippedContent(localOutputPath)) {\n continue;\n }\n\n const outputPath = resolveSafeChildPath(outputDir, localOutputPath);\n if (fs.existsSync(outputPath) && !ctx.input.replace) {\n continue;\n }\n\n if (!renderContents && !extension) {\n ctx.logger.info(\n `Copying file/directory ${location} without processing.`,\n );\n }\n\n if (location.endsWith('/')) {\n ctx.logger.info(\n `Writing directory ${location} to template output path.`,\n );\n await fs.ensureDir(outputPath);\n } else {\n const inputFilePath = resolveSafeChildPath(templateDir, location);\n const stats = await fs.promises.lstat(inputFilePath);\n\n if (stats.isSymbolicLink() || (await isBinaryFile(inputFilePath))) {\n ctx.logger.info(\n `Copying file binary or symbolic link at ${location}, to template output path.`,\n );\n await fs.copy(inputFilePath, outputPath);\n } else {\n const statsObj = await fs.stat(inputFilePath);\n ctx.logger.info(\n `Writing file ${location} to template output path with mode ${statsObj.mode}.`,\n );\n const inputFileContents = await fs.readFile(inputFilePath, 'utf-8');\n await fs.outputFile(\n outputPath,\n renderContents\n ? renderTemplate(inputFileContents, context)\n : inputFileContents,\n { mode: statsObj.mode },\n );\n }\n }\n }\n\n ctx.logger.info(`Template result written to ${outputDir}`);\n },\n });\n}\n\nfunction containsSkippedContent(localOutputPath: string): boolean {\n // if the path is empty means that there is a file skipped in the root\n // if the path starts with a separator it means that the root directory has been skipped\n // if the path includes // means that there is a subdirectory skipped\n // All paths returned are considered with / separator because of globby returning the linux separator for all os'.\n return (\n localOutputPath === '' ||\n localOutputPath.startsWith('/') ||\n localOutputPath.includes('//')\n );\n}\n"],"names":["convertFiltersToRecord","createDefaultFilters","createTemplateAction","examples","resolveSafeChildPath","InputError","fetchContents","globby","SecureTemplater","extname","fs","isBinaryFile"],"mappings":"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"}
@@ -4,7 +4,7 @@ var backendPluginApi = require('@backstage/backend-plugin-api');
4
4
  var templateFile_examples = require('./templateFile.examples.cjs.js');
5
5
  var pluginScaffolderNode = require('@backstage/plugin-scaffolder-node');
6
6
  var SecureTemplater = require('../../../../lib/templating/SecureTemplater.cjs.js');
7
- var filters = require('../../../../lib/templating/filters.cjs.js');
7
+ var createDefaultFilters = require('../../../../lib/templating/filters/createDefaultFilters.cjs.js');
8
8
  var path = require('path');
9
9
  var fs = require('fs-extra');
10
10
  var templating = require('../../../../util/templating.cjs.js');
@@ -22,7 +22,7 @@ function createFetchTemplateFileAction(options) {
22
22
  additionalTemplateGlobals
23
23
  } = options;
24
24
  const defaultTemplateFilters = templating.convertFiltersToRecord(
25
- filters.default({ integrations })
25
+ createDefaultFilters.createDefaultFilters({ integrations })
26
26
  );
27
27
  return pluginScaffolderNode.createTemplateAction({
28
28
  id: "fetch:template:file",
@@ -1 +1 @@
1
- {"version":3,"file":"templateFile.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/fetch/templateFile.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { UrlReaderService } from '@backstage/backend-plugin-api';\nimport { resolveSafeChildPath } from '@backstage/backend-plugin-api';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { examples } from './templateFile.examples';\nimport {\n createTemplateAction,\n fetchFile,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport { SecureTemplater } from '../../../../lib/templating/SecureTemplater';\nimport createDefaultFilters from '../../../../lib/templating/filters';\nimport path from 'path';\nimport fs from 'fs-extra';\nimport { convertFiltersToRecord } from '../../../../util/templating';\n\n/**\n * Downloads a single file and templates variables into file.\n * Then places the result in the workspace, or optionally in a subdirectory\n * specified by the 'targetPath' input option.\n * @public\n */\nexport function createFetchTemplateFileAction(options: {\n reader: UrlReaderService;\n integrations: ScmIntegrations;\n additionalTemplateFilters?: Record<string, TemplateFilter>;\n additionalTemplateGlobals?: Record<string, TemplateGlobal>;\n}) {\n const {\n reader,\n integrations,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n } = options;\n\n const defaultTemplateFilters = convertFiltersToRecord(\n createDefaultFilters({ integrations }),\n );\n\n return createTemplateAction<{\n url: string;\n targetPath: string;\n values: any;\n cookiecutterCompat?: boolean;\n replace?: boolean;\n trimBlocks?: boolean;\n lstripBlocks?: boolean;\n token?: string;\n }>({\n id: 'fetch:template:file',\n description: 'Downloads single file and places it in the workspace.',\n examples,\n schema: {\n input: {\n type: 'object',\n required: ['url', 'targetPath'],\n properties: {\n url: {\n title: 'Fetch URL',\n description:\n 'Relative path or absolute URL pointing to the single file to fetch.',\n type: 'string',\n },\n targetPath: {\n title: 'Target Path',\n description:\n 'Target path within the working directory to download the file as.',\n type: 'string',\n },\n values: {\n title: 'Template Values',\n description: 'Values to pass on to the templating engine',\n type: 'object',\n },\n cookiecutterCompat: {\n title: 'Cookiecutter compatibility mode',\n description:\n 'Enable features to maximise compatibility with templates built for fetch:cookiecutter',\n type: 'boolean',\n },\n replace: {\n title: 'Replace file',\n description:\n 'If set, replace file in targetPath instead of overwriting existing one.',\n type: 'boolean',\n },\n token: {\n title: 'Token',\n description:\n 'An optional token to use for authentication when reading the resources.',\n type: 'string',\n },\n },\n },\n },\n supportsDryRun: true,\n async handler(ctx) {\n ctx.logger.info('Fetching template file content from remote URL');\n\n const workDir = await ctx.createTemporaryDirectory();\n // Write to a tmp file, render the template, then copy to workspace.\n const tmpFilePath = path.join(workDir, 'tmp');\n\n const outputPath = resolveSafeChildPath(\n ctx.workspacePath,\n ctx.input.targetPath,\n );\n\n if (fs.existsSync(outputPath) && !ctx.input.replace) {\n ctx.logger.info(\n `File ${ctx.input.targetPath} already exists in workspace, not replacing.`,\n );\n return;\n }\n\n await fetchFile({\n reader,\n integrations,\n baseUrl: ctx.templateInfo?.baseUrl,\n fetchUrl: ctx.input.url,\n outputPath: tmpFilePath,\n token: ctx.input.token,\n });\n\n const { cookiecutterCompat, values } = ctx.input;\n const context = {\n [cookiecutterCompat ? 'cookiecutter' : 'values']: values,\n };\n\n ctx.logger.info(\n `Processing template file with input values`,\n ctx.input.values,\n );\n\n const renderTemplate = await SecureTemplater.loadRenderer({\n cookiecutterCompat,\n templateFilters: {\n ...defaultTemplateFilters,\n ...additionalTemplateFilters,\n },\n templateGlobals: additionalTemplateGlobals,\n nunjucksConfigs: {\n trimBlocks: ctx.input.trimBlocks,\n lstripBlocks: ctx.input.lstripBlocks,\n },\n });\n\n const contents = await fs.readFile(tmpFilePath, 'utf-8');\n const result = renderTemplate(contents, context);\n await fs.ensureDir(path.dirname(outputPath));\n await fs.outputFile(outputPath, result);\n\n ctx.logger.info(`Template file has been written to ${outputPath}`);\n },\n });\n}\n"],"names":["convertFiltersToRecord","createDefaultFilters","createTemplateAction","examples","path","resolveSafeChildPath","fs","fetchFile","SecureTemplater"],"mappings":"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"}
1
+ {"version":3,"file":"templateFile.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/fetch/templateFile.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { UrlReaderService } from '@backstage/backend-plugin-api';\nimport { resolveSafeChildPath } from '@backstage/backend-plugin-api';\nimport { ScmIntegrations } from '@backstage/integration';\nimport { examples } from './templateFile.examples';\nimport {\n createTemplateAction,\n fetchFile,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport { SecureTemplater } from '../../../../lib/templating/SecureTemplater';\nimport { createDefaultFilters } from '../../../../lib/templating/filters/createDefaultFilters';\nimport path from 'path';\nimport fs from 'fs-extra';\nimport { convertFiltersToRecord } from '../../../../util/templating';\n\n/**\n * Downloads a single file and templates variables into file.\n * Then places the result in the workspace, or optionally in a subdirectory\n * specified by the 'targetPath' input option.\n * @public\n */\nexport function createFetchTemplateFileAction(options: {\n reader: UrlReaderService;\n integrations: ScmIntegrations;\n additionalTemplateFilters?: Record<string, TemplateFilter>;\n additionalTemplateGlobals?: Record<string, TemplateGlobal>;\n}) {\n const {\n reader,\n integrations,\n additionalTemplateFilters,\n additionalTemplateGlobals,\n } = options;\n\n const defaultTemplateFilters = convertFiltersToRecord(\n createDefaultFilters({ integrations }),\n );\n\n return createTemplateAction<{\n url: string;\n targetPath: string;\n values: any;\n cookiecutterCompat?: boolean;\n replace?: boolean;\n trimBlocks?: boolean;\n lstripBlocks?: boolean;\n token?: string;\n }>({\n id: 'fetch:template:file',\n description: 'Downloads single file and places it in the workspace.',\n examples,\n schema: {\n input: {\n type: 'object',\n required: ['url', 'targetPath'],\n properties: {\n url: {\n title: 'Fetch URL',\n description:\n 'Relative path or absolute URL pointing to the single file to fetch.',\n type: 'string',\n },\n targetPath: {\n title: 'Target Path',\n description:\n 'Target path within the working directory to download the file as.',\n type: 'string',\n },\n values: {\n title: 'Template Values',\n description: 'Values to pass on to the templating engine',\n type: 'object',\n },\n cookiecutterCompat: {\n title: 'Cookiecutter compatibility mode',\n description:\n 'Enable features to maximise compatibility with templates built for fetch:cookiecutter',\n type: 'boolean',\n },\n replace: {\n title: 'Replace file',\n description:\n 'If set, replace file in targetPath instead of overwriting existing one.',\n type: 'boolean',\n },\n token: {\n title: 'Token',\n description:\n 'An optional token to use for authentication when reading the resources.',\n type: 'string',\n },\n },\n },\n },\n supportsDryRun: true,\n async handler(ctx) {\n ctx.logger.info('Fetching template file content from remote URL');\n\n const workDir = await ctx.createTemporaryDirectory();\n // Write to a tmp file, render the template, then copy to workspace.\n const tmpFilePath = path.join(workDir, 'tmp');\n\n const outputPath = resolveSafeChildPath(\n ctx.workspacePath,\n ctx.input.targetPath,\n );\n\n if (fs.existsSync(outputPath) && !ctx.input.replace) {\n ctx.logger.info(\n `File ${ctx.input.targetPath} already exists in workspace, not replacing.`,\n );\n return;\n }\n\n await fetchFile({\n reader,\n integrations,\n baseUrl: ctx.templateInfo?.baseUrl,\n fetchUrl: ctx.input.url,\n outputPath: tmpFilePath,\n token: ctx.input.token,\n });\n\n const { cookiecutterCompat, values } = ctx.input;\n const context = {\n [cookiecutterCompat ? 'cookiecutter' : 'values']: values,\n };\n\n ctx.logger.info(\n `Processing template file with input values`,\n ctx.input.values,\n );\n\n const renderTemplate = await SecureTemplater.loadRenderer({\n cookiecutterCompat,\n templateFilters: {\n ...defaultTemplateFilters,\n ...additionalTemplateFilters,\n },\n templateGlobals: additionalTemplateGlobals,\n nunjucksConfigs: {\n trimBlocks: ctx.input.trimBlocks,\n lstripBlocks: ctx.input.lstripBlocks,\n },\n });\n\n const contents = await fs.readFile(tmpFilePath, 'utf-8');\n const result = renderTemplate(contents, context);\n await fs.ensureDir(path.dirname(outputPath));\n await fs.outputFile(outputPath, result);\n\n ctx.logger.info(`Template file has been written to ${outputPath}`);\n },\n });\n}\n"],"names":["convertFiltersToRecord","createDefaultFilters","createTemplateAction","examples","path","resolveSafeChildPath","fs","fetchFile","SecureTemplater"],"mappings":";;;;;;;;;;;;;;;;AAsCO,SAAS,8BAA8B,OAK3C,EAAA;AACD,EAAM,MAAA;AAAA,IACJ,MAAA;AAAA,IACA,YAAA;AAAA,IACA,yBAAA;AAAA,IACA;AAAA,GACE,GAAA,OAAA;AAEJ,EAAA,MAAM,sBAAyB,GAAAA,iCAAA;AAAA,IAC7BC,yCAAA,CAAqB,EAAE,YAAA,EAAc;AAAA,GACvC;AAEA,EAAA,OAAOC,yCASJ,CAAA;AAAA,IACD,EAAI,EAAA,qBAAA;AAAA,IACJ,WAAa,EAAA,uDAAA;AAAA,cACbC,8BAAA;AAAA,IACA,MAAQ,EAAA;AAAA,MACN,KAAO,EAAA;AAAA,QACL,IAAM,EAAA,QAAA;AAAA,QACN,QAAA,EAAU,CAAC,KAAA,EAAO,YAAY,CAAA;AAAA,QAC9B,UAAY,EAAA;AAAA,UACV,GAAK,EAAA;AAAA,YACH,KAAO,EAAA,WAAA;AAAA,YACP,WACE,EAAA,qEAAA;AAAA,YACF,IAAM,EAAA;AAAA,WACR;AAAA,UACA,UAAY,EAAA;AAAA,YACV,KAAO,EAAA,aAAA;AAAA,YACP,WACE,EAAA,mEAAA;AAAA,YACF,IAAM,EAAA;AAAA,WACR;AAAA,UACA,MAAQ,EAAA;AAAA,YACN,KAAO,EAAA,iBAAA;AAAA,YACP,WAAa,EAAA,4CAAA;AAAA,YACb,IAAM,EAAA;AAAA,WACR;AAAA,UACA,kBAAoB,EAAA;AAAA,YAClB,KAAO,EAAA,iCAAA;AAAA,YACP,WACE,EAAA,uFAAA;AAAA,YACF,IAAM,EAAA;AAAA,WACR;AAAA,UACA,OAAS,EAAA;AAAA,YACP,KAAO,EAAA,cAAA;AAAA,YACP,WACE,EAAA,yEAAA;AAAA,YACF,IAAM,EAAA;AAAA,WACR;AAAA,UACA,KAAO,EAAA;AAAA,YACL,KAAO,EAAA,OAAA;AAAA,YACP,WACE,EAAA,yEAAA;AAAA,YACF,IAAM,EAAA;AAAA;AACR;AACF;AACF,KACF;AAAA,IACA,cAAgB,EAAA,IAAA;AAAA,IAChB,MAAM,QAAQ,GAAK,EAAA;AACjB,MAAI,GAAA,CAAA,MAAA,CAAO,KAAK,gDAAgD,CAAA;AAEhE,MAAM,MAAA,OAAA,GAAU,MAAM,GAAA,CAAI,wBAAyB,EAAA;AAEnD,MAAA,MAAM,WAAc,GAAAC,qBAAA,CAAK,IAAK,CAAA,OAAA,EAAS,KAAK,CAAA;AAE5C,MAAA,MAAM,UAAa,GAAAC,qCAAA;AAAA,QACjB,GAAI,CAAA,aAAA;AAAA,QACJ,IAAI,KAAM,CAAA;AAAA,OACZ;AAEA,MAAA,IAAIC,oBAAG,UAAW,CAAA,UAAU,KAAK,CAAC,GAAA,CAAI,MAAM,OAAS,EAAA;AACnD,QAAA,GAAA,CAAI,MAAO,CAAA,IAAA;AAAA,UACT,CAAA,KAAA,EAAQ,GAAI,CAAA,KAAA,CAAM,UAAU,CAAA,4CAAA;AAAA,SAC9B;AACA,QAAA;AAAA;AAGF,MAAA,MAAMC,8BAAU,CAAA;AAAA,QACd,MAAA;AAAA,QACA,YAAA;AAAA,QACA,OAAA,EAAS,IAAI,YAAc,EAAA,OAAA;AAAA,QAC3B,QAAA,EAAU,IAAI,KAAM,CAAA,GAAA;AAAA,QACpB,UAAY,EAAA,WAAA;AAAA,QACZ,KAAA,EAAO,IAAI,KAAM,CAAA;AAAA,OAClB,CAAA;AAED,MAAA,MAAM,EAAE,kBAAA,EAAoB,MAAO,EAAA,GAAI,GAAI,CAAA,KAAA;AAC3C,MAAA,MAAM,OAAU,GAAA;AAAA,QACd,CAAC,kBAAA,GAAqB,cAAiB,GAAA,QAAQ,GAAG;AAAA,OACpD;AAEA,MAAA,GAAA,CAAI,MAAO,CAAA,IAAA;AAAA,QACT,CAAA,0CAAA,CAAA;AAAA,QACA,IAAI,KAAM,CAAA;AAAA,OACZ;AAEA,MAAM,MAAA,cAAA,GAAiB,MAAMC,+BAAA,CAAgB,YAAa,CAAA;AAAA,QACxD,kBAAA;AAAA,QACA,eAAiB,EAAA;AAAA,UACf,GAAG,sBAAA;AAAA,UACH,GAAG;AAAA,SACL;AAAA,QACA,eAAiB,EAAA,yBAAA;AAAA,QACjB,eAAiB,EAAA;AAAA,UACf,UAAA,EAAY,IAAI,KAAM,CAAA,UAAA;AAAA,UACtB,YAAA,EAAc,IAAI,KAAM,CAAA;AAAA;AAC1B,OACD,CAAA;AAED,MAAA,MAAM,QAAW,GAAA,MAAMF,mBAAG,CAAA,QAAA,CAAS,aAAa,OAAO,CAAA;AACvD,MAAM,MAAA,MAAA,GAAS,cAAe,CAAA,QAAA,EAAU,OAAO,CAAA;AAC/C,MAAA,MAAMA,mBAAG,CAAA,SAAA,CAAUF,qBAAK,CAAA,OAAA,CAAQ,UAAU,CAAC,CAAA;AAC3C,MAAM,MAAAE,mBAAA,CAAG,UAAW,CAAA,UAAA,EAAY,MAAM,CAAA;AAEtC,MAAA,GAAA,CAAI,MAAO,CAAA,IAAA,CAAK,CAAqC,kCAAA,EAAA,UAAU,CAAE,CAAA,CAAA;AAAA;AACnE,GACD,CAAA;AACH;;;;"}