@backstage/plugin-scaffolder-backend 1.32.1 → 1.33.0-next.1

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.
package/CHANGELOG.md CHANGED
@@ -1,10 +1,73 @@
1
1
  # @backstage/plugin-scaffolder-backend
2
2
 
3
- ## 1.32.1
3
+ ## 1.33.0-next.1
4
4
 
5
- ### Patch Changes
5
+ ### Minor Changes
6
6
 
7
- - 40de23c: Fixing a bug where the name for `templatingExtensions` was incorrectly set to `templateExtensions`
7
+ - 587cb05: Added `workspace:template` and `workspace:template:file` actions to complement respective `fetch:*` actions
8
+
9
+ ### Patch Changes
10
+
11
+ - eb39388: Fixed bug in fs:delete that prevented wildcard patterns from matching paths starting with "."
12
+ - 72d019d: Removed various typos
13
+ - Updated dependencies
14
+ - @backstage/backend-defaults@0.10.0-next.1
15
+ - @backstage/plugin-catalog-node@1.17.0-next.1
16
+ - @backstage/plugin-auth-node@0.6.3-next.1
17
+ - @backstage/backend-plugin-api@1.3.1-next.1
18
+ - @backstage/integration@1.16.4-next.1
19
+ - @backstage/plugin-permission-common@0.9.0-next.0
20
+ - @backstage/plugin-permission-node@0.10.0-next.1
21
+ - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.9-next.1
22
+ - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.9-next.1
23
+ - @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.10-next.1
24
+ - @backstage/plugin-scaffolder-backend-module-gerrit@0.2.9-next.1
25
+ - @backstage/plugin-scaffolder-backend-module-github@0.7.1-next.1
26
+ - @backstage/plugin-scaffolder-backend-module-gitlab@0.9.1-next.1
27
+ - @backstage/plugin-scaffolder-node@0.8.2-next.1
28
+ - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.8-next.1
29
+ - @backstage/catalog-client@1.10.0-next.0
30
+ - @backstage/catalog-model@1.7.3
31
+ - @backstage/config@1.3.2
32
+ - @backstage/errors@1.2.7
33
+ - @backstage/types@1.2.1
34
+ - @backstage/plugin-bitbucket-cloud-common@0.3.0-next.1
35
+ - @backstage/plugin-events-node@0.4.11-next.1
36
+ - @backstage/plugin-scaffolder-backend-module-azure@0.2.9-next.1
37
+ - @backstage/plugin-scaffolder-backend-module-gitea@0.2.9-next.1
38
+ - @backstage/plugin-scaffolder-common@1.5.11-next.0
39
+
40
+ ## 1.32.2-next.0
41
+
42
+ ### Patch Changes
43
+
44
+ - 36ae651: Fixing a bug where the name for `templatingExtensions` was incorrectly set to `templateExtensions`
45
+ - Updated dependencies
46
+ - @backstage/integration@1.16.4-next.0
47
+ - @backstage/plugin-scaffolder-backend-module-gitlab@0.9.1-next.0
48
+ - @backstage/plugin-bitbucket-cloud-common@0.3.0-next.0
49
+ - @backstage/plugin-scaffolder-backend-module-github@0.7.1-next.0
50
+ - @backstage/catalog-client@1.10.0-next.0
51
+ - @backstage/plugin-catalog-node@1.17.0-next.0
52
+ - @backstage/backend-defaults@0.9.1-next.0
53
+ - @backstage/plugin-scaffolder-backend-module-azure@0.2.9-next.0
54
+ - @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.10-next.0
55
+ - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.9-next.0
56
+ - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.9-next.0
57
+ - @backstage/plugin-scaffolder-backend-module-gerrit@0.2.9-next.0
58
+ - @backstage/plugin-scaffolder-backend-module-gitea@0.2.9-next.0
59
+ - @backstage/plugin-scaffolder-node@0.8.2-next.0
60
+ - @backstage/backend-plugin-api@1.3.1-next.0
61
+ - @backstage/plugin-auth-node@0.6.3-next.0
62
+ - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.8-next.0
63
+ - @backstage/plugin-events-node@0.4.11-next.0
64
+ - @backstage/plugin-permission-node@0.9.2-next.0
65
+ - @backstage/catalog-model@1.7.3
66
+ - @backstage/config@1.3.2
67
+ - @backstage/errors@1.2.7
68
+ - @backstage/types@1.2.1
69
+ - @backstage/plugin-permission-common@0.8.4
70
+ - @backstage/plugin-scaffolder-common@1.5.10
8
71
 
9
72
  ## 1.32.0
10
73
 
package/dist/index.d.ts CHANGED
@@ -330,6 +330,7 @@ declare const createPublishGithubPullRequestAction: (options: CreateGithubPullRe
330
330
  sourcePath?: string;
331
331
  token?: string;
332
332
  reviewers?: string[];
333
+ assignees?: string[];
333
334
  teamReviewers?: string[];
334
335
  commitMessage?: string;
335
336
  update?: boolean;
@@ -1,32 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var path = require('path');
4
3
  var backendPluginApi = require('@backstage/backend-plugin-api');
5
- var errors = require('@backstage/errors');
6
4
  var pluginScaffolderNode = require('@backstage/plugin-scaffolder-node');
7
- var globby = require('globby');
8
- var fs = require('fs-extra');
9
- var isbinaryfile = require('isbinaryfile');
10
- var SecureTemplater = require('../../../../lib/templating/SecureTemplater.cjs.js');
11
- var createDefaultFilters = require('../../../../lib/templating/filters/createDefaultFilters.cjs.js');
12
5
  var template_examples = require('./template.examples.cjs.js');
13
- var templating = require('../../../../util/templating.cjs.js');
14
-
15
- function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
16
-
17
- var globby__default = /*#__PURE__*/_interopDefaultCompat(globby);
18
- var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
6
+ var templateActionHandler = require('./templateActionHandler.cjs.js');
19
7
 
20
8
  function createFetchTemplateAction(options) {
21
- const {
22
- reader,
23
- integrations,
24
- additionalTemplateFilters,
25
- additionalTemplateGlobals
26
- } = options;
27
- const defaultTemplateFilters = templating.convertFiltersToRecord(
28
- createDefaultFilters.createDefaultFilters({ integrations })
29
- );
30
9
  return pluginScaffolderNode.createTemplateAction({
31
10
  id: "fetch:template",
32
11
  description: "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.",
@@ -91,154 +70,25 @@ function createFetchTemplateAction(options) {
91
70
  }
92
71
  },
93
72
  supportsDryRun: true,
94
- async handler(ctx) {
95
- ctx.logger.info("Fetching template content from remote URL");
96
- const workDir = await ctx.createTemporaryDirectory();
97
- const templateDir = backendPluginApi.resolveSafeChildPath(workDir, "template");
98
- const targetPath = ctx.input.targetPath ?? "./";
99
- const outputDir = backendPluginApi.resolveSafeChildPath(ctx.workspacePath, targetPath);
100
- if (ctx.input.copyWithoutRender && ctx.input.copyWithoutTemplating) {
101
- throw new errors.InputError(
102
- "Fetch action input copyWithoutRender and copyWithoutTemplating can not be used at the same time"
103
- );
104
- }
105
- let copyOnlyPatterns;
106
- let renderFilename;
107
- if (ctx.input.copyWithoutRender) {
108
- ctx.logger.warn(
109
- "[Deprecated] copyWithoutRender is deprecated Please use copyWithoutTemplating instead."
110
- );
111
- copyOnlyPatterns = ctx.input.copyWithoutRender;
112
- renderFilename = false;
113
- } else {
114
- copyOnlyPatterns = ctx.input.copyWithoutTemplating;
115
- renderFilename = true;
116
- }
117
- if (copyOnlyPatterns && !Array.isArray(copyOnlyPatterns)) {
118
- throw new errors.InputError(
119
- "Fetch action input copyWithoutRender/copyWithoutTemplating must be an Array"
120
- );
121
- }
122
- if (ctx.input.templateFileExtension && (copyOnlyPatterns || ctx.input.cookiecutterCompat)) {
123
- throw new errors.InputError(
124
- "Fetch action input extension incompatible with copyWithoutRender/copyWithoutTemplating and cookiecutterCompat"
125
- );
126
- }
127
- let extension = false;
128
- if (ctx.input.templateFileExtension) {
129
- extension = ctx.input.templateFileExtension === true ? ".njk" : ctx.input.templateFileExtension;
130
- if (!extension.startsWith(".")) {
131
- extension = `.${extension}`;
132
- }
133
- }
134
- await pluginScaffolderNode.fetchContents({
135
- reader,
136
- integrations,
137
- baseUrl: ctx.templateInfo?.baseUrl,
138
- fetchUrl: ctx.input.url,
139
- outputPath: templateDir,
140
- token: ctx.input.token
141
- });
142
- ctx.logger.info("Listing files and directories in template");
143
- const allEntriesInTemplate = await globby__default.default(`**/*`, {
144
- cwd: templateDir,
145
- dot: true,
146
- onlyFiles: false,
147
- markDirectories: true,
148
- followSymbolicLinks: false
149
- });
150
- const nonTemplatedEntries = new Set(
151
- await globby__default.default(copyOnlyPatterns || [], {
152
- cwd: templateDir,
153
- dot: true,
154
- onlyFiles: false,
155
- markDirectories: true,
156
- followSymbolicLinks: false
157
- })
158
- );
159
- const { cookiecutterCompat, values } = ctx.input;
160
- const context = {
161
- [cookiecutterCompat ? "cookiecutter" : "values"]: values
162
- };
163
- ctx.logger.info(
164
- `Processing ${allEntriesInTemplate.length} template files/directories with input values`,
165
- ctx.input.values
166
- );
167
- const renderTemplate = await SecureTemplater.SecureTemplater.loadRenderer({
168
- cookiecutterCompat: ctx.input.cookiecutterCompat,
169
- templateFilters: {
170
- ...defaultTemplateFilters,
171
- ...additionalTemplateFilters ?? {}
172
- },
173
- templateGlobals: additionalTemplateGlobals,
174
- nunjucksConfigs: {
175
- trimBlocks: ctx.input.trimBlocks,
176
- lstripBlocks: ctx.input.lstripBlocks
177
- }
178
- });
179
- for (const location of allEntriesInTemplate) {
180
- let renderContents;
181
- let localOutputPath = location;
182
- if (extension) {
183
- renderContents = path.extname(localOutputPath) === extension;
184
- if (renderContents) {
185
- localOutputPath = localOutputPath.slice(0, -extension.length);
186
- }
187
- localOutputPath = renderTemplate(localOutputPath, context);
188
- } else {
189
- renderContents = !nonTemplatedEntries.has(location);
190
- if (renderFilename) {
191
- localOutputPath = renderTemplate(localOutputPath, context);
192
- } else {
193
- localOutputPath = renderContents ? renderTemplate(localOutputPath, context) : localOutputPath;
194
- }
195
- }
196
- if (containsSkippedContent(localOutputPath)) {
197
- continue;
198
- }
199
- const outputPath = backendPluginApi.resolveSafeChildPath(outputDir, localOutputPath);
200
- if (fs__default.default.existsSync(outputPath) && !ctx.input.replace) {
201
- continue;
202
- }
203
- if (!renderContents && !extension) {
204
- ctx.logger.info(
205
- `Copying file/directory ${location} without processing.`
206
- );
207
- }
208
- if (location.endsWith("/")) {
209
- ctx.logger.info(
210
- `Writing directory ${location} to template output path.`
211
- );
212
- await fs__default.default.ensureDir(outputPath);
213
- } else {
214
- const inputFilePath = backendPluginApi.resolveSafeChildPath(templateDir, location);
215
- const stats = await fs__default.default.promises.lstat(inputFilePath);
216
- if (stats.isSymbolicLink() || await isbinaryfile.isBinaryFile(inputFilePath)) {
217
- ctx.logger.info(
218
- `Copying file binary or symbolic link at ${location}, to template output path.`
219
- );
220
- await fs__default.default.copy(inputFilePath, outputPath);
221
- } else {
222
- const statsObj = await fs__default.default.stat(inputFilePath);
223
- ctx.logger.info(
224
- `Writing file ${location} to template output path with mode ${statsObj.mode}.`
225
- );
226
- const inputFileContents = await fs__default.default.readFile(inputFilePath, "utf-8");
227
- await fs__default.default.outputFile(
228
- outputPath,
229
- renderContents ? renderTemplate(inputFileContents, context) : inputFileContents,
230
- { mode: statsObj.mode }
231
- );
232
- }
233
- }
234
- }
235
- ctx.logger.info(`Template result written to ${outputDir}`);
236
- }
73
+ handler: (ctx) => templateActionHandler.createTemplateActionHandler({
74
+ ctx,
75
+ resolveTemplate: async () => {
76
+ ctx.logger.info("Fetching template content from remote URL");
77
+ const workDir = await ctx.createTemporaryDirectory();
78
+ const templateDir = backendPluginApi.resolveSafeChildPath(workDir, "template");
79
+ await pluginScaffolderNode.fetchContents({
80
+ baseUrl: ctx.templateInfo?.baseUrl,
81
+ fetchUrl: ctx.input.url,
82
+ outputPath: templateDir,
83
+ token: ctx.input.token,
84
+ ...options
85
+ });
86
+ return templateDir;
87
+ },
88
+ ...options
89
+ })
237
90
  });
238
91
  }
239
- function containsSkippedContent(localOutputPath) {
240
- return localOutputPath === "" || localOutputPath.startsWith("/") || localOutputPath.includes("//");
241
- }
242
92
 
243
93
  exports.createFetchTemplateAction = createFetchTemplateAction;
244
94
  //# sourceMappingURL=template.cjs.js.map
@@ -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/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":";;;;;;;;;;;;;;;;;;;AA0CO,SAAS,0BAA0B,OAKvC,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,yCAiBJ,CAAA;AAAA,IACD,EAAI,EAAA,gBAAA;AAAA,IACJ,WACE,EAAA,0MAAA;AAAA,cACFC,0BAAA;AAAA,IACA,MAAQ,EAAA;AAAA,MACN,KAAO,EAAA;AAAA,QACL,IAAM,EAAA,QAAA;AAAA,QACN,QAAA,EAAU,CAAC,KAAK,CAAA;AAAA,QAChB,UAAY,EAAA;AAAA,UACV,GAAK,EAAA;AAAA,YACH,KAAO,EAAA,WAAA;AAAA,YACP,WACE,EAAA,uEAAA;AAAA,YACF,IAAM,EAAA;AAAA,WACR;AAAA,UACA,UAAY,EAAA;AAAA,YACV,KAAO,EAAA,aAAA;AAAA,YACP,WACE,EAAA,+GAAA;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,iBAAmB,EAAA;AAAA,YACjB,KAAO,EAAA,kCAAA;AAAA,YACP,WACE,EAAA,kHAAA;AAAA,YACF,IAAM,EAAA,OAAA;AAAA,YACN,KAAO,EAAA;AAAA,cACL,IAAM,EAAA;AAAA;AACR,WACF;AAAA,UACA,qBAAuB,EAAA;AAAA,YACrB,KAAO,EAAA,yBAAA;AAAA,YACP,WACE,EAAA,6IAAA;AAAA,YACF,IAAM,EAAA,OAAA;AAAA,YACN,KAAO,EAAA;AAAA,cACL,IAAM,EAAA;AAAA;AACR,WACF;AAAA,UACA,kBAAoB,EAAA;AAAA,YAClB,KAAO,EAAA,iCAAA;AAAA,YACP,WACE,EAAA,uFAAA;AAAA,YACF,IAAM,EAAA;AAAA,WACR;AAAA,UACA,qBAAuB,EAAA;AAAA,YACrB,KAAO,EAAA,yBAAA;AAAA,YACP,WACE,EAAA,wHAAA;AAAA,YACF,IAAA,EAAM,CAAC,QAAA,EAAU,SAAS;AAAA,WAC5B;AAAA,UACA,OAAS,EAAA;AAAA,YACP,KAAO,EAAA,eAAA;AAAA,YACP,WACE,EAAA,wEAAA;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,2CAA2C,CAAA;AAE3D,MAAM,MAAA,OAAA,GAAU,MAAM,GAAA,CAAI,wBAAyB,EAAA;AACnD,MAAM,MAAA,WAAA,GAAcC,qCAAqB,CAAA,OAAA,EAAS,UAAU,CAAA;AAE5D,MAAM,MAAA,UAAA,GAAa,GAAI,CAAA,KAAA,CAAM,UAAc,IAAA,IAAA;AAC3C,MAAA,MAAM,SAAY,GAAAA,qCAAA,CAAqB,GAAI,CAAA,aAAA,EAAe,UAAU,CAAA;AACpE,MAAA,IAAI,GAAI,CAAA,KAAA,CAAM,iBAAqB,IAAA,GAAA,CAAI,MAAM,qBAAuB,EAAA;AAClE,QAAA,MAAM,IAAIC,iBAAA;AAAA,UACR;AAAA,SACF;AAAA;AAGF,MAAI,IAAA,gBAAA;AACJ,MAAI,IAAA,cAAA;AACJ,MAAI,IAAA,GAAA,CAAI,MAAM,iBAAmB,EAAA;AAC/B,QAAA,GAAA,CAAI,MAAO,CAAA,IAAA;AAAA,UACT;AAAA,SACF;AACA,QAAA,gBAAA,GAAmB,IAAI,KAAM,CAAA,iBAAA;AAC7B,QAAiB,cAAA,GAAA,KAAA;AAAA,OACZ,MAAA;AACL,QAAA,gBAAA,GAAmB,IAAI,KAAM,CAAA,qBAAA;AAC7B,QAAiB,cAAA,GAAA,IAAA;AAAA;AAGnB,MAAA,IAAI,gBAAoB,IAAA,CAAC,KAAM,CAAA,OAAA,CAAQ,gBAAgB,CAAG,EAAA;AACxD,QAAA,MAAM,IAAIA,iBAAA;AAAA,UACR;AAAA,SACF;AAAA;AAGF,MAAA,IACE,IAAI,KAAM,CAAA,qBAAA,KACT,gBAAoB,IAAA,GAAA,CAAI,MAAM,kBAC/B,CAAA,EAAA;AACA,QAAA,MAAM,IAAIA,iBAAA;AAAA,UACR;AAAA,SACF;AAAA;AAGF,MAAA,IAAI,SAA4B,GAAA,KAAA;AAChC,MAAI,IAAA,GAAA,CAAI,MAAM,qBAAuB,EAAA;AACnC,QAAA,SAAA,GACE,IAAI,KAAM,CAAA,qBAAA,KAA0B,IAChC,GAAA,MAAA,GACA,IAAI,KAAM,CAAA,qBAAA;AAChB,QAAA,IAAI,CAAC,SAAA,CAAU,UAAW,CAAA,GAAG,CAAG,EAAA;AAC9B,UAAA,SAAA,GAAY,IAAI,SAAS,CAAA,CAAA;AAAA;AAC3B;AAGF,MAAA,MAAMC,kCAAc,CAAA;AAAA,QAClB,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,MAAI,GAAA,CAAA,MAAA,CAAO,KAAK,2CAA2C,CAAA;AAC3D,MAAM,MAAA,oBAAA,GAAuB,MAAMC,uBAAA,CAAO,CAAQ,IAAA,CAAA,EAAA;AAAA,QAChD,GAAK,EAAA,WAAA;AAAA,QACL,GAAK,EAAA,IAAA;AAAA,QACL,SAAW,EAAA,KAAA;AAAA,QACX,eAAiB,EAAA,IAAA;AAAA,QACjB,mBAAqB,EAAA;AAAA,OACtB,CAAA;AAED,MAAA,MAAM,sBAAsB,IAAI,GAAA;AAAA,QAC9B,MAAMA,uBAAA,CAAO,gBAAoB,IAAA,EAAI,EAAA;AAAA,UACnC,GAAK,EAAA,WAAA;AAAA,UACL,GAAK,EAAA,IAAA;AAAA,UACL,SAAW,EAAA,KAAA;AAAA,UACX,eAAiB,EAAA,IAAA;AAAA,UACjB,mBAAqB,EAAA;AAAA,SACtB;AAAA,OACH;AAMA,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,WAAA,EAAc,qBAAqB,MAAM,CAAA,6CAAA,CAAA;AAAA,QACzC,IAAI,KAAM,CAAA;AAAA,OACZ;AAEA,MAAM,MAAA,cAAA,GAAiB,MAAMC,+BAAA,CAAgB,YAAa,CAAA;AAAA,QACxD,kBAAA,EAAoB,IAAI,KAAM,CAAA,kBAAA;AAAA,QAC9B,eAAiB,EAAA;AAAA,UACf,GAAG,sBAAA;AAAA,UACH,GAAI,6BAA6B;AAAC,SACpC;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,KAAA,MAAW,YAAY,oBAAsB,EAAA;AAC3C,QAAI,IAAA,cAAA;AAEJ,QAAA,IAAI,eAAkB,GAAA,QAAA;AACtB,QAAA,IAAI,SAAW,EAAA;AACb,UAAiB,cAAA,GAAAC,YAAA,CAAQ,eAAe,CAAM,KAAA,SAAA;AAC9C,UAAA,IAAI,cAAgB,EAAA;AAClB,YAAA,eAAA,GAAkB,eAAgB,CAAA,KAAA,CAAM,CAAG,EAAA,CAAC,UAAU,MAAM,CAAA;AAAA;AAI9D,UAAkB,eAAA,GAAA,cAAA,CAAe,iBAAiB,OAAO,CAAA;AAAA,SACpD,MAAA;AACL,UAAiB,cAAA,GAAA,CAAC,mBAAoB,CAAA,GAAA,CAAI,QAAQ,CAAA;AAMlD,UAAA,IAAI,cAAgB,EAAA;AAClB,YAAkB,eAAA,GAAA,cAAA,CAAe,iBAAiB,OAAO,CAAA;AAAA,WACpD,MAAA;AACL,YAAA,eAAA,GAAkB,cACd,GAAA,cAAA,CAAe,eAAiB,EAAA,OAAO,CACvC,GAAA,eAAA;AAAA;AACN;AAGF,QAAI,IAAA,sBAAA,CAAuB,eAAe,CAAG,EAAA;AAC3C,UAAA;AAAA;AAGF,QAAM,MAAA,UAAA,GAAaL,qCAAqB,CAAA,SAAA,EAAW,eAAe,CAAA;AAClE,QAAA,IAAIM,oBAAG,UAAW,CAAA,UAAU,KAAK,CAAC,GAAA,CAAI,MAAM,OAAS,EAAA;AACnD,UAAA;AAAA;AAGF,QAAI,IAAA,CAAC,cAAkB,IAAA,CAAC,SAAW,EAAA;AACjC,UAAA,GAAA,CAAI,MAAO,CAAA,IAAA;AAAA,YACT,0BAA0B,QAAQ,CAAA,oBAAA;AAAA,WACpC;AAAA;AAGF,QAAI,IAAA,QAAA,CAAS,QAAS,CAAA,GAAG,CAAG,EAAA;AAC1B,UAAA,GAAA,CAAI,MAAO,CAAA,IAAA;AAAA,YACT,qBAAqB,QAAQ,CAAA,yBAAA;AAAA,WAC/B;AACA,UAAM,MAAAA,mBAAA,CAAG,UAAU,UAAU,CAAA;AAAA,SACxB,MAAA;AACL,UAAM,MAAA,aAAA,GAAgBN,qCAAqB,CAAA,WAAA,EAAa,QAAQ,CAAA;AAChE,UAAA,MAAM,KAAQ,GAAA,MAAMM,mBAAG,CAAA,QAAA,CAAS,MAAM,aAAa,CAAA;AAEnD,UAAA,IAAI,MAAM,cAAe,EAAA,IAAM,MAAMC,yBAAA,CAAa,aAAa,CAAI,EAAA;AACjE,YAAA,GAAA,CAAI,MAAO,CAAA,IAAA;AAAA,cACT,2CAA2C,QAAQ,CAAA,0BAAA;AAAA,aACrD;AACA,YAAM,MAAAD,mBAAA,CAAG,IAAK,CAAA,aAAA,EAAe,UAAU,CAAA;AAAA,WAClC,MAAA;AACL,YAAA,MAAM,QAAW,GAAA,MAAMA,mBAAG,CAAA,IAAA,CAAK,aAAa,CAAA;AAC5C,YAAA,GAAA,CAAI,MAAO,CAAA,IAAA;AAAA,cACT,CAAgB,aAAA,EAAA,QAAQ,CAAsC,mCAAA,EAAA,QAAA,CAAS,IAAI,CAAA,CAAA;AAAA,aAC7E;AACA,YAAA,MAAM,iBAAoB,GAAA,MAAMA,mBAAG,CAAA,QAAA,CAAS,eAAe,OAAO,CAAA;AAClE,YAAA,MAAMA,mBAAG,CAAA,UAAA;AAAA,cACP,UAAA;AAAA,cACA,cACI,GAAA,cAAA,CAAe,iBAAmB,EAAA,OAAO,CACzC,GAAA,iBAAA;AAAA,cACJ,EAAE,IAAM,EAAA,QAAA,CAAS,IAAK;AAAA,aACxB;AAAA;AACF;AACF;AAGF,MAAA,GAAA,CAAI,MAAO,CAAA,IAAA,CAAK,CAA8B,2BAAA,EAAA,SAAS,CAAE,CAAA,CAAA;AAAA;AAC3D,GACD,CAAA;AACH;AAEA,SAAS,uBAAuB,eAAkC,EAAA;AAKhE,EACE,OAAA,eAAA,KAAoB,MACpB,eAAgB,CAAA,UAAA,CAAW,GAAG,CAC9B,IAAA,eAAA,CAAgB,SAAS,IAAI,CAAA;AAEjC;;;;"}
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 {\n resolveSafeChildPath,\n UrlReaderService,\n} from '@backstage/backend-plugin-api';\nimport { ScmIntegrations } from '@backstage/integration';\nimport {\n createTemplateAction,\n fetchContents,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport { examples } from './template.examples';\nimport { createTemplateActionHandler } from './templateActionHandler';\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 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 handler: ctx =>\n createTemplateActionHandler({\n ctx,\n resolveTemplate: async () => {\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 await fetchContents({\n baseUrl: ctx.templateInfo?.baseUrl,\n fetchUrl: ctx.input.url,\n outputPath: templateDir,\n token: ctx.input.token,\n ...options,\n });\n\n return templateDir;\n },\n ...options,\n }),\n });\n}\n"],"names":["createTemplateAction","examples","createTemplateActionHandler","resolveSafeChildPath","fetchContents"],"mappings":";;;;;;;AAqCO,SAAS,0BAA0B,OAKvC,EAAA;AACD,EAAA,OAAOA,yCAiBJ,CAAA;AAAA,IACD,EAAI,EAAA,gBAAA;AAAA,IACJ,WACE,EAAA,0MAAA;AAAA,cACFC,0BAAA;AAAA,IACA,MAAQ,EAAA;AAAA,MACN,KAAO,EAAA;AAAA,QACL,IAAM,EAAA,QAAA;AAAA,QACN,QAAA,EAAU,CAAC,KAAK,CAAA;AAAA,QAChB,UAAY,EAAA;AAAA,UACV,GAAK,EAAA;AAAA,YACH,KAAO,EAAA,WAAA;AAAA,YACP,WACE,EAAA,uEAAA;AAAA,YACF,IAAM,EAAA;AAAA,WACR;AAAA,UACA,UAAY,EAAA;AAAA,YACV,KAAO,EAAA,aAAA;AAAA,YACP,WACE,EAAA,+GAAA;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,iBAAmB,EAAA;AAAA,YACjB,KAAO,EAAA,kCAAA;AAAA,YACP,WACE,EAAA,kHAAA;AAAA,YACF,IAAM,EAAA,OAAA;AAAA,YACN,KAAO,EAAA;AAAA,cACL,IAAM,EAAA;AAAA;AACR,WACF;AAAA,UACA,qBAAuB,EAAA;AAAA,YACrB,KAAO,EAAA,yBAAA;AAAA,YACP,WACE,EAAA,6IAAA;AAAA,YACF,IAAM,EAAA,OAAA;AAAA,YACN,KAAO,EAAA;AAAA,cACL,IAAM,EAAA;AAAA;AACR,WACF;AAAA,UACA,kBAAoB,EAAA;AAAA,YAClB,KAAO,EAAA,iCAAA;AAAA,YACP,WACE,EAAA,uFAAA;AAAA,YACF,IAAM,EAAA;AAAA,WACR;AAAA,UACA,qBAAuB,EAAA;AAAA,YACrB,KAAO,EAAA,yBAAA;AAAA,YACP,WACE,EAAA,wHAAA;AAAA,YACF,IAAA,EAAM,CAAC,QAAA,EAAU,SAAS;AAAA,WAC5B;AAAA,UACA,OAAS,EAAA;AAAA,YACP,KAAO,EAAA,eAAA;AAAA,YACP,WACE,EAAA,wEAAA;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,OAAA,EAAS,SACPC,iDAA4B,CAAA;AAAA,MAC1B,GAAA;AAAA,MACA,iBAAiB,YAAY;AAC3B,QAAI,GAAA,CAAA,MAAA,CAAO,KAAK,2CAA2C,CAAA;AAE3D,QAAM,MAAA,OAAA,GAAU,MAAM,GAAA,CAAI,wBAAyB,EAAA;AACnD,QAAM,MAAA,WAAA,GAAcC,qCAAqB,CAAA,OAAA,EAAS,UAAU,CAAA;AAE5D,QAAA,MAAMC,kCAAc,CAAA;AAAA,UAClB,OAAA,EAAS,IAAI,YAAc,EAAA,OAAA;AAAA,UAC3B,QAAA,EAAU,IAAI,KAAM,CAAA,GAAA;AAAA,UACpB,UAAY,EAAA,WAAA;AAAA,UACZ,KAAA,EAAO,IAAI,KAAM,CAAA,KAAA;AAAA,UACjB,GAAG;AAAA,SACJ,CAAA;AAED,QAAO,OAAA,WAAA;AAAA,OACT;AAAA,MACA,GAAG;AAAA,KACJ;AAAA,GACJ,CAAA;AACH;;;;"}
@@ -0,0 +1,172 @@
1
+ 'use strict';
2
+
3
+ var backendPluginApi = require('@backstage/backend-plugin-api');
4
+ var errors = require('@backstage/errors');
5
+ var fs = require('fs-extra');
6
+ var globby = require('globby');
7
+ var isbinaryfile = require('isbinaryfile');
8
+ var createDefaultFilters = require('../../../../lib/templating/filters/createDefaultFilters.cjs.js');
9
+ var templating = require('../../../../util/templating.cjs.js');
10
+ var SecureTemplater = require('../../../../lib/templating/SecureTemplater.cjs.js');
11
+ var path = require('path');
12
+
13
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
14
+
15
+ var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
16
+ var globby__default = /*#__PURE__*/_interopDefaultCompat(globby);
17
+
18
+ async function createTemplateActionHandler(options) {
19
+ const {
20
+ resolveTemplate,
21
+ integrations,
22
+ additionalTemplateFilters,
23
+ additionalTemplateGlobals: templateGlobals,
24
+ ctx
25
+ } = options;
26
+ const templateFilters = {
27
+ ...templating.convertFiltersToRecord(createDefaultFilters.createDefaultFilters({ integrations })),
28
+ ...additionalTemplateFilters
29
+ };
30
+ const { outputDir, copyOnlyPatterns, renderFilename, extension } = resolveTemplateActionSettings(ctx);
31
+ const templateDir = await resolveTemplate();
32
+ if (backendPluginApi.isChildPath(templateDir, outputDir)) {
33
+ throw new errors.InputError("targetPath must not be within template path");
34
+ }
35
+ ctx.logger.info("Listing files and directories in template");
36
+ const allEntriesInTemplate = await globby__default.default(`**/*`, {
37
+ cwd: templateDir,
38
+ dot: true,
39
+ onlyFiles: false,
40
+ markDirectories: true,
41
+ followSymbolicLinks: false
42
+ });
43
+ const nonTemplatedEntries = new Set(
44
+ await globby__default.default(copyOnlyPatterns || [], {
45
+ cwd: templateDir,
46
+ dot: true,
47
+ onlyFiles: false,
48
+ markDirectories: true,
49
+ followSymbolicLinks: false
50
+ })
51
+ );
52
+ const { cookiecutterCompat, values } = ctx.input;
53
+ const context = {
54
+ [cookiecutterCompat ? "cookiecutter" : "values"]: values
55
+ };
56
+ ctx.logger.info(
57
+ `Processing ${allEntriesInTemplate.length} template files/directories with input values`,
58
+ ctx.input.values
59
+ );
60
+ const renderTemplate = await SecureTemplater.SecureTemplater.loadRenderer({
61
+ cookiecutterCompat: ctx.input.cookiecutterCompat,
62
+ templateFilters,
63
+ templateGlobals,
64
+ nunjucksConfigs: {
65
+ trimBlocks: ctx.input.trimBlocks,
66
+ lstripBlocks: ctx.input.lstripBlocks
67
+ }
68
+ });
69
+ for (const location of allEntriesInTemplate) {
70
+ let renderContents;
71
+ let localOutputPath = location;
72
+ if (extension) {
73
+ renderContents = path.extname(localOutputPath) === extension;
74
+ if (renderContents) {
75
+ localOutputPath = localOutputPath.slice(0, -extension.length);
76
+ }
77
+ localOutputPath = renderTemplate(localOutputPath, context);
78
+ } else {
79
+ renderContents = !nonTemplatedEntries.has(location);
80
+ if (renderFilename) {
81
+ localOutputPath = renderTemplate(localOutputPath, context);
82
+ } else {
83
+ localOutputPath = renderContents ? renderTemplate(localOutputPath, context) : localOutputPath;
84
+ }
85
+ }
86
+ if (containsSkippedContent(localOutputPath)) {
87
+ continue;
88
+ }
89
+ const outputPath = backendPluginApi.resolveSafeChildPath(outputDir, localOutputPath);
90
+ if (fs__default.default.existsSync(outputPath) && !ctx.input.replace) {
91
+ continue;
92
+ }
93
+ if (!renderContents && !extension) {
94
+ ctx.logger.info(`Copying file/directory ${location} without processing.`);
95
+ }
96
+ if (location.endsWith("/")) {
97
+ ctx.logger.info(`Writing directory ${location} to template output path.`);
98
+ await fs__default.default.ensureDir(outputPath);
99
+ } else {
100
+ const inputFilePath = backendPluginApi.resolveSafeChildPath(templateDir, location);
101
+ const stats = await fs__default.default.promises.lstat(inputFilePath);
102
+ if (stats.isSymbolicLink() || await isbinaryfile.isBinaryFile(inputFilePath)) {
103
+ ctx.logger.info(
104
+ `Copying file binary or symbolic link at ${location}, to template output path.`
105
+ );
106
+ await fs__default.default.copy(inputFilePath, outputPath);
107
+ } else {
108
+ const statsObj = await fs__default.default.stat(inputFilePath);
109
+ ctx.logger.info(
110
+ `Writing file ${location} to template output path with mode ${statsObj.mode}.`
111
+ );
112
+ const inputFileContents = await fs__default.default.readFile(inputFilePath, "utf-8");
113
+ await fs__default.default.outputFile(
114
+ outputPath,
115
+ renderContents ? renderTemplate(inputFileContents, context) : inputFileContents,
116
+ { mode: statsObj.mode }
117
+ );
118
+ }
119
+ }
120
+ }
121
+ ctx.logger.info(`Template result written to ${outputDir}`);
122
+ }
123
+ function resolveTemplateActionSettings(ctx) {
124
+ const targetPath = ctx.input.targetPath ?? "./";
125
+ const outputDir = backendPluginApi.resolveSafeChildPath(ctx.workspacePath, targetPath);
126
+ if (ctx.input.copyWithoutRender && ctx.input.copyWithoutTemplating) {
127
+ throw new errors.InputError(
128
+ "Fetch action input copyWithoutRender and copyWithoutTemplating can not be used at the same time"
129
+ );
130
+ }
131
+ let copyOnlyPatterns;
132
+ let renderFilename;
133
+ if (ctx.input.copyWithoutRender) {
134
+ ctx.logger.warn(
135
+ "[Deprecated] copyWithoutRender is deprecated Please use copyWithoutTemplating instead."
136
+ );
137
+ copyOnlyPatterns = ctx.input.copyWithoutRender;
138
+ renderFilename = false;
139
+ } else {
140
+ copyOnlyPatterns = ctx.input.copyWithoutTemplating;
141
+ renderFilename = true;
142
+ }
143
+ if (copyOnlyPatterns && !Array.isArray(copyOnlyPatterns)) {
144
+ throw new errors.InputError(
145
+ "Fetch action input copyWithoutRender/copyWithoutTemplating must be an Array"
146
+ );
147
+ }
148
+ if (ctx.input.templateFileExtension && (copyOnlyPatterns || ctx.input.cookiecutterCompat)) {
149
+ throw new errors.InputError(
150
+ "Fetch action input extension incompatible with copyWithoutRender/copyWithoutTemplating and cookiecutterCompat"
151
+ );
152
+ }
153
+ let extension = false;
154
+ if (ctx.input.templateFileExtension) {
155
+ extension = ctx.input.templateFileExtension === true ? ".njk" : ctx.input.templateFileExtension;
156
+ if (!extension.startsWith(".")) {
157
+ extension = `.${extension}`;
158
+ }
159
+ }
160
+ return {
161
+ outputDir,
162
+ copyOnlyPatterns,
163
+ renderFilename,
164
+ extension
165
+ };
166
+ }
167
+ function containsSkippedContent(localOutputPath) {
168
+ return localOutputPath === "" || localOutputPath.startsWith("/") || localOutputPath.includes("//");
169
+ }
170
+
171
+ exports.createTemplateActionHandler = createTemplateActionHandler;
172
+ //# sourceMappingURL=templateActionHandler.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templateActionHandler.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/fetch/templateActionHandler.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 {\n isChildPath,\n resolveSafeChildPath,\n} from '@backstage/backend-plugin-api';\nimport { InputError } from '@backstage/errors';\nimport { ScmIntegrations } from '@backstage/integration';\nimport {\n ActionContext,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport fs from 'fs-extra';\nimport globby from 'globby';\nimport { isBinaryFile } from 'isbinaryfile';\nimport { createDefaultFilters } from '../../../../lib/templating/filters/createDefaultFilters';\nimport { convertFiltersToRecord } from '../../../../util/templating';\nimport { SecureTemplater } from '../../../../lib/templating/SecureTemplater';\nimport { extname } from 'path';\n\nexport type TemplateActionInput = {\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};\n\nexport async function createTemplateActionHandler<\n I extends TemplateActionInput,\n>(options: {\n ctx: ActionContext<I, any, any>;\n resolveTemplate: () => Promise<string>;\n integrations: ScmIntegrations;\n additionalTemplateFilters?: Record<string, TemplateFilter>;\n additionalTemplateGlobals?: Record<string, TemplateGlobal>;\n}) {\n const {\n resolveTemplate,\n integrations,\n additionalTemplateFilters,\n additionalTemplateGlobals: templateGlobals,\n ctx,\n } = options;\n\n const templateFilters = {\n ...convertFiltersToRecord(createDefaultFilters({ integrations })),\n ...additionalTemplateFilters,\n };\n\n const { outputDir, copyOnlyPatterns, renderFilename, extension } =\n resolveTemplateActionSettings(ctx);\n\n const templateDir = await resolveTemplate();\n\n if (isChildPath(templateDir, outputDir)) {\n throw new InputError('targetPath must not be within template path');\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 templateGlobals,\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(`Copying file/directory ${location} without processing.`);\n }\n\n if (location.endsWith('/')) {\n ctx.logger.info(`Writing directory ${location} to template output path.`);\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 ctx.logger.info(`Template result written to ${outputDir}`);\n}\n\nfunction resolveTemplateActionSettings<I extends TemplateActionInput>(\n ctx: ActionContext<I, any, any>,\n): {\n outputDir: string;\n copyOnlyPatterns?: string[];\n renderFilename: boolean;\n extension: string | false;\n} {\n const targetPath = ctx.input.targetPath ?? './';\n const outputDir = resolveSafeChildPath(ctx.workspacePath, targetPath);\n\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 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 if (copyOnlyPatterns && !Array.isArray(copyOnlyPatterns)) {\n throw new InputError(\n 'Fetch action input copyWithoutRender/copyWithoutTemplating must be an Array',\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 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 return {\n outputDir,\n copyOnlyPatterns,\n renderFilename,\n extension,\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","isChildPath","InputError","globby","SecureTemplater","extname","resolveSafeChildPath","fs","isBinaryFile"],"mappings":"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"}
@@ -1,29 +1,15 @@
1
1
  'use strict';
2
2
 
3
- var backendPluginApi = require('@backstage/backend-plugin-api');
4
- var templateFile_examples = require('./templateFile.examples.cjs.js');
5
3
  var pluginScaffolderNode = require('@backstage/plugin-scaffolder-node');
6
- var SecureTemplater = require('../../../../lib/templating/SecureTemplater.cjs.js');
7
- var createDefaultFilters = require('../../../../lib/templating/filters/createDefaultFilters.cjs.js');
8
4
  var path = require('path');
9
- var fs = require('fs-extra');
10
- var templating = require('../../../../util/templating.cjs.js');
5
+ var templateFile_examples = require('./templateFile.examples.cjs.js');
6
+ var templateFileActionHandler = require('./templateFileActionHandler.cjs.js');
11
7
 
12
8
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
13
9
 
14
10
  var path__default = /*#__PURE__*/_interopDefaultCompat(path);
15
- var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
16
11
 
17
12
  function createFetchTemplateFileAction(options) {
18
- const {
19
- reader,
20
- integrations,
21
- additionalTemplateFilters,
22
- additionalTemplateGlobals
23
- } = options;
24
- const defaultTemplateFilters = templating.convertFiltersToRecord(
25
- createDefaultFilters.createDefaultFilters({ integrations })
26
- );
27
13
  return pluginScaffolderNode.createTemplateAction({
28
14
  id: "fetch:template:file",
29
15
  description: "Downloads single file and places it in the workspace.",
@@ -67,54 +53,23 @@ function createFetchTemplateFileAction(options) {
67
53
  }
68
54
  },
69
55
  supportsDryRun: true,
70
- async handler(ctx) {
71
- ctx.logger.info("Fetching template file content from remote URL");
72
- const workDir = await ctx.createTemporaryDirectory();
73
- const tmpFilePath = path__default.default.join(workDir, "tmp");
74
- const outputPath = backendPluginApi.resolveSafeChildPath(
75
- ctx.workspacePath,
76
- ctx.input.targetPath
77
- );
78
- if (fs__default.default.existsSync(outputPath) && !ctx.input.replace) {
79
- ctx.logger.info(
80
- `File ${ctx.input.targetPath} already exists in workspace, not replacing.`
81
- );
82
- return;
83
- }
84
- await pluginScaffolderNode.fetchFile({
85
- reader,
86
- integrations,
87
- baseUrl: ctx.templateInfo?.baseUrl,
88
- fetchUrl: ctx.input.url,
89
- outputPath: tmpFilePath,
90
- token: ctx.input.token
91
- });
92
- const { cookiecutterCompat, values } = ctx.input;
93
- const context = {
94
- [cookiecutterCompat ? "cookiecutter" : "values"]: values
95
- };
96
- ctx.logger.info(
97
- `Processing template file with input values`,
98
- ctx.input.values
99
- );
100
- const renderTemplate = await SecureTemplater.SecureTemplater.loadRenderer({
101
- cookiecutterCompat,
102
- templateFilters: {
103
- ...defaultTemplateFilters,
104
- ...additionalTemplateFilters
105
- },
106
- templateGlobals: additionalTemplateGlobals,
107
- nunjucksConfigs: {
108
- trimBlocks: ctx.input.trimBlocks,
109
- lstripBlocks: ctx.input.lstripBlocks
110
- }
111
- });
112
- const contents = await fs__default.default.readFile(tmpFilePath, "utf-8");
113
- const result = renderTemplate(contents, context);
114
- await fs__default.default.ensureDir(path__default.default.dirname(outputPath));
115
- await fs__default.default.outputFile(outputPath, result);
116
- ctx.logger.info(`Template file has been written to ${outputPath}`);
117
- }
56
+ handler: (ctx) => templateFileActionHandler.createTemplateFileActionHandler({
57
+ ctx,
58
+ resolveTemplateFile: async () => {
59
+ ctx.logger.info("Fetching template file content from remote URL");
60
+ const workDir = await ctx.createTemporaryDirectory();
61
+ const tmpFilePath = path__default.default.join(workDir, "tmp");
62
+ await pluginScaffolderNode.fetchFile({
63
+ baseUrl: ctx.templateInfo?.baseUrl,
64
+ fetchUrl: ctx.input.url,
65
+ outputPath: tmpFilePath,
66
+ token: ctx.input.token,
67
+ ...options
68
+ });
69
+ return tmpFilePath;
70
+ },
71
+ ...options
72
+ })
118
73
  });
119
74
  }
120
75
 
@@ -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/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":"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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 { ScmIntegrations } from '@backstage/integration';\nimport {\n createTemplateAction,\n fetchFile,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport path from 'path';\nimport { examples } from './templateFile.examples';\nimport { createTemplateFileActionHandler } from './templateFileActionHandler';\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 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 handler: ctx =>\n createTemplateFileActionHandler({\n ctx,\n resolveTemplateFile: async () => {\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 await fetchFile({\n baseUrl: ctx.templateInfo?.baseUrl,\n fetchUrl: ctx.input.url,\n outputPath: tmpFilePath,\n token: ctx.input.token,\n ...options,\n });\n return tmpFilePath;\n },\n ...options,\n }),\n });\n}\n"],"names":["createTemplateAction","examples","createTemplateFileActionHandler","path","fetchFile"],"mappings":";;;;;;;;;;;AAkCO,SAAS,8BAA8B,OAK3C,EAAA;AACD,EAAA,OAAOA,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,OAAA,EAAS,SACPC,yDAAgC,CAAA;AAAA,MAC9B,GAAA;AAAA,MACA,qBAAqB,YAAY;AAC/B,QAAI,GAAA,CAAA,MAAA,CAAO,KAAK,gDAAgD,CAAA;AAEhE,QAAM,MAAA,OAAA,GAAU,MAAM,GAAA,CAAI,wBAAyB,EAAA;AAEnD,QAAA,MAAM,WAAc,GAAAC,qBAAA,CAAK,IAAK,CAAA,OAAA,EAAS,KAAK,CAAA;AAE5C,QAAA,MAAMC,8BAAU,CAAA;AAAA,UACd,OAAA,EAAS,IAAI,YAAc,EAAA,OAAA;AAAA,UAC3B,QAAA,EAAU,IAAI,KAAM,CAAA,GAAA;AAAA,UACpB,UAAY,EAAA,WAAA;AAAA,UACZ,KAAA,EAAO,IAAI,KAAM,CAAA,KAAA;AAAA,UACjB,GAAG;AAAA,SACJ,CAAA;AACD,QAAO,OAAA,WAAA;AAAA,OACT;AAAA,MACA,GAAG;AAAA,KACJ;AAAA,GACJ,CAAA;AACH;;;;"}
@@ -0,0 +1,63 @@
1
+ 'use strict';
2
+
3
+ var fs = require('fs-extra');
4
+ var createDefaultFilters = require('../../../../lib/templating/filters/createDefaultFilters.cjs.js');
5
+ var templating = require('../../../../util/templating.cjs.js');
6
+ var backendPluginApi = require('@backstage/backend-plugin-api');
7
+ var path = require('path');
8
+ var SecureTemplater = require('../../../../lib/templating/SecureTemplater.cjs.js');
9
+
10
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
11
+
12
+ var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
13
+ var path__default = /*#__PURE__*/_interopDefaultCompat(path);
14
+
15
+ async function createTemplateFileActionHandler(options) {
16
+ const {
17
+ resolveTemplateFile,
18
+ integrations,
19
+ additionalTemplateFilters,
20
+ additionalTemplateGlobals: templateGlobals,
21
+ ctx
22
+ } = options;
23
+ const templateFilters = {
24
+ ...templating.convertFiltersToRecord(createDefaultFilters.createDefaultFilters({ integrations })),
25
+ ...additionalTemplateFilters
26
+ };
27
+ const outputPath = backendPluginApi.resolveSafeChildPath(
28
+ ctx.workspacePath,
29
+ ctx.input.targetPath
30
+ );
31
+ if (fs__default.default.existsSync(outputPath) && !ctx.input.replace) {
32
+ ctx.logger.info(
33
+ `File ${ctx.input.targetPath} already exists in workspace, not replacing.`
34
+ );
35
+ return;
36
+ }
37
+ const filePath = await resolveTemplateFile();
38
+ const { cookiecutterCompat, values } = ctx.input;
39
+ const context = {
40
+ [cookiecutterCompat ? "cookiecutter" : "values"]: values
41
+ };
42
+ ctx.logger.info(
43
+ `Processing template file with input values`,
44
+ ctx.input.values
45
+ );
46
+ const renderTemplate = await SecureTemplater.SecureTemplater.loadRenderer({
47
+ cookiecutterCompat,
48
+ templateFilters,
49
+ templateGlobals,
50
+ nunjucksConfigs: {
51
+ trimBlocks: ctx.input.trimBlocks,
52
+ lstripBlocks: ctx.input.lstripBlocks
53
+ }
54
+ });
55
+ const contents = await fs__default.default.readFile(filePath, "utf-8");
56
+ const result = renderTemplate(contents, context);
57
+ await fs__default.default.ensureDir(path__default.default.dirname(outputPath));
58
+ await fs__default.default.outputFile(outputPath, result);
59
+ ctx.logger.info(`Template file has been written to ${outputPath}`);
60
+ }
61
+
62
+ exports.createTemplateFileActionHandler = createTemplateFileActionHandler;
63
+ //# sourceMappingURL=templateFileActionHandler.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templateFileActionHandler.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/fetch/templateFileActionHandler.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 {\n ActionContext,\n TemplateFilter,\n TemplateGlobal,\n} from '@backstage/plugin-scaffolder-node';\nimport fs from 'fs-extra';\nimport { createDefaultFilters } from '../../../../lib/templating/filters/createDefaultFilters';\nimport { convertFiltersToRecord } from '../../../../util/templating';\nimport { resolveSafeChildPath } from '@backstage/backend-plugin-api';\nimport path from 'path';\nimport { SecureTemplater } from '../../../../lib/templating/SecureTemplater';\n\nexport type TemplateFileActionInput = {\n targetPath: string;\n values: any;\n cookiecutterCompat?: boolean;\n replace?: boolean;\n trimBlocks?: boolean;\n lstripBlocks?: boolean;\n};\n\nexport async function createTemplateFileActionHandler<\n I extends TemplateFileActionInput = TemplateFileActionInput,\n>(options: {\n ctx: ActionContext<I, any, any>;\n resolveTemplateFile: () => Promise<string>;\n integrations: ScmIntegrations;\n additionalTemplateFilters?: Record<string, TemplateFilter>;\n additionalTemplateGlobals?: Record<string, TemplateGlobal>;\n}) {\n const {\n resolveTemplateFile,\n integrations,\n additionalTemplateFilters,\n additionalTemplateGlobals: templateGlobals,\n ctx,\n } = options;\n\n const templateFilters = {\n ...convertFiltersToRecord(createDefaultFilters({ integrations })),\n ...additionalTemplateFilters,\n };\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 const filePath = await resolveTemplateFile();\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 templateGlobals,\n nunjucksConfigs: {\n trimBlocks: ctx.input.trimBlocks,\n lstripBlocks: ctx.input.lstripBlocks,\n },\n });\n\n const contents = await fs.readFile(filePath, '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"],"names":["convertFiltersToRecord","createDefaultFilters","resolveSafeChildPath","fs","SecureTemplater","path"],"mappings":";;;;;;;;;;;;;;AAqCA,eAAsB,gCAEpB,OAMC,EAAA;AACD,EAAM,MAAA;AAAA,IACJ,mBAAA;AAAA,IACA,YAAA;AAAA,IACA,yBAAA;AAAA,IACA,yBAA2B,EAAA,eAAA;AAAA,IAC3B;AAAA,GACE,GAAA,OAAA;AAEJ,EAAA,MAAM,eAAkB,GAAA;AAAA,IACtB,GAAGA,iCAAuB,CAAAC,yCAAA,CAAqB,EAAE,YAAA,EAAc,CAAC,CAAA;AAAA,IAChE,GAAG;AAAA,GACL;AAEA,EAAA,MAAM,UAAa,GAAAC,qCAAA;AAAA,IACjB,GAAI,CAAA,aAAA;AAAA,IACJ,IAAI,KAAM,CAAA;AAAA,GACZ;AAEA,EAAA,IAAIC,oBAAG,UAAW,CAAA,UAAU,KAAK,CAAC,GAAA,CAAI,MAAM,OAAS,EAAA;AACnD,IAAA,GAAA,CAAI,MAAO,CAAA,IAAA;AAAA,MACT,CAAA,KAAA,EAAQ,GAAI,CAAA,KAAA,CAAM,UAAU,CAAA,4CAAA;AAAA,KAC9B;AACA,IAAA;AAAA;AAEF,EAAM,MAAA,QAAA,GAAW,MAAM,mBAAoB,EAAA;AAE3C,EAAA,MAAM,EAAE,kBAAA,EAAoB,MAAO,EAAA,GAAI,GAAI,CAAA,KAAA;AAC3C,EAAA,MAAM,OAAU,GAAA;AAAA,IACd,CAAC,kBAAA,GAAqB,cAAiB,GAAA,QAAQ,GAAG;AAAA,GACpD;AAEA,EAAA,GAAA,CAAI,MAAO,CAAA,IAAA;AAAA,IACT,CAAA,0CAAA,CAAA;AAAA,IACA,IAAI,KAAM,CAAA;AAAA,GACZ;AAEA,EAAM,MAAA,cAAA,GAAiB,MAAMC,+BAAA,CAAgB,YAAa,CAAA;AAAA,IACxD,kBAAA;AAAA,IACA,eAAA;AAAA,IACA,eAAA;AAAA,IACA,eAAiB,EAAA;AAAA,MACf,UAAA,EAAY,IAAI,KAAM,CAAA,UAAA;AAAA,MACtB,YAAA,EAAc,IAAI,KAAM,CAAA;AAAA;AAC1B,GACD,CAAA;AAED,EAAA,MAAM,QAAW,GAAA,MAAMD,mBAAG,CAAA,QAAA,CAAS,UAAU,OAAO,CAAA;AACpD,EAAM,MAAA,MAAA,GAAS,cAAe,CAAA,QAAA,EAAU,OAAO,CAAA;AAC/C,EAAA,MAAMA,mBAAG,CAAA,SAAA,CAAUE,qBAAK,CAAA,OAAA,CAAQ,UAAU,CAAC,CAAA;AAC3C,EAAM,MAAAF,mBAAA,CAAG,UAAW,CAAA,UAAA,EAAY,MAAM,CAAA;AAEtC,EAAA,GAAA,CAAI,MAAO,CAAA,IAAA,CAAK,CAAqC,kCAAA,EAAA,UAAU,CAAE,CAAA,CAAA;AACnE;;;;"}
@@ -45,7 +45,8 @@ const createFilesystemDeleteAction = () => {
45
45
  ).replace(/\\/g, "/");
46
46
  const resolvedPaths = await globby__default.default(safeFilepath, {
47
47
  cwd: ctx.workspacePath,
48
- absolute: true
48
+ absolute: true,
49
+ dot: true
49
50
  });
50
51
  for (const filepath of resolvedPaths) {
51
52
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"delete.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/filesystem/delete.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 { createTemplateAction } from '@backstage/plugin-scaffolder-node';\nimport { InputError } from '@backstage/errors';\nimport { resolveSafeChildPath } from '@backstage/backend-plugin-api';\nimport fs from 'fs-extra';\nimport globby from 'globby';\nimport { examples } from './delete.examples';\n\n/**\n * Creates new action that enables deletion of files and directories in the workspace.\n * @public\n */\nexport const createFilesystemDeleteAction = () => {\n return createTemplateAction<{ files: string[] }>({\n id: 'fs:delete',\n description: 'Deletes files and directories from the workspace',\n examples,\n schema: {\n input: {\n required: ['files'],\n type: 'object',\n properties: {\n files: {\n title: 'Files',\n description: 'A list of files and directories that will be deleted',\n type: 'array',\n items: {\n type: 'string',\n },\n },\n },\n },\n },\n supportsDryRun: true,\n async handler(ctx) {\n if (!Array.isArray(ctx.input?.files)) {\n throw new InputError('files must be an Array');\n }\n\n for (const file of ctx.input.files) {\n // globby cannot handle backslash file separators\n const safeFilepath = resolveSafeChildPath(\n ctx.workspacePath,\n file,\n ).replace(/\\\\/g, '/');\n const resolvedPaths = await globby(safeFilepath, {\n cwd: ctx.workspacePath,\n absolute: true,\n });\n\n for (const filepath of resolvedPaths) {\n try {\n await fs.remove(filepath);\n ctx.logger.info(`File ${filepath} deleted successfully`);\n } catch (err) {\n ctx.logger.error(`Failed to delete file ${filepath}:`, err);\n throw err;\n }\n }\n }\n },\n });\n};\n"],"names":["createTemplateAction","examples","InputError","resolveSafeChildPath","globby","fs"],"mappings":";;;;;;;;;;;;;;AA2BO,MAAM,+BAA+B,MAAM;AAChD,EAAA,OAAOA,yCAA0C,CAAA;AAAA,IAC/C,EAAI,EAAA,WAAA;AAAA,IACJ,WAAa,EAAA,kDAAA;AAAA,cACbC,wBAAA;AAAA,IACA,MAAQ,EAAA;AAAA,MACN,KAAO,EAAA;AAAA,QACL,QAAA,EAAU,CAAC,OAAO,CAAA;AAAA,QAClB,IAAM,EAAA,QAAA;AAAA,QACN,UAAY,EAAA;AAAA,UACV,KAAO,EAAA;AAAA,YACL,KAAO,EAAA,OAAA;AAAA,YACP,WAAa,EAAA,sDAAA;AAAA,YACb,IAAM,EAAA,OAAA;AAAA,YACN,KAAO,EAAA;AAAA,cACL,IAAM,EAAA;AAAA;AACR;AACF;AACF;AACF,KACF;AAAA,IACA,cAAgB,EAAA,IAAA;AAAA,IAChB,MAAM,QAAQ,GAAK,EAAA;AACjB,MAAA,IAAI,CAAC,KAAM,CAAA,OAAA,CAAQ,GAAI,CAAA,KAAA,EAAO,KAAK,CAAG,EAAA;AACpC,QAAM,MAAA,IAAIC,kBAAW,wBAAwB,CAAA;AAAA;AAG/C,MAAW,KAAA,MAAA,IAAA,IAAQ,GAAI,CAAA,KAAA,CAAM,KAAO,EAAA;AAElC,QAAA,MAAM,YAAe,GAAAC,qCAAA;AAAA,UACnB,GAAI,CAAA,aAAA;AAAA,UACJ;AAAA,SACF,CAAE,OAAQ,CAAA,KAAA,EAAO,GAAG,CAAA;AACpB,QAAM,MAAA,aAAA,GAAgB,MAAMC,uBAAA,CAAO,YAAc,EAAA;AAAA,UAC/C,KAAK,GAAI,CAAA,aAAA;AAAA,UACT,QAAU,EAAA;AAAA,SACX,CAAA;AAED,QAAA,KAAA,MAAW,YAAY,aAAe,EAAA;AACpC,UAAI,IAAA;AACF,YAAM,MAAAC,mBAAA,CAAG,OAAO,QAAQ,CAAA;AACxB,YAAA,GAAA,CAAI,MAAO,CAAA,IAAA,CAAK,CAAQ,KAAA,EAAA,QAAQ,CAAuB,qBAAA,CAAA,CAAA;AAAA,mBAChD,GAAK,EAAA;AACZ,YAAA,GAAA,CAAI,MAAO,CAAA,KAAA,CAAM,CAAyB,sBAAA,EAAA,QAAQ,KAAK,GAAG,CAAA;AAC1D,YAAM,MAAA,GAAA;AAAA;AACR;AACF;AACF;AACF,GACD,CAAA;AACH;;;;"}
1
+ {"version":3,"file":"delete.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/filesystem/delete.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 { createTemplateAction } from '@backstage/plugin-scaffolder-node';\nimport { InputError } from '@backstage/errors';\nimport { resolveSafeChildPath } from '@backstage/backend-plugin-api';\nimport fs from 'fs-extra';\nimport globby from 'globby';\nimport { examples } from './delete.examples';\n\n/**\n * Creates new action that enables deletion of files and directories in the workspace.\n * @public\n */\nexport const createFilesystemDeleteAction = () => {\n return createTemplateAction<{ files: string[] }>({\n id: 'fs:delete',\n description: 'Deletes files and directories from the workspace',\n examples,\n schema: {\n input: {\n required: ['files'],\n type: 'object',\n properties: {\n files: {\n title: 'Files',\n description: 'A list of files and directories that will be deleted',\n type: 'array',\n items: {\n type: 'string',\n },\n },\n },\n },\n },\n supportsDryRun: true,\n async handler(ctx) {\n if (!Array.isArray(ctx.input?.files)) {\n throw new InputError('files must be an Array');\n }\n\n for (const file of ctx.input.files) {\n // globby cannot handle backslash file separators\n const safeFilepath = resolveSafeChildPath(\n ctx.workspacePath,\n file,\n ).replace(/\\\\/g, '/');\n const resolvedPaths = await globby(safeFilepath, {\n cwd: ctx.workspacePath,\n absolute: true,\n dot: true,\n });\n\n for (const filepath of resolvedPaths) {\n try {\n await fs.remove(filepath);\n ctx.logger.info(`File ${filepath} deleted successfully`);\n } catch (err) {\n ctx.logger.error(`Failed to delete file ${filepath}:`, err);\n throw err;\n }\n }\n }\n },\n });\n};\n"],"names":["createTemplateAction","examples","InputError","resolveSafeChildPath","globby","fs"],"mappings":";;;;;;;;;;;;;;AA2BO,MAAM,+BAA+B,MAAM;AAChD,EAAA,OAAOA,yCAA0C,CAAA;AAAA,IAC/C,EAAI,EAAA,WAAA;AAAA,IACJ,WAAa,EAAA,kDAAA;AAAA,cACbC,wBAAA;AAAA,IACA,MAAQ,EAAA;AAAA,MACN,KAAO,EAAA;AAAA,QACL,QAAA,EAAU,CAAC,OAAO,CAAA;AAAA,QAClB,IAAM,EAAA,QAAA;AAAA,QACN,UAAY,EAAA;AAAA,UACV,KAAO,EAAA;AAAA,YACL,KAAO,EAAA,OAAA;AAAA,YACP,WAAa,EAAA,sDAAA;AAAA,YACb,IAAM,EAAA,OAAA;AAAA,YACN,KAAO,EAAA;AAAA,cACL,IAAM,EAAA;AAAA;AACR;AACF;AACF;AACF,KACF;AAAA,IACA,cAAgB,EAAA,IAAA;AAAA,IAChB,MAAM,QAAQ,GAAK,EAAA;AACjB,MAAA,IAAI,CAAC,KAAM,CAAA,OAAA,CAAQ,GAAI,CAAA,KAAA,EAAO,KAAK,CAAG,EAAA;AACpC,QAAM,MAAA,IAAIC,kBAAW,wBAAwB,CAAA;AAAA;AAG/C,MAAW,KAAA,MAAA,IAAA,IAAQ,GAAI,CAAA,KAAA,CAAM,KAAO,EAAA;AAElC,QAAA,MAAM,YAAe,GAAAC,qCAAA;AAAA,UACnB,GAAI,CAAA,aAAA;AAAA,UACJ;AAAA,SACF,CAAE,OAAQ,CAAA,KAAA,EAAO,GAAG,CAAA;AACpB,QAAM,MAAA,aAAA,GAAgB,MAAMC,uBAAA,CAAO,YAAc,EAAA;AAAA,UAC/C,KAAK,GAAI,CAAA,aAAA;AAAA,UACT,QAAU,EAAA,IAAA;AAAA,UACV,GAAK,EAAA;AAAA,SACN,CAAA;AAED,QAAA,KAAA,MAAW,YAAY,aAAe,EAAA;AACpC,UAAI,IAAA;AACF,YAAM,MAAAC,mBAAA,CAAG,OAAO,QAAQ,CAAA;AACxB,YAAA,GAAA,CAAI,MAAO,CAAA,IAAA,CAAK,CAAQ,KAAA,EAAA,QAAQ,CAAuB,qBAAA,CAAA,CAAA;AAAA,mBAChD,GAAK,EAAA;AACZ,YAAA,GAAA,CAAI,MAAO,CAAA,KAAA,CAAM,CAAyB,sBAAA,EAAA,QAAQ,KAAK,GAAG,CAAA;AAC1D,YAAM,MAAA,GAAA;AAAA;AACR;AACF;AACF;AACF,GACD,CAAA;AACH;;;;"}
@@ -52,6 +52,21 @@ const examples = [
52
52
  }
53
53
  ]
54
54
  })
55
+ },
56
+ {
57
+ description: "Delete all files in workspace",
58
+ example: yaml__namespace.stringify({
59
+ steps: [
60
+ {
61
+ action: "fs:delete",
62
+ id: "deleteFiles",
63
+ name: "Delete files",
64
+ input: {
65
+ files: ["**"]
66
+ }
67
+ }
68
+ ]
69
+ })
55
70
  }
56
71
  ];
57
72
 
@@ -1 +1 @@
1
- {"version":3,"file":"delete.examples.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/filesystem/delete.examples.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 { TemplateExample } from '@backstage/plugin-scaffolder-node';\nimport * as yaml from 'yaml';\n\nexport const examples: TemplateExample[] = [\n {\n description: 'Delete specified files',\n example: yaml.stringify({\n steps: [\n {\n action: 'fs:delete',\n id: 'deleteFiles',\n name: 'Delete files',\n input: {\n files: ['file1.txt', 'file2.txt'],\n },\n },\n ],\n }),\n },\n {\n description: 'Delete files with wildcard',\n example: yaml.stringify({\n steps: [\n {\n action: 'fs:delete',\n id: 'deleteFiles',\n name: 'Delete files',\n input: {\n files: ['*.txt'],\n },\n },\n ],\n }),\n },\n];\n"],"names":["yaml"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAmBO,MAAM,QAA8B,GAAA;AAAA,EACzC;AAAA,IACE,WAAa,EAAA,wBAAA;AAAA,IACb,OAAA,EAASA,gBAAK,SAAU,CAAA;AAAA,MACtB,KAAO,EAAA;AAAA,QACL;AAAA,UACE,MAAQ,EAAA,WAAA;AAAA,UACR,EAAI,EAAA,aAAA;AAAA,UACJ,IAAM,EAAA,cAAA;AAAA,UACN,KAAO,EAAA;AAAA,YACL,KAAA,EAAO,CAAC,WAAA,EAAa,WAAW;AAAA;AAClC;AACF;AACF,KACD;AAAA,GACH;AAAA,EACA;AAAA,IACE,WAAa,EAAA,4BAAA;AAAA,IACb,OAAA,EAASA,gBAAK,SAAU,CAAA;AAAA,MACtB,KAAO,EAAA;AAAA,QACL;AAAA,UACE,MAAQ,EAAA,WAAA;AAAA,UACR,EAAI,EAAA,aAAA;AAAA,UACJ,IAAM,EAAA,cAAA;AAAA,UACN,KAAO,EAAA;AAAA,YACL,KAAA,EAAO,CAAC,OAAO;AAAA;AACjB;AACF;AACF,KACD;AAAA;AAEL;;;;"}
1
+ {"version":3,"file":"delete.examples.cjs.js","sources":["../../../../../src/scaffolder/actions/builtin/filesystem/delete.examples.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 { TemplateExample } from '@backstage/plugin-scaffolder-node';\nimport * as yaml from 'yaml';\n\nexport const examples: TemplateExample[] = [\n {\n description: 'Delete specified files',\n example: yaml.stringify({\n steps: [\n {\n action: 'fs:delete',\n id: 'deleteFiles',\n name: 'Delete files',\n input: {\n files: ['file1.txt', 'file2.txt'],\n },\n },\n ],\n }),\n },\n {\n description: 'Delete files with wildcard',\n example: yaml.stringify({\n steps: [\n {\n action: 'fs:delete',\n id: 'deleteFiles',\n name: 'Delete files',\n input: {\n files: ['*.txt'],\n },\n },\n ],\n }),\n },\n {\n description: 'Delete all files in workspace',\n example: yaml.stringify({\n steps: [\n {\n action: 'fs:delete',\n id: 'deleteFiles',\n name: 'Delete files',\n input: {\n files: ['**'],\n },\n },\n ],\n }),\n },\n];\n"],"names":["yaml"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAmBO,MAAM,QAA8B,GAAA;AAAA,EACzC;AAAA,IACE,WAAa,EAAA,wBAAA;AAAA,IACb,OAAA,EAASA,gBAAK,SAAU,CAAA;AAAA,MACtB,KAAO,EAAA;AAAA,QACL;AAAA,UACE,MAAQ,EAAA,WAAA;AAAA,UACR,EAAI,EAAA,aAAA;AAAA,UACJ,IAAM,EAAA,cAAA;AAAA,UACN,KAAO,EAAA;AAAA,YACL,KAAA,EAAO,CAAC,WAAA,EAAa,WAAW;AAAA;AAClC;AACF;AACF,KACD;AAAA,GACH;AAAA,EACA;AAAA,IACE,WAAa,EAAA,4BAAA;AAAA,IACb,OAAA,EAASA,gBAAK,SAAU,CAAA;AAAA,MACtB,KAAO,EAAA;AAAA,QACL;AAAA,UACE,MAAQ,EAAA,WAAA;AAAA,UACR,EAAI,EAAA,aAAA;AAAA,UACJ,IAAM,EAAA,cAAA;AAAA,UACN,KAAO,EAAA;AAAA,YACL,KAAA,EAAO,CAAC,OAAO;AAAA;AACjB;AACF;AACF,KACD;AAAA,GACH;AAAA,EACA;AAAA,IACE,WAAa,EAAA,+BAAA;AAAA,IACb,OAAA,EAASA,gBAAK,SAAU,CAAA;AAAA,MACtB,KAAO,EAAA;AAAA,QACL;AAAA,UACE,MAAQ,EAAA,WAAA;AAAA,UACR,EAAI,EAAA,aAAA;AAAA,UACJ,IAAM,EAAA,cAAA;AAAA,UACN,KAAO,EAAA;AAAA,YACL,KAAA,EAAO,CAAC,IAAI;AAAA;AACd;AACF;AACF,KACD;AAAA;AAEL;;;;"}
@@ -18,14 +18,14 @@ require('luxon');
18
18
  require('../actions/builtin/debug/wait.examples.cjs.js');
19
19
  require('../actions/builtin/fetch/plain.examples.cjs.js');
20
20
  require('../actions/builtin/fetch/plainFile.examples.cjs.js');
21
+ require('../actions/builtin/fetch/template.examples.cjs.js');
21
22
  require('globby');
22
23
  require('isbinaryfile');
23
- require('isolated-vm');
24
24
  require('@backstage/plugin-scaffolder-node/alpha');
25
25
  require('../../lib/templating/filters/parseEntityRef/filter.cjs.js');
26
26
  require('../../lib/templating/filters/pick/filter.cjs.js');
27
- require('../actions/builtin/fetch/template.examples.cjs.js');
28
27
  require('zod-to-json-schema');
28
+ require('isolated-vm');
29
29
  require('../actions/builtin/fetch/templateFile.examples.cjs.js');
30
30
  require('../actions/builtin/filesystem/delete.examples.cjs.js');
31
31
  require('../actions/builtin/filesystem/rename.examples.cjs.js');
@@ -29,12 +29,12 @@ require('fs');
29
29
  require('../scaffolder/actions/builtin/debug/wait.examples.cjs.js');
30
30
  require('../scaffolder/actions/builtin/fetch/plain.examples.cjs.js');
31
31
  require('../scaffolder/actions/builtin/fetch/plainFile.examples.cjs.js');
32
+ require('../scaffolder/actions/builtin/fetch/template.examples.cjs.js');
32
33
  require('globby');
33
34
  require('isbinaryfile');
34
- require('isolated-vm');
35
35
  var createDefaultFilters = require('../lib/templating/filters/createDefaultFilters.cjs.js');
36
- require('../scaffolder/actions/builtin/fetch/template.examples.cjs.js');
37
36
  var templating = require('../util/templating.cjs.js');
37
+ require('isolated-vm');
38
38
  require('../scaffolder/actions/builtin/fetch/templateFile.examples.cjs.js');
39
39
  require('../scaffolder/actions/builtin/filesystem/delete.examples.cjs.js');
40
40
  require('../scaffolder/actions/builtin/filesystem/rename.examples.cjs.js');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-scaffolder-backend",
3
- "version": "1.32.1",
3
+ "version": "1.33.0-next.1",
4
4
  "description": "The Backstage backend plugin that helps you create new things",
5
5
  "backstage": {
6
6
  "role": "backend-plugin",
@@ -76,31 +76,31 @@
76
76
  },
77
77
  "dependencies": {
78
78
  "@backstage/backend-common": "^0.25.0",
79
- "@backstage/backend-defaults": "^0.9.0",
80
- "@backstage/backend-plugin-api": "^1.3.0",
81
- "@backstage/catalog-client": "^1.9.1",
82
- "@backstage/catalog-model": "^1.7.3",
83
- "@backstage/config": "^1.3.2",
84
- "@backstage/errors": "^1.2.7",
85
- "@backstage/integration": "^1.16.3",
86
- "@backstage/plugin-auth-node": "^0.6.2",
87
- "@backstage/plugin-bitbucket-cloud-common": "^0.2.29",
88
- "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "^0.2.7",
89
- "@backstage/plugin-catalog-node": "^1.16.3",
90
- "@backstage/plugin-events-node": "^0.4.10",
91
- "@backstage/plugin-permission-common": "^0.8.4",
92
- "@backstage/plugin-permission-node": "^0.9.1",
93
- "@backstage/plugin-scaffolder-backend-module-azure": "^0.2.8",
94
- "@backstage/plugin-scaffolder-backend-module-bitbucket": "^0.3.9",
95
- "@backstage/plugin-scaffolder-backend-module-bitbucket-cloud": "^0.2.8",
96
- "@backstage/plugin-scaffolder-backend-module-bitbucket-server": "^0.2.8",
97
- "@backstage/plugin-scaffolder-backend-module-gerrit": "^0.2.8",
98
- "@backstage/plugin-scaffolder-backend-module-gitea": "^0.2.8",
99
- "@backstage/plugin-scaffolder-backend-module-github": "^0.7.0",
100
- "@backstage/plugin-scaffolder-backend-module-gitlab": "^0.9.0",
101
- "@backstage/plugin-scaffolder-common": "^1.5.10",
102
- "@backstage/plugin-scaffolder-node": "^0.8.1",
103
- "@backstage/types": "^1.2.1",
79
+ "@backstage/backend-defaults": "0.10.0-next.1",
80
+ "@backstage/backend-plugin-api": "1.3.1-next.1",
81
+ "@backstage/catalog-client": "1.10.0-next.0",
82
+ "@backstage/catalog-model": "1.7.3",
83
+ "@backstage/config": "1.3.2",
84
+ "@backstage/errors": "1.2.7",
85
+ "@backstage/integration": "1.16.4-next.1",
86
+ "@backstage/plugin-auth-node": "0.6.3-next.1",
87
+ "@backstage/plugin-bitbucket-cloud-common": "0.3.0-next.1",
88
+ "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "0.2.8-next.1",
89
+ "@backstage/plugin-catalog-node": "1.17.0-next.1",
90
+ "@backstage/plugin-events-node": "0.4.11-next.1",
91
+ "@backstage/plugin-permission-common": "0.9.0-next.0",
92
+ "@backstage/plugin-permission-node": "0.10.0-next.1",
93
+ "@backstage/plugin-scaffolder-backend-module-azure": "0.2.9-next.1",
94
+ "@backstage/plugin-scaffolder-backend-module-bitbucket": "0.3.10-next.1",
95
+ "@backstage/plugin-scaffolder-backend-module-bitbucket-cloud": "0.2.9-next.1",
96
+ "@backstage/plugin-scaffolder-backend-module-bitbucket-server": "0.2.9-next.1",
97
+ "@backstage/plugin-scaffolder-backend-module-gerrit": "0.2.9-next.1",
98
+ "@backstage/plugin-scaffolder-backend-module-gitea": "0.2.9-next.1",
99
+ "@backstage/plugin-scaffolder-backend-module-github": "0.7.1-next.1",
100
+ "@backstage/plugin-scaffolder-backend-module-gitlab": "0.9.1-next.1",
101
+ "@backstage/plugin-scaffolder-common": "1.5.11-next.0",
102
+ "@backstage/plugin-scaffolder-node": "0.8.2-next.1",
103
+ "@backstage/types": "1.2.1",
104
104
  "@opentelemetry/api": "^1.9.0",
105
105
  "@types/express": "^4.17.6",
106
106
  "@types/luxon": "^3.0.0",
@@ -131,11 +131,11 @@
131
131
  "zod-to-json-schema": "^3.20.4"
132
132
  },
133
133
  "devDependencies": {
134
- "@backstage/backend-app-api": "^1.2.2",
135
- "@backstage/backend-defaults": "^0.9.0",
136
- "@backstage/backend-test-utils": "^1.4.0",
137
- "@backstage/cli": "^0.32.0",
138
- "@backstage/plugin-scaffolder-node-test-utils": "^0.2.1",
134
+ "@backstage/backend-app-api": "1.2.3-next.1",
135
+ "@backstage/backend-defaults": "0.10.0-next.1",
136
+ "@backstage/backend-test-utils": "1.5.0-next.1",
137
+ "@backstage/cli": "0.32.1-next.1",
138
+ "@backstage/plugin-scaffolder-node-test-utils": "0.2.2-next.1",
139
139
  "@types/fs-extra": "^11.0.0",
140
140
  "@types/nunjucks": "^3.1.4",
141
141
  "@types/supertest": "^2.0.8",