@backstage/plugin-scaffolder-node 0.4.4-next.2 → 0.4.5-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # @backstage/plugin-scaffolder-node
2
2
 
3
+ ## 0.4.5-next.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ - @backstage/backend-common@0.22.1-next.0
9
+ - @backstage/backend-plugin-api@0.6.19-next.0
10
+ - @backstage/catalog-model@1.5.0
11
+ - @backstage/errors@1.2.4
12
+ - @backstage/integration@1.11.0
13
+ - @backstage/types@1.1.1
14
+ - @backstage/plugin-scaffolder-common@1.5.2
15
+
16
+ ## 0.4.4
17
+
18
+ ### Patch Changes
19
+
20
+ - d229dc4: Move path utilities from `backend-common` to the `backend-plugin-api` package.
21
+ - e4b50ab: Scaffolder workspace serialization
22
+ - f633efa: To remove the dependency on the soon-to-be-deprecated `backend-common` package, this package now maintains its own isomorphic Git class implementation.
23
+ - Updated dependencies
24
+ - @backstage/plugin-scaffolder-common@1.5.2
25
+ - @backstage/catalog-model@1.5.0
26
+ - @backstage/backend-common@0.22.0
27
+ - @backstage/backend-plugin-api@0.6.18
28
+ - @backstage/integration@1.11.0
29
+
3
30
  ## 0.4.4-next.2
4
31
 
5
32
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-scaffolder-node",
3
- "version": "0.4.4-next.2",
3
+ "version": "0.4.5-next.0",
4
4
  "main": "../dist/alpha.cjs.js",
5
5
  "types": "../dist/alpha.d.ts"
6
6
  }
package/dist/index.cjs.js CHANGED
@@ -3,10 +3,12 @@
3
3
  var zodToJsonSchema = require('zod-to-json-schema');
4
4
  var child_process = require('child_process');
5
5
  var stream = require('stream');
6
- var backendCommon = require('@backstage/backend-common');
6
+ var backendPluginApi = require('@backstage/backend-plugin-api');
7
7
  var errors = require('@backstage/errors');
8
8
  var fs = require('fs-extra');
9
9
  var path = require('path');
10
+ var git = require('isomorphic-git');
11
+ var http = require('isomorphic-git/http/node');
10
12
  var fs$1 = require('fs');
11
13
  var globby = require('globby');
12
14
  var limiterFactory = require('p-limit');
@@ -16,13 +18,14 @@ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'defau
16
18
  var zodToJsonSchema__default = /*#__PURE__*/_interopDefaultCompat(zodToJsonSchema);
17
19
  var fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
18
20
  var path__default = /*#__PURE__*/_interopDefaultCompat(path);
21
+ var git__default = /*#__PURE__*/_interopDefaultCompat(git);
22
+ var http__default = /*#__PURE__*/_interopDefaultCompat(http);
19
23
  var globby__default = /*#__PURE__*/_interopDefaultCompat(globby);
20
24
  var limiterFactory__default = /*#__PURE__*/_interopDefaultCompat(limiterFactory);
21
25
 
22
26
  const createTemplateAction = (action) => {
23
- var _a, _b, _c, _d;
24
- const inputSchema = ((_a = action.schema) == null ? void 0 : _a.input) && "safeParseAsync" in action.schema.input ? zodToJsonSchema__default.default(action.schema.input) : (_b = action.schema) == null ? void 0 : _b.input;
25
- const outputSchema = ((_c = action.schema) == null ? void 0 : _c.output) && "safeParseAsync" in action.schema.output ? zodToJsonSchema__default.default(action.schema.output) : (_d = action.schema) == null ? void 0 : _d.output;
27
+ const inputSchema = action.schema?.input && "safeParseAsync" in action.schema.input ? zodToJsonSchema__default.default(action.schema.input) : action.schema?.input;
28
+ const outputSchema = action.schema?.output && "safeParseAsync" in action.schema.output ? zodToJsonSchema__default.default(action.schema.output) : action.schema?.output;
26
29
  return {
27
30
  ...action,
28
31
  schema: {
@@ -72,9 +75,9 @@ async function fetchContents(options) {
72
75
  token
73
76
  } = options;
74
77
  const fetchUrlIsAbsolute = isFetchUrlAbsolute(fetchUrl);
75
- if (!fetchUrlIsAbsolute && (baseUrl == null ? void 0 : baseUrl.startsWith("file://"))) {
78
+ if (!fetchUrlIsAbsolute && baseUrl?.startsWith("file://")) {
76
79
  const basePath = baseUrl.slice("file://".length);
77
- const srcDir = backendCommon.resolveSafeChildPath(path__default.default.dirname(basePath), fetchUrl);
80
+ const srcDir = backendPluginApi.resolveSafeChildPath(path__default.default.dirname(basePath), fetchUrl);
78
81
  await fs__default.default.copy(srcDir, outputPath);
79
82
  } else {
80
83
  const readUrl = getReadUrl(fetchUrl, baseUrl, integrations);
@@ -93,9 +96,9 @@ async function fetchFile(options) {
93
96
  token
94
97
  } = options;
95
98
  const fetchUrlIsAbsolute = isFetchUrlAbsolute(fetchUrl);
96
- if (!fetchUrlIsAbsolute && (baseUrl == null ? void 0 : baseUrl.startsWith("file://"))) {
99
+ if (!fetchUrlIsAbsolute && baseUrl?.startsWith("file://")) {
97
100
  const basePath = baseUrl.slice("file://".length);
98
- const src = backendCommon.resolveSafeChildPath(path__default.default.dirname(basePath), fetchUrl);
101
+ const src = backendPluginApi.resolveSafeChildPath(path__default.default.dirname(basePath), fetchUrl);
99
102
  await fs__default.default.copyFile(src, outputPath);
100
103
  } else {
101
104
  const readUrl = getReadUrl(fetchUrl, baseUrl, integrations);
@@ -132,8 +135,212 @@ function getReadUrl(fetchUrl, baseUrl, integrations) {
132
135
  );
133
136
  }
134
137
 
138
+ function isAuthCallbackOptions(options) {
139
+ return "onAuth" in options;
140
+ }
141
+ class Git {
142
+ constructor(config) {
143
+ this.config = config;
144
+ this.onAuth = config.onAuth;
145
+ this.headers = {
146
+ "user-agent": "git/@isomorphic-git",
147
+ ...config.token ? { Authorization: `Bearer ${config.token}` } : {}
148
+ };
149
+ }
150
+ headers;
151
+ async add(options) {
152
+ const { dir, filepath } = options;
153
+ this.config.logger?.info(`Adding file {dir=${dir},filepath=${filepath}}`);
154
+ return git__default.default.add({ fs: fs__default.default, dir, filepath });
155
+ }
156
+ async addRemote(options) {
157
+ const { dir, url, remote, force } = options;
158
+ this.config.logger?.info(
159
+ `Creating new remote {dir=${dir},remote=${remote},url=${url}}`
160
+ );
161
+ return git__default.default.addRemote({ fs: fs__default.default, dir, remote, url, force });
162
+ }
163
+ async deleteRemote(options) {
164
+ const { dir, remote } = options;
165
+ this.config.logger?.info(`Deleting remote {dir=${dir},remote=${remote}}`);
166
+ return git__default.default.deleteRemote({ fs: fs__default.default, dir, remote });
167
+ }
168
+ async checkout(options) {
169
+ const { dir, ref } = options;
170
+ this.config.logger?.info(`Checking out branch {dir=${dir},ref=${ref}}`);
171
+ return git__default.default.checkout({ fs: fs__default.default, dir, ref });
172
+ }
173
+ async branch(options) {
174
+ const { dir, ref } = options;
175
+ this.config.logger?.info(`Creating branch {dir=${dir},ref=${ref}`);
176
+ return git__default.default.branch({ fs: fs__default.default, dir, ref });
177
+ }
178
+ async commit(options) {
179
+ const { dir, message, author, committer } = options;
180
+ this.config.logger?.info(
181
+ `Committing file to repo {dir=${dir},message=${message}}`
182
+ );
183
+ return git__default.default.commit({ fs: fs__default.default, dir, message, author, committer });
184
+ }
185
+ /** https://isomorphic-git.org/docs/en/clone */
186
+ async clone(options) {
187
+ const { url, dir, ref, depth, noCheckout } = options;
188
+ this.config.logger?.info(`Cloning repo {dir=${dir},url=${url}}`);
189
+ try {
190
+ return await git__default.default.clone({
191
+ fs: fs__default.default,
192
+ http: http__default.default,
193
+ url,
194
+ dir,
195
+ ref,
196
+ singleBranch: true,
197
+ depth: depth ?? 1,
198
+ noCheckout,
199
+ onProgress: this.onProgressHandler(),
200
+ headers: this.headers,
201
+ onAuth: this.onAuth
202
+ });
203
+ } catch (ex) {
204
+ this.config.logger?.error(`Failed to clone repo {dir=${dir},url=${url}}`);
205
+ if (ex.data) {
206
+ throw new Error(`${ex.message} {data=${JSON.stringify(ex.data)}}`);
207
+ }
208
+ throw ex;
209
+ }
210
+ }
211
+ /** https://isomorphic-git.org/docs/en/currentBranch */
212
+ async currentBranch(options) {
213
+ const { dir, fullName = false } = options;
214
+ return git__default.default.currentBranch({ fs: fs__default.default, dir, fullname: fullName });
215
+ }
216
+ /** https://isomorphic-git.org/docs/en/fetch */
217
+ async fetch(options) {
218
+ const { dir, remote = "origin", tags = false } = options;
219
+ this.config.logger?.info(
220
+ `Fetching remote=${remote} for repository {dir=${dir}}`
221
+ );
222
+ try {
223
+ await git__default.default.fetch({
224
+ fs: fs__default.default,
225
+ http: http__default.default,
226
+ dir,
227
+ remote,
228
+ tags,
229
+ onProgress: this.onProgressHandler(),
230
+ headers: this.headers,
231
+ onAuth: this.onAuth
232
+ });
233
+ } catch (ex) {
234
+ this.config.logger?.error(
235
+ `Failed to fetch repo {dir=${dir},remote=${remote}}`
236
+ );
237
+ if (ex.data) {
238
+ throw new Error(`${ex.message} {data=${JSON.stringify(ex.data)}}`);
239
+ }
240
+ throw ex;
241
+ }
242
+ }
243
+ async init(options) {
244
+ const { dir, defaultBranch = "master" } = options;
245
+ this.config.logger?.info(`Init git repository {dir=${dir}}`);
246
+ return git__default.default.init({
247
+ fs: fs__default.default,
248
+ dir,
249
+ defaultBranch
250
+ });
251
+ }
252
+ /** https://isomorphic-git.org/docs/en/merge */
253
+ async merge(options) {
254
+ const { dir, theirs, ours, author, committer } = options;
255
+ this.config.logger?.info(
256
+ `Merging branch '${theirs}' into '${ours}' for repository {dir=${dir}}`
257
+ );
258
+ return git__default.default.merge({
259
+ fs: fs__default.default,
260
+ dir,
261
+ ours,
262
+ theirs,
263
+ author,
264
+ committer
265
+ });
266
+ }
267
+ async push(options) {
268
+ const { dir, remote, remoteRef, force } = options;
269
+ this.config.logger?.info(
270
+ `Pushing directory to remote {dir=${dir},remote=${remote}}`
271
+ );
272
+ try {
273
+ return await git__default.default.push({
274
+ fs: fs__default.default,
275
+ dir,
276
+ http: http__default.default,
277
+ onProgress: this.onProgressHandler(),
278
+ remoteRef,
279
+ force,
280
+ headers: this.headers,
281
+ remote,
282
+ onAuth: this.onAuth
283
+ });
284
+ } catch (ex) {
285
+ this.config.logger?.error(
286
+ `Failed to push to repo {dir=${dir}, remote=${remote}}`
287
+ );
288
+ if (ex.data) {
289
+ throw new Error(`${ex.message} {data=${JSON.stringify(ex.data)}}`);
290
+ }
291
+ throw ex;
292
+ }
293
+ }
294
+ /** https://isomorphic-git.org/docs/en/readCommit */
295
+ async readCommit(options) {
296
+ const { dir, sha } = options;
297
+ return git__default.default.readCommit({ fs: fs__default.default, dir, oid: sha });
298
+ }
299
+ /** https://isomorphic-git.org/docs/en/remove */
300
+ async remove(options) {
301
+ const { dir, filepath } = options;
302
+ this.config.logger?.info(
303
+ `Removing file from git index {dir=${dir},filepath=${filepath}}`
304
+ );
305
+ return git__default.default.remove({ fs: fs__default.default, dir, filepath });
306
+ }
307
+ /** https://isomorphic-git.org/docs/en/resolveRef */
308
+ async resolveRef(options) {
309
+ const { dir, ref } = options;
310
+ return git__default.default.resolveRef({ fs: fs__default.default, dir, ref });
311
+ }
312
+ /** https://isomorphic-git.org/docs/en/log */
313
+ async log(options) {
314
+ const { dir, ref } = options;
315
+ return git__default.default.log({
316
+ fs: fs__default.default,
317
+ dir,
318
+ ref: ref ?? "HEAD"
319
+ });
320
+ }
321
+ onAuth;
322
+ onProgressHandler = () => {
323
+ let currentPhase = "";
324
+ return (event) => {
325
+ if (currentPhase !== event.phase) {
326
+ currentPhase = event.phase;
327
+ this.config.logger?.info(event.phase);
328
+ }
329
+ const total = event.total ? `${Math.round(event.loaded / event.total * 100)}%` : event.loaded;
330
+ this.config.logger?.debug(`status={${event.phase},total={${total}}}`);
331
+ };
332
+ };
333
+ static fromAuth = (options) => {
334
+ if (isAuthCallbackOptions(options)) {
335
+ const { onAuth, logger: logger2 } = options;
336
+ return new Git({ onAuth, logger: logger2 });
337
+ }
338
+ const { username, password, token, logger } = options;
339
+ return new Git({ onAuth: () => ({ username, password }), token, logger });
340
+ };
341
+ }
342
+
135
343
  async function initRepoAndPush(input) {
136
- var _a, _b;
137
344
  const {
138
345
  dir,
139
346
  remoteUrl,
@@ -143,7 +350,7 @@ async function initRepoAndPush(input) {
143
350
  commitMessage = "Initial commit",
144
351
  gitAuthorInfo
145
352
  } = input;
146
- const git = backendCommon.Git.fromAuth({
353
+ const git = Git.fromAuth({
147
354
  ...auth,
148
355
  logger
149
356
  });
@@ -153,8 +360,8 @@ async function initRepoAndPush(input) {
153
360
  });
154
361
  await git.add({ dir, filepath: "." });
155
362
  const authorInfo = {
156
- name: (_a = gitAuthorInfo == null ? void 0 : gitAuthorInfo.name) != null ? _a : "Scaffolder",
157
- email: (_b = gitAuthorInfo == null ? void 0 : gitAuthorInfo.email) != null ? _b : "scaffolder@backstage.io"
363
+ name: gitAuthorInfo?.name ?? "Scaffolder",
364
+ email: gitAuthorInfo?.email ?? "scaffolder@backstage.io"
158
365
  };
159
366
  const commitHash = await git.commit({
160
367
  dir,
@@ -174,7 +381,6 @@ async function initRepoAndPush(input) {
174
381
  return { commitHash };
175
382
  }
176
383
  async function commitAndPushRepo(input) {
177
- var _a, _b;
178
384
  const {
179
385
  dir,
180
386
  auth,
@@ -184,7 +390,7 @@ async function commitAndPushRepo(input) {
184
390
  branch = "master",
185
391
  remoteRef
186
392
  } = input;
187
- const git = backendCommon.Git.fromAuth({
393
+ const git = Git.fromAuth({
188
394
  ...auth,
189
395
  logger
190
396
  });
@@ -192,8 +398,8 @@ async function commitAndPushRepo(input) {
192
398
  await git.checkout({ dir, ref: branch });
193
399
  await git.add({ dir, filepath: "." });
194
400
  const authorInfo = {
195
- name: (_a = gitAuthorInfo == null ? void 0 : gitAuthorInfo.name) != null ? _a : "Scaffolder",
196
- email: (_b = gitAuthorInfo == null ? void 0 : gitAuthorInfo.email) != null ? _b : "scaffolder@backstage.io"
401
+ name: gitAuthorInfo?.name ?? "Scaffolder",
402
+ email: gitAuthorInfo?.email ?? "scaffolder@backstage.io"
197
403
  };
198
404
  const commitHash = await git.commit({
199
405
  dir,
@@ -204,13 +410,13 @@ async function commitAndPushRepo(input) {
204
410
  await git.push({
205
411
  dir,
206
412
  remote: "origin",
207
- remoteRef: remoteRef != null ? remoteRef : `refs/heads/${branch}`
413
+ remoteRef: remoteRef ?? `refs/heads/${branch}`
208
414
  });
209
415
  return { commitHash };
210
416
  }
211
417
  async function cloneRepo(options) {
212
418
  const { url, dir, auth, logger, ref, depth, noCheckout } = options;
213
- const git = backendCommon.Git.fromAuth({
419
+ const git = Git.fromAuth({
214
420
  ...auth,
215
421
  logger
216
422
  });
@@ -218,7 +424,7 @@ async function cloneRepo(options) {
218
424
  }
219
425
  async function createBranch(options) {
220
426
  const { dir, ref, auth, logger } = options;
221
- const git = backendCommon.Git.fromAuth({
427
+ const git = Git.fromAuth({
222
428
  ...auth,
223
429
  logger
224
430
  });
@@ -226,14 +432,13 @@ async function createBranch(options) {
226
432
  }
227
433
  async function addFiles(options) {
228
434
  const { dir, filepath, auth, logger } = options;
229
- const git = backendCommon.Git.fromAuth({
435
+ const git = Git.fromAuth({
230
436
  ...auth,
231
437
  logger
232
438
  });
233
439
  await git.add({ dir, filepath });
234
440
  }
235
441
  async function commitAndPushBranch(options) {
236
- var _a, _b;
237
442
  const {
238
443
  dir,
239
444
  auth,
@@ -244,13 +449,13 @@ async function commitAndPushBranch(options) {
244
449
  remoteRef,
245
450
  remote = "origin"
246
451
  } = options;
247
- const git = backendCommon.Git.fromAuth({
452
+ const git = Git.fromAuth({
248
453
  ...auth,
249
454
  logger
250
455
  });
251
456
  const authorInfo = {
252
- name: (_a = gitAuthorInfo == null ? void 0 : gitAuthorInfo.name) != null ? _a : "Scaffolder",
253
- email: (_b = gitAuthorInfo == null ? void 0 : gitAuthorInfo.email) != null ? _b : "scaffolder@backstage.io"
457
+ name: gitAuthorInfo?.name ?? "Scaffolder",
458
+ email: gitAuthorInfo?.email ?? "scaffolder@backstage.io"
254
459
  };
255
460
  const commitHash = await git.commit({
256
461
  dir,
@@ -261,7 +466,7 @@ async function commitAndPushBranch(options) {
261
466
  await git.push({
262
467
  dir,
263
468
  remote,
264
- remoteRef: remoteRef != null ? remoteRef : `refs/heads/${branch}`
469
+ remoteRef: remoteRef ?? `refs/heads/${branch}`
265
470
  });
266
471
  return { commitHash };
267
472
  }
@@ -273,7 +478,7 @@ const getRepoSourceDirectory = (workspacePath, sourcePath) => {
273
478
  ""
274
479
  );
275
480
  const path$1 = path.join(workspacePath, safeSuffix);
276
- if (!backendCommon.isChildPath(workspacePath, path$1)) {
481
+ if (!backendPluginApi.isChildPath(workspacePath, path$1)) {
277
482
  throw new Error("Invalid source path");
278
483
  }
279
484
  return path$1;
@@ -281,7 +486,6 @@ const getRepoSourceDirectory = (workspacePath, sourcePath) => {
281
486
  return workspacePath;
282
487
  };
283
488
  const parseRepoUrl = (repoUrl, integrations) => {
284
- var _a, _b, _c, _d, _e;
285
489
  let parsed;
286
490
  try {
287
491
  parsed = new URL(`https://${repoUrl}`);
@@ -291,11 +495,11 @@ const parseRepoUrl = (repoUrl, integrations) => {
291
495
  );
292
496
  }
293
497
  const host = parsed.host;
294
- const owner = (_a = parsed.searchParams.get("owner")) != null ? _a : void 0;
295
- const organization = (_b = parsed.searchParams.get("organization")) != null ? _b : void 0;
296
- const workspace = (_c = parsed.searchParams.get("workspace")) != null ? _c : void 0;
297
- const project = (_d = parsed.searchParams.get("project")) != null ? _d : void 0;
298
- const type = (_e = integrations.byHost(host)) == null ? void 0 : _e.type;
498
+ const owner = parsed.searchParams.get("owner") ?? void 0;
499
+ const organization = parsed.searchParams.get("organization") ?? void 0;
500
+ const workspace = parsed.searchParams.get("workspace") ?? void 0;
501
+ const project = parsed.searchParams.get("project") ?? void 0;
502
+ const type = integrations.byHost(host)?.type;
299
503
  if (!type) {
300
504
  throw new errors.InputError(
301
505
  `No matching integration configuration for host ${host}, please check your integrations config`
@@ -355,11 +559,10 @@ async function asyncFilter(array, callback) {
355
559
  return array.filter((_value, index) => filterMap[index]);
356
560
  }
357
561
  async function serializeDirectoryContents(sourcePath, options) {
358
- var _a;
359
- const paths = await globby__default.default((_a = options == null ? void 0 : options.globPatterns) != null ? _a : DEFAULT_GLOB_PATTERNS, {
562
+ const paths = await globby__default.default(options?.globPatterns ?? DEFAULT_GLOB_PATTERNS, {
360
563
  cwd: sourcePath,
361
564
  dot: true,
362
- gitignore: options == null ? void 0 : options.gitignore,
565
+ gitignore: options?.gitignore,
363
566
  followSymbolicLinks: false,
364
567
  // In order to pick up 'broken' symlinks, we oxymoronically request files AND folders yet we filter out folders
365
568
  // This is because broken symlinks aren't classed as files so we need to glob everything
@@ -373,7 +576,7 @@ async function serializeDirectoryContents(sourcePath, options) {
373
576
  return false;
374
577
  if (!dirent.isSymbolicLink())
375
578
  return true;
376
- const safePath = backendCommon.resolveSafeChildPath(sourcePath, path);
579
+ const safePath = backendPluginApi.resolveSafeChildPath(sourcePath, path);
377
580
  try {
378
581
  await fs$1.promises.stat(safePath);
379
582
  return false;
@@ -385,13 +588,13 @@ async function serializeDirectoryContents(sourcePath, options) {
385
588
  valid.map(async ({ dirent, path, stats }) => ({
386
589
  path,
387
590
  content: await limiter(async () => {
388
- const absFilePath = backendCommon.resolveSafeChildPath(sourcePath, path);
591
+ const absFilePath = backendPluginApi.resolveSafeChildPath(sourcePath, path);
389
592
  if (dirent.isSymbolicLink()) {
390
593
  return fs$1.promises.readlink(absFilePath, "buffer");
391
594
  }
392
595
  return fs$1.promises.readFile(absFilePath);
393
596
  }),
394
- executable: isExecutable(stats == null ? void 0 : stats.mode),
597
+ executable: isExecutable(stats?.mode),
395
598
  symlink: dirent.isSymbolicLink()
396
599
  }))
397
600
  );
@@ -399,7 +602,7 @@ async function serializeDirectoryContents(sourcePath, options) {
399
602
 
400
603
  async function deserializeDirectoryContents(targetPath, files) {
401
604
  for (const file of files) {
402
- const filePath = backendCommon.resolveSafeChildPath(targetPath, file.path);
605
+ const filePath = backendPluginApi.resolveSafeChildPath(targetPath, file.path);
403
606
  await fs__default.default.ensureDir(path.dirname(filePath));
404
607
  await fs__default.default.writeFile(filePath, file.content);
405
608
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../src/actions/createTemplateAction.ts","../src/actions/executeShellCommand.ts","../src/actions/fetch.ts","../src/actions/gitHelpers.ts","../src/actions/util.ts","../src/files/serializeDirectoryContents.ts","../src/files/deserializeDirectoryContents.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 { ActionContext, TemplateAction } from './types';\nimport { z } from 'zod';\nimport { Schema } from 'jsonschema';\nimport zodToJsonSchema from 'zod-to-json-schema';\nimport { JsonObject } from '@backstage/types';\n\n/** @public */\nexport type TemplateExample = {\n description: string;\n example: string;\n};\n\n/** @public */\nexport type TemplateActionOptions<\n TActionInput extends JsonObject = {},\n TActionOutput extends JsonObject = {},\n TInputSchema extends Schema | z.ZodType = {},\n TOutputSchema extends Schema | z.ZodType = {},\n> = {\n id: string;\n description?: string;\n examples?: TemplateExample[];\n supportsDryRun?: boolean;\n schema?: {\n input?: TInputSchema;\n output?: TOutputSchema;\n };\n handler: (ctx: ActionContext<TActionInput, TActionOutput>) => Promise<void>;\n};\n\n/**\n * This function is used to create new template actions to get type safety.\n * Will convert zod schemas to json schemas for use throughout the system.\n * @public\n */\nexport const createTemplateAction = <\n TInputParams extends JsonObject = JsonObject,\n TOutputParams extends JsonObject = JsonObject,\n TInputSchema extends Schema | z.ZodType = {},\n TOutputSchema extends Schema | z.ZodType = {},\n TActionInput extends JsonObject = TInputSchema extends z.ZodType<\n any,\n any,\n infer IReturn\n >\n ? IReturn\n : TInputParams,\n TActionOutput extends JsonObject = TOutputSchema extends z.ZodType<\n any,\n any,\n infer IReturn\n >\n ? IReturn\n : TOutputParams,\n>(\n action: TemplateActionOptions<\n TActionInput,\n TActionOutput,\n TInputSchema,\n TOutputSchema\n >,\n): TemplateAction<TActionInput, TActionOutput> => {\n const inputSchema =\n action.schema?.input && 'safeParseAsync' in action.schema.input\n ? zodToJsonSchema(action.schema.input)\n : action.schema?.input;\n\n const outputSchema =\n action.schema?.output && 'safeParseAsync' in action.schema.output\n ? zodToJsonSchema(action.schema.output)\n : action.schema?.output;\n\n return {\n ...action,\n schema: {\n ...action.schema,\n input: inputSchema as TInputSchema,\n output: outputSchema as TOutputSchema,\n },\n };\n};\n","/*\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 { spawn, SpawnOptionsWithoutStdio } from 'child_process';\nimport { PassThrough, Writable } from 'stream';\n\n/**\n * Options for {@link executeShellCommand}.\n *\n * @public\n */\nexport type ExecuteShellCommandOptions = {\n /** command to run */\n command: string;\n /** arguments to pass the command */\n args: string[];\n /** options to pass to spawn */\n options?: SpawnOptionsWithoutStdio;\n /** stream to capture stdout and stderr output */\n logStream?: Writable;\n};\n\n/**\n * Run a command in a sub-process, normally a shell command.\n *\n * @public\n */\nexport async function executeShellCommand(\n options: ExecuteShellCommandOptions,\n): Promise<void> {\n const {\n command,\n args,\n options: spawnOptions,\n logStream = new PassThrough(),\n } = options;\n\n await new Promise<void>((resolve, reject) => {\n const process = spawn(command, args, spawnOptions);\n\n process.stdout.on('data', stream => {\n logStream.write(stream);\n });\n\n process.stderr.on('data', stream => {\n logStream.write(stream);\n });\n\n process.on('error', error => {\n return reject(error);\n });\n\n process.on('close', code => {\n if (code !== 0) {\n return reject(\n new Error(`Command ${command} failed, exit code: ${code}`),\n );\n }\n return resolve();\n });\n });\n}\n","/*\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 { resolveSafeChildPath, UrlReader } from '@backstage/backend-common';\nimport { InputError } from '@backstage/errors';\nimport { ScmIntegrations } from '@backstage/integration';\nimport fs from 'fs-extra';\nimport path from 'path';\n\n/**\n * A helper function that reads the contents of a directory from the given URL.\n * Can be used in your own actions, and also used behind fetch:template and fetch:plain\n *\n * @public\n */\nexport async function fetchContents(options: {\n reader: UrlReader;\n integrations: ScmIntegrations;\n baseUrl?: string;\n fetchUrl?: string;\n outputPath: string;\n token?: string;\n}) {\n const {\n reader,\n integrations,\n baseUrl,\n fetchUrl = '.',\n outputPath,\n token,\n } = options;\n\n const fetchUrlIsAbsolute = isFetchUrlAbsolute(fetchUrl);\n\n // We handle both file locations and url ones\n if (!fetchUrlIsAbsolute && baseUrl?.startsWith('file://')) {\n const basePath = baseUrl.slice('file://'.length);\n const srcDir = resolveSafeChildPath(path.dirname(basePath), fetchUrl);\n await fs.copy(srcDir, outputPath);\n } else {\n const readUrl = getReadUrl(fetchUrl, baseUrl, integrations);\n\n const res = await reader.readTree(readUrl, { token });\n await fs.ensureDir(outputPath);\n await res.dir({ targetDir: outputPath });\n }\n}\n\n/**\n * A helper function that reads the content of a single file from the given URL.\n * Can be used in your own actions, and also used behind `fetch:plain:file`\n *\n * @public\n */\nexport async function fetchFile(options: {\n reader: UrlReader;\n integrations: ScmIntegrations;\n baseUrl?: string;\n fetchUrl?: string;\n outputPath: string;\n token?: string;\n}) {\n const {\n reader,\n integrations,\n baseUrl,\n fetchUrl = '.',\n outputPath,\n token,\n } = options;\n\n const fetchUrlIsAbsolute = isFetchUrlAbsolute(fetchUrl);\n\n // We handle both file locations and url ones\n if (!fetchUrlIsAbsolute && baseUrl?.startsWith('file://')) {\n const basePath = baseUrl.slice('file://'.length);\n const src = resolveSafeChildPath(path.dirname(basePath), fetchUrl);\n await fs.copyFile(src, outputPath);\n } else {\n const readUrl = getReadUrl(fetchUrl, baseUrl, integrations);\n\n const res = await reader.readUrl(readUrl, { token });\n await fs.ensureDir(path.dirname(outputPath));\n const buffer = await res.buffer();\n await fs.outputFile(outputPath, buffer);\n }\n}\n\nfunction isFetchUrlAbsolute(fetchUrl: string) {\n let fetchUrlIsAbsolute = false;\n try {\n // eslint-disable-next-line no-new\n new URL(fetchUrl);\n fetchUrlIsAbsolute = true;\n } catch {\n /* ignored */\n }\n return fetchUrlIsAbsolute;\n}\n\nfunction getReadUrl(\n fetchUrl: string,\n baseUrl: string | undefined,\n integrations: ScmIntegrations,\n) {\n if (isFetchUrlAbsolute(fetchUrl)) {\n return fetchUrl;\n } else if (baseUrl) {\n const integration = integrations.byUrl(baseUrl);\n if (!integration) {\n throw new InputError(`No integration found for location ${baseUrl}`);\n }\n\n return integration.resolveUrl({\n url: fetchUrl,\n base: baseUrl,\n });\n }\n throw new InputError(\n `Failed to fetch, template location could not be determined and the fetch URL is relative, ${fetchUrl}`,\n );\n}\n","/*\n * Copyright 2023 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 { Git } from '@backstage/backend-common';\nimport { Logger } from 'winston';\n\n/**\n * @public\n */\nexport async function initRepoAndPush(input: {\n dir: string;\n remoteUrl: string;\n // For use cases where token has to be used with Basic Auth\n // it has to be provided as password together with a username\n // which may be a fixed value defined by the provider.\n auth: { username: string; password: string } | { token: string };\n logger: Logger;\n defaultBranch?: string;\n commitMessage?: string;\n gitAuthorInfo?: { name?: string; email?: string };\n}): Promise<{ commitHash: string }> {\n const {\n dir,\n remoteUrl,\n auth,\n logger,\n defaultBranch = 'master',\n commitMessage = 'Initial commit',\n gitAuthorInfo,\n } = input;\n const git = Git.fromAuth({\n ...auth,\n logger,\n });\n\n await git.init({\n dir,\n defaultBranch,\n });\n\n await git.add({ dir, filepath: '.' });\n\n // use provided info if possible, otherwise use fallbacks\n const authorInfo = {\n name: gitAuthorInfo?.name ?? 'Scaffolder',\n email: gitAuthorInfo?.email ?? 'scaffolder@backstage.io',\n };\n\n const commitHash = await git.commit({\n dir,\n message: commitMessage,\n author: authorInfo,\n committer: authorInfo,\n });\n await git.addRemote({\n dir,\n url: remoteUrl,\n remote: 'origin',\n });\n\n await git.push({\n dir,\n remote: 'origin',\n });\n\n return { commitHash };\n}\n\n/**\n * @public\n */\nexport async function commitAndPushRepo(input: {\n dir: string;\n // For use cases where token has to be used with Basic Auth\n // it has to be provided as password together with a username\n // which may be a fixed value defined by the provider.\n auth: { username: string; password: string } | { token: string };\n logger: Logger;\n commitMessage: string;\n gitAuthorInfo?: { name?: string; email?: string };\n branch?: string;\n remoteRef?: string;\n}): Promise<{ commitHash: string }> {\n const {\n dir,\n auth,\n logger,\n commitMessage,\n gitAuthorInfo,\n branch = 'master',\n remoteRef,\n } = input;\n\n const git = Git.fromAuth({\n ...auth,\n logger,\n });\n\n await git.fetch({ dir });\n await git.checkout({ dir, ref: branch });\n await git.add({ dir, filepath: '.' });\n\n // use provided info if possible, otherwise use fallbacks\n const authorInfo = {\n name: gitAuthorInfo?.name ?? 'Scaffolder',\n email: gitAuthorInfo?.email ?? 'scaffolder@backstage.io',\n };\n\n const commitHash = await git.commit({\n dir,\n message: commitMessage,\n author: authorInfo,\n committer: authorInfo,\n });\n\n await git.push({\n dir,\n remote: 'origin',\n remoteRef: remoteRef ?? `refs/heads/${branch}`,\n });\n\n return { commitHash };\n}\n\n/**\n * @public\n */\nexport async function cloneRepo(options: {\n url: string;\n dir: string;\n // For use cases where token has to be used with Basic Auth\n // it has to be provided as password together with a username\n // which may be a fixed value defined by the provider.\n auth: { username: string; password: string } | { token: string };\n logger?: Logger | undefined;\n ref?: string | undefined;\n depth?: number | undefined;\n noCheckout?: boolean | undefined;\n}): Promise<void> {\n const { url, dir, auth, logger, ref, depth, noCheckout } = options;\n\n const git = Git.fromAuth({\n ...auth,\n logger,\n });\n\n await git.clone({ url, dir, ref, depth, noCheckout });\n}\n\n/**\n * @public\n */\nexport async function createBranch(options: {\n dir: string;\n ref: string;\n // For use cases where token has to be used with Basic Auth\n // it has to be provided as password together with a username\n // which may be a fixed value defined by the provider.\n auth: { username: string; password: string } | { token: string };\n logger?: Logger | undefined;\n}): Promise<void> {\n const { dir, ref, auth, logger } = options;\n const git = Git.fromAuth({\n ...auth,\n logger,\n });\n\n await git.checkout({ dir, ref });\n}\n\n/**\n * @public\n */\nexport async function addFiles(options: {\n dir: string;\n filepath: string;\n // For use cases where token has to be used with Basic Auth\n // it has to be provided as password together with a username\n // which may be a fixed value defined by the provider.\n auth: { username: string; password: string } | { token: string };\n logger?: Logger | undefined;\n}): Promise<void> {\n const { dir, filepath, auth, logger } = options;\n const git = Git.fromAuth({\n ...auth,\n logger,\n });\n\n await git.add({ dir, filepath });\n}\n\n/**\n * @public\n */\nexport async function commitAndPushBranch(options: {\n dir: string;\n // For use cases where token has to be used with Basic Auth\n // it has to be provided as password together with a username\n // which may be a fixed value defined by the provider.\n auth: { username: string; password: string } | { token: string };\n logger?: Logger | undefined;\n commitMessage: string;\n gitAuthorInfo?: { name?: string; email?: string };\n branch?: string;\n remoteRef?: string;\n remote?: string;\n}): Promise<{ commitHash: string }> {\n const {\n dir,\n auth,\n logger,\n commitMessage,\n gitAuthorInfo,\n branch = 'master',\n remoteRef,\n remote = 'origin',\n } = options;\n const git = Git.fromAuth({\n ...auth,\n logger,\n });\n\n // use provided info if possible, otherwise use fallbacks\n const authorInfo = {\n name: gitAuthorInfo?.name ?? 'Scaffolder',\n email: gitAuthorInfo?.email ?? 'scaffolder@backstage.io',\n };\n\n const commitHash = await git.commit({\n dir,\n message: commitMessage,\n author: authorInfo,\n committer: authorInfo,\n });\n\n await git.push({\n dir,\n remote,\n remoteRef: remoteRef ?? `refs/heads/${branch}`,\n });\n\n return { commitHash };\n}\n","/*\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 { InputError } from '@backstage/errors';\nimport { isChildPath } from '@backstage/backend-common';\nimport { join as joinPath, normalize as normalizePath } from 'path';\nimport { ScmIntegrationRegistry } from '@backstage/integration';\n\n/**\n * @public\n */\nexport const getRepoSourceDirectory = (\n workspacePath: string,\n sourcePath: string | undefined,\n) => {\n if (sourcePath) {\n const safeSuffix = normalizePath(sourcePath).replace(\n /^(\\.\\.(\\/|\\\\|$))+/,\n '',\n );\n const path = joinPath(workspacePath, safeSuffix);\n if (!isChildPath(workspacePath, path)) {\n throw new Error('Invalid source path');\n }\n return path;\n }\n return workspacePath;\n};\n\n/**\n * @public\n */\nexport const parseRepoUrl = (\n repoUrl: string,\n integrations: ScmIntegrationRegistry,\n): {\n repo: string;\n host: string;\n owner?: string;\n organization?: string;\n workspace?: string;\n project?: string;\n} => {\n let parsed;\n try {\n parsed = new URL(`https://${repoUrl}`);\n } catch (error) {\n throw new InputError(\n `Invalid repo URL passed to publisher, got ${repoUrl}, ${error}`,\n );\n }\n const host = parsed.host;\n const owner = parsed.searchParams.get('owner') ?? undefined;\n const organization = parsed.searchParams.get('organization') ?? undefined;\n const workspace = parsed.searchParams.get('workspace') ?? undefined;\n const project = parsed.searchParams.get('project') ?? undefined;\n\n const type = integrations.byHost(host)?.type;\n\n if (!type) {\n throw new InputError(\n `No matching integration configuration for host ${host}, please check your integrations config`,\n );\n }\n\n const repo: string = parsed.searchParams.get('repo')!;\n switch (type) {\n case 'bitbucket': {\n if (host === 'www.bitbucket.org') {\n checkRequiredParams(parsed, 'workspace');\n }\n checkRequiredParams(parsed, 'project', 'repo');\n break;\n }\n case 'gitlab': {\n // project is the projectID, and if defined, owner and repo won't be needed.\n if (!project) {\n checkRequiredParams(parsed, 'owner', 'repo');\n }\n break;\n }\n case 'gitea': {\n checkRequiredParams(parsed, 'repo');\n break;\n }\n case 'gerrit': {\n checkRequiredParams(parsed, 'repo');\n break;\n }\n default: {\n checkRequiredParams(parsed, 'repo', 'owner');\n break;\n }\n }\n\n return { host, owner, repo, organization, workspace, project };\n};\n\nfunction checkRequiredParams(repoUrl: URL, ...params: string[]) {\n for (let i = 0; i < params.length; i++) {\n if (!repoUrl.searchParams.get(params[i])) {\n throw new InputError(\n `Invalid repo URL passed to publisher: ${repoUrl.toString()}, missing ${\n params[i]\n }`,\n );\n }\n }\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { promises as fs } from 'fs';\nimport globby from 'globby';\nimport limiterFactory from 'p-limit';\nimport { resolveSafeChildPath } from '@backstage/backend-common';\nimport { SerializedFile } from './types';\nimport { isError } from '@backstage/errors';\n\nconst DEFAULT_GLOB_PATTERNS = ['./**', '!.git'];\n\nexport const isExecutable = (fileMode: number | undefined) => {\n if (!fileMode) {\n return false;\n }\n\n const executeBitMask = 0o000111;\n const res = fileMode & executeBitMask;\n return res > 0;\n};\n\nasync function asyncFilter<T>(\n array: T[],\n callback: (value: T, index: number, array: T[]) => Promise<boolean>,\n): Promise<T[]> {\n const filterMap = await Promise.all(array.map(callback));\n return array.filter((_value, index) => filterMap[index]);\n}\n\n/**\n * @public\n */\nexport async function serializeDirectoryContents(\n sourcePath: string,\n options?: {\n gitignore?: boolean;\n globPatterns?: string[];\n },\n): Promise<SerializedFile[]> {\n const paths = await globby(options?.globPatterns ?? DEFAULT_GLOB_PATTERNS, {\n cwd: sourcePath,\n dot: true,\n gitignore: options?.gitignore,\n followSymbolicLinks: false,\n // In order to pick up 'broken' symlinks, we oxymoronically request files AND folders yet we filter out folders\n // This is because broken symlinks aren't classed as files so we need to glob everything\n onlyFiles: false,\n objectMode: true,\n stats: true,\n });\n\n const limiter = limiterFactory(10);\n\n const valid = await asyncFilter(paths, async ({ dirent, path }) => {\n if (dirent.isDirectory()) return false;\n if (!dirent.isSymbolicLink()) return true;\n\n const safePath = resolveSafeChildPath(sourcePath, path);\n\n // we only want files that don't exist\n try {\n await fs.stat(safePath);\n return false;\n } catch (e) {\n return isError(e) && e.code === 'ENOENT';\n }\n });\n\n return Promise.all(\n valid.map(async ({ dirent, path, stats }) => ({\n path,\n content: await limiter(async () => {\n const absFilePath = resolveSafeChildPath(sourcePath, path);\n if (dirent.isSymbolicLink()) {\n return fs.readlink(absFilePath, 'buffer');\n }\n return fs.readFile(absFilePath);\n }),\n executable: isExecutable(stats?.mode),\n symlink: dirent.isSymbolicLink(),\n })),\n );\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport fs from 'fs-extra';\nimport { dirname } from 'path';\nimport { resolveSafeChildPath } from '@backstage/backend-common';\nimport { SerializedFile } from './types';\n\n/**\n * Deserializes a list of serialized files into the target directory.\n *\n * This method uses `resolveSafeChildPath` to make sure that files are\n * not written outside of the target directory.\n *\n * @public\n */\nexport async function deserializeDirectoryContents(\n targetPath: string,\n files: SerializedFile[],\n): Promise<void> {\n for (const file of files) {\n const filePath = resolveSafeChildPath(targetPath, file.path);\n await fs.ensureDir(dirname(filePath));\n await fs.writeFile(filePath, file.content); // Ignore file mode\n }\n}\n"],"names":["zodToJsonSchema","PassThrough","spawn","resolveSafeChildPath","path","fs","InputError","Git","normalizePath","joinPath","isChildPath","globby","limiterFactory","isError","dirname"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAmDa,MAAA,oBAAA,GAAuB,CAoBlC,MAMgD,KAAA;AA7ElD,EAAA,IAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,CAAA;AA8EE,EAAA,MAAM,gBACJ,EAAO,GAAA,MAAA,CAAA,MAAA,KAAP,IAAe,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,KAAA,KAAS,oBAAoB,MAAO,CAAA,MAAA,CAAO,KACtD,GAAAA,gCAAA,CAAgB,OAAO,MAAO,CAAA,KAAK,CACnC,GAAA,CAAA,EAAA,GAAA,MAAA,CAAO,WAAP,IAAe,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,KAAA,CAAA;AAErB,EAAA,MAAM,iBACJ,EAAO,GAAA,MAAA,CAAA,MAAA,KAAP,IAAe,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,MAAA,KAAU,oBAAoB,MAAO,CAAA,MAAA,CAAO,MACvD,GAAAA,gCAAA,CAAgB,OAAO,MAAO,CAAA,MAAM,CACpC,GAAA,CAAA,EAAA,GAAA,MAAA,CAAO,WAAP,IAAe,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,MAAA,CAAA;AAErB,EAAO,OAAA;AAAA,IACL,GAAG,MAAA;AAAA,IACH,MAAQ,EAAA;AAAA,MACN,GAAG,MAAO,CAAA,MAAA;AAAA,MACV,KAAO,EAAA,WAAA;AAAA,MACP,MAAQ,EAAA,YAAA;AAAA,KACV;AAAA,GACF,CAAA;AACF;;ACxDA,eAAsB,oBACpB,OACe,EAAA;AACf,EAAM,MAAA;AAAA,IACJ,OAAA;AAAA,IACA,IAAA;AAAA,IACA,OAAS,EAAA,YAAA;AAAA,IACT,SAAA,GAAY,IAAIC,kBAAY,EAAA;AAAA,GAC1B,GAAA,OAAA,CAAA;AAEJ,EAAA,MAAM,IAAI,OAAA,CAAc,CAAC,OAAA,EAAS,MAAW,KAAA;AAC3C,IAAA,MAAM,OAAU,GAAAC,mBAAA,CAAM,OAAS,EAAA,IAAA,EAAM,YAAY,CAAA,CAAA;AAEjD,IAAQ,OAAA,CAAA,MAAA,CAAO,EAAG,CAAA,MAAA,EAAQ,CAAU,MAAA,KAAA;AAClC,MAAA,SAAA,CAAU,MAAM,MAAM,CAAA,CAAA;AAAA,KACvB,CAAA,CAAA;AAED,IAAQ,OAAA,CAAA,MAAA,CAAO,EAAG,CAAA,MAAA,EAAQ,CAAU,MAAA,KAAA;AAClC,MAAA,SAAA,CAAU,MAAM,MAAM,CAAA,CAAA;AAAA,KACvB,CAAA,CAAA;AAED,IAAQ,OAAA,CAAA,EAAA,CAAG,SAAS,CAAS,KAAA,KAAA;AAC3B,MAAA,OAAO,OAAO,KAAK,CAAA,CAAA;AAAA,KACpB,CAAA,CAAA;AAED,IAAQ,OAAA,CAAA,EAAA,CAAG,SAAS,CAAQ,IAAA,KAAA;AAC1B,MAAA,IAAI,SAAS,CAAG,EAAA;AACd,QAAO,OAAA,MAAA;AAAA,UACL,IAAI,KAAM,CAAA,CAAA,QAAA,EAAW,OAAO,CAAA,oBAAA,EAAuB,IAAI,CAAE,CAAA,CAAA;AAAA,SAC3D,CAAA;AAAA,OACF;AACA,MAAA,OAAO,OAAQ,EAAA,CAAA;AAAA,KAChB,CAAA,CAAA;AAAA,GACF,CAAA,CAAA;AACH;;AC9CA,eAAsB,cAAc,OAOjC,EAAA;AACD,EAAM,MAAA;AAAA,IACJ,MAAA;AAAA,IACA,YAAA;AAAA,IACA,OAAA;AAAA,IACA,QAAW,GAAA,GAAA;AAAA,IACX,UAAA;AAAA,IACA,KAAA;AAAA,GACE,GAAA,OAAA,CAAA;AAEJ,EAAM,MAAA,kBAAA,GAAqB,mBAAmB,QAAQ,CAAA,CAAA;AAGtD,EAAA,IAAI,CAAC,kBAAA,KAAsB,OAAS,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,OAAA,CAAA,UAAA,CAAW,SAAY,CAAA,CAAA,EAAA;AACzD,IAAA,MAAM,QAAW,GAAA,OAAA,CAAQ,KAAM,CAAA,SAAA,CAAU,MAAM,CAAA,CAAA;AAC/C,IAAA,MAAM,SAASC,kCAAqB,CAAAC,qBAAA,CAAK,OAAQ,CAAA,QAAQ,GAAG,QAAQ,CAAA,CAAA;AACpE,IAAM,MAAAC,mBAAA,CAAG,IAAK,CAAA,MAAA,EAAQ,UAAU,CAAA,CAAA;AAAA,GAC3B,MAAA;AACL,IAAA,MAAM,OAAU,GAAA,UAAA,CAAW,QAAU,EAAA,OAAA,EAAS,YAAY,CAAA,CAAA;AAE1D,IAAA,MAAM,MAAM,MAAM,MAAA,CAAO,SAAS,OAAS,EAAA,EAAE,OAAO,CAAA,CAAA;AACpD,IAAM,MAAAA,mBAAA,CAAG,UAAU,UAAU,CAAA,CAAA;AAC7B,IAAA,MAAM,GAAI,CAAA,GAAA,CAAI,EAAE,SAAA,EAAW,YAAY,CAAA,CAAA;AAAA,GACzC;AACF,CAAA;AAQA,eAAsB,UAAU,OAO7B,EAAA;AACD,EAAM,MAAA;AAAA,IACJ,MAAA;AAAA,IACA,YAAA;AAAA,IACA,OAAA;AAAA,IACA,QAAW,GAAA,GAAA;AAAA,IACX,UAAA;AAAA,IACA,KAAA;AAAA,GACE,GAAA,OAAA,CAAA;AAEJ,EAAM,MAAA,kBAAA,GAAqB,mBAAmB,QAAQ,CAAA,CAAA;AAGtD,EAAA,IAAI,CAAC,kBAAA,KAAsB,OAAS,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,OAAA,CAAA,UAAA,CAAW,SAAY,CAAA,CAAA,EAAA;AACzD,IAAA,MAAM,QAAW,GAAA,OAAA,CAAQ,KAAM,CAAA,SAAA,CAAU,MAAM,CAAA,CAAA;AAC/C,IAAA,MAAM,MAAMF,kCAAqB,CAAAC,qBAAA,CAAK,OAAQ,CAAA,QAAQ,GAAG,QAAQ,CAAA,CAAA;AACjE,IAAM,MAAAC,mBAAA,CAAG,QAAS,CAAA,GAAA,EAAK,UAAU,CAAA,CAAA;AAAA,GAC5B,MAAA;AACL,IAAA,MAAM,OAAU,GAAA,UAAA,CAAW,QAAU,EAAA,OAAA,EAAS,YAAY,CAAA,CAAA;AAE1D,IAAA,MAAM,MAAM,MAAM,MAAA,CAAO,QAAQ,OAAS,EAAA,EAAE,OAAO,CAAA,CAAA;AACnD,IAAA,MAAMA,mBAAG,CAAA,SAAA,CAAUD,qBAAK,CAAA,OAAA,CAAQ,UAAU,CAAC,CAAA,CAAA;AAC3C,IAAM,MAAA,MAAA,GAAS,MAAM,GAAA,CAAI,MAAO,EAAA,CAAA;AAChC,IAAM,MAAAC,mBAAA,CAAG,UAAW,CAAA,UAAA,EAAY,MAAM,CAAA,CAAA;AAAA,GACxC;AACF,CAAA;AAEA,SAAS,mBAAmB,QAAkB,EAAA;AAC5C,EAAA,IAAI,kBAAqB,GAAA,KAAA,CAAA;AACzB,EAAI,IAAA;AAEF,IAAA,IAAI,IAAI,QAAQ,CAAA,CAAA;AAChB,IAAqB,kBAAA,GAAA,IAAA,CAAA;AAAA,GACf,CAAA,MAAA;AAAA,GAER;AACA,EAAO,OAAA,kBAAA,CAAA;AACT,CAAA;AAEA,SAAS,UAAA,CACP,QACA,EAAA,OAAA,EACA,YACA,EAAA;AACA,EAAI,IAAA,kBAAA,CAAmB,QAAQ,CAAG,EAAA;AAChC,IAAO,OAAA,QAAA,CAAA;AAAA,aACE,OAAS,EAAA;AAClB,IAAM,MAAA,WAAA,GAAc,YAAa,CAAA,KAAA,CAAM,OAAO,CAAA,CAAA;AAC9C,IAAA,IAAI,CAAC,WAAa,EAAA;AAChB,MAAA,MAAM,IAAIC,iBAAA,CAAW,CAAqC,kCAAA,EAAA,OAAO,CAAE,CAAA,CAAA,CAAA;AAAA,KACrE;AAEA,IAAA,OAAO,YAAY,UAAW,CAAA;AAAA,MAC5B,GAAK,EAAA,QAAA;AAAA,MACL,IAAM,EAAA,OAAA;AAAA,KACP,CAAA,CAAA;AAAA,GACH;AACA,EAAA,MAAM,IAAIA,iBAAA;AAAA,IACR,6FAA6F,QAAQ,CAAA,CAAA;AAAA,GACvG,CAAA;AACF;;AChHA,eAAsB,gBAAgB,KAWF,EAAA;AAjCpC,EAAA,IAAA,EAAA,EAAA,EAAA,CAAA;AAkCE,EAAM,MAAA;AAAA,IACJ,GAAA;AAAA,IACA,SAAA;AAAA,IACA,IAAA;AAAA,IACA,MAAA;AAAA,IACA,aAAgB,GAAA,QAAA;AAAA,IAChB,aAAgB,GAAA,gBAAA;AAAA,IAChB,aAAA;AAAA,GACE,GAAA,KAAA,CAAA;AACJ,EAAM,MAAA,GAAA,GAAMC,kBAAI,QAAS,CAAA;AAAA,IACvB,GAAG,IAAA;AAAA,IACH,MAAA;AAAA,GACD,CAAA,CAAA;AAED,EAAA,MAAM,IAAI,IAAK,CAAA;AAAA,IACb,GAAA;AAAA,IACA,aAAA;AAAA,GACD,CAAA,CAAA;AAED,EAAA,MAAM,IAAI,GAAI,CAAA,EAAE,GAAK,EAAA,QAAA,EAAU,KAAK,CAAA,CAAA;AAGpC,EAAA,MAAM,UAAa,GAAA;AAAA,IACjB,IAAA,EAAA,CAAM,EAAe,GAAA,aAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,aAAA,CAAA,IAAA,KAAf,IAAuB,GAAA,EAAA,GAAA,YAAA;AAAA,IAC7B,KAAA,EAAA,CAAO,EAAe,GAAA,aAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,aAAA,CAAA,KAAA,KAAf,IAAwB,GAAA,EAAA,GAAA,yBAAA;AAAA,GACjC,CAAA;AAEA,EAAM,MAAA,UAAA,GAAa,MAAM,GAAA,CAAI,MAAO,CAAA;AAAA,IAClC,GAAA;AAAA,IACA,OAAS,EAAA,aAAA;AAAA,IACT,MAAQ,EAAA,UAAA;AAAA,IACR,SAAW,EAAA,UAAA;AAAA,GACZ,CAAA,CAAA;AACD,EAAA,MAAM,IAAI,SAAU,CAAA;AAAA,IAClB,GAAA;AAAA,IACA,GAAK,EAAA,SAAA;AAAA,IACL,MAAQ,EAAA,QAAA;AAAA,GACT,CAAA,CAAA;AAED,EAAA,MAAM,IAAI,IAAK,CAAA;AAAA,IACb,GAAA;AAAA,IACA,MAAQ,EAAA,QAAA;AAAA,GACT,CAAA,CAAA;AAED,EAAA,OAAO,EAAE,UAAW,EAAA,CAAA;AACtB,CAAA;AAKA,eAAsB,kBAAkB,KAWJ,EAAA;AA/FpC,EAAA,IAAA,EAAA,EAAA,EAAA,CAAA;AAgGE,EAAM,MAAA;AAAA,IACJ,GAAA;AAAA,IACA,IAAA;AAAA,IACA,MAAA;AAAA,IACA,aAAA;AAAA,IACA,aAAA;AAAA,IACA,MAAS,GAAA,QAAA;AAAA,IACT,SAAA;AAAA,GACE,GAAA,KAAA,CAAA;AAEJ,EAAM,MAAA,GAAA,GAAMA,kBAAI,QAAS,CAAA;AAAA,IACvB,GAAG,IAAA;AAAA,IACH,MAAA;AAAA,GACD,CAAA,CAAA;AAED,EAAA,MAAM,GAAI,CAAA,KAAA,CAAM,EAAE,GAAA,EAAK,CAAA,CAAA;AACvB,EAAA,MAAM,IAAI,QAAS,CAAA,EAAE,GAAK,EAAA,GAAA,EAAK,QAAQ,CAAA,CAAA;AACvC,EAAA,MAAM,IAAI,GAAI,CAAA,EAAE,GAAK,EAAA,QAAA,EAAU,KAAK,CAAA,CAAA;AAGpC,EAAA,MAAM,UAAa,GAAA;AAAA,IACjB,IAAA,EAAA,CAAM,EAAe,GAAA,aAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,aAAA,CAAA,IAAA,KAAf,IAAuB,GAAA,EAAA,GAAA,YAAA;AAAA,IAC7B,KAAA,EAAA,CAAO,EAAe,GAAA,aAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,aAAA,CAAA,KAAA,KAAf,IAAwB,GAAA,EAAA,GAAA,yBAAA;AAAA,GACjC,CAAA;AAEA,EAAM,MAAA,UAAA,GAAa,MAAM,GAAA,CAAI,MAAO,CAAA;AAAA,IAClC,GAAA;AAAA,IACA,OAAS,EAAA,aAAA;AAAA,IACT,MAAQ,EAAA,UAAA;AAAA,IACR,SAAW,EAAA,UAAA;AAAA,GACZ,CAAA,CAAA;AAED,EAAA,MAAM,IAAI,IAAK,CAAA;AAAA,IACb,GAAA;AAAA,IACA,MAAQ,EAAA,QAAA;AAAA,IACR,SAAA,EAAW,SAAa,IAAA,IAAA,GAAA,SAAA,GAAA,CAAA,WAAA,EAAc,MAAM,CAAA,CAAA;AAAA,GAC7C,CAAA,CAAA;AAED,EAAA,OAAO,EAAE,UAAW,EAAA,CAAA;AACtB,CAAA;AAKA,eAAsB,UAAU,OAWd,EAAA;AAChB,EAAM,MAAA,EAAE,KAAK,GAAK,EAAA,IAAA,EAAM,QAAQ,GAAK,EAAA,KAAA,EAAO,YAAe,GAAA,OAAA,CAAA;AAE3D,EAAM,MAAA,GAAA,GAAMA,kBAAI,QAAS,CAAA;AAAA,IACvB,GAAG,IAAA;AAAA,IACH,MAAA;AAAA,GACD,CAAA,CAAA;AAED,EAAM,MAAA,GAAA,CAAI,MAAM,EAAE,GAAA,EAAK,KAAK,GAAK,EAAA,KAAA,EAAO,YAAY,CAAA,CAAA;AACtD,CAAA;AAKA,eAAsB,aAAa,OAQjB,EAAA;AAChB,EAAA,MAAM,EAAE,GAAA,EAAK,GAAK,EAAA,IAAA,EAAM,QAAW,GAAA,OAAA,CAAA;AACnC,EAAM,MAAA,GAAA,GAAMA,kBAAI,QAAS,CAAA;AAAA,IACvB,GAAG,IAAA;AAAA,IACH,MAAA;AAAA,GACD,CAAA,CAAA;AAED,EAAA,MAAM,GAAI,CAAA,QAAA,CAAS,EAAE,GAAA,EAAK,KAAK,CAAA,CAAA;AACjC,CAAA;AAKA,eAAsB,SAAS,OAQb,EAAA;AAChB,EAAA,MAAM,EAAE,GAAA,EAAK,QAAU,EAAA,IAAA,EAAM,QAAW,GAAA,OAAA,CAAA;AACxC,EAAM,MAAA,GAAA,GAAMA,kBAAI,QAAS,CAAA;AAAA,IACvB,GAAG,IAAA;AAAA,IACH,MAAA;AAAA,GACD,CAAA,CAAA;AAED,EAAA,MAAM,GAAI,CAAA,GAAA,CAAI,EAAE,GAAA,EAAK,UAAU,CAAA,CAAA;AACjC,CAAA;AAKA,eAAsB,oBAAoB,OAYN,EAAA;AA3NpC,EAAA,IAAA,EAAA,EAAA,EAAA,CAAA;AA4NE,EAAM,MAAA;AAAA,IACJ,GAAA;AAAA,IACA,IAAA;AAAA,IACA,MAAA;AAAA,IACA,aAAA;AAAA,IACA,aAAA;AAAA,IACA,MAAS,GAAA,QAAA;AAAA,IACT,SAAA;AAAA,IACA,MAAS,GAAA,QAAA;AAAA,GACP,GAAA,OAAA,CAAA;AACJ,EAAM,MAAA,GAAA,GAAMA,kBAAI,QAAS,CAAA;AAAA,IACvB,GAAG,IAAA;AAAA,IACH,MAAA;AAAA,GACD,CAAA,CAAA;AAGD,EAAA,MAAM,UAAa,GAAA;AAAA,IACjB,IAAA,EAAA,CAAM,EAAe,GAAA,aAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,aAAA,CAAA,IAAA,KAAf,IAAuB,GAAA,EAAA,GAAA,YAAA;AAAA,IAC7B,KAAA,EAAA,CAAO,EAAe,GAAA,aAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,aAAA,CAAA,KAAA,KAAf,IAAwB,GAAA,EAAA,GAAA,yBAAA;AAAA,GACjC,CAAA;AAEA,EAAM,MAAA,UAAA,GAAa,MAAM,GAAA,CAAI,MAAO,CAAA;AAAA,IAClC,GAAA;AAAA,IACA,OAAS,EAAA,aAAA;AAAA,IACT,MAAQ,EAAA,UAAA;AAAA,IACR,SAAW,EAAA,UAAA;AAAA,GACZ,CAAA,CAAA;AAED,EAAA,MAAM,IAAI,IAAK,CAAA;AAAA,IACb,GAAA;AAAA,IACA,MAAA;AAAA,IACA,SAAA,EAAW,SAAa,IAAA,IAAA,GAAA,SAAA,GAAA,CAAA,WAAA,EAAc,MAAM,CAAA,CAAA;AAAA,GAC7C,CAAA,CAAA;AAED,EAAA,OAAO,EAAE,UAAW,EAAA,CAAA;AACtB;;ACvOa,MAAA,sBAAA,GAAyB,CACpC,aAAA,EACA,UACG,KAAA;AACH,EAAA,IAAI,UAAY,EAAA;AACd,IAAM,MAAA,UAAA,GAAaC,cAAc,CAAA,UAAU,CAAE,CAAA,OAAA;AAAA,MAC3C,mBAAA;AAAA,MACA,EAAA;AAAA,KACF,CAAA;AACA,IAAM,MAAAJ,MAAA,GAAOK,SAAS,CAAA,aAAA,EAAe,UAAU,CAAA,CAAA;AAC/C,IAAA,IAAI,CAACC,yBAAA,CAAY,aAAe,EAAAN,MAAI,CAAG,EAAA;AACrC,MAAM,MAAA,IAAI,MAAM,qBAAqB,CAAA,CAAA;AAAA,KACvC;AACA,IAAO,OAAAA,MAAA,CAAA;AAAA,GACT;AACA,EAAO,OAAA,aAAA,CAAA;AACT,EAAA;AAKa,MAAA,YAAA,GAAe,CAC1B,OAAA,EACA,YAQG,KAAA;AAvDL,EAAA,IAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,CAAA;AAwDE,EAAI,IAAA,MAAA,CAAA;AACJ,EAAI,IAAA;AACF,IAAA,MAAA,GAAS,IAAI,GAAA,CAAI,CAAW,QAAA,EAAA,OAAO,CAAE,CAAA,CAAA,CAAA;AAAA,WAC9B,KAAO,EAAA;AACd,IAAA,MAAM,IAAIE,iBAAA;AAAA,MACR,CAAA,0CAAA,EAA6C,OAAO,CAAA,EAAA,EAAK,KAAK,CAAA,CAAA;AAAA,KAChE,CAAA;AAAA,GACF;AACA,EAAA,MAAM,OAAO,MAAO,CAAA,IAAA,CAAA;AACpB,EAAA,MAAM,SAAQ,EAAO,GAAA,MAAA,CAAA,YAAA,CAAa,GAAI,CAAA,OAAO,MAA/B,IAAoC,GAAA,EAAA,GAAA,KAAA,CAAA,CAAA;AAClD,EAAA,MAAM,gBAAe,EAAO,GAAA,MAAA,CAAA,YAAA,CAAa,GAAI,CAAA,cAAc,MAAtC,IAA2C,GAAA,EAAA,GAAA,KAAA,CAAA,CAAA;AAChE,EAAA,MAAM,aAAY,EAAO,GAAA,MAAA,CAAA,YAAA,CAAa,GAAI,CAAA,WAAW,MAAnC,IAAwC,GAAA,EAAA,GAAA,KAAA,CAAA,CAAA;AAC1D,EAAA,MAAM,WAAU,EAAO,GAAA,MAAA,CAAA,YAAA,CAAa,GAAI,CAAA,SAAS,MAAjC,IAAsC,GAAA,EAAA,GAAA,KAAA,CAAA,CAAA;AAEtD,EAAA,MAAM,IAAO,GAAA,CAAA,EAAA,GAAA,YAAA,CAAa,MAAO,CAAA,IAAI,MAAxB,IAA2B,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,IAAA,CAAA;AAExC,EAAA,IAAI,CAAC,IAAM,EAAA;AACT,IAAA,MAAM,IAAIA,iBAAA;AAAA,MACR,kDAAkD,IAAI,CAAA,uCAAA,CAAA;AAAA,KACxD,CAAA;AAAA,GACF;AAEA,EAAA,MAAM,IAAe,GAAA,MAAA,CAAO,YAAa,CAAA,GAAA,CAAI,MAAM,CAAA,CAAA;AACnD,EAAA,QAAQ,IAAM;AAAA,IACZ,KAAK,WAAa,EAAA;AAChB,MAAA,IAAI,SAAS,mBAAqB,EAAA;AAChC,QAAA,mBAAA,CAAoB,QAAQ,WAAW,CAAA,CAAA;AAAA,OACzC;AACA,MAAoB,mBAAA,CAAA,MAAA,EAAQ,WAAW,MAAM,CAAA,CAAA;AAC7C,MAAA,MAAA;AAAA,KACF;AAAA,IACA,KAAK,QAAU,EAAA;AAEb,MAAA,IAAI,CAAC,OAAS,EAAA;AACZ,QAAoB,mBAAA,CAAA,MAAA,EAAQ,SAAS,MAAM,CAAA,CAAA;AAAA,OAC7C;AACA,MAAA,MAAA;AAAA,KACF;AAAA,IACA,KAAK,OAAS,EAAA;AACZ,MAAA,mBAAA,CAAoB,QAAQ,MAAM,CAAA,CAAA;AAClC,MAAA,MAAA;AAAA,KACF;AAAA,IACA,KAAK,QAAU,EAAA;AACb,MAAA,mBAAA,CAAoB,QAAQ,MAAM,CAAA,CAAA;AAClC,MAAA,MAAA;AAAA,KACF;AAAA,IACA,SAAS;AACP,MAAoB,mBAAA,CAAA,MAAA,EAAQ,QAAQ,OAAO,CAAA,CAAA;AAC3C,MAAA,MAAA;AAAA,KACF;AAAA,GACF;AAEA,EAAA,OAAO,EAAE,IAAM,EAAA,KAAA,EAAO,IAAM,EAAA,YAAA,EAAc,WAAW,OAAQ,EAAA,CAAA;AAC/D,EAAA;AAEA,SAAS,mBAAA,CAAoB,YAAiB,MAAkB,EAAA;AAC9D,EAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,MAAA,CAAO,QAAQ,CAAK,EAAA,EAAA;AACtC,IAAA,IAAI,CAAC,OAAQ,CAAA,YAAA,CAAa,IAAI,MAAO,CAAA,CAAC,CAAC,CAAG,EAAA;AACxC,MAAA,MAAM,IAAIA,iBAAA;AAAA,QACR,yCAAyC,OAAQ,CAAA,QAAA,EAAU,CACzD,UAAA,EAAA,MAAA,CAAO,CAAC,CACV,CAAA,CAAA;AAAA,OACF,CAAA;AAAA,KACF;AAAA,GACF;AACF;;AClGA,MAAM,qBAAA,GAAwB,CAAC,MAAA,EAAQ,OAAO,CAAA,CAAA;AAEjC,MAAA,YAAA,GAAe,CAAC,QAAiC,KAAA;AAC5D,EAAA,IAAI,CAAC,QAAU,EAAA;AACb,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AAEA,EAAA,MAAM,cAAiB,GAAA,EAAA,CAAA;AACvB,EAAA,MAAM,MAAM,QAAW,GAAA,cAAA,CAAA;AACvB,EAAA,OAAO,GAAM,GAAA,CAAA,CAAA;AACf,CAAA,CAAA;AAEA,eAAe,WAAA,CACb,OACA,QACc,EAAA;AACd,EAAA,MAAM,YAAY,MAAM,OAAA,CAAQ,IAAI,KAAM,CAAA,GAAA,CAAI,QAAQ,CAAC,CAAA,CAAA;AACvD,EAAA,OAAO,MAAM,MAAO,CAAA,CAAC,QAAQ,KAAU,KAAA,SAAA,CAAU,KAAK,CAAC,CAAA,CAAA;AACzD,CAAA;AAKsB,eAAA,0BAAA,CACpB,YACA,OAI2B,EAAA;AApD7B,EAAA,IAAA,EAAA,CAAA;AAqDE,EAAA,MAAM,QAAQ,MAAMK,uBAAA,CAAA,CAAO,EAAS,GAAA,OAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,OAAA,CAAA,YAAA,KAAT,YAAyB,qBAAuB,EAAA;AAAA,IACzE,GAAK,EAAA,UAAA;AAAA,IACL,GAAK,EAAA,IAAA;AAAA,IACL,WAAW,OAAS,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,OAAA,CAAA,SAAA;AAAA,IACpB,mBAAqB,EAAA,KAAA;AAAA;AAAA;AAAA,IAGrB,SAAW,EAAA,KAAA;AAAA,IACX,UAAY,EAAA,IAAA;AAAA,IACZ,KAAO,EAAA,IAAA;AAAA,GACR,CAAA,CAAA;AAED,EAAM,MAAA,OAAA,GAAUC,gCAAe,EAAE,CAAA,CAAA;AAEjC,EAAM,MAAA,KAAA,GAAQ,MAAM,WAAY,CAAA,KAAA,EAAO,OAAO,EAAE,MAAA,EAAQ,MAAW,KAAA;AACjE,IAAA,IAAI,OAAO,WAAY,EAAA;AAAG,MAAO,OAAA,KAAA,CAAA;AACjC,IAAI,IAAA,CAAC,OAAO,cAAe,EAAA;AAAG,MAAO,OAAA,IAAA,CAAA;AAErC,IAAM,MAAA,QAAA,GAAWT,kCAAqB,CAAA,UAAA,EAAY,IAAI,CAAA,CAAA;AAGtD,IAAI,IAAA;AACF,MAAM,MAAAE,aAAA,CAAG,KAAK,QAAQ,CAAA,CAAA;AACtB,MAAO,OAAA,KAAA,CAAA;AAAA,aACA,CAAG,EAAA;AACV,MAAA,OAAOQ,cAAQ,CAAA,CAAC,CAAK,IAAA,CAAA,CAAE,IAAS,KAAA,QAAA,CAAA;AAAA,KAClC;AAAA,GACD,CAAA,CAAA;AAED,EAAA,OAAO,OAAQ,CAAA,GAAA;AAAA,IACb,MAAM,GAAI,CAAA,OAAO,EAAE,MAAQ,EAAA,IAAA,EAAM,OAAa,MAAA;AAAA,MAC5C,IAAA;AAAA,MACA,OAAA,EAAS,MAAM,OAAA,CAAQ,YAAY;AACjC,QAAM,MAAA,WAAA,GAAcV,kCAAqB,CAAA,UAAA,EAAY,IAAI,CAAA,CAAA;AACzD,QAAI,IAAA,MAAA,CAAO,gBAAkB,EAAA;AAC3B,UAAO,OAAAE,aAAA,CAAG,QAAS,CAAA,WAAA,EAAa,QAAQ,CAAA,CAAA;AAAA,SAC1C;AACA,QAAO,OAAAA,aAAA,CAAG,SAAS,WAAW,CAAA,CAAA;AAAA,OAC/B,CAAA;AAAA,MACD,UAAA,EAAY,YAAa,CAAA,KAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,KAAA,CAAO,IAAI,CAAA;AAAA,MACpC,OAAA,EAAS,OAAO,cAAe,EAAA;AAAA,KAC/B,CAAA,CAAA;AAAA,GACJ,CAAA;AACF;;ACnEsB,eAAA,4BAAA,CACpB,YACA,KACe,EAAA;AACf,EAAA,KAAA,MAAW,QAAQ,KAAO,EAAA;AACxB,IAAA,MAAM,QAAW,GAAAF,kCAAA,CAAqB,UAAY,EAAA,IAAA,CAAK,IAAI,CAAA,CAAA;AAC3D,IAAA,MAAME,mBAAG,CAAA,SAAA,CAAUS,YAAQ,CAAA,QAAQ,CAAC,CAAA,CAAA;AACpC,IAAA,MAAMT,mBAAG,CAAA,SAAA,CAAU,QAAU,EAAA,IAAA,CAAK,OAAO,CAAA,CAAA;AAAA,GAC3C;AACF;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/actions/createTemplateAction.ts","../src/actions/executeShellCommand.ts","../src/actions/fetch.ts","../src/scm/git.ts","../src/actions/gitHelpers.ts","../src/actions/util.ts","../src/files/serializeDirectoryContents.ts","../src/files/deserializeDirectoryContents.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 { ActionContext, TemplateAction } from './types';\nimport { z } from 'zod';\nimport { Schema } from 'jsonschema';\nimport zodToJsonSchema from 'zod-to-json-schema';\nimport { JsonObject } from '@backstage/types';\n\n/** @public */\nexport type TemplateExample = {\n description: string;\n example: string;\n};\n\n/** @public */\nexport type TemplateActionOptions<\n TActionInput extends JsonObject = {},\n TActionOutput extends JsonObject = {},\n TInputSchema extends Schema | z.ZodType = {},\n TOutputSchema extends Schema | z.ZodType = {},\n> = {\n id: string;\n description?: string;\n examples?: TemplateExample[];\n supportsDryRun?: boolean;\n schema?: {\n input?: TInputSchema;\n output?: TOutputSchema;\n };\n handler: (ctx: ActionContext<TActionInput, TActionOutput>) => Promise<void>;\n};\n\n/**\n * This function is used to create new template actions to get type safety.\n * Will convert zod schemas to json schemas for use throughout the system.\n * @public\n */\nexport const createTemplateAction = <\n TInputParams extends JsonObject = JsonObject,\n TOutputParams extends JsonObject = JsonObject,\n TInputSchema extends Schema | z.ZodType = {},\n TOutputSchema extends Schema | z.ZodType = {},\n TActionInput extends JsonObject = TInputSchema extends z.ZodType<\n any,\n any,\n infer IReturn\n >\n ? IReturn\n : TInputParams,\n TActionOutput extends JsonObject = TOutputSchema extends z.ZodType<\n any,\n any,\n infer IReturn\n >\n ? IReturn\n : TOutputParams,\n>(\n action: TemplateActionOptions<\n TActionInput,\n TActionOutput,\n TInputSchema,\n TOutputSchema\n >,\n): TemplateAction<TActionInput, TActionOutput> => {\n const inputSchema =\n action.schema?.input && 'safeParseAsync' in action.schema.input\n ? zodToJsonSchema(action.schema.input)\n : action.schema?.input;\n\n const outputSchema =\n action.schema?.output && 'safeParseAsync' in action.schema.output\n ? zodToJsonSchema(action.schema.output)\n : action.schema?.output;\n\n return {\n ...action,\n schema: {\n ...action.schema,\n input: inputSchema as TInputSchema,\n output: outputSchema as TOutputSchema,\n },\n };\n};\n","/*\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 { spawn, SpawnOptionsWithoutStdio } from 'child_process';\nimport { PassThrough, Writable } from 'stream';\n\n/**\n * Options for {@link executeShellCommand}.\n *\n * @public\n */\nexport type ExecuteShellCommandOptions = {\n /** command to run */\n command: string;\n /** arguments to pass the command */\n args: string[];\n /** options to pass to spawn */\n options?: SpawnOptionsWithoutStdio;\n /** stream to capture stdout and stderr output */\n logStream?: Writable;\n};\n\n/**\n * Run a command in a sub-process, normally a shell command.\n *\n * @public\n */\nexport async function executeShellCommand(\n options: ExecuteShellCommandOptions,\n): Promise<void> {\n const {\n command,\n args,\n options: spawnOptions,\n logStream = new PassThrough(),\n } = options;\n\n await new Promise<void>((resolve, reject) => {\n const process = spawn(command, args, spawnOptions);\n\n process.stdout.on('data', stream => {\n logStream.write(stream);\n });\n\n process.stderr.on('data', stream => {\n logStream.write(stream);\n });\n\n process.on('error', error => {\n return reject(error);\n });\n\n process.on('close', code => {\n if (code !== 0) {\n return reject(\n new Error(`Command ${command} failed, exit code: ${code}`),\n );\n }\n return resolve();\n });\n });\n}\n","/*\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 { UrlReader } from '@backstage/backend-common';\nimport { resolveSafeChildPath } from '@backstage/backend-plugin-api';\nimport { InputError } from '@backstage/errors';\nimport { ScmIntegrations } from '@backstage/integration';\nimport fs from 'fs-extra';\nimport path from 'path';\n\n/**\n * A helper function that reads the contents of a directory from the given URL.\n * Can be used in your own actions, and also used behind fetch:template and fetch:plain\n *\n * @public\n */\nexport async function fetchContents(options: {\n reader: UrlReader;\n integrations: ScmIntegrations;\n baseUrl?: string;\n fetchUrl?: string;\n outputPath: string;\n token?: string;\n}) {\n const {\n reader,\n integrations,\n baseUrl,\n fetchUrl = '.',\n outputPath,\n token,\n } = options;\n\n const fetchUrlIsAbsolute = isFetchUrlAbsolute(fetchUrl);\n\n // We handle both file locations and url ones\n if (!fetchUrlIsAbsolute && baseUrl?.startsWith('file://')) {\n const basePath = baseUrl.slice('file://'.length);\n const srcDir = resolveSafeChildPath(path.dirname(basePath), fetchUrl);\n await fs.copy(srcDir, outputPath);\n } else {\n const readUrl = getReadUrl(fetchUrl, baseUrl, integrations);\n\n const res = await reader.readTree(readUrl, { token });\n await fs.ensureDir(outputPath);\n await res.dir({ targetDir: outputPath });\n }\n}\n\n/**\n * A helper function that reads the content of a single file from the given URL.\n * Can be used in your own actions, and also used behind `fetch:plain:file`\n *\n * @public\n */\nexport async function fetchFile(options: {\n reader: UrlReader;\n integrations: ScmIntegrations;\n baseUrl?: string;\n fetchUrl?: string;\n outputPath: string;\n token?: string;\n}) {\n const {\n reader,\n integrations,\n baseUrl,\n fetchUrl = '.',\n outputPath,\n token,\n } = options;\n\n const fetchUrlIsAbsolute = isFetchUrlAbsolute(fetchUrl);\n\n // We handle both file locations and url ones\n if (!fetchUrlIsAbsolute && baseUrl?.startsWith('file://')) {\n const basePath = baseUrl.slice('file://'.length);\n const src = resolveSafeChildPath(path.dirname(basePath), fetchUrl);\n await fs.copyFile(src, outputPath);\n } else {\n const readUrl = getReadUrl(fetchUrl, baseUrl, integrations);\n\n const res = await reader.readUrl(readUrl, { token });\n await fs.ensureDir(path.dirname(outputPath));\n const buffer = await res.buffer();\n await fs.outputFile(outputPath, buffer);\n }\n}\n\nfunction isFetchUrlAbsolute(fetchUrl: string) {\n let fetchUrlIsAbsolute = false;\n try {\n // eslint-disable-next-line no-new\n new URL(fetchUrl);\n fetchUrlIsAbsolute = true;\n } catch {\n /* ignored */\n }\n return fetchUrlIsAbsolute;\n}\n\nfunction getReadUrl(\n fetchUrl: string,\n baseUrl: string | undefined,\n integrations: ScmIntegrations,\n) {\n if (isFetchUrlAbsolute(fetchUrl)) {\n return fetchUrl;\n } else if (baseUrl) {\n const integration = integrations.byUrl(baseUrl);\n if (!integration) {\n throw new InputError(`No integration found for location ${baseUrl}`);\n }\n\n return integration.resolveUrl({\n url: fetchUrl,\n base: baseUrl,\n });\n }\n throw new InputError(\n `Failed to fetch, template location could not be determined and the fetch URL is relative, ${fetchUrl}`,\n );\n}\n","/*\n * Copyright 2020 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 git, {\n ProgressCallback,\n MergeResult,\n ReadCommitResult,\n AuthCallback,\n} from 'isomorphic-git';\nimport http from 'isomorphic-git/http/node';\nimport fs from 'fs-extra';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\nfunction isAuthCallbackOptions(\n options: StaticAuthOptions | AuthCallbackOptions,\n): options is AuthCallbackOptions {\n return 'onAuth' in options;\n}\n\n/**\n * Configure static credential for authentication\n *\n * @public\n */\nexport type StaticAuthOptions = {\n username?: string;\n password?: string;\n token?: string;\n logger?: LoggerService;\n};\n\n/**\n * Configure an authentication callback that can provide credentials on demand\n *\n * @public\n */\nexport type AuthCallbackOptions = {\n onAuth: AuthCallback;\n logger?: LoggerService;\n};\n\n/*\nprovider username password\nAzure 'notempty' token\nBitbucket Cloud 'x-token-auth' token\nBitbucket Server username password or token\nGitHub 'x-access-token' token\nGitLab 'oauth2' token\n\nFrom : https://isomorphic-git.org/docs/en/onAuth with fix for GitHub\n\nOr token provided as `token` for Bearer auth header\ninstead of Basic Auth (e.g., Bitbucket Server).\n*/\n\n/**\n * A convenience wrapper around the `isomorphic-git` library.\n *\n * @public\n */\n\nexport class Git {\n private readonly headers: {\n [x: string]: string;\n };\n\n private constructor(\n private readonly config: {\n onAuth: AuthCallback;\n token?: string;\n logger?: LoggerService;\n },\n ) {\n this.onAuth = config.onAuth;\n\n this.headers = {\n 'user-agent': 'git/@isomorphic-git',\n ...(config.token ? { Authorization: `Bearer ${config.token}` } : {}),\n };\n }\n\n async add(options: { dir: string; filepath: string }): Promise<void> {\n const { dir, filepath } = options;\n this.config.logger?.info(`Adding file {dir=${dir},filepath=${filepath}}`);\n\n return git.add({ fs, dir, filepath });\n }\n\n async addRemote(options: {\n dir: string;\n remote: string;\n url: string;\n force?: boolean;\n }): Promise<void> {\n const { dir, url, remote, force } = options;\n this.config.logger?.info(\n `Creating new remote {dir=${dir},remote=${remote},url=${url}}`,\n );\n return git.addRemote({ fs, dir, remote, url, force });\n }\n\n async deleteRemote(options: { dir: string; remote: string }): Promise<void> {\n const { dir, remote } = options;\n this.config.logger?.info(`Deleting remote {dir=${dir},remote=${remote}}`);\n return git.deleteRemote({ fs, dir, remote });\n }\n\n async checkout(options: { dir: string; ref: string }): Promise<void> {\n const { dir, ref } = options;\n this.config.logger?.info(`Checking out branch {dir=${dir},ref=${ref}}`);\n\n return git.checkout({ fs, dir, ref });\n }\n\n async branch(options: { dir: string; ref: string }): Promise<void> {\n const { dir, ref } = options;\n this.config.logger?.info(`Creating branch {dir=${dir},ref=${ref}`);\n\n return git.branch({ fs, dir, ref });\n }\n\n async commit(options: {\n dir: string;\n message: string;\n author: { name: string; email: string };\n committer: { name: string; email: string };\n }): Promise<string> {\n const { dir, message, author, committer } = options;\n this.config.logger?.info(\n `Committing file to repo {dir=${dir},message=${message}}`,\n );\n return git.commit({ fs, dir, message, author, committer });\n }\n\n /** https://isomorphic-git.org/docs/en/clone */\n async clone(options: {\n url: string;\n dir: string;\n ref?: string;\n depth?: number;\n noCheckout?: boolean;\n }): Promise<void> {\n const { url, dir, ref, depth, noCheckout } = options;\n this.config.logger?.info(`Cloning repo {dir=${dir},url=${url}}`);\n\n try {\n return await git.clone({\n fs,\n http,\n url,\n dir,\n ref,\n singleBranch: true,\n depth: depth ?? 1,\n noCheckout,\n onProgress: this.onProgressHandler(),\n headers: this.headers,\n onAuth: this.onAuth,\n });\n } catch (ex) {\n this.config.logger?.error(`Failed to clone repo {dir=${dir},url=${url}}`);\n if (ex.data) {\n throw new Error(`${ex.message} {data=${JSON.stringify(ex.data)}}`);\n }\n throw ex;\n }\n }\n\n /** https://isomorphic-git.org/docs/en/currentBranch */\n async currentBranch(options: {\n dir: string;\n fullName?: boolean;\n }): Promise<string | undefined> {\n const { dir, fullName = false } = options;\n return git.currentBranch({ fs, dir, fullname: fullName }) as Promise<\n string | undefined\n >;\n }\n\n /** https://isomorphic-git.org/docs/en/fetch */\n async fetch(options: {\n dir: string;\n remote?: string;\n tags?: boolean;\n }): Promise<void> {\n const { dir, remote = 'origin', tags = false } = options;\n this.config.logger?.info(\n `Fetching remote=${remote} for repository {dir=${dir}}`,\n );\n\n try {\n await git.fetch({\n fs,\n http,\n dir,\n remote,\n tags,\n onProgress: this.onProgressHandler(),\n headers: this.headers,\n onAuth: this.onAuth,\n });\n } catch (ex) {\n this.config.logger?.error(\n `Failed to fetch repo {dir=${dir},remote=${remote}}`,\n );\n if (ex.data) {\n throw new Error(`${ex.message} {data=${JSON.stringify(ex.data)}}`);\n }\n throw ex;\n }\n }\n\n async init(options: { dir: string; defaultBranch?: string }): Promise<void> {\n const { dir, defaultBranch = 'master' } = options;\n this.config.logger?.info(`Init git repository {dir=${dir}}`);\n\n return git.init({\n fs,\n dir,\n defaultBranch,\n });\n }\n\n /** https://isomorphic-git.org/docs/en/merge */\n async merge(options: {\n dir: string;\n theirs: string;\n ours?: string;\n author: { name: string; email: string };\n committer: { name: string; email: string };\n }): Promise<MergeResult> {\n const { dir, theirs, ours, author, committer } = options;\n this.config.logger?.info(\n `Merging branch '${theirs}' into '${ours}' for repository {dir=${dir}}`,\n );\n\n // If ours is undefined, current branch is used.\n return git.merge({\n fs,\n dir,\n ours,\n theirs,\n author,\n committer,\n });\n }\n\n async push(options: {\n dir: string;\n remote: string;\n remoteRef?: string;\n force?: boolean;\n }) {\n const { dir, remote, remoteRef, force } = options;\n this.config.logger?.info(\n `Pushing directory to remote {dir=${dir},remote=${remote}}`,\n );\n try {\n return await git.push({\n fs,\n dir,\n http,\n onProgress: this.onProgressHandler(),\n remoteRef,\n force,\n headers: this.headers,\n remote,\n onAuth: this.onAuth,\n });\n } catch (ex) {\n this.config.logger?.error(\n `Failed to push to repo {dir=${dir}, remote=${remote}}`,\n );\n if (ex.data) {\n throw new Error(`${ex.message} {data=${JSON.stringify(ex.data)}}`);\n }\n throw ex;\n }\n }\n\n /** https://isomorphic-git.org/docs/en/readCommit */\n async readCommit(options: {\n dir: string;\n sha: string;\n }): Promise<ReadCommitResult> {\n const { dir, sha } = options;\n return git.readCommit({ fs, dir, oid: sha });\n }\n\n /** https://isomorphic-git.org/docs/en/remove */\n async remove(options: { dir: string; filepath: string }): Promise<void> {\n const { dir, filepath } = options;\n this.config.logger?.info(\n `Removing file from git index {dir=${dir},filepath=${filepath}}`,\n );\n return git.remove({ fs, dir, filepath });\n }\n\n /** https://isomorphic-git.org/docs/en/resolveRef */\n async resolveRef(options: { dir: string; ref: string }): Promise<string> {\n const { dir, ref } = options;\n return git.resolveRef({ fs, dir, ref });\n }\n\n /** https://isomorphic-git.org/docs/en/log */\n async log(options: {\n dir: string;\n ref?: string;\n }): Promise<ReadCommitResult[]> {\n const { dir, ref } = options;\n return git.log({\n fs,\n dir,\n ref: ref ?? 'HEAD',\n });\n }\n\n private onAuth: AuthCallback;\n\n private onProgressHandler = (): ProgressCallback => {\n let currentPhase = '';\n\n return event => {\n if (currentPhase !== event.phase) {\n currentPhase = event.phase;\n this.config.logger?.info(event.phase);\n }\n const total = event.total\n ? `${Math.round((event.loaded / event.total) * 100)}%`\n : event.loaded;\n this.config.logger?.debug(`status={${event.phase},total={${total}}}`);\n };\n };\n\n static fromAuth = (options: StaticAuthOptions | AuthCallbackOptions) => {\n if (isAuthCallbackOptions(options)) {\n const { onAuth, logger } = options;\n return new Git({ onAuth, logger });\n }\n\n const { username, password, token, logger } = options;\n return new Git({ onAuth: () => ({ username, password }), token, logger });\n };\n}\n","/*\n * Copyright 2023 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 { Logger } from 'winston';\nimport { Git } from '../scm';\n\n/**\n * @public\n */\nexport async function initRepoAndPush(input: {\n dir: string;\n remoteUrl: string;\n // For use cases where token has to be used with Basic Auth\n // it has to be provided as password together with a username\n // which may be a fixed value defined by the provider.\n auth: { username: string; password: string } | { token: string };\n logger: Logger;\n defaultBranch?: string;\n commitMessage?: string;\n gitAuthorInfo?: { name?: string; email?: string };\n}): Promise<{ commitHash: string }> {\n const {\n dir,\n remoteUrl,\n auth,\n logger,\n defaultBranch = 'master',\n commitMessage = 'Initial commit',\n gitAuthorInfo,\n } = input;\n const git = Git.fromAuth({\n ...auth,\n logger,\n });\n\n await git.init({\n dir,\n defaultBranch,\n });\n\n await git.add({ dir, filepath: '.' });\n\n // use provided info if possible, otherwise use fallbacks\n const authorInfo = {\n name: gitAuthorInfo?.name ?? 'Scaffolder',\n email: gitAuthorInfo?.email ?? 'scaffolder@backstage.io',\n };\n\n const commitHash = await git.commit({\n dir,\n message: commitMessage,\n author: authorInfo,\n committer: authorInfo,\n });\n await git.addRemote({\n dir,\n url: remoteUrl,\n remote: 'origin',\n });\n\n await git.push({\n dir,\n remote: 'origin',\n });\n\n return { commitHash };\n}\n\n/**\n * @public\n */\nexport async function commitAndPushRepo(input: {\n dir: string;\n // For use cases where token has to be used with Basic Auth\n // it has to be provided as password together with a username\n // which may be a fixed value defined by the provider.\n auth: { username: string; password: string } | { token: string };\n logger: Logger;\n commitMessage: string;\n gitAuthorInfo?: { name?: string; email?: string };\n branch?: string;\n remoteRef?: string;\n}): Promise<{ commitHash: string }> {\n const {\n dir,\n auth,\n logger,\n commitMessage,\n gitAuthorInfo,\n branch = 'master',\n remoteRef,\n } = input;\n\n const git = Git.fromAuth({\n ...auth,\n logger,\n });\n\n await git.fetch({ dir });\n await git.checkout({ dir, ref: branch });\n await git.add({ dir, filepath: '.' });\n\n // use provided info if possible, otherwise use fallbacks\n const authorInfo = {\n name: gitAuthorInfo?.name ?? 'Scaffolder',\n email: gitAuthorInfo?.email ?? 'scaffolder@backstage.io',\n };\n\n const commitHash = await git.commit({\n dir,\n message: commitMessage,\n author: authorInfo,\n committer: authorInfo,\n });\n\n await git.push({\n dir,\n remote: 'origin',\n remoteRef: remoteRef ?? `refs/heads/${branch}`,\n });\n\n return { commitHash };\n}\n\n/**\n * @public\n */\nexport async function cloneRepo(options: {\n url: string;\n dir: string;\n // For use cases where token has to be used with Basic Auth\n // it has to be provided as password together with a username\n // which may be a fixed value defined by the provider.\n auth: { username: string; password: string } | { token: string };\n logger?: Logger | undefined;\n ref?: string | undefined;\n depth?: number | undefined;\n noCheckout?: boolean | undefined;\n}): Promise<void> {\n const { url, dir, auth, logger, ref, depth, noCheckout } = options;\n\n const git = Git.fromAuth({\n ...auth,\n logger,\n });\n\n await git.clone({ url, dir, ref, depth, noCheckout });\n}\n\n/**\n * @public\n */\nexport async function createBranch(options: {\n dir: string;\n ref: string;\n // For use cases where token has to be used with Basic Auth\n // it has to be provided as password together with a username\n // which may be a fixed value defined by the provider.\n auth: { username: string; password: string } | { token: string };\n logger?: Logger | undefined;\n}): Promise<void> {\n const { dir, ref, auth, logger } = options;\n const git = Git.fromAuth({\n ...auth,\n logger,\n });\n\n await git.checkout({ dir, ref });\n}\n\n/**\n * @public\n */\nexport async function addFiles(options: {\n dir: string;\n filepath: string;\n // For use cases where token has to be used with Basic Auth\n // it has to be provided as password together with a username\n // which may be a fixed value defined by the provider.\n auth: { username: string; password: string } | { token: string };\n logger?: Logger | undefined;\n}): Promise<void> {\n const { dir, filepath, auth, logger } = options;\n const git = Git.fromAuth({\n ...auth,\n logger,\n });\n\n await git.add({ dir, filepath });\n}\n\n/**\n * @public\n */\nexport async function commitAndPushBranch(options: {\n dir: string;\n // For use cases where token has to be used with Basic Auth\n // it has to be provided as password together with a username\n // which may be a fixed value defined by the provider.\n auth: { username: string; password: string } | { token: string };\n logger?: Logger | undefined;\n commitMessage: string;\n gitAuthorInfo?: { name?: string; email?: string };\n branch?: string;\n remoteRef?: string;\n remote?: string;\n}): Promise<{ commitHash: string }> {\n const {\n dir,\n auth,\n logger,\n commitMessage,\n gitAuthorInfo,\n branch = 'master',\n remoteRef,\n remote = 'origin',\n } = options;\n const git = Git.fromAuth({\n ...auth,\n logger,\n });\n\n // use provided info if possible, otherwise use fallbacks\n const authorInfo = {\n name: gitAuthorInfo?.name ?? 'Scaffolder',\n email: gitAuthorInfo?.email ?? 'scaffolder@backstage.io',\n };\n\n const commitHash = await git.commit({\n dir,\n message: commitMessage,\n author: authorInfo,\n committer: authorInfo,\n });\n\n await git.push({\n dir,\n remote,\n remoteRef: remoteRef ?? `refs/heads/${branch}`,\n });\n\n return { commitHash };\n}\n","/*\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 { InputError } from '@backstage/errors';\nimport { isChildPath } from '@backstage/backend-plugin-api';\nimport { join as joinPath, normalize as normalizePath } from 'path';\nimport { ScmIntegrationRegistry } from '@backstage/integration';\n\n/**\n * @public\n */\nexport const getRepoSourceDirectory = (\n workspacePath: string,\n sourcePath: string | undefined,\n) => {\n if (sourcePath) {\n const safeSuffix = normalizePath(sourcePath).replace(\n /^(\\.\\.(\\/|\\\\|$))+/,\n '',\n );\n const path = joinPath(workspacePath, safeSuffix);\n if (!isChildPath(workspacePath, path)) {\n throw new Error('Invalid source path');\n }\n return path;\n }\n return workspacePath;\n};\n\n/**\n * @public\n */\nexport const parseRepoUrl = (\n repoUrl: string,\n integrations: ScmIntegrationRegistry,\n): {\n repo: string;\n host: string;\n owner?: string;\n organization?: string;\n workspace?: string;\n project?: string;\n} => {\n let parsed;\n try {\n parsed = new URL(`https://${repoUrl}`);\n } catch (error) {\n throw new InputError(\n `Invalid repo URL passed to publisher, got ${repoUrl}, ${error}`,\n );\n }\n const host = parsed.host;\n const owner = parsed.searchParams.get('owner') ?? undefined;\n const organization = parsed.searchParams.get('organization') ?? undefined;\n const workspace = parsed.searchParams.get('workspace') ?? undefined;\n const project = parsed.searchParams.get('project') ?? undefined;\n\n const type = integrations.byHost(host)?.type;\n\n if (!type) {\n throw new InputError(\n `No matching integration configuration for host ${host}, please check your integrations config`,\n );\n }\n\n const repo: string = parsed.searchParams.get('repo')!;\n switch (type) {\n case 'bitbucket': {\n if (host === 'www.bitbucket.org') {\n checkRequiredParams(parsed, 'workspace');\n }\n checkRequiredParams(parsed, 'project', 'repo');\n break;\n }\n case 'gitlab': {\n // project is the projectID, and if defined, owner and repo won't be needed.\n if (!project) {\n checkRequiredParams(parsed, 'owner', 'repo');\n }\n break;\n }\n case 'gitea': {\n checkRequiredParams(parsed, 'repo');\n break;\n }\n case 'gerrit': {\n checkRequiredParams(parsed, 'repo');\n break;\n }\n default: {\n checkRequiredParams(parsed, 'repo', 'owner');\n break;\n }\n }\n\n return { host, owner, repo, organization, workspace, project };\n};\n\nfunction checkRequiredParams(repoUrl: URL, ...params: string[]) {\n for (let i = 0; i < params.length; i++) {\n if (!repoUrl.searchParams.get(params[i])) {\n throw new InputError(\n `Invalid repo URL passed to publisher: ${repoUrl.toString()}, missing ${\n params[i]\n }`,\n );\n }\n }\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { promises as fs } from 'fs';\nimport globby from 'globby';\nimport limiterFactory from 'p-limit';\nimport { resolveSafeChildPath } from '@backstage/backend-plugin-api';\nimport { SerializedFile } from './types';\nimport { isError } from '@backstage/errors';\n\nconst DEFAULT_GLOB_PATTERNS = ['./**', '!.git'];\n\nexport const isExecutable = (fileMode: number | undefined) => {\n if (!fileMode) {\n return false;\n }\n\n const executeBitMask = 0o000111;\n const res = fileMode & executeBitMask;\n return res > 0;\n};\n\nasync function asyncFilter<T>(\n array: T[],\n callback: (value: T, index: number, array: T[]) => Promise<boolean>,\n): Promise<T[]> {\n const filterMap = await Promise.all(array.map(callback));\n return array.filter((_value, index) => filterMap[index]);\n}\n\n/**\n * @public\n */\nexport async function serializeDirectoryContents(\n sourcePath: string,\n options?: {\n gitignore?: boolean;\n globPatterns?: string[];\n },\n): Promise<SerializedFile[]> {\n const paths = await globby(options?.globPatterns ?? DEFAULT_GLOB_PATTERNS, {\n cwd: sourcePath,\n dot: true,\n gitignore: options?.gitignore,\n followSymbolicLinks: false,\n // In order to pick up 'broken' symlinks, we oxymoronically request files AND folders yet we filter out folders\n // This is because broken symlinks aren't classed as files so we need to glob everything\n onlyFiles: false,\n objectMode: true,\n stats: true,\n });\n\n const limiter = limiterFactory(10);\n\n const valid = await asyncFilter(paths, async ({ dirent, path }) => {\n if (dirent.isDirectory()) return false;\n if (!dirent.isSymbolicLink()) return true;\n\n const safePath = resolveSafeChildPath(sourcePath, path);\n\n // we only want files that don't exist\n try {\n await fs.stat(safePath);\n return false;\n } catch (e) {\n return isError(e) && e.code === 'ENOENT';\n }\n });\n\n return Promise.all(\n valid.map(async ({ dirent, path, stats }) => ({\n path,\n content: await limiter(async () => {\n const absFilePath = resolveSafeChildPath(sourcePath, path);\n if (dirent.isSymbolicLink()) {\n return fs.readlink(absFilePath, 'buffer');\n }\n return fs.readFile(absFilePath);\n }),\n executable: isExecutable(stats?.mode),\n symlink: dirent.isSymbolicLink(),\n })),\n );\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport fs from 'fs-extra';\nimport { dirname } from 'path';\nimport { resolveSafeChildPath } from '@backstage/backend-plugin-api';\nimport { SerializedFile } from './types';\n\n/**\n * Deserializes a list of serialized files into the target directory.\n *\n * This method uses `resolveSafeChildPath` to make sure that files are\n * not written outside of the target directory.\n *\n * @public\n */\nexport async function deserializeDirectoryContents(\n targetPath: string,\n files: SerializedFile[],\n): Promise<void> {\n for (const file of files) {\n const filePath = resolveSafeChildPath(targetPath, file.path);\n await fs.ensureDir(dirname(filePath));\n await fs.writeFile(filePath, file.content); // Ignore file mode\n }\n}\n"],"names":["zodToJsonSchema","PassThrough","spawn","resolveSafeChildPath","path","fs","InputError","git","http","logger","normalizePath","joinPath","isChildPath","globby","limiterFactory","isError","dirname"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-scaffolder-node",
3
- "version": "0.4.4-next.2",
3
+ "version": "0.4.5-next.0",
4
4
  "description": "The plugin-scaffolder-node module for @backstage/plugin-scaffolder-backend",
5
5
  "backstage": {
6
6
  "role": "node-library"
@@ -44,15 +44,16 @@
44
44
  "test": "backstage-cli package test"
45
45
  },
46
46
  "dependencies": {
47
- "@backstage/backend-common": "^0.22.0-next.2",
48
- "@backstage/backend-plugin-api": "^0.6.18-next.1",
49
- "@backstage/catalog-model": "^1.5.0-next.0",
47
+ "@backstage/backend-common": "^0.22.1-next.0",
48
+ "@backstage/backend-plugin-api": "^0.6.19-next.0",
49
+ "@backstage/catalog-model": "^1.5.0",
50
50
  "@backstage/errors": "^1.2.4",
51
- "@backstage/integration": "^1.11.0-next.0",
52
- "@backstage/plugin-scaffolder-common": "^1.5.2-next.1",
51
+ "@backstage/integration": "^1.11.0",
52
+ "@backstage/plugin-scaffolder-common": "^1.5.2",
53
53
  "@backstage/types": "^1.1.1",
54
54
  "fs-extra": "^11.2.0",
55
55
  "globby": "^11.0.0",
56
+ "isomorphic-git": "^1.23.0",
56
57
  "jsonschema": "^1.2.6",
57
58
  "p-limit": "^3.1.0",
58
59
  "winston": "^3.2.1",
@@ -60,8 +61,8 @@
60
61
  "zod-to-json-schema": "^3.20.4"
61
62
  },
62
63
  "devDependencies": {
63
- "@backstage/backend-test-utils": "^0.3.8-next.2",
64
- "@backstage/cli": "^0.26.5-next.1",
64
+ "@backstage/backend-test-utils": "^0.3.9-next.0",
65
+ "@backstage/cli": "^0.26.6-next.0",
65
66
  "@backstage/config": "^1.2.0"
66
67
  }
67
68
  }