extension-create 4.0.15 → 4.0.16

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/README.md CHANGED
@@ -2,8 +2,8 @@
2
2
  [npm-version-url]: https://www.npmjs.com/package/extension-create
3
3
  [npm-downloads-image]: https://img.shields.io/npm/dm/extension-create.svg?color=0971fe
4
4
  [npm-downloads-url]: https://www.npmjs.com/package/extension-create
5
- [action-image]: https://github.com/extension-js/create/actions/workflows/ci.yml/badge.svg?branch=main
6
- [action-url]: https://github.com/extension-js/create/actions/workflows/ci.yml
5
+ [action-image]: https://github.com/extension-js/extension.js/actions/workflows/ci.yml/badge.svg?branch=main
6
+ [action-url]: https://github.com/extension-js/extension.js/actions/workflows/ci.yml
7
7
 
8
8
  [![Version][npm-version-image]][npm-version-url] [![Downloads][npm-downloads-image]][npm-downloads-url] [![CI][action-image]][action-url]
9
9
 
@@ -26,6 +26,8 @@ export declare function writingPackageJsonMetadata(): string;
26
26
  export declare function writingPackageJsonMetadataError(projectName: string, error: unknown): string;
27
27
  export declare function writingDenoJsonc(): string;
28
28
  export declare function writingDenoJsoncError(projectName: string, error: unknown): string;
29
+ export declare function writingTemplateProvenance(): string;
30
+ export declare function writingTemplateProvenanceError(error: unknown): string;
29
31
  export declare function writingManifestJsonMetadata(): string;
30
32
  export declare function writingManifestJsonMetadataError(projectName: string, error: unknown): string;
31
33
  export declare function writingReadmeMetaData(): string;
package/dist/module.cjs CHANGED
@@ -178,6 +178,12 @@ function writingDenoJsonc() {
178
178
  function writingDenoJsoncError(projectName, error) {
179
179
  return `${external_pintor_default().red('Error')} Couldn't write ${external_pintor_default().yellow('deno.jsonc')} for ${external_pintor_default().blue(projectName)}.\n${external_pintor_default().red(String(error))}\n${external_pintor_default().red('Next step: check file permissions, then try again.')}`;
180
180
  }
181
+ function writingTemplateProvenance() {
182
+ return `${statusPrefix} Writing ${external_pintor_default().yellow('.extension-create.json')}...`;
183
+ }
184
+ function writingTemplateProvenanceError(error) {
185
+ return `${external_pintor_default().red('Warning')} Couldn't write ${external_pintor_default().yellow('.extension-create.json')} provenance (non-fatal).\n${external_pintor_default().red(String(error))}`;
186
+ }
181
187
  function writingManifestJsonMetadata() {
182
188
  return `${statusPrefix} Writing ${external_pintor_default().yellow('manifest.json')}...`;
183
189
  }
@@ -361,7 +367,22 @@ const NETWORK_TIMEOUT_MS = (()=>{
361
367
  const raw = parseInt(String(process.env.EXTENSION_CREATE_TIMEOUT_MS || ''), 10);
362
368
  return Number.isFinite(raw) && raw > 0 ? raw : 60000;
363
369
  })();
364
- const EXAMPLES_REF = process.env.EXTENSION_CREATE_TEMPLATE_REF || 'main';
370
+ const CODELOAD_BASE = 'https://codeload.github.com/extension-js/examples/zip';
371
+ function resolveCatalogUrls(ref, overrideUrl) {
372
+ if (overrideUrl) return [
373
+ overrideUrl
374
+ ];
375
+ if (/^refs\/(heads|tags)\//.test(ref)) return [
376
+ `${CODELOAD_BASE}/${ref}`
377
+ ];
378
+ if (/^[0-9a-f]{40}$/i.test(ref)) return [
379
+ `${CODELOAD_BASE}/${ref}`
380
+ ];
381
+ const urls = [];
382
+ if (/^[0-9a-f]{7,39}$/i.test(ref)) urls.push(`${CODELOAD_BASE}/${ref}`);
383
+ urls.push(`${CODELOAD_BASE}/refs/heads/${ref}`, `${CODELOAD_BASE}/refs/tags/${ref}`);
384
+ return urls;
385
+ }
365
386
  class TemplateNotFoundError extends Error {
366
387
  constructor(templateName, cause){
367
388
  super(`template not found in catalog: ${templateName}`), _define_property(this, "templateName", void 0);
@@ -394,7 +415,10 @@ async function downloadArchive(url, timeoutMs, attempts = 2) {
394
415
  return Buffer.from(data);
395
416
  } catch (error) {
396
417
  lastError = error;
397
- if (attempt < attempts) await sleep(400 * attempt);
418
+ const status = error?.response?.status;
419
+ const retriable = void 0 === status || 429 === status || status >= 500;
420
+ if (attempt >= attempts || !retriable) break;
421
+ await sleep(400 * attempt);
398
422
  }
399
423
  throw lastError;
400
424
  }
@@ -420,14 +444,25 @@ async function extractExamplesTemplateFromZip(zipBuffer, templateName, projectPa
420
444
  return written;
421
445
  }
422
446
  async function importFromExamplesCatalog(templateName, projectPath) {
423
- const url = `https://codeload.github.com/extension-js/examples/zip/refs/heads/${EXAMPLES_REF}`;
447
+ const ref = process.env.EXTENSION_CREATE_TEMPLATE_REF || 'main';
448
+ const overrideUrl = process.env.EXTENSION_CREATE_TEMPLATE_URL || void 0;
449
+ const urls = resolveCatalogUrls(ref, overrideUrl);
424
450
  let buffer;
425
- try {
426
- buffer = await downloadArchive(url, NETWORK_TIMEOUT_MS);
451
+ let source;
452
+ let lastError;
453
+ for (const candidate of urls)try {
454
+ buffer = await downloadArchive(candidate, NETWORK_TIMEOUT_MS);
455
+ source = candidate;
456
+ break;
427
457
  } catch (error) {
428
- throw new TemplateDownloadError(templateName, error);
458
+ lastError = error;
429
459
  }
460
+ if (!buffer || !source) throw new TemplateDownloadError(templateName, lastError);
430
461
  await extractExamplesTemplateFromZip(buffer, templateName, projectPath);
462
+ return {
463
+ source,
464
+ ref: overrideUrl ? void 0 : ref
465
+ };
431
466
  }
432
467
  function isAuthorOrDevMode() {
433
468
  return 'development' === process.env.EXTENSION_ENV || 'true' === process.env.EXTENSION_AUTHOR_MODE;
@@ -509,7 +544,10 @@ async function importExternalTemplate(projectPath, projectName, template, logger
509
544
  if ((0, external_node_fs_namespaceObject.existsSync)(localTemplate)) {
510
545
  await copyDirectoryWithSymlinks(localTemplate, projectPath);
511
546
  await removeTemplateScaffoldingFiles(projectPath);
512
- return;
547
+ return {
548
+ template: resolvedTemplateName,
549
+ source: 'bundled'
550
+ };
513
551
  }
514
552
  }
515
553
  const tempRoot = await promises_namespaceObject.mkdtemp(external_node_path_namespaceObject.join(external_node_os_namespaceObject.tmpdir(), 'extension-js-create-'));
@@ -535,6 +573,7 @@ async function importExternalTemplate(projectPath, projectName, template, logger
535
573
  else process.env[k] = v;
536
574
  }
537
575
  };
576
+ let provenance;
538
577
  if (isGithub) {
539
578
  await runGoGitIt(template, tempPath);
540
579
  const candidates = await promises_namespaceObject.readdir(tempPath, {
@@ -543,6 +582,10 @@ async function importExternalTemplate(projectPath, projectName, template, logger
543
582
  const preferred = candidates.find((d)=>d.isDirectory() && d.name === templateName);
544
583
  const srcPath = preferred ? external_node_path_namespaceObject.join(tempPath, templateName) : tempPath;
545
584
  await moveDirectoryContents(srcPath, projectPath);
585
+ provenance = {
586
+ template: resolvedTemplateName,
587
+ source: template
588
+ };
546
589
  } else if (isHttp) {
547
590
  const { data, headers } = await external_axios_default().get(template, {
548
591
  responseType: 'arraybuffer',
@@ -556,12 +599,26 @@ async function importExternalTemplate(projectPath, projectName, template, logger
556
599
  zip.extractAllTo(tempPath, true);
557
600
  const sourcePath = await getZipSourcePath(tempPath, template);
558
601
  await moveDirectoryContents(sourcePath, projectPath);
559
- } else await importFromExamplesCatalog(resolvedTemplateName, projectPath);
602
+ provenance = {
603
+ template: resolvedTemplateName,
604
+ source: template
605
+ };
606
+ } else {
607
+ const catalog = await importFromExamplesCatalog(resolvedTemplateName, projectPath);
608
+ provenance = {
609
+ template: resolvedTemplateName,
610
+ source: catalog.source,
611
+ ...catalog.ref ? {
612
+ ref: catalog.ref
613
+ } : {}
614
+ };
615
+ }
560
616
  await removeTemplateScaffoldingFiles(projectPath);
561
617
  await promises_namespaceObject.rm(tempRoot, {
562
618
  recursive: true,
563
619
  force: true
564
620
  });
621
+ return provenance;
565
622
  } catch (error) {
566
623
  if (error instanceof TemplateNotFoundError) logger.error(templateNotFoundInCatalog(templateName, error.cause));
567
624
  else if (error instanceof TemplateDownloadError) logger.error(templateDownloadFailed(templateName, error));
@@ -1439,13 +1496,44 @@ async function writeReadmeFile(projectPath, projectName, logger) {
1439
1496
  throw error;
1440
1497
  }
1441
1498
  }
1499
+ const TEMPLATE_PROVENANCE_FILE = '.extension-create.json';
1500
+ function ownCreateVersion() {
1501
+ try {
1502
+ const pkg = JSON.parse((0, external_node_fs_namespaceObject.readFileSync)(external_node_path_namespaceObject.join(__dirname, '..', 'package.json'), 'utf8'));
1503
+ return 'string' == typeof pkg.version && pkg.version ? `extension-create@${pkg.version}` : void 0;
1504
+ } catch {
1505
+ return;
1506
+ }
1507
+ }
1508
+ function buildProvenanceRecord(provenance) {
1509
+ return {
1510
+ ...ownCreateVersion() ? {
1511
+ createdWith: ownCreateVersion()
1512
+ } : {},
1513
+ template: provenance.template,
1514
+ source: provenance.source,
1515
+ ...provenance.ref ? {
1516
+ ref: provenance.ref
1517
+ } : {}
1518
+ };
1519
+ }
1520
+ async function writeTemplateProvenance(projectPath, provenance, logger) {
1521
+ if (!provenance?.template) return;
1522
+ const record = buildProvenanceRecord(provenance);
1523
+ try {
1524
+ logger.log(writingTemplateProvenance());
1525
+ await promises_namespaceObject.writeFile(external_node_path_namespaceObject.join(projectPath, TEMPLATE_PROVENANCE_FILE), `${JSON.stringify(record, null, 2)}\n`);
1526
+ } catch (error) {
1527
+ logger.error(writingTemplateProvenanceError(error));
1528
+ }
1529
+ }
1442
1530
  async function extensionCreate(projectNameInput, { cliVersion, template = "javascript", install = false, logger = console }) {
1443
1531
  if (!projectNameInput) throw new Error(noProjectName());
1444
1532
  if (projectNameInput.startsWith('http')) throw new Error(noUrlAllowed());
1445
1533
  const projectPath = external_node_path_namespaceObject.isAbsolute(projectNameInput) ? projectNameInput : external_node_path_namespaceObject.join(process.cwd(), projectNameInput);
1446
1534
  const projectName = external_node_path_namespaceObject.basename(projectPath);
1447
1535
  await createDirectory(projectPath, projectName, logger);
1448
- await importExternalTemplate(projectPath, projectName, template, logger);
1536
+ const templateProvenance = await importExternalTemplate(projectPath, projectName, template, logger);
1449
1537
  const isMonorepoTemplate = String(template).toLowerCase().includes('monorepo');
1450
1538
  if (isDenoRuntime() && !isMonorepoTemplate) await writeDenoJsonc(projectPath, projectName, {
1451
1539
  template,
@@ -1461,6 +1549,7 @@ async function extensionCreate(projectNameInput, { cliVersion, template = "javas
1461
1549
  template
1462
1550
  }, logger);
1463
1551
  }
1552
+ await writeTemplateProvenance(projectPath, templateProvenance, logger);
1464
1553
  if (install) {
1465
1554
  await installDependencies(projectPath, projectName, logger);
1466
1555
  await installInternalDependencies(projectPath, logger);
@@ -1478,7 +1567,8 @@ async function extensionCreate(projectNameInput, { cliVersion, template = "javas
1478
1567
  projectName,
1479
1568
  template,
1480
1569
  depsInstalled: install,
1481
- packageManager: resolveScaffoldPackageManager()
1570
+ packageManager: resolveScaffoldPackageManager(),
1571
+ templateProvenance
1482
1572
  };
1483
1573
  }
1484
1574
  exports.extensionCreate = __webpack_exports__.extensionCreate;
package/dist/module.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { type ScaffoldPackageManager } from './lib/package-manager';
2
+ import { type TemplateProvenance } from './steps/import-external-template';
2
3
  export interface CreateLogger {
3
4
  log: (...args: unknown[]) => void;
4
5
  error: (...args: unknown[]) => void;
@@ -15,5 +16,6 @@ export interface CreateResult {
15
16
  template: string;
16
17
  depsInstalled: boolean;
17
18
  packageManager: ScaffoldPackageManager;
19
+ templateProvenance: TemplateProvenance;
18
20
  }
19
21
  export declare function extensionCreate(projectNameInput: string | undefined, { cliVersion, template, install, logger }: CreateOptions): Promise<CreateResult>;
@@ -1,3 +1,9 @@
1
+ export declare function resolveCatalogUrls(ref: string, overrideUrl?: string): string[];
2
+ export interface TemplateProvenance {
3
+ template: string;
4
+ source: string;
5
+ ref?: string;
6
+ }
1
7
  export declare class TemplateNotFoundError extends Error {
2
8
  readonly templateName: string;
3
9
  constructor(templateName: string, cause?: unknown);
@@ -12,4 +18,4 @@ export declare function removeTemplateScaffoldingFiles(projectPath: string): Pro
12
18
  export declare function importExternalTemplate(projectPath: string, projectName: string, template: string, logger: {
13
19
  log(...args: unknown[]): void;
14
20
  error(...args: unknown[]): void;
15
- }): Promise<void>;
21
+ }): Promise<TemplateProvenance>;
@@ -0,0 +1,7 @@
1
+ import type { TemplateProvenance } from './import-external-template';
2
+ export declare const TEMPLATE_PROVENANCE_FILE = ".extension-create.json";
3
+ export declare function buildProvenanceRecord(provenance: TemplateProvenance): Record<string, string>;
4
+ export declare function writeTemplateProvenance(projectPath: string, provenance: TemplateProvenance, logger: {
5
+ log(...args: unknown[]): void;
6
+ error(...args: unknown[]): void;
7
+ }): Promise<void>;
@@ -0,0 +1,5 @@
1
+ {
2
+ "createdWith": "extension-create@4.0.15",
3
+ "template": "javascript",
4
+ "source": "bundled"
5
+ }
@@ -21,7 +21,7 @@
21
21
  },
22
22
  "dependencies": {},
23
23
  "devDependencies": {
24
- "extension": "^4.0.14"
24
+ "extension": "^4.0.15"
25
25
  },
26
26
  "packageManager": "pnpm@10.28.0",
27
27
  "pnpm": {
package/package.json CHANGED
@@ -25,7 +25,7 @@
25
25
  "templates"
26
26
  ],
27
27
  "name": "extension-create",
28
- "version": "4.0.15",
28
+ "version": "4.0.16",
29
29
  "description": "The standalone extension creation engine for Extension.js",
30
30
  "author": {
31
31
  "name": "Cezar Augusto",