wp-typia 0.20.4 → 0.21.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.
@@ -1,10 +1,10 @@
1
1
  // @bun
2
2
  import {
3
3
  getPackageVersions
4
- } from "./cli-tesygdnr.js";
4
+ } from "./cli-syg9qpxw.js";
5
5
  import {
6
6
  seedProjectMigrations
7
- } from "./cli-2rev5hqm.js";
7
+ } from "./cli-jfj54qej.js";
8
8
  import {
9
9
  ensureMigrationDirectories,
10
10
  isPlainObject,
@@ -59,10 +59,14 @@ import {
59
59
  toTitleCase,
60
60
  validateBlockSlug,
61
61
  validateNamespace
62
- } from "./cli-3w3qxq9w.js";
62
+ } from "./cli-hx88xwr4.js";
63
63
  import {
64
64
  createManagedTempRoot
65
65
  } from "./cli-t73q5aqz.js";
66
+ import {
67
+ CLI_DIAGNOSTIC_CODES,
68
+ createCliDiagnosticCodeError
69
+ } from "./cli-p95wr1q8.js";
66
70
  import {
67
71
  __commonJS,
68
72
  __require,
@@ -695,13 +699,13 @@ var require_hosts = __commonJS((exports, module) => {
695
699
  var defaults = {
696
700
  sshtemplate: ({ domain, user, project, committish }) => `git@${domain}:${user}/${project}.git${maybeJoin("#", committish)}`,
697
701
  sshurltemplate: ({ domain, user, project, committish }) => `git+ssh://git@${domain}/${user}/${project}.git${maybeJoin("#", committish)}`,
698
- edittemplate: ({ domain, user, project, committish, editpath, path: path10 }) => `https://${domain}/${user}/${project}${maybeJoin("/", editpath, "/", maybeEncode(committish || "HEAD"), "/", path10)}`,
702
+ edittemplate: ({ domain, user, project, committish, editpath, path: path6 }) => `https://${domain}/${user}/${project}${maybeJoin("/", editpath, "/", maybeEncode(committish || "HEAD"), "/", path6)}`,
699
703
  browsetemplate: ({ domain, user, project, committish, treepath }) => `https://${domain}/${user}/${project}${maybeJoin("/", treepath, "/", maybeEncode(committish))}`,
700
- browsetreetemplate: ({ domain, user, project, committish, treepath, path: path10, fragment, hashformat }) => `https://${domain}/${user}/${project}/${treepath}/${maybeEncode(committish || "HEAD")}/${path10}${maybeJoin("#", hashformat(fragment || ""))}`,
701
- browseblobtemplate: ({ domain, user, project, committish, blobpath, path: path10, fragment, hashformat }) => `https://${domain}/${user}/${project}/${blobpath}/${maybeEncode(committish || "HEAD")}/${path10}${maybeJoin("#", hashformat(fragment || ""))}`,
704
+ browsetreetemplate: ({ domain, user, project, committish, treepath, path: path6, fragment, hashformat }) => `https://${domain}/${user}/${project}/${treepath}/${maybeEncode(committish || "HEAD")}/${path6}${maybeJoin("#", hashformat(fragment || ""))}`,
705
+ browseblobtemplate: ({ domain, user, project, committish, blobpath, path: path6, fragment, hashformat }) => `https://${domain}/${user}/${project}/${blobpath}/${maybeEncode(committish || "HEAD")}/${path6}${maybeJoin("#", hashformat(fragment || ""))}`,
702
706
  docstemplate: ({ domain, user, project, treepath, committish }) => `https://${domain}/${user}/${project}${maybeJoin("/", treepath, "/", maybeEncode(committish))}#readme`,
703
707
  httpstemplate: ({ auth, domain, user, project, committish }) => `git+https://${maybeJoin(auth, "@")}${domain}/${user}/${project}.git${maybeJoin("#", committish)}`,
704
- filetemplate: ({ domain, user, project, committish, path: path10 }) => `https://${domain}/${user}/${project}/raw/${maybeEncode(committish || "HEAD")}/${path10}`,
708
+ filetemplate: ({ domain, user, project, committish, path: path6 }) => `https://${domain}/${user}/${project}/raw/${maybeEncode(committish || "HEAD")}/${path6}`,
705
709
  shortcuttemplate: ({ type, user, project, committish }) => `${type}:${user}/${project}${maybeJoin("#", committish)}`,
706
710
  pathtemplate: ({ user, project, committish }) => `${user}/${project}${maybeJoin("#", committish)}`,
707
711
  bugstemplate: ({ domain, user, project }) => `https://${domain}/${user}/${project}/issues`,
@@ -714,7 +718,7 @@ var require_hosts = __commonJS((exports, module) => {
714
718
  treepath: "tree",
715
719
  blobpath: "blob",
716
720
  editpath: "edit",
717
- filetemplate: ({ auth, user, project, committish, path: path10 }) => `https://${maybeJoin(auth, "@")}raw.githubusercontent.com/${user}/${project}/${maybeEncode(committish || "HEAD")}/${path10}`,
721
+ filetemplate: ({ auth, user, project, committish, path: path6 }) => `https://${maybeJoin(auth, "@")}raw.githubusercontent.com/${user}/${project}/${maybeEncode(committish || "HEAD")}/${path6}`,
718
722
  gittemplate: ({ auth, domain, user, project, committish }) => `git://${maybeJoin(auth, "@")}${domain}/${user}/${project}.git${maybeJoin("#", committish)}`,
719
723
  tarballtemplate: ({ domain, user, project, committish }) => `https://codeload.${domain}/${user}/${project}/tar.gz/${maybeEncode(committish || "HEAD")}`,
720
724
  extract: (url) => {
@@ -740,7 +744,7 @@ var require_hosts = __commonJS((exports, module) => {
740
744
  treepath: "src",
741
745
  blobpath: "src",
742
746
  editpath: "?mode=edit",
743
- edittemplate: ({ domain, user, project, committish, treepath, path: path10, editpath }) => `https://${domain}/${user}/${project}${maybeJoin("/", treepath, "/", maybeEncode(committish || "HEAD"), "/", path10, editpath)}`,
747
+ edittemplate: ({ domain, user, project, committish, treepath, path: path6, editpath }) => `https://${domain}/${user}/${project}${maybeJoin("/", treepath, "/", maybeEncode(committish || "HEAD"), "/", path6, editpath)}`,
744
748
  tarballtemplate: ({ domain, user, project, committish }) => `https://${domain}/${user}/${project}/get/${maybeEncode(committish || "HEAD")}.tar.gz`,
745
749
  extract: (url) => {
746
750
  let [, user, project, aux] = url.pathname.split("/", 4);
@@ -764,11 +768,11 @@ var require_hosts = __commonJS((exports, module) => {
764
768
  editpath: "-/edit",
765
769
  tarballtemplate: ({ domain, user, project, committish }) => `https://${domain}/${user}/${project}/repository/archive.tar.gz?ref=${maybeEncode(committish || "HEAD")}`,
766
770
  extract: (url) => {
767
- const path10 = url.pathname.slice(1);
768
- if (path10.includes("/-/") || path10.includes("/archive.tar.gz")) {
771
+ const path6 = url.pathname.slice(1);
772
+ if (path6.includes("/-/") || path6.includes("/archive.tar.gz")) {
769
773
  return;
770
774
  }
771
- const segments = path10.split("/");
775
+ const segments = path6.split("/");
772
776
  let project = segments.pop();
773
777
  if (project.endsWith(".git")) {
774
778
  project = project.slice(0, -4);
@@ -788,11 +792,11 @@ var require_hosts = __commonJS((exports, module) => {
788
792
  sshurltemplate: ({ domain, project, committish }) => `git+ssh://git@${domain}/${project}.git${maybeJoin("#", committish)}`,
789
793
  edittemplate: ({ domain, user, project, committish, editpath }) => `https://${domain}/${user}/${project}${maybeJoin("/", maybeEncode(committish))}/${editpath}`,
790
794
  browsetemplate: ({ domain, project, committish }) => `https://${domain}/${project}${maybeJoin("/", maybeEncode(committish))}`,
791
- browsetreetemplate: ({ domain, project, committish, path: path10, hashformat }) => `https://${domain}/${project}${maybeJoin("/", maybeEncode(committish))}${maybeJoin("#", hashformat(path10))}`,
792
- browseblobtemplate: ({ domain, project, committish, path: path10, hashformat }) => `https://${domain}/${project}${maybeJoin("/", maybeEncode(committish))}${maybeJoin("#", hashformat(path10))}`,
795
+ browsetreetemplate: ({ domain, project, committish, path: path6, hashformat }) => `https://${domain}/${project}${maybeJoin("/", maybeEncode(committish))}${maybeJoin("#", hashformat(path6))}`,
796
+ browseblobtemplate: ({ domain, project, committish, path: path6, hashformat }) => `https://${domain}/${project}${maybeJoin("/", maybeEncode(committish))}${maybeJoin("#", hashformat(path6))}`,
793
797
  docstemplate: ({ domain, project, committish }) => `https://${domain}/${project}${maybeJoin("/", maybeEncode(committish))}`,
794
798
  httpstemplate: ({ domain, project, committish }) => `git+https://${domain}/${project}.git${maybeJoin("#", committish)}`,
795
- filetemplate: ({ user, project, committish, path: path10 }) => `https://gist.githubusercontent.com/${user}/${project}/raw${maybeJoin("/", maybeEncode(committish))}/${path10}`,
799
+ filetemplate: ({ user, project, committish, path: path6 }) => `https://gist.githubusercontent.com/${user}/${project}/raw${maybeJoin("/", maybeEncode(committish))}/${path6}`,
796
800
  shortcuttemplate: ({ type, project, committish }) => `${type}:${project}${maybeJoin("#", committish)}`,
797
801
  pathtemplate: ({ project, committish }) => `${project}${maybeJoin("#", committish)}`,
798
802
  bugstemplate: ({ domain, project }) => `https://${domain}/${project}`,
@@ -824,7 +828,7 @@ var require_hosts = __commonJS((exports, module) => {
824
828
  domain: "git.sr.ht",
825
829
  treepath: "tree",
826
830
  blobpath: "tree",
827
- filetemplate: ({ domain, user, project, committish, path: path10 }) => `https://${domain}/${user}/${project}/blob/${maybeEncode(committish) || "HEAD"}/${path10}`,
831
+ filetemplate: ({ domain, user, project, committish, path: path6 }) => `https://${domain}/${user}/${project}/blob/${maybeEncode(committish) || "HEAD"}/${path6}`,
828
832
  httpstemplate: ({ domain, user, project, committish }) => `https://${domain}/${user}/${project}.git${maybeJoin("#", committish)}`,
829
833
  tarballtemplate: ({ domain, user, project, committish }) => `https://${domain}/${user}/${project}/archive/${maybeEncode(committish) || "HEAD"}.tar.gz`,
830
834
  bugstemplate: () => null,
@@ -1005,8 +1009,8 @@ var require_lib = __commonJS((exports, module) => {
1005
1009
  return null;
1006
1010
  }
1007
1011
  const proto = /(?:git\+)http:$/.test(protocol) ? "http:" : "https:";
1008
- const path10 = pathname.replace(/\.git$/, "");
1009
- return `${proto}//${hostname}${path10}`;
1012
+ const path6 = pathname.replace(/\.git$/, "");
1013
+ return `${proto}//${hostname}${path6}`;
1010
1014
  } catch {
1011
1015
  return null;
1012
1016
  }
@@ -1099,20 +1103,20 @@ var require_lib = __commonJS((exports, module) => {
1099
1103
  sshurl(opts) {
1100
1104
  return this.#fill(this.sshurltemplate, opts);
1101
1105
  }
1102
- browse(path10, ...args) {
1103
- if (typeof path10 !== "string") {
1104
- return this.#fill(this.browsetemplate, path10);
1106
+ browse(path6, ...args) {
1107
+ if (typeof path6 !== "string") {
1108
+ return this.#fill(this.browsetemplate, path6);
1105
1109
  }
1106
1110
  if (typeof args[0] !== "string") {
1107
- return this.#fill(this.browsetreetemplate, { ...args[0], path: path10 });
1111
+ return this.#fill(this.browsetreetemplate, { ...args[0], path: path6 });
1108
1112
  }
1109
- return this.#fill(this.browsetreetemplate, { ...args[1], fragment: args[0], path: path10 });
1113
+ return this.#fill(this.browsetreetemplate, { ...args[1], fragment: args[0], path: path6 });
1110
1114
  }
1111
- browseFile(path10, ...args) {
1115
+ browseFile(path6, ...args) {
1112
1116
  if (typeof args[0] !== "string") {
1113
- return this.#fill(this.browseblobtemplate, { ...args[0], path: path10 });
1117
+ return this.#fill(this.browseblobtemplate, { ...args[0], path: path6 });
1114
1118
  }
1115
- return this.#fill(this.browseblobtemplate, { ...args[1], fragment: args[0], path: path10 });
1119
+ return this.#fill(this.browseblobtemplate, { ...args[1], fragment: args[0], path: path6 });
1116
1120
  }
1117
1121
  docs(opts) {
1118
1122
  return this.#fill(this.docstemplate, opts);
@@ -1135,11 +1139,11 @@ var require_lib = __commonJS((exports, module) => {
1135
1139
  tarball(opts) {
1136
1140
  return this.#fill(this.tarballtemplate, { ...opts, noCommittish: false });
1137
1141
  }
1138
- file(path10, opts) {
1139
- return this.#fill(this.filetemplate, { ...opts, path: path10 });
1142
+ file(path6, opts) {
1143
+ return this.#fill(this.filetemplate, { ...opts, path: path6 });
1140
1144
  }
1141
- edit(path10, opts) {
1142
- return this.#fill(this.edittemplate, { ...opts, path: path10 });
1145
+ edit(path6, opts) {
1146
+ return this.#fill(this.edittemplate, { ...opts, path: path6 });
1143
1147
  }
1144
1148
  getDefaultRepresentation() {
1145
1149
  return this.default;
@@ -3199,7 +3203,7 @@ var require_lib3 = __commonJS((exports, module) => {
3199
3203
  var require_npa = __commonJS((exports, module) => {
3200
3204
  var isWindows = process.platform === "win32";
3201
3205
  var { URL: URL2 } = __require("url");
3202
- var path10 = isWindows ? __require("path/win32") : __require("path");
3206
+ var path6 = isWindows ? __require("path/win32") : __require("path");
3203
3207
  var { homedir } = __require("os");
3204
3208
  var HostedGit = require_lib();
3205
3209
  var semver = require_semver2();
@@ -3455,7 +3459,7 @@ var require_npa = __commonJS((exports, module) => {
3455
3459
  let resolvedUrl;
3456
3460
  let specUrl;
3457
3461
  try {
3458
- resolvedUrl = new URL2(rawSpec, `${pathToFileURL(path10.resolve(where))}/`);
3462
+ resolvedUrl = new URL2(rawSpec, `${pathToFileURL(path6.resolve(where))}/`);
3459
3463
  specUrl = new URL2(rawSpec);
3460
3464
  } catch (originalError) {
3461
3465
  const er = new Error("Invalid file: URL, must comply with RFC 8089");
@@ -3474,13 +3478,13 @@ var require_npa = __commonJS((exports, module) => {
3474
3478
  }
3475
3479
  if (/^\/~(\/|$)/.test(specPath)) {
3476
3480
  res.saveSpec = `file:${specPath.substr(1)}`;
3477
- resolvedPath = path10.resolve(homedir(), specPath.substr(3));
3478
- } else if (!path10.isAbsolute(rawSpec.slice(5))) {
3479
- res.saveSpec = `file:${path10.relative(where, resolvedPath)}`;
3481
+ resolvedPath = path6.resolve(homedir(), specPath.substr(3));
3482
+ } else if (!path6.isAbsolute(rawSpec.slice(5))) {
3483
+ res.saveSpec = `file:${path6.relative(where, resolvedPath)}`;
3480
3484
  } else {
3481
- res.saveSpec = `file:${path10.resolve(resolvedPath)}`;
3485
+ res.saveSpec = `file:${path6.resolve(resolvedPath)}`;
3482
3486
  }
3483
- res.fetchSpec = path10.resolve(where, resolvedPath);
3487
+ res.fetchSpec = path6.resolve(where, resolvedPath);
3484
3488
  res.saveSpec = res.saveSpec.split("\\").join("/");
3485
3489
  if (res.saveSpec.startsWith("file://")) {
3486
3490
  res.saveSpec = `file:/${res.saveSpec.slice(7)}`;
@@ -5803,13 +5807,13 @@ function resolveLocalCliPathOption(options) {
5803
5807
  }
5804
5808
  const resolvedPath = path5.resolve(options.cwd, normalizedValue);
5805
5809
  if (!fs3.existsSync(resolvedPath)) {
5806
- throw new Error(`\`${options.label}\` path does not exist: ${resolvedPath}. Check the path relative to ${options.cwd}.`);
5810
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, `\`${options.label}\` path does not exist: ${resolvedPath}. Check the path relative to ${options.cwd}.`);
5807
5811
  }
5808
5812
  return resolvedPath;
5809
5813
  }
5810
5814
  function assertExternalLayerCompositionOptions(options) {
5811
5815
  if (options.externalLayerId && !options.externalLayerSource) {
5812
- throw new Error("externalLayerId requires externalLayerSource when composing built-in template layers.");
5816
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, "externalLayerId requires externalLayerSource when composing built-in template layers.");
5813
5817
  }
5814
5818
  }
5815
5819
  function createBuiltInVariantErrorMessage(options) {
@@ -5819,7 +5823,7 @@ function assertBuiltInTemplateVariantAllowed(options) {
5819
5823
  if (!options.variant) {
5820
5824
  return;
5821
5825
  }
5822
- throw new Error(createBuiltInVariantErrorMessage({
5826
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, createBuiltInVariantErrorMessage({
5823
5827
  templateId: options.templateId,
5824
5828
  variant: options.variant
5825
5829
  }));
@@ -5916,6 +5920,72 @@ function getCompoundInnerBlocksPresetDefinition(value) {
5916
5920
 
5917
5921
  // ../wp-typia-project-tools/src/runtime/scaffold-answer-resolution.ts
5918
5922
  import { execSync } from "child_process";
5923
+ import path7 from "path";
5924
+
5925
+ // ../wp-typia-project-tools/src/runtime/template-source-locators.ts
5926
+ var import_npm_package_arg = __toESM(require_npa(), 1);
5927
+ import path6 from "path";
5928
+ function isTemplatePathLocator(templateId) {
5929
+ return path6.isAbsolute(templateId) || templateId.startsWith("./") || templateId.startsWith("../");
5930
+ }
5931
+ function parseGitHubTemplateLocator(templateId) {
5932
+ if (!templateId.startsWith("github:")) {
5933
+ return null;
5934
+ }
5935
+ const [locatorBody, refSegment] = templateId.slice("github:".length).split("#", 2);
5936
+ const segments = locatorBody.split("/").filter(Boolean);
5937
+ if (segments.length < 3) {
5938
+ throw new Error(`GitHub template locators must look like github:owner/repo/path[#ref]. Received: ${templateId}`);
5939
+ }
5940
+ const [owner, repo, ...sourcePathSegments] = segments;
5941
+ return {
5942
+ owner,
5943
+ repo,
5944
+ ref: refSegment ?? null,
5945
+ sourcePath: sourcePathSegments.join("/")
5946
+ };
5947
+ }
5948
+ function parseNpmTemplateLocator(templateId) {
5949
+ if (isBuiltInTemplateId(templateId) || isTemplatePathLocator(templateId) || templateId.startsWith("github:")) {
5950
+ return null;
5951
+ }
5952
+ try {
5953
+ const parsed = import_npm_package_arg.default(templateId);
5954
+ if (!parsed.registry || !parsed.name) {
5955
+ return null;
5956
+ }
5957
+ const parsedWithRawSpec = parsed;
5958
+ const rawSpec = typeof parsedWithRawSpec.rawSpec === "string" ? parsedWithRawSpec.rawSpec : "";
5959
+ return {
5960
+ fetchSpec: typeof parsed.fetchSpec === "string" ? parsed.fetchSpec : "",
5961
+ name: parsed.name,
5962
+ raw: templateId,
5963
+ rawSpec,
5964
+ type: parsed.type
5965
+ };
5966
+ } catch {
5967
+ return null;
5968
+ }
5969
+ }
5970
+ function parseTemplateLocator(templateId) {
5971
+ if (isRemovedBuiltInTemplateId(templateId)) {
5972
+ throw new Error(getRemovedBuiltInTemplateMessage(templateId));
5973
+ }
5974
+ const githubLocator = parseGitHubTemplateLocator(templateId);
5975
+ if (githubLocator) {
5976
+ return { kind: "github", locator: githubLocator };
5977
+ }
5978
+ if (isTemplatePathLocator(templateId)) {
5979
+ return { kind: "path", templatePath: templateId };
5980
+ }
5981
+ const npmLocator = parseNpmTemplateLocator(templateId);
5982
+ if (npmLocator) {
5983
+ return { kind: "npm", locator: npmLocator };
5984
+ }
5985
+ throw new Error(`Unknown template "${templateId}". Expected one of: ${BUILTIN_TEMPLATE_IDS.join(", ")}, a local path, github:owner/repo/path[#ref], or an npm package spec.`);
5986
+ }
5987
+
5988
+ // ../wp-typia-project-tools/src/runtime/scaffold-answer-resolution.ts
5919
5989
  var WORKSPACE_TEMPLATE_ALIAS = "workspace";
5920
5990
  var TEMPLATE_SELECTION_HINT = `--template <${[
5921
5991
  ...TEMPLATE_IDS,
@@ -5923,6 +5993,10 @@ var TEMPLATE_SELECTION_HINT = `--template <${[
5923
5993
  ].join("|")}|./path|github:owner/repo/path[#ref]|npm-package>`;
5924
5994
  var TEMPLATE_SUGGESTION_IDS = [...TEMPLATE_IDS, WORKSPACE_TEMPLATE_ALIAS];
5925
5995
  var QUERY_POST_TYPE_RULE = 'Use lowercase, 1-20 chars, and only a-z, 0-9, "_" or "-".';
5996
+ var USER_FACING_TEMPLATE_IDS = [
5997
+ ...TEMPLATE_IDS,
5998
+ WORKSPACE_TEMPLATE_ALIAS
5999
+ ];
5926
6000
  function detectAuthor() {
5927
6001
  try {
5928
6002
  return execSync("git config user.name", {
@@ -5966,15 +6040,21 @@ function normalizeQueryPostType(value) {
5966
6040
  }
5967
6041
  const validationResult = validateQueryPostType(value);
5968
6042
  if (validationResult !== true) {
5969
- throw new Error(validationResult);
6043
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT, validationResult);
5970
6044
  }
5971
6045
  return value.trim().toLowerCase();
5972
6046
  }
5973
6047
  function normalizeTemplateSelection(templateId) {
5974
6048
  return templateId === WORKSPACE_TEMPLATE_ALIAS ? OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE : templateId;
5975
6049
  }
6050
+ function looksLikeWindowsAbsoluteTemplatePath(templateId) {
6051
+ return /^[a-z]:[\\/]/iu.test(templateId) || /^\\\\[^\\]+\\[^\\]+/u.test(templateId);
6052
+ }
6053
+ function looksLikeExplicitNonNpmExternalTemplateLocator(templateId) {
6054
+ return path7.isAbsolute(templateId) || looksLikeWindowsAbsoluteTemplatePath(templateId) || templateId.startsWith("./") || templateId.startsWith("../") || templateId.startsWith("@") || templateId.startsWith("github:") || templateId.includes("/");
6055
+ }
5976
6056
  function looksLikeExplicitExternalTemplateLocator(templateId) {
5977
- return templateId.startsWith("./") || templateId.startsWith("../") || templateId.startsWith("/") || templateId.startsWith("@") || templateId.startsWith("github:") || templateId.includes("/");
6057
+ return looksLikeExplicitNonNpmExternalTemplateLocator(templateId) || parseNpmTemplateLocator(templateId) !== null;
5978
6058
  }
5979
6059
  function getEditDistance(left, right) {
5980
6060
  const previous = Array.from({ length: right.length + 1 }, (_, index) => index);
@@ -5993,7 +6073,7 @@ function getEditDistance(left, right) {
5993
6073
  }
5994
6074
  function findMistypedBuiltInTemplateSuggestion(templateId) {
5995
6075
  const normalizedTemplateId = templateId.trim().toLowerCase();
5996
- if (normalizedTemplateId.length === 0 || looksLikeExplicitExternalTemplateLocator(normalizedTemplateId)) {
6076
+ if (normalizedTemplateId.length === 0 || looksLikeExplicitNonNpmExternalTemplateLocator(normalizedTemplateId)) {
5997
6077
  return null;
5998
6078
  }
5999
6079
  let bestCandidate = null;
@@ -6016,6 +6096,13 @@ function getMistypedBuiltInTemplateMessage(templateId) {
6016
6096
  const suggestionDescription = suggestion === WORKSPACE_TEMPLATE_ALIAS ? "official workspace scaffold" : "built-in scaffold";
6017
6097
  return `Unknown template "${templateId}". Did you mean "${suggestion}"? Use \`--template ${suggestion}\` for the ${suggestionDescription}, or pass a local path, \`github:owner/repo/path[#ref]\`, or an npm package spec for an external template.`;
6018
6098
  }
6099
+ function getUnknownTemplateMessage(templateId) {
6100
+ return [
6101
+ `Unknown template "${templateId}". Expected one of: ${USER_FACING_TEMPLATE_IDS.join(", ")}.`,
6102
+ "Run `wp-typia templates list` to inspect available templates.",
6103
+ "Pass an explicit external template locator such as `./path`, `github:owner/repo/path[#ref]`, or `@scope/template` for custom templates."
6104
+ ].join(" ");
6105
+ }
6019
6106
  async function resolveTemplateId({
6020
6107
  templateId,
6021
6108
  yes = false,
@@ -6025,7 +6112,7 @@ async function resolveTemplateId({
6025
6112
  if (templateId) {
6026
6113
  const normalizedTemplateId = normalizeTemplateSelection(templateId);
6027
6114
  if (isRemovedBuiltInTemplateId(templateId)) {
6028
- throw new Error(getRemovedBuiltInTemplateMessage(templateId));
6115
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.UNKNOWN_TEMPLATE, getRemovedBuiltInTemplateMessage(templateId));
6029
6116
  }
6030
6117
  if (normalizedTemplateId === OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE) {
6031
6118
  return normalizedTemplateId;
@@ -6035,7 +6122,10 @@ async function resolveTemplateId({
6035
6122
  }
6036
6123
  const mistypedBuiltInTemplateMessage = getMistypedBuiltInTemplateMessage(templateId);
6037
6124
  if (mistypedBuiltInTemplateMessage) {
6038
- throw new Error(mistypedBuiltInTemplateMessage);
6125
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.UNKNOWN_TEMPLATE, mistypedBuiltInTemplateMessage);
6126
+ }
6127
+ if (!looksLikeExplicitExternalTemplateLocator(normalizedTemplateId)) {
6128
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.UNKNOWN_TEMPLATE, getUnknownTemplateMessage(templateId));
6039
6129
  }
6040
6130
  return normalizedTemplateId;
6041
6131
  }
@@ -6043,7 +6133,7 @@ async function resolveTemplateId({
6043
6133
  return "basic";
6044
6134
  }
6045
6135
  if (!isInteractive || !selectTemplate) {
6046
- throw new Error(`Template is required in non-interactive mode. Use ${TEMPLATE_SELECTION_HINT}.`);
6136
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, `Template is required in non-interactive mode. Use ${TEMPLATE_SELECTION_HINT}.`);
6047
6137
  }
6048
6138
  return normalizeTemplateSelection(await selectTemplate());
6049
6139
  }
@@ -6060,7 +6150,7 @@ async function resolvePackageManagerId({
6060
6150
  return "npm";
6061
6151
  }
6062
6152
  if (!isInteractive || !selectPackageManager) {
6063
- throw new Error(`Package manager is required in non-interactive mode. Use --package-manager <${PACKAGE_MANAGER_IDS.join("|")}>.`);
6153
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.MISSING_ARGUMENT, `Package manager is required in non-interactive mode. Use --package-manager <${PACKAGE_MANAGER_IDS.join("|")}>.`);
6064
6154
  }
6065
6155
  return selectPackageManager();
6066
6156
  }
@@ -6077,7 +6167,7 @@ async function collectScaffoldAnswers({
6077
6167
  textDomain
6078
6168
  }) {
6079
6169
  const defaults = getDefaultAnswers(projectName, templateId);
6080
- if (yes) {
6170
+ if (yes || !isBuiltInTemplateId(templateId) && !promptText) {
6081
6171
  const identifiers2 = resolveScaffoldIdentifiers({
6082
6172
  namespace: namespace ?? defaults.namespace,
6083
6173
  phpPrefix,
@@ -6118,25 +6208,25 @@ async function collectScaffoldAnswers({
6118
6208
  }
6119
6209
 
6120
6210
  // ../wp-typia-project-tools/src/runtime/scaffold.ts
6121
- import fs14 from "fs";
6122
- import { promises as fsp10 } from "fs";
6123
- import path16 from "path";
6211
+ import fs15 from "fs";
6212
+ import { promises as fsp11 } from "fs";
6213
+ import path18 from "path";
6124
6214
 
6125
6215
  // ../wp-typia-project-tools/src/runtime/scaffold-apply-utils.ts
6126
6216
  import fs6 from "fs";
6127
6217
  import { promises as fsp6 } from "fs";
6128
- import path9 from "path";
6218
+ import path11 from "path";
6129
6219
  import { execSync as execSync3 } from "child_process";
6130
6220
  import { fileURLToPath } from "url";
6131
6221
 
6132
6222
  // ../wp-typia-project-tools/src/runtime/migration-ui-capability.ts
6133
6223
  import { promises as fsp4 } from "fs";
6134
- import path6 from "path";
6224
+ import path8 from "path";
6135
6225
  var INITIAL_MIGRATION_VERSION = "v1";
6136
6226
  var BLOCK_METADATA_IMPORT_LINE = "import metadata from './block-metadata';";
6137
6227
  var LEGACY_BLOCK_JSON_IMPORT_LINE = "import metadata from './block.json';";
6138
6228
  async function mutatePackageJson2(projectDir, mutate) {
6139
- const packageJsonPath = path6.join(projectDir, "package.json");
6229
+ const packageJsonPath = path8.join(projectDir, "package.json");
6140
6230
  const packageJson = JSON.parse(await fsp4.readFile(packageJsonPath, "utf8"));
6141
6231
  mutate(packageJson);
6142
6232
  await fsp4.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, "\t")}
@@ -6210,8 +6300,8 @@ function buildMigrationBlocks(templateId, variables) {
6210
6300
  ];
6211
6301
  }
6212
6302
  async function applySingleBlockPatches(projectDir, variables) {
6213
- const editPath = path6.join(projectDir, "src", "edit.tsx");
6214
- const indexPath = path6.join(projectDir, "src", "index.tsx");
6303
+ const editPath = path8.join(projectDir, "src", "edit.tsx");
6304
+ const indexPath = path8.join(projectDir, "src", "index.tsx");
6215
6305
  const deprecatedImport = `import { deprecated } from './migrations/generated/${variables.slugKebabCase}/deprecated';`;
6216
6306
  const deprecatedLine = " deprecated,";
6217
6307
  const dashboardImport = `import { MigrationDashboard } from './admin/migration-dashboard';`;
@@ -6232,10 +6322,10 @@ async function applySingleBlockPatches(projectDir, variables) {
6232
6322
  });
6233
6323
  }
6234
6324
  async function applyCompoundPatches(projectDir, variables) {
6235
- const parentEditPath = path6.join(projectDir, "src", "blocks", variables.slugKebabCase, "edit.tsx");
6236
- const parentIndexPath = path6.join(projectDir, "src", "blocks", variables.slugKebabCase, "index.tsx");
6237
- const childIndexPath = path6.join(projectDir, "src", "blocks", `${variables.slugKebabCase}-item`, "index.tsx");
6238
- const addChildScriptPath = path6.join(projectDir, "scripts", "add-compound-child.ts");
6325
+ const parentEditPath = path8.join(projectDir, "src", "blocks", variables.slugKebabCase, "edit.tsx");
6326
+ const parentIndexPath = path8.join(projectDir, "src", "blocks", variables.slugKebabCase, "index.tsx");
6327
+ const childIndexPath = path8.join(projectDir, "src", "blocks", `${variables.slugKebabCase}-item`, "index.tsx");
6328
+ const addChildScriptPath = path8.join(projectDir, "scripts", "add-compound-child.ts");
6239
6329
  await patchFile(parentIndexPath, (source) => {
6240
6330
  let nextSource = injectAfterBlockMetadataImport(source, `import { deprecated } from '../../migrations/generated/${variables.slugKebabCase}/deprecated';`);
6241
6331
  nextSource = injectBefore(nextSource, "\tedit: Edit,", "\tdeprecated,");
@@ -6305,7 +6395,7 @@ async function applyMigrationUiCapability({
6305
6395
  templateId,
6306
6396
  variables
6307
6397
  }) {
6308
- const commonTemplateDir = path6.join(SHARED_MIGRATION_UI_TEMPLATE_ROOT, "common");
6398
+ const commonTemplateDir = path8.join(SHARED_MIGRATION_UI_TEMPLATE_ROOT, "common");
6309
6399
  await copyInterpolatedDirectory(commonTemplateDir, projectDir, variables);
6310
6400
  await mutatePackageJson2(projectDir, (packageJson) => {
6311
6401
  const wpTypiaPackageVersion = getPackageVersions().wpTypiaPackageVersion;
@@ -6549,7 +6639,7 @@ function mergeTextLines(primaryContent, existingContent) {
6549
6639
  import fs4 from "fs";
6550
6640
  import { promises as fsp5 } from "fs";
6551
6641
  import { execSync as execSync2 } from "child_process";
6552
- import path7 from "path";
6642
+ import path9 from "path";
6553
6643
  var LOCKFILES = {
6554
6644
  bun: ["bun.lock", "bun.lockb"],
6555
6645
  npm: ["package-lock.json"],
@@ -6557,7 +6647,7 @@ var LOCKFILES = {
6557
6647
  yarn: ["yarn.lock"]
6558
6648
  };
6559
6649
  async function normalizePackageManagerFiles(targetDir, packageManagerId) {
6560
- const yarnRcPath = path7.join(targetDir, ".yarnrc.yml");
6650
+ const yarnRcPath = path9.join(targetDir, ".yarnrc.yml");
6561
6651
  if (packageManagerId === "yarn") {
6562
6652
  await fsp5.writeFile(yarnRcPath, `nodeLinker: node-modules
6563
6653
  `, "utf8");
@@ -6566,7 +6656,7 @@ async function normalizePackageManagerFiles(targetDir, packageManagerId) {
6566
6656
  await fsp5.rm(yarnRcPath, { force: true });
6567
6657
  }
6568
6658
  async function normalizePackageJson(targetDir, packageManagerId) {
6569
- const packageJsonPath = path7.join(targetDir, "package.json");
6659
+ const packageJsonPath = path9.join(targetDir, "package.json");
6570
6660
  if (!fs4.existsSync(packageJsonPath)) {
6571
6661
  return;
6572
6662
  }
@@ -6594,7 +6684,7 @@ async function removeUnexpectedLockfiles(targetDir, packageManagerId) {
6594
6684
  if (keep.has(filename)) {
6595
6685
  return;
6596
6686
  }
6597
- await fsp5.rm(path7.join(targetDir, filename), { force: true });
6687
+ await fsp5.rm(path9.join(targetDir, filename), { force: true });
6598
6688
  }));
6599
6689
  }
6600
6690
  async function defaultInstallDependencies({
@@ -6606,11 +6696,10 @@ async function defaultInstallDependencies({
6606
6696
  stdio: "inherit"
6607
6697
  });
6608
6698
  }
6609
-
6610
6699
  // ../wp-typia-project-tools/src/runtime/scaffold-repository-reference.ts
6611
6700
  import fs5 from "fs";
6612
6701
  import { createRequire } from "module";
6613
- import path8 from "path";
6702
+ import path10 from "path";
6614
6703
  var require2 = createRequire(import.meta.url);
6615
6704
  var DEFAULT_SCAFFOLD_REPOSITORY_REFERENCE = "imjlk/wp-typia";
6616
6705
  function getErrorCode(error) {
@@ -6676,9 +6765,9 @@ function parseRepositoryReference(value) {
6676
6765
  }
6677
6766
  function getDefaultRepositoryManifestPaths() {
6678
6767
  const candidatePaths = [
6679
- path8.resolve(PROJECT_TOOLS_PACKAGE_ROOT, "..", "..", "package.json"),
6680
- path8.resolve(PROJECT_TOOLS_PACKAGE_ROOT, "..", "wp-typia", "package.json"),
6681
- path8.join(PROJECT_TOOLS_PACKAGE_ROOT, "package.json"),
6768
+ path10.resolve(PROJECT_TOOLS_PACKAGE_ROOT, "..", "..", "package.json"),
6769
+ path10.resolve(PROJECT_TOOLS_PACKAGE_ROOT, "..", "wp-typia", "package.json"),
6770
+ path10.join(PROJECT_TOOLS_PACKAGE_ROOT, "package.json"),
6682
6771
  resolveInstalledPackageManifestPath("wp-typia"),
6683
6772
  resolveInstalledPackageManifestPath("@wp-typia/project-tools")
6684
6773
  ].filter((candidatePath) => Boolean(candidatePath));
@@ -6705,7 +6794,7 @@ async function reportScaffoldProgress(onProgress, event) {
6705
6794
  await onProgress?.(event);
6706
6795
  }
6707
6796
  var EPHEMERAL_NODE_MODULES_LINK_TYPE2 = process.platform === "win32" ? "junction" : "dir";
6708
- var __dirname2 = path9.dirname(fileURLToPath(import.meta.url));
6797
+ var __dirname2 = path11.dirname(fileURLToPath(import.meta.url));
6709
6798
  var LOCKFILES2 = {
6710
6799
  bun: ["bun.lock", "bun.lockb"],
6711
6800
  npm: ["package-lock.json"],
@@ -6731,42 +6820,42 @@ async function writeStarterManifestFiles2(targetDir, templateId, variables, arti
6731
6820
  relativePath: `${artifact.relativeDir}/typia.manifest.json`
6732
6821
  })) : getStarterManifestFiles(templateId, variables);
6733
6822
  for (const { document, relativePath } of manifests) {
6734
- const destinationPath = path9.join(targetDir, relativePath);
6735
- await fsp6.mkdir(path9.dirname(destinationPath), { recursive: true });
6823
+ const destinationPath = path11.join(targetDir, relativePath);
6824
+ await fsp6.mkdir(path11.dirname(destinationPath), { recursive: true });
6736
6825
  await fsp6.writeFile(destinationPath, stringifyStarterManifest(document), "utf8");
6737
6826
  }
6738
6827
  }
6739
6828
  async function writeBuiltInStructuralArtifacts(targetDir, artifacts) {
6740
6829
  for (const artifact of artifacts) {
6741
- const destinationDir = path9.join(targetDir, artifact.relativeDir);
6830
+ const destinationDir = path11.join(targetDir, artifact.relativeDir);
6742
6831
  await fsp6.mkdir(destinationDir, { recursive: true });
6743
- await fsp6.writeFile(path9.join(destinationDir, "types.ts"), artifact.typesSource, "utf8");
6744
- await fsp6.writeFile(path9.join(destinationDir, "block.json"), stringifyBuiltInBlockJsonDocument(artifact.blockJsonDocument), "utf8");
6832
+ await fsp6.writeFile(path11.join(destinationDir, "types.ts"), artifact.typesSource, "utf8");
6833
+ await fsp6.writeFile(path11.join(destinationDir, "block.json"), stringifyBuiltInBlockJsonDocument(artifact.blockJsonDocument), "utf8");
6745
6834
  }
6746
6835
  }
6747
6836
  async function writeBuiltInCodeArtifacts(targetDir, codeArtifacts) {
6748
6837
  for (const artifact of codeArtifacts) {
6749
- const destinationPath = path9.join(targetDir, artifact.relativePath);
6750
- await fsp6.mkdir(path9.dirname(destinationPath), { recursive: true });
6838
+ const destinationPath = path11.join(targetDir, artifact.relativePath);
6839
+ await fsp6.mkdir(path11.dirname(destinationPath), { recursive: true });
6751
6840
  await fsp6.writeFile(destinationPath, artifact.source, "utf8");
6752
6841
  }
6753
6842
  }
6754
6843
  function resolveScaffoldGeneratorNodeModulesPath2() {
6755
- const projectToolsPackageRoot = path9.resolve(__dirname2, "..", "..");
6844
+ const projectToolsPackageRoot = path11.resolve(__dirname2, "..", "..");
6756
6845
  const candidates = [
6757
- path9.join(projectToolsPackageRoot, "node_modules"),
6758
- path9.resolve(projectToolsPackageRoot, "..", ".."),
6759
- path9.resolve(projectToolsPackageRoot, "..", "..", "node_modules")
6846
+ path11.join(projectToolsPackageRoot, "node_modules"),
6847
+ path11.resolve(projectToolsPackageRoot, "..", ".."),
6848
+ path11.resolve(projectToolsPackageRoot, "..", "..", "node_modules")
6760
6849
  ];
6761
6850
  for (const candidate of candidates) {
6762
- if (fs6.existsSync(path9.join(candidate, "typia", "package.json"))) {
6851
+ if (fs6.existsSync(path11.join(candidate, "typia", "package.json"))) {
6763
6852
  return candidate;
6764
6853
  }
6765
6854
  }
6766
6855
  return null;
6767
6856
  }
6768
6857
  async function withEphemeralScaffoldNodeModules2(targetDir, callback) {
6769
- const targetNodeModulesPath = path9.join(targetDir, "node_modules");
6858
+ const targetNodeModulesPath = path11.join(targetDir, "node_modules");
6770
6859
  if (fs6.existsSync(targetNodeModulesPath)) {
6771
6860
  await callback();
6772
6861
  return;
@@ -6790,7 +6879,7 @@ async function seedBuiltInPersistenceArtifacts2(targetDir, templateId, variables
6790
6879
  await withEphemeralScaffoldNodeModules2(targetDir, async () => {
6791
6880
  if (templateId === "persistence") {
6792
6881
  await syncPersistenceRestArtifacts({
6793
- apiTypesFile: path9.join("src", "api-types.ts"),
6882
+ apiTypesFile: path11.join("src", "api-types.ts"),
6794
6883
  outputDir: "src",
6795
6884
  projectDir: targetDir,
6796
6885
  variables
@@ -6798,15 +6887,15 @@ async function seedBuiltInPersistenceArtifacts2(targetDir, templateId, variables
6798
6887
  return;
6799
6888
  }
6800
6889
  await syncPersistenceRestArtifacts({
6801
- apiTypesFile: path9.join("src", "blocks", variables.slugKebabCase, "api-types.ts"),
6802
- outputDir: path9.join("src", "blocks", variables.slugKebabCase),
6890
+ apiTypesFile: path11.join("src", "blocks", variables.slugKebabCase, "api-types.ts"),
6891
+ outputDir: path11.join("src", "blocks", variables.slugKebabCase),
6803
6892
  projectDir: targetDir,
6804
6893
  variables
6805
6894
  });
6806
6895
  });
6807
6896
  }
6808
6897
  async function normalizePackageManagerFiles2(targetDir, packageManagerId) {
6809
- const yarnRcPath = path9.join(targetDir, ".yarnrc.yml");
6898
+ const yarnRcPath = path11.join(targetDir, ".yarnrc.yml");
6810
6899
  if (packageManagerId === "yarn") {
6811
6900
  await fsp6.writeFile(yarnRcPath, `nodeLinker: node-modules
6812
6901
  `, "utf8");
@@ -6820,7 +6909,7 @@ async function removeQueryLoopPlaceholderFiles(projectDir, templateId) {
6820
6909
  if (templateId !== "query-loop") {
6821
6910
  return;
6822
6911
  }
6823
- await fsp6.rm(path9.join(projectDir, "src", "validator-toolkit.ts"), {
6912
+ await fsp6.rm(path11.join(projectDir, "src", "validator-toolkit.ts"), {
6824
6913
  force: true
6825
6914
  });
6826
6915
  }
@@ -6831,7 +6920,7 @@ async function removeUnexpectedLockfiles2(targetDir, packageManagerId) {
6831
6920
  if (keep.has(filename)) {
6832
6921
  return;
6833
6922
  }
6834
- const filePath = path9.join(targetDir, filename);
6923
+ const filePath = path11.join(targetDir, filename);
6835
6924
  if (fs6.existsSync(filePath)) {
6836
6925
  await fsp6.rm(filePath, { force: true });
6837
6926
  }
@@ -6861,11 +6950,11 @@ async function replaceTextRecursively(targetDir, packageManagerId, {
6861
6950
  if (stats.isDirectory()) {
6862
6951
  const entries = await fsp6.readdir(currentPath);
6863
6952
  for (const entry of entries) {
6864
- await visit(path9.join(currentPath, entry));
6953
+ await visit(path11.join(currentPath, entry));
6865
6954
  }
6866
6955
  return;
6867
6956
  }
6868
- if (path9.basename(currentPath) === "package.json" || !textExtensions.has(path9.extname(currentPath))) {
6957
+ if (path11.basename(currentPath) === "package.json" || !textExtensions.has(path11.extname(currentPath))) {
6869
6958
  return;
6870
6959
  }
6871
6960
  const content = await fsp6.readFile(currentPath, "utf8");
@@ -6943,7 +7032,7 @@ async function applyBuiltInScaffoldProjectFiles({
6943
7032
  phase: "finalize-project",
6944
7033
  title: "Finalizing scaffold output"
6945
7034
  });
6946
- const readmePath = path9.join(projectDir, "README.md");
7035
+ const readmePath = path11.join(projectDir, "README.md");
6947
7036
  if (!fs6.existsSync(readmePath)) {
6948
7037
  await fsp6.writeFile(readmePath, readmeContent ?? buildReadme(templateId, variables, packageManager, {
6949
7038
  withMigrationUi,
@@ -6951,7 +7040,7 @@ async function applyBuiltInScaffoldProjectFiles({
6951
7040
  withWpEnv
6952
7041
  }), "utf8");
6953
7042
  }
6954
- const gitignorePath = path9.join(projectDir, ".gitignore");
7043
+ const gitignorePath = path11.join(projectDir, ".gitignore");
6955
7044
  const existingGitignore = fs6.existsSync(gitignorePath) ? await fsp6.readFile(gitignorePath, "utf8") : "";
6956
7045
  await fsp6.writeFile(gitignorePath, mergeTextLines(gitignoreContent ?? buildGitignore(), existingGitignore), "utf8");
6957
7046
  await normalizePackageJson(projectDir, packageManager);
@@ -6983,83 +7072,20 @@ async function applyBuiltInScaffoldProjectFiles({
6983
7072
  }
6984
7073
  }
6985
7074
 
6986
- // ../wp-typia-project-tools/src/runtime/template-source-locators.ts
6987
- var import_npm_package_arg = __toESM(require_npa(), 1);
6988
- import path10 from "path";
6989
- function isTemplatePathLocator(templateId) {
6990
- return path10.isAbsolute(templateId) || templateId.startsWith("./") || templateId.startsWith("../");
6991
- }
6992
- function parseGitHubTemplateLocator(templateId) {
6993
- if (!templateId.startsWith("github:")) {
6994
- return null;
6995
- }
6996
- const [locatorBody, refSegment] = templateId.slice("github:".length).split("#", 2);
6997
- const segments = locatorBody.split("/").filter(Boolean);
6998
- if (segments.length < 3) {
6999
- throw new Error(`GitHub template locators must look like github:owner/repo/path[#ref]. Received: ${templateId}`);
7000
- }
7001
- const [owner, repo, ...sourcePathSegments] = segments;
7002
- return {
7003
- owner,
7004
- repo,
7005
- ref: refSegment ?? null,
7006
- sourcePath: sourcePathSegments.join("/")
7007
- };
7008
- }
7009
- function parseNpmTemplateLocator(templateId) {
7010
- if (isBuiltInTemplateId(templateId) || isTemplatePathLocator(templateId) || templateId.startsWith("github:")) {
7011
- return null;
7012
- }
7013
- try {
7014
- const parsed = import_npm_package_arg.default(templateId);
7015
- if (!parsed.registry || !parsed.name) {
7016
- return null;
7017
- }
7018
- const parsedWithRawSpec = parsed;
7019
- const rawSpec = typeof parsedWithRawSpec.rawSpec === "string" ? parsedWithRawSpec.rawSpec : "";
7020
- return {
7021
- fetchSpec: typeof parsed.fetchSpec === "string" ? parsed.fetchSpec : "",
7022
- name: parsed.name,
7023
- raw: templateId,
7024
- rawSpec,
7025
- type: parsed.type
7026
- };
7027
- } catch {
7028
- return null;
7029
- }
7030
- }
7031
- function parseTemplateLocator(templateId) {
7032
- if (isRemovedBuiltInTemplateId(templateId)) {
7033
- throw new Error(getRemovedBuiltInTemplateMessage(templateId));
7034
- }
7035
- const githubLocator = parseGitHubTemplateLocator(templateId);
7036
- if (githubLocator) {
7037
- return { kind: "github", locator: githubLocator };
7038
- }
7039
- if (isTemplatePathLocator(templateId)) {
7040
- return { kind: "path", templatePath: templateId };
7041
- }
7042
- const npmLocator = parseNpmTemplateLocator(templateId);
7043
- if (npmLocator) {
7044
- return { kind: "npm", locator: npmLocator };
7045
- }
7046
- throw new Error(`Unknown template "${templateId}". Expected one of: ${BUILTIN_TEMPLATE_IDS.join(", ")}, a local path, github:owner/repo/path[#ref], or an npm package spec.`);
7047
- }
7048
-
7049
7075
  // ../wp-typia-project-tools/src/runtime/template-source-normalization.ts
7050
7076
  import fs11 from "fs";
7051
- import path14 from "path";
7077
+ import path15 from "path";
7052
7078
 
7053
7079
  // ../wp-typia-project-tools/src/runtime/template-layers.ts
7054
7080
  import fs7 from "fs";
7055
- import path11 from "path";
7081
+ import path12 from "path";
7056
7082
  import { promises as fsp7 } from "fs";
7057
7083
  var TEMPLATE_LAYER_MANIFEST_FILENAME = "wp-typia.layers.json";
7058
7084
  var TEMPLATE_LAYER_MANIFEST_VERSION = 1;
7059
7085
  function resolveLayerPath(sourceRoot, relativePath) {
7060
- const targetPath = path11.resolve(sourceRoot, relativePath);
7061
- const relativeTarget = path11.relative(sourceRoot, targetPath);
7062
- if (relativeTarget.startsWith("..") || path11.isAbsolute(relativeTarget)) {
7086
+ const targetPath = path12.resolve(sourceRoot, relativePath);
7087
+ const relativeTarget = path12.relative(sourceRoot, targetPath);
7088
+ if (relativeTarget.startsWith("..") || path12.isAbsolute(relativeTarget)) {
7063
7089
  throw new Error(`Template layer path "${relativePath}" must stay within ${sourceRoot}.`);
7064
7090
  }
7065
7091
  return targetPath;
@@ -7073,7 +7099,7 @@ async function assertNoSymlinks(sourceDir) {
7073
7099
  return;
7074
7100
  }
7075
7101
  for (const entry of await fsp7.readdir(sourceDir)) {
7076
- await assertNoSymlinks(path11.join(sourceDir, entry));
7102
+ await assertNoSymlinks(path12.join(sourceDir, entry));
7077
7103
  }
7078
7104
  }
7079
7105
  function parseLayerDefinition(layerId, value) {
@@ -7102,7 +7128,7 @@ function parseLayerDefinition(layerId, value) {
7102
7128
  };
7103
7129
  }
7104
7130
  async function loadExternalTemplateLayerManifest(sourceRoot) {
7105
- const manifestPath = path11.join(sourceRoot, TEMPLATE_LAYER_MANIFEST_FILENAME);
7131
+ const manifestPath = path12.join(sourceRoot, TEMPLATE_LAYER_MANIFEST_FILENAME);
7106
7132
  if (!fs7.existsSync(manifestPath)) {
7107
7133
  return null;
7108
7134
  }
@@ -7239,7 +7265,7 @@ async function assertExternalTemplateLayersDoNotWriteProtectedOutputs({
7239
7265
 
7240
7266
  // ../wp-typia-project-tools/src/runtime/template-source-external.ts
7241
7267
  import fs9 from "fs";
7242
- import path12 from "path";
7268
+ import path13 from "path";
7243
7269
  import { pathToFileURL } from "url";
7244
7270
 
7245
7271
  // ../wp-typia-project-tools/src/runtime/external-template-guards.ts
@@ -7383,16 +7409,16 @@ function getTemplateWarning(key) {
7383
7409
  return `Ignoring external template config key "${key}": ${TEMPLATE_WARNING_MESSAGE}`;
7384
7410
  }
7385
7411
  function resolveSourceSubpath(sourceDir, relativePath) {
7386
- const targetPath = path12.resolve(sourceDir, relativePath);
7387
- const relativeTarget = path12.relative(sourceDir, targetPath);
7388
- if (relativeTarget.startsWith("..") || path12.isAbsolute(relativeTarget)) {
7412
+ const targetPath = path13.resolve(sourceDir, relativePath);
7413
+ const relativeTarget = path13.relative(sourceDir, targetPath);
7414
+ if (relativeTarget.startsWith("..") || path13.isAbsolute(relativeTarget)) {
7389
7415
  throw new Error(`Template path "${relativePath}" must stay within ${sourceDir}.`);
7390
7416
  }
7391
7417
  return targetPath;
7392
7418
  }
7393
7419
  function getExternalTemplateEntry(sourceDir) {
7394
7420
  for (const filename of EXTERNAL_TEMPLATE_ENTRY_CANDIDATES) {
7395
- const candidate = path12.join(sourceDir, filename);
7421
+ const candidate = path13.join(sourceDir, filename);
7396
7422
  if (fs9.existsSync(candidate)) {
7397
7423
  return candidate;
7398
7424
  }
@@ -7514,22 +7540,22 @@ async function renderCreateBlockExternalTemplate(sourceDir, context, requestedVa
7514
7540
  const { folderName, formatHint, templatePath } = resolveConfiguredTemplatePath(config, variantConfig);
7515
7541
  const { path: tempRoot, cleanup } = await createManagedTempRoot("wp-typia-create-block-external-");
7516
7542
  try {
7517
- const renderedRoot = path12.join(tempRoot, "rendered");
7543
+ const renderedRoot = path13.join(tempRoot, "rendered");
7518
7544
  const blockDir = resolveSourceSubpath(renderedRoot, folderName);
7519
7545
  const view = await buildExternalTemplateView(context, config, selectedVariant, variantConfig);
7520
7546
  const blockTemplateDir = resolveSourceSubpath(sourceDir, templatePath);
7521
7547
  await copyRenderedDirectory(blockTemplateDir, blockDir, view, {
7522
7548
  filter: (sourcePath, _destinationPath, entry) => {
7523
- const mustacheVariantPath = path12.join(path12.dirname(sourcePath), `${entry.name}.mustache`);
7549
+ const mustacheVariantPath = path13.join(path13.dirname(sourcePath), `${entry.name}.mustache`);
7524
7550
  return !(entry.isFile() && (entry.name === "package.json" || entry.name === "README.md") && fs9.existsSync(mustacheVariantPath));
7525
7551
  }
7526
7552
  });
7527
7553
  const assetsPath = typeof variantConfig.assetsPath === "string" ? variantConfig.assetsPath : config.assetsPath;
7528
7554
  if (typeof assetsPath === "string" && assetsPath.trim().length > 0) {
7529
- await copyRawDirectory(resolveSourceSubpath(sourceDir, assetsPath), path12.join(tempRoot, "assets"));
7555
+ await copyRawDirectory(resolveSourceSubpath(sourceDir, assetsPath), path13.join(tempRoot, "assets"));
7530
7556
  }
7531
7557
  return {
7532
- assetsDir: fs9.existsSync(path12.join(tempRoot, "assets")) ? path12.join(tempRoot, "assets") : undefined,
7558
+ assetsDir: fs9.existsSync(path13.join(tempRoot, "assets")) ? path13.join(tempRoot, "assets") : undefined,
7533
7559
  blockDir,
7534
7560
  cleanup,
7535
7561
  formatHint,
@@ -7546,7 +7572,7 @@ async function renderCreateBlockExternalTemplate(sourceDir, context, requestedVa
7546
7572
  // ../wp-typia-project-tools/src/runtime/template-source-remote.ts
7547
7573
  import fs10 from "fs";
7548
7574
  import { promises as fsp8 } from "fs";
7549
- import path13 from "path";
7575
+ import path14 from "path";
7550
7576
  async function cleanupSeedRootPair(cleanup, seedCleanup) {
7551
7577
  let cleanupError;
7552
7578
  try {
@@ -7567,10 +7593,10 @@ function getDefaultCategoryFromBlockJson(blockJson) {
7567
7593
  return typeof blockJson.category === "string" && blockJson.category.trim().length > 0 ? blockJson.category.trim() : "widgets";
7568
7594
  }
7569
7595
  function readRemoteBlockJson(blockDir) {
7570
- const sourceRoot = fs10.existsSync(path13.join(blockDir, "src")) ? path13.join(blockDir, "src") : blockDir;
7596
+ const sourceRoot = fs10.existsSync(path14.join(blockDir, "src")) ? path14.join(blockDir, "src") : blockDir;
7571
7597
  for (const candidate of [
7572
- path13.join(blockDir, "block.json"),
7573
- path13.join(sourceRoot, "block.json")
7598
+ path14.join(blockDir, "block.json"),
7599
+ path14.join(sourceRoot, "block.json")
7574
7600
  ]) {
7575
7601
  if (fs10.existsSync(candidate)) {
7576
7602
  return JSON.parse(fs10.readFileSync(candidate, "utf8"));
@@ -7588,8 +7614,8 @@ function getDefaultCategory(sourceDir) {
7588
7614
  }
7589
7615
  function readTemplatePackageJson(sourceDir) {
7590
7616
  for (const candidate of [
7591
- path13.join(sourceDir, "package.json.mustache"),
7592
- path13.join(sourceDir, "package.json")
7617
+ path14.join(sourceDir, "package.json.mustache"),
7618
+ path14.join(sourceDir, "package.json")
7593
7619
  ]) {
7594
7620
  if (!fs10.existsSync(candidate)) {
7595
7621
  continue;
@@ -7626,16 +7652,16 @@ function getTemplateProjectType(sourceDir) {
7626
7652
  }
7627
7653
  async function normalizeWpTypiaTemplateSeed(seed) {
7628
7654
  const { path: tempRoot, cleanup } = await createManagedTempRoot("wp-typia-template-source-");
7629
- const normalizedDir = path13.join(tempRoot, "template");
7655
+ const normalizedDir = path14.join(tempRoot, "template");
7630
7656
  try {
7631
7657
  await copyRawDirectory(seed.blockDir, normalizedDir, {
7632
7658
  filter: (sourcePath, _targetPath, entry) => {
7633
- const mustacheVariantPath = path13.join(path13.dirname(sourcePath), `${entry.name}.mustache`);
7659
+ const mustacheVariantPath = path14.join(path14.dirname(sourcePath), `${entry.name}.mustache`);
7634
7660
  return !(entry.isFile() && (entry.name === "package.json" || entry.name === "README.md") && fs10.existsSync(mustacheVariantPath));
7635
7661
  }
7636
7662
  });
7637
7663
  if (seed.assetsDir && fs10.existsSync(seed.assetsDir)) {
7638
- await fsp8.cp(seed.assetsDir, path13.join(normalizedDir, "assets"), {
7664
+ await fsp8.cp(seed.assetsDir, path14.join(normalizedDir, "assets"), {
7639
7665
  recursive: true,
7640
7666
  force: true
7641
7667
  });
@@ -7724,21 +7750,21 @@ function buildRemoteBlockJsonTemplate(blockJson) {
7724
7750
  }
7725
7751
  async function rewriteBlockJsonImports(directory) {
7726
7752
  const textExtensions = new Set([".js", ".jsx", ".ts", ".tsx"]);
7727
- const targetBlockJsonPath = path13.join(directory, "block.json");
7753
+ const targetBlockJsonPath = path14.join(directory, "block.json");
7728
7754
  async function visit(currentPath) {
7729
7755
  const stats = await fsp8.stat(currentPath);
7730
7756
  if (stats.isDirectory()) {
7731
7757
  const entries = await fsp8.readdir(currentPath);
7732
7758
  for (const entry of entries) {
7733
- await visit(path13.join(currentPath, entry));
7759
+ await visit(path14.join(currentPath, entry));
7734
7760
  }
7735
7761
  return;
7736
7762
  }
7737
- if (!textExtensions.has(path13.extname(currentPath))) {
7763
+ if (!textExtensions.has(path14.extname(currentPath))) {
7738
7764
  return;
7739
7765
  }
7740
7766
  const content = await fsp8.readFile(currentPath, "utf8");
7741
- const relativeSpecifier = path13.relative(path13.dirname(currentPath), targetBlockJsonPath).replace(/\\/g, "/");
7767
+ const relativeSpecifier = path14.relative(path14.dirname(currentPath), targetBlockJsonPath).replace(/\\/g, "/");
7742
7768
  const normalizedSpecifier = relativeSpecifier.startsWith(".") ? relativeSpecifier : `./${relativeSpecifier}`;
7743
7769
  const next = content.replace(/(['"])\.{1,2}\/[^'"]*block\.json\1/g, `$1${normalizedSpecifier}$1`);
7744
7770
  if (next !== content) {
@@ -7748,7 +7774,7 @@ async function rewriteBlockJsonImports(directory) {
7748
7774
  await visit(directory);
7749
7775
  }
7750
7776
  async function patchRemotePackageJson(templateDir, needsInteractivity) {
7751
- const packageJsonPath = path13.join(templateDir, "package.json.mustache");
7777
+ const packageJsonPath = path14.join(templateDir, "package.json.mustache");
7752
7778
  const packageJson = JSON.parse(await fsp8.readFile(packageJsonPath, "utf8"));
7753
7779
  const existingDependencies = { ...packageJson.dependencies ?? {} };
7754
7780
  const existingDevDependencies = { ...packageJson.devDependencies ?? {} };
@@ -7773,12 +7799,12 @@ async function patchRemotePackageJson(templateDir, needsInteractivity) {
7773
7799
  `, "utf8");
7774
7800
  }
7775
7801
  function getSeedSourceRoot(blockDir) {
7776
- return fs10.existsSync(path13.join(blockDir, "src")) ? path13.join(blockDir, "src") : blockDir;
7802
+ return fs10.existsSync(path14.join(blockDir, "src")) ? path14.join(blockDir, "src") : blockDir;
7777
7803
  }
7778
7804
  function findSeedRenderPhp(seed) {
7779
7805
  for (const candidate of [
7780
- path13.join(seed.blockDir, "render.php"),
7781
- path13.join(seed.rootDir, "render.php")
7806
+ path14.join(seed.blockDir, "render.php"),
7807
+ path14.join(seed.rootDir, "render.php")
7782
7808
  ]) {
7783
7809
  if (fs10.existsSync(candidate)) {
7784
7810
  return candidate;
@@ -7819,13 +7845,13 @@ async function removeSeedEntryConflicts(templateDir) {
7819
7845
  "view.ts",
7820
7846
  "view.tsx"
7821
7847
  ]) {
7822
- await fsp8.rm(path13.join(templateDir, "src", filename), { force: true });
7848
+ await fsp8.rm(path14.join(templateDir, "src", filename), { force: true });
7823
7849
  }
7824
7850
  }
7825
7851
  async function normalizeCreateBlockSubset(seed, context) {
7826
7852
  const { path: tempRoot, cleanup } = await createManagedTempRoot("wp-typia-remote-template-");
7827
7853
  try {
7828
- const templateDir = path13.join(tempRoot, "template");
7854
+ const templateDir = path14.join(tempRoot, "template");
7829
7855
  const blockJson = readRemoteBlockJson(seed.blockDir);
7830
7856
  const sourceRoot = getSeedSourceRoot(seed.blockDir);
7831
7857
  await fsp8.mkdir(templateDir, { recursive: true });
@@ -7842,24 +7868,24 @@ async function normalizeCreateBlockSubset(seed, context) {
7842
7868
  });
7843
7869
  }
7844
7870
  await removeSeedEntryConflicts(templateDir);
7845
- await fsp8.cp(sourceRoot, path13.join(templateDir, "src"), {
7871
+ await fsp8.cp(sourceRoot, path14.join(templateDir, "src"), {
7846
7872
  recursive: true,
7847
7873
  force: true
7848
7874
  });
7849
7875
  const remoteRenderPath = findSeedRenderPhp(seed);
7850
7876
  if (remoteRenderPath) {
7851
- await fsp8.copyFile(remoteRenderPath, path13.join(templateDir, "render.php"));
7877
+ await fsp8.copyFile(remoteRenderPath, path14.join(templateDir, "render.php"));
7852
7878
  }
7853
7879
  if (seed.assetsDir && fs10.existsSync(seed.assetsDir)) {
7854
- await fsp8.cp(seed.assetsDir, path13.join(templateDir, "assets"), {
7880
+ await fsp8.cp(seed.assetsDir, path14.join(templateDir, "assets"), {
7855
7881
  recursive: true,
7856
7882
  force: true
7857
7883
  });
7858
7884
  }
7859
- await fsp8.writeFile(path13.join(templateDir, "src", "types.ts"), buildRemoteTypesSource(blockJson, context), "utf8");
7860
- await fsp8.writeFile(path13.join(templateDir, "src", "block.json"), buildRemoteBlockJsonTemplate(blockJson), "utf8");
7861
- await rewriteBlockJsonImports(path13.join(templateDir, "src"));
7862
- const needsInteractivity = typeof blockJson.viewScriptModule === "string" || typeof blockJson.viewScript === "string" || fs10.existsSync(path13.join(templateDir, "src", "view.js")) || fs10.existsSync(path13.join(templateDir, "src", "view.ts")) || fs10.existsSync(path13.join(templateDir, "src", "view.tsx")) || fs10.existsSync(path13.join(templateDir, "src", "interactivity.js")) || fs10.existsSync(path13.join(templateDir, "src", "interactivity.ts"));
7885
+ await fsp8.writeFile(path14.join(templateDir, "src", "types.ts"), buildRemoteTypesSource(blockJson, context), "utf8");
7886
+ await fsp8.writeFile(path14.join(templateDir, "src", "block.json"), buildRemoteBlockJsonTemplate(blockJson), "utf8");
7887
+ await rewriteBlockJsonImports(path14.join(templateDir, "src"));
7888
+ const needsInteractivity = typeof blockJson.viewScriptModule === "string" || typeof blockJson.viewScript === "string" || fs10.existsSync(path14.join(templateDir, "src", "view.js")) || fs10.existsSync(path14.join(templateDir, "src", "view.ts")) || fs10.existsSync(path14.join(templateDir, "src", "view.tsx")) || fs10.existsSync(path14.join(templateDir, "src", "interactivity.js")) || fs10.existsSync(path14.join(templateDir, "src", "interactivity.ts"));
7863
7889
  await patchRemotePackageJson(templateDir, needsInteractivity);
7864
7890
  return {
7865
7891
  id: "remote:create-block-subset",
@@ -7909,7 +7935,7 @@ function getTemplateVariableContext(variables) {
7909
7935
  };
7910
7936
  }
7911
7937
  async function detectTemplateSourceFormat(sourceDir) {
7912
- if (fs11.existsSync(path14.join(sourceDir, "package.json.mustache"))) {
7938
+ if (fs11.existsSync(path15.join(sourceDir, "package.json.mustache"))) {
7913
7939
  return "wp-typia";
7914
7940
  }
7915
7941
  if (await loadExternalTemplateLayerManifest(sourceDir)) {
@@ -7921,15 +7947,15 @@ async function detectTemplateSourceFormat(sourceDir) {
7921
7947
  if (getTemplateProjectType(sourceDir) !== null) {
7922
7948
  return "wp-typia";
7923
7949
  }
7924
- const sourceRoot = fs11.existsSync(path14.join(sourceDir, "src")) ? path14.join(sourceDir, "src") : sourceDir;
7950
+ const sourceRoot = fs11.existsSync(path15.join(sourceDir, "src")) ? path15.join(sourceDir, "src") : sourceDir;
7925
7951
  const blockJsonCandidates = [
7926
- path14.join(sourceDir, "block.json"),
7927
- path14.join(sourceRoot, "block.json")
7952
+ path15.join(sourceDir, "block.json"),
7953
+ path15.join(sourceRoot, "block.json")
7928
7954
  ];
7929
7955
  const hasBlockJson = blockJsonCandidates.some((candidate) => fs11.existsSync(candidate));
7930
- const hasIndexFile = ["index.js", "index.jsx", "index.ts", "index.tsx"].some((filename) => fs11.existsSync(path14.join(sourceRoot, filename)));
7931
- const hasEditFile = ["edit.js", "edit.jsx", "edit.ts", "edit.tsx"].some((filename) => fs11.existsSync(path14.join(sourceRoot, filename)));
7932
- const hasSaveFile = ["save.js", "save.jsx", "save.ts", "save.tsx"].some((filename) => fs11.existsSync(path14.join(sourceRoot, filename)));
7956
+ const hasIndexFile = ["index.js", "index.jsx", "index.ts", "index.tsx"].some((filename) => fs11.existsSync(path15.join(sourceRoot, filename)));
7957
+ const hasEditFile = ["edit.js", "edit.jsx", "edit.ts", "edit.tsx"].some((filename) => fs11.existsSync(path15.join(sourceRoot, filename)));
7958
+ const hasSaveFile = ["save.js", "save.jsx", "save.ts", "save.tsx"].some((filename) => fs11.existsSync(path15.join(sourceRoot, filename)));
7933
7959
  if (hasBlockJson && hasIndexFile && hasEditFile && hasSaveFile) {
7934
7960
  return "create-block-subset";
7935
7961
  }
@@ -7938,10 +7964,10 @@ async function detectTemplateSourceFormat(sourceDir) {
7938
7964
 
7939
7965
  // ../wp-typia-project-tools/src/runtime/template-source-seeds.ts
7940
7966
  var import_semver = __toESM(require_semver2(), 1);
7941
- import fs13 from "fs";
7942
- import { promises as fsp9 } from "fs";
7967
+ import fs14 from "fs";
7968
+ import { promises as fsp10 } from "fs";
7943
7969
  import { createRequire as createRequire2 } from "module";
7944
- import path15 from "path";
7970
+ import path17 from "path";
7945
7971
  import { spawnSync } from "child_process";
7946
7972
 
7947
7973
  // ../../node_modules/.bun/tar@7.5.13/node_modules/tar/dist/esm/index.min.js
@@ -11091,7 +11117,386 @@ var So = (s3) => {
11091
11117
  s3.mtimeCache || (s3.mtimeCache = new Map), s3.filter = t ? (e, i) => t(e, i) && !((s3.mtimeCache?.get(e) ?? i.mtime ?? 0) > (i.mtime ?? 0)) : (e, i) => !((s3.mtimeCache?.get(e) ?? i.mtime ?? 0) > (i.mtime ?? 0));
11092
11118
  };
11093
11119
 
11120
+ // ../wp-typia-project-tools/src/runtime/template-source-cache.ts
11121
+ import { createHash } from "crypto";
11122
+ import fs13 from "fs";
11123
+ import { promises as fsp9 } from "fs";
11124
+ import os2 from "os";
11125
+ import path16 from "path";
11126
+ var EXTERNAL_TEMPLATE_CACHE_ENV = "WP_TYPIA_EXTERNAL_TEMPLATE_CACHE";
11127
+ var EXTERNAL_TEMPLATE_CACHE_DIR_ENV = "WP_TYPIA_EXTERNAL_TEMPLATE_CACHE_DIR";
11128
+ var CACHE_MARKER_FILE = "wp-typia-template-cache.json";
11129
+ var PRIVATE_CACHE_DIRECTORY_MODE = 448;
11130
+ var REDACTED_CACHE_METADATA_VALUE = "[redacted]";
11131
+ var DISABLED_CACHE_VALUES = new Set(["0", "false", "no", "off"]);
11132
+ var CACHE_PUBLISH_RACE_ERROR_CODES = new Set(["EEXIST", "ENOTEMPTY"]);
11133
+ var CACHE_UNAVAILABLE_ERROR_CODES = new Set([
11134
+ "EACCES",
11135
+ "ENOSPC",
11136
+ "ENOTDIR",
11137
+ "EPERM",
11138
+ "EROFS"
11139
+ ]);
11140
+ var URL_LIKE_METADATA_KEY = /(url|uri|registry|tarball)/iu;
11141
+ var SAFE_CACHE_NAMESPACE_SEGMENT = /^[A-Za-z0-9_.-]+$/u;
11142
+ function isExternalTemplateCacheEnabled(env = process.env) {
11143
+ const rawValue2 = env[EXTERNAL_TEMPLATE_CACHE_ENV];
11144
+ if (rawValue2 === undefined) {
11145
+ return true;
11146
+ }
11147
+ return !DISABLED_CACHE_VALUES.has(rawValue2.trim().toLowerCase());
11148
+ }
11149
+ function getExternalTemplateCacheRoot(env = process.env) {
11150
+ const configuredCacheDir = env[EXTERNAL_TEMPLATE_CACHE_DIR_ENV]?.trim();
11151
+ if (configuredCacheDir) {
11152
+ return path16.resolve(configuredCacheDir);
11153
+ }
11154
+ return path16.join(os2.tmpdir(), `wp-typia-template-source-cache-${getCurrentUserCacheSegment()}`);
11155
+ }
11156
+ function createExternalTemplateCacheKey(keyParts) {
11157
+ return createHash("sha256").update(JSON.stringify(keyParts)).digest("hex");
11158
+ }
11159
+ async function pathExists(filePath) {
11160
+ try {
11161
+ await fsp9.access(filePath, fs13.constants.F_OK);
11162
+ return true;
11163
+ } catch {
11164
+ return false;
11165
+ }
11166
+ }
11167
+ async function isDirectoryPath(directory) {
11168
+ try {
11169
+ const stats = await fsp9.lstat(directory);
11170
+ return stats.isDirectory() && !stats.isSymbolicLink();
11171
+ } catch {
11172
+ return false;
11173
+ }
11174
+ }
11175
+ function getNodeErrorCode(error) {
11176
+ return typeof error === "object" && error !== null && "code" in error ? String(error.code) : "";
11177
+ }
11178
+ async function removeTemporaryCacheEntry(entryDir) {
11179
+ try {
11180
+ await fsp9.rm(entryDir, { force: true, recursive: true });
11181
+ } catch {}
11182
+ }
11183
+ function getCurrentUserCacheSegment() {
11184
+ if (typeof process.getuid === "function") {
11185
+ return String(process.getuid());
11186
+ }
11187
+ try {
11188
+ const safeUsername = os2.userInfo().username.trim().replace(/[^A-Za-z0-9._-]+/gu, "-");
11189
+ return safeUsername.length > 0 ? safeUsername : "user";
11190
+ } catch {
11191
+ return "user";
11192
+ }
11193
+ }
11194
+ function getCurrentUid() {
11195
+ return typeof process.getuid === "function" ? process.getuid() : null;
11196
+ }
11197
+ async function isPrivateCacheDirectory(directory) {
11198
+ try {
11199
+ const stats = await fsp9.lstat(directory);
11200
+ if (!stats.isDirectory() || stats.isSymbolicLink()) {
11201
+ return false;
11202
+ }
11203
+ const currentUid = getCurrentUid();
11204
+ if (currentUid !== null && stats.uid !== currentUid) {
11205
+ return false;
11206
+ }
11207
+ if (process.platform !== "win32" && (stats.mode & 63) !== 0) {
11208
+ return false;
11209
+ }
11210
+ return true;
11211
+ } catch {
11212
+ return false;
11213
+ }
11214
+ }
11215
+ async function ensurePrivateCacheDirectory(directory) {
11216
+ try {
11217
+ await fsp9.mkdir(directory, {
11218
+ mode: PRIVATE_CACHE_DIRECTORY_MODE,
11219
+ recursive: true
11220
+ });
11221
+ const stats = await fsp9.lstat(directory);
11222
+ if (!stats.isDirectory() || stats.isSymbolicLink()) {
11223
+ return false;
11224
+ }
11225
+ const currentUid = getCurrentUid();
11226
+ if (currentUid !== null && stats.uid !== currentUid) {
11227
+ return false;
11228
+ }
11229
+ if (process.platform !== "win32") {
11230
+ if ((stats.mode & 63) !== 0) {
11231
+ await fsp9.chmod(directory, PRIVATE_CACHE_DIRECTORY_MODE);
11232
+ }
11233
+ }
11234
+ return isPrivateCacheDirectory(directory);
11235
+ } catch {
11236
+ return false;
11237
+ }
11238
+ }
11239
+ function sanitizeCacheMetadataValue(key, value) {
11240
+ if (!URL_LIKE_METADATA_KEY.test(key)) {
11241
+ return value;
11242
+ }
11243
+ try {
11244
+ const url = new URL(value);
11245
+ url.username = "";
11246
+ url.password = "";
11247
+ url.search = "";
11248
+ url.hash = "";
11249
+ return url.toString();
11250
+ } catch {
11251
+ return REDACTED_CACHE_METADATA_VALUE;
11252
+ }
11253
+ }
11254
+ function sanitizeCacheMetadata(metadata) {
11255
+ return Object.fromEntries(Object.entries(metadata).map(([key, value]) => [
11256
+ key,
11257
+ value === null ? null : sanitizeCacheMetadataValue(key, value)
11258
+ ]));
11259
+ }
11260
+ function resolveCacheNamespaceDir(cacheRoot, namespace) {
11261
+ if (namespace === "." || namespace === ".." || !SAFE_CACHE_NAMESPACE_SEGMENT.test(namespace)) {
11262
+ return null;
11263
+ }
11264
+ const namespaceDir = path16.join(cacheRoot, namespace);
11265
+ const relativeNamespaceDir = path16.relative(cacheRoot, namespaceDir);
11266
+ if (relativeNamespaceDir.length === 0 || relativeNamespaceDir.startsWith("..") || path16.isAbsolute(relativeNamespaceDir)) {
11267
+ return null;
11268
+ }
11269
+ return namespaceDir;
11270
+ }
11271
+ function getCacheEntryPaths(descriptor) {
11272
+ const cacheKey = createExternalTemplateCacheKey(descriptor.keyParts);
11273
+ const cacheRoot = getExternalTemplateCacheRoot();
11274
+ const namespaceDir = resolveCacheNamespaceDir(cacheRoot, descriptor.namespace);
11275
+ if (!namespaceDir) {
11276
+ return null;
11277
+ }
11278
+ const entryDir = path16.join(namespaceDir, cacheKey);
11279
+ return {
11280
+ cacheKey,
11281
+ cacheRoot,
11282
+ entryDir,
11283
+ markerPath: path16.join(entryDir, CACHE_MARKER_FILE),
11284
+ namespaceDir,
11285
+ sourceDir: path16.join(entryDir, "source")
11286
+ };
11287
+ }
11288
+ async function isReusableCacheEntry(entryDir, markerPath, sourceDir) {
11289
+ return await isPrivateCacheDirectory(entryDir) && await pathExists(markerPath) && await isDirectoryPath(sourceDir);
11290
+ }
11291
+ function parseCacheMarkerMetadata(markerText) {
11292
+ let marker;
11293
+ try {
11294
+ marker = JSON.parse(markerText);
11295
+ } catch {
11296
+ return null;
11297
+ }
11298
+ if (typeof marker !== "object" || marker === null || Array.isArray(marker)) {
11299
+ return null;
11300
+ }
11301
+ const rawMetadata = marker.metadata;
11302
+ if (typeof rawMetadata !== "object" || rawMetadata === null || Array.isArray(rawMetadata)) {
11303
+ return null;
11304
+ }
11305
+ const metadata = {};
11306
+ for (const [key, value] of Object.entries(rawMetadata)) {
11307
+ if (typeof value !== "string" && value !== null) {
11308
+ return null;
11309
+ }
11310
+ metadata[key] = value;
11311
+ }
11312
+ const rawCreatedAt = marker.createdAt;
11313
+ const createdAtMs = typeof rawCreatedAt === "string" ? Date.parse(rawCreatedAt) : 0;
11314
+ return {
11315
+ createdAtMs: Number.isFinite(createdAtMs) ? createdAtMs : 0,
11316
+ metadata
11317
+ };
11318
+ }
11319
+ function cacheMetadataMatches(actual, expected) {
11320
+ return Object.entries(expected).every(([key, value]) => actual[key] === value);
11321
+ }
11322
+ async function findReusableExternalTemplateSourceCache(descriptor) {
11323
+ if (!isExternalTemplateCacheEnabled()) {
11324
+ return null;
11325
+ }
11326
+ const cacheRoot = getExternalTemplateCacheRoot();
11327
+ const namespaceDir = resolveCacheNamespaceDir(cacheRoot, descriptor.namespace);
11328
+ if (!namespaceDir) {
11329
+ return null;
11330
+ }
11331
+ if (!await isPrivateCacheDirectory(cacheRoot) || !await isPrivateCacheDirectory(namespaceDir)) {
11332
+ return null;
11333
+ }
11334
+ let entries;
11335
+ try {
11336
+ entries = await fsp9.readdir(namespaceDir, { withFileTypes: true });
11337
+ } catch {
11338
+ return null;
11339
+ }
11340
+ let bestEntry = null;
11341
+ for (const entry of entries) {
11342
+ if (!entry.isDirectory()) {
11343
+ continue;
11344
+ }
11345
+ const entryDir = path16.join(namespaceDir, entry.name);
11346
+ const markerPath = path16.join(entryDir, CACHE_MARKER_FILE);
11347
+ const sourceDir = path16.join(entryDir, "source");
11348
+ if (!await isReusableCacheEntry(entryDir, markerPath, sourceDir)) {
11349
+ continue;
11350
+ }
11351
+ let markerText;
11352
+ try {
11353
+ markerText = await fsp9.readFile(markerPath, "utf8");
11354
+ } catch {
11355
+ continue;
11356
+ }
11357
+ const marker = parseCacheMarkerMetadata(markerText);
11358
+ if (!marker || !cacheMetadataMatches(marker.metadata, descriptor.metadata)) {
11359
+ continue;
11360
+ }
11361
+ if (!bestEntry || marker.createdAtMs > bestEntry.createdAtMs) {
11362
+ bestEntry = {
11363
+ createdAtMs: marker.createdAtMs,
11364
+ sourceDir
11365
+ };
11366
+ }
11367
+ }
11368
+ return bestEntry ? {
11369
+ cacheHit: true,
11370
+ sourceDir: bestEntry.sourceDir
11371
+ } : null;
11372
+ }
11373
+ async function resolveExternalTemplateSourceCache(descriptor, populateSourceDir) {
11374
+ if (!isExternalTemplateCacheEnabled()) {
11375
+ return null;
11376
+ }
11377
+ const cacheEntryPaths = getCacheEntryPaths(descriptor);
11378
+ if (!cacheEntryPaths) {
11379
+ return null;
11380
+ }
11381
+ const { cacheKey, cacheRoot, entryDir, markerPath, namespaceDir, sourceDir } = cacheEntryPaths;
11382
+ if (!await ensurePrivateCacheDirectory(cacheRoot) || !await ensurePrivateCacheDirectory(namespaceDir)) {
11383
+ return null;
11384
+ }
11385
+ if (await isReusableCacheEntry(entryDir, markerPath, sourceDir)) {
11386
+ return {
11387
+ cacheHit: true,
11388
+ sourceDir
11389
+ };
11390
+ }
11391
+ const temporaryEntryDir = path16.join(namespaceDir, `.tmp-${cacheKey}-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`);
11392
+ const temporarySourceDir = path16.join(temporaryEntryDir, "source");
11393
+ let populateFailed = false;
11394
+ try {
11395
+ await fsp9.mkdir(temporarySourceDir, {
11396
+ mode: PRIVATE_CACHE_DIRECTORY_MODE,
11397
+ recursive: true
11398
+ });
11399
+ if (process.platform !== "win32") {
11400
+ await fsp9.chmod(temporaryEntryDir, PRIVATE_CACHE_DIRECTORY_MODE);
11401
+ }
11402
+ try {
11403
+ await populateSourceDir(temporarySourceDir);
11404
+ } catch (error) {
11405
+ populateFailed = true;
11406
+ throw error;
11407
+ }
11408
+ await fsp9.writeFile(path16.join(temporaryEntryDir, CACHE_MARKER_FILE), `${JSON.stringify({
11409
+ createdAt: new Date().toISOString(),
11410
+ key: cacheKey,
11411
+ metadata: sanitizeCacheMetadata(descriptor.metadata),
11412
+ namespace: descriptor.namespace
11413
+ }, null, 2)}
11414
+ `, "utf8");
11415
+ await fsp9.rename(temporaryEntryDir, entryDir);
11416
+ return {
11417
+ cacheHit: false,
11418
+ sourceDir
11419
+ };
11420
+ } catch (error) {
11421
+ await removeTemporaryCacheEntry(temporaryEntryDir);
11422
+ if (populateFailed) {
11423
+ if (CACHE_UNAVAILABLE_ERROR_CODES.has(getNodeErrorCode(error))) {
11424
+ return null;
11425
+ }
11426
+ throw error;
11427
+ }
11428
+ const errorCode = getNodeErrorCode(error);
11429
+ if (CACHE_PUBLISH_RACE_ERROR_CODES.has(errorCode) && await isReusableCacheEntry(entryDir, markerPath, sourceDir)) {
11430
+ return {
11431
+ cacheHit: true,
11432
+ sourceDir
11433
+ };
11434
+ }
11435
+ if (CACHE_PUBLISH_RACE_ERROR_CODES.has(errorCode) || CACHE_UNAVAILABLE_ERROR_CODES.has(errorCode)) {
11436
+ return null;
11437
+ }
11438
+ throw error;
11439
+ }
11440
+ }
11441
+
11094
11442
  // ../wp-typia-project-tools/src/runtime/template-source-seeds.ts
11443
+ var USER_FACING_TEMPLATE_IDS2 = [
11444
+ ...TEMPLATE_IDS,
11445
+ OFFICIAL_WORKSPACE_TEMPLATE_ALIAS
11446
+ ];
11447
+ var GITHUB_TEMPLATE_CACHE_REVISION_RACE_CODE = "github-template-cache-revision-race";
11448
+ function createGitHubTemplateCacheRevisionRaceError(message) {
11449
+ const error = new Error(message);
11450
+ error.code = GITHUB_TEMPLATE_CACHE_REVISION_RACE_CODE;
11451
+ return error;
11452
+ }
11453
+ function isGitHubTemplateCacheRevisionRaceError(error) {
11454
+ return typeof error === "object" && error !== null && "code" in error && error.code === GITHUB_TEMPLATE_CACHE_REVISION_RACE_CODE;
11455
+ }
11456
+ function getUnknownNpmTemplateMessage(templateId) {
11457
+ return [
11458
+ `Unknown template "${templateId}". Expected one of: ${USER_FACING_TEMPLATE_IDS2.join(", ")}.`,
11459
+ "Run `wp-typia templates list` to inspect available templates.",
11460
+ "If you meant an npm template package, verify the package name and configured npm registry."
11461
+ ].join(" ");
11462
+ }
11463
+ function readOptionalDistString(dist, key) {
11464
+ const value = dist[key];
11465
+ return typeof value === "string" && value.length > 0 ? value : null;
11466
+ }
11467
+ function normalizeNpmRegistryCacheKey(registryBase) {
11468
+ try {
11469
+ const url = new URL(registryBase);
11470
+ url.username = "";
11471
+ url.password = "";
11472
+ url.search = "";
11473
+ url.hash = "";
11474
+ return url.toString().replace(/\/$/u, "");
11475
+ } catch {
11476
+ return registryBase;
11477
+ }
11478
+ }
11479
+ async function downloadNpmTemplateTarball(locator, resolvedVersion, tarballUrl, unpackDir) {
11480
+ const tarballResponse = await fetchWithExternalTemplateTimeout(tarballUrl, {
11481
+ label: `downloading npm template tarball for ${locator.raw}@${resolvedVersion}`
11482
+ });
11483
+ if (!tarballResponse.ok) {
11484
+ throw new Error(`Failed to download npm template tarball for ${locator.raw}: ${tarballResponse.status}`);
11485
+ }
11486
+ const tarballPath = path17.join(path17.dirname(unpackDir), "template.tgz");
11487
+ await fsp10.mkdir(unpackDir, { recursive: true });
11488
+ await fsp10.writeFile(tarballPath, await readBufferResponseWithLimit(tarballResponse, {
11489
+ label: `npm template tarball for ${locator.raw}@${resolvedVersion}`,
11490
+ maxBytes: getExternalTemplateTarballMaxBytes()
11491
+ }));
11492
+ await co({
11493
+ cwd: unpackDir,
11494
+ file: tarballPath,
11495
+ strip: 1
11496
+ });
11497
+ await fsp10.rm(tarballPath, { force: true });
11498
+ await assertNoSymlinks2(unpackDir);
11499
+ }
11095
11500
  function selectRegistryVersion(metadata, locator) {
11096
11501
  const distTags = isPlainObject(metadata["dist-tags"]) ? metadata["dist-tags"] : {};
11097
11502
  const versions = isPlainObject(metadata.versions) ? metadata.versions : {};
@@ -11130,6 +11535,9 @@ async function fetchNpmTemplateSource(locator) {
11130
11535
  label: metadataLabel
11131
11536
  });
11132
11537
  if (!metadataResponse.ok) {
11538
+ if (metadataResponse.status === 404) {
11539
+ throw createCliDiagnosticCodeError(CLI_DIAGNOSTIC_CODES.UNKNOWN_TEMPLATE, getUnknownNpmTemplateMessage(locator.raw));
11540
+ }
11133
11541
  throw new Error(`Failed to fetch npm template metadata for ${locator.raw}: ${metadataResponse.status}`);
11134
11542
  }
11135
11543
  const metadata = await readJsonResponseWithLimit(metadataResponse, {
@@ -11146,27 +11554,43 @@ async function fetchNpmTemplateSource(locator) {
11146
11554
  if (typeof tarballUrl !== "string" || tarballUrl.length === 0) {
11147
11555
  throw new Error(`npm template metadata is missing tarball URL for ${locator.raw}@${resolvedVersion}.`);
11148
11556
  }
11557
+ const tarballIntegrity = readOptionalDistString(versionMetadata.dist, "integrity");
11558
+ const tarballShasum = readOptionalDistString(versionMetadata.dist, "shasum");
11559
+ if (tarballIntegrity || tarballShasum) {
11560
+ const registryCacheKey = normalizeNpmRegistryCacheKey(registryBase);
11561
+ const cachedSource = await resolveExternalTemplateSourceCache({
11562
+ keyParts: [
11563
+ "npm",
11564
+ registryCacheKey,
11565
+ locator.name,
11566
+ locator.raw,
11567
+ resolvedVersion,
11568
+ tarballIntegrity ?? "",
11569
+ tarballShasum ?? ""
11570
+ ],
11571
+ metadata: {
11572
+ integrity: tarballIntegrity,
11573
+ package: locator.name,
11574
+ raw: locator.raw,
11575
+ registry: registryBase,
11576
+ shasum: tarballShasum,
11577
+ tarball: tarballUrl,
11578
+ version: resolvedVersion
11579
+ },
11580
+ namespace: "npm"
11581
+ }, (unpackDir) => downloadNpmTemplateTarball(locator, resolvedVersion, tarballUrl, unpackDir));
11582
+ if (cachedSource) {
11583
+ await assertNoSymlinks2(cachedSource.sourceDir);
11584
+ return {
11585
+ blockDir: cachedSource.sourceDir,
11586
+ rootDir: cachedSource.sourceDir
11587
+ };
11588
+ }
11589
+ }
11149
11590
  const { path: tempRoot, cleanup } = await createManagedTempRoot("wp-typia-template-source-");
11150
11591
  try {
11151
- const tarballResponse = await fetchWithExternalTemplateTimeout(tarballUrl, {
11152
- label: `downloading npm template tarball for ${locator.raw}@${resolvedVersion}`
11153
- });
11154
- if (!tarballResponse.ok) {
11155
- throw new Error(`Failed to download npm template tarball for ${locator.raw}: ${tarballResponse.status}`);
11156
- }
11157
- const tarballPath = path15.join(tempRoot, "template.tgz");
11158
- const unpackDir = path15.join(tempRoot, "source");
11159
- await fsp9.mkdir(unpackDir, { recursive: true });
11160
- await fsp9.writeFile(tarballPath, await readBufferResponseWithLimit(tarballResponse, {
11161
- label: `npm template tarball for ${locator.raw}@${resolvedVersion}`,
11162
- maxBytes: getExternalTemplateTarballMaxBytes()
11163
- }));
11164
- await co({
11165
- cwd: unpackDir,
11166
- file: tarballPath,
11167
- strip: 1
11168
- });
11169
- await assertNoSymlinks2(unpackDir);
11592
+ const unpackDir = path17.join(tempRoot, "source");
11593
+ await downloadNpmTemplateTarball(locator, resolvedVersion, tarballUrl, unpackDir);
11170
11594
  return {
11171
11595
  blockDir: unpackDir,
11172
11596
  cleanup,
@@ -11181,20 +11605,20 @@ function resolveInstalledNpmTemplateSource(locator, cwd) {
11181
11605
  if (locator.rawSpec !== "" && locator.rawSpec !== "*") {
11182
11606
  return null;
11183
11607
  }
11184
- const workspacePackagesRoot = path15.resolve(PROJECT_TOOLS_PACKAGE_ROOT, "..");
11185
- if (fs13.existsSync(workspacePackagesRoot)) {
11186
- for (const entry of fs13.readdirSync(workspacePackagesRoot, {
11608
+ const workspacePackagesRoot = path17.resolve(PROJECT_TOOLS_PACKAGE_ROOT, "..");
11609
+ if (fs14.existsSync(workspacePackagesRoot)) {
11610
+ for (const entry of fs14.readdirSync(workspacePackagesRoot, {
11187
11611
  withFileTypes: true
11188
11612
  })) {
11189
11613
  if (!entry.isDirectory()) {
11190
11614
  continue;
11191
11615
  }
11192
- const packageDir = path15.join(workspacePackagesRoot, entry.name);
11193
- const packageJsonPath = path15.join(packageDir, "package.json");
11194
- if (!fs13.existsSync(packageJsonPath)) {
11616
+ const packageDir = path17.join(workspacePackagesRoot, entry.name);
11617
+ const packageJsonPath = path17.join(packageDir, "package.json");
11618
+ if (!fs14.existsSync(packageJsonPath)) {
11195
11619
  continue;
11196
11620
  }
11197
- const manifest = JSON.parse(fs13.readFileSync(packageJsonPath, "utf8"));
11621
+ const manifest = JSON.parse(fs14.readFileSync(packageJsonPath, "utf8"));
11198
11622
  if (manifest.name === locator.name) {
11199
11623
  return {
11200
11624
  blockDir: packageDir,
@@ -11203,10 +11627,10 @@ function resolveInstalledNpmTemplateSource(locator, cwd) {
11203
11627
  }
11204
11628
  }
11205
11629
  }
11206
- const workspaceRequire = createRequire2(path15.join(path15.resolve(cwd), "__wp_typia_template_resolver__.cjs"));
11630
+ const workspaceRequire = createRequire2(path17.join(path17.resolve(cwd), "__wp_typia_template_resolver__.cjs"));
11207
11631
  try {
11208
- const packageJsonPath = fs13.realpathSync(workspaceRequire.resolve(`${locator.name}/package.json`));
11209
- const sourceDir = path15.dirname(packageJsonPath);
11632
+ const packageJsonPath = fs14.realpathSync(workspaceRequire.resolve(`${locator.name}/package.json`));
11633
+ const sourceDir = path17.dirname(packageJsonPath);
11210
11634
  return {
11211
11635
  blockDir: sourceDir,
11212
11636
  rootDir: sourceDir
@@ -11215,11 +11639,11 @@ function resolveInstalledNpmTemplateSource(locator, cwd) {
11215
11639
  const errorCode = typeof error === "object" && error !== null && "code" in error ? String(error.code) : "";
11216
11640
  if (errorCode === "MODULE_NOT_FOUND" || errorCode === "ERR_PACKAGE_PATH_NOT_EXPORTED") {
11217
11641
  for (const basePath of workspaceRequire.resolve.paths(locator.name) ?? []) {
11218
- const packageJsonPath = path15.join(basePath, locator.name, "package.json");
11219
- if (!fs13.existsSync(packageJsonPath)) {
11642
+ const packageJsonPath = path17.join(basePath, locator.name, "package.json");
11643
+ if (!fs14.existsSync(packageJsonPath)) {
11220
11644
  continue;
11221
11645
  }
11222
- const sourceDir = path15.dirname(fs13.realpathSync(packageJsonPath));
11646
+ const sourceDir = path17.dirname(fs14.realpathSync(packageJsonPath));
11223
11647
  return {
11224
11648
  blockDir: sourceDir,
11225
11649
  rootDir: sourceDir
@@ -11231,64 +11655,250 @@ function resolveInstalledNpmTemplateSource(locator, cwd) {
11231
11655
  }
11232
11656
  }
11233
11657
  function isOfficialWorkspaceTemplateSeed(seed) {
11234
- const packageJsonPath = path15.join(seed.rootDir, "package.json");
11235
- if (!fs13.existsSync(packageJsonPath)) {
11658
+ const packageJsonPath = path17.join(seed.rootDir, "package.json");
11659
+ if (!fs14.existsSync(packageJsonPath)) {
11236
11660
  return false;
11237
11661
  }
11238
11662
  try {
11239
- const packageJson = JSON.parse(fs13.readFileSync(packageJsonPath, "utf8"));
11663
+ const packageJson = JSON.parse(fs14.readFileSync(packageJsonPath, "utf8"));
11240
11664
  return packageJson.name === OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE;
11241
11665
  } catch {
11242
11666
  return false;
11243
11667
  }
11244
11668
  }
11245
11669
  async function assertNoSymlinks2(sourceDir) {
11246
- const stats = await fsp9.lstat(sourceDir);
11670
+ const stats = await fsp10.lstat(sourceDir);
11247
11671
  if (stats.isSymbolicLink()) {
11248
11672
  throw new Error(`Template sources may not include symbolic links: ${sourceDir}`);
11249
11673
  }
11250
11674
  if (!stats.isDirectory()) {
11251
11675
  return;
11252
11676
  }
11253
- for (const entry of await fsp9.readdir(sourceDir)) {
11254
- await assertNoSymlinks2(path15.join(sourceDir, entry));
11677
+ for (const entry of await fsp10.readdir(sourceDir)) {
11678
+ await assertNoSymlinks2(path17.join(sourceDir, entry));
11255
11679
  }
11256
11680
  }
11257
- async function resolveGitHubTemplateSource(locator) {
11258
- const { path: remoteRoot, cleanup } = await createManagedTempRoot("wp-typia-template-source-");
11259
- const checkoutDir = path15.join(remoteRoot, "source");
11260
- try {
11261
- const args = ["clone", "--depth", "1"];
11262
- if (locator.ref) {
11263
- args.push("--branch", locator.ref);
11264
- }
11265
- args.push(`https://github.com/${locator.owner}/${locator.repo}.git`, checkoutDir);
11266
- const cloneTimeoutMs = getExternalTemplateTimeoutMs();
11267
- const cloneResult = spawnSync("git", args, {
11268
- stdio: "ignore",
11269
- timeout: cloneTimeoutMs
11270
- });
11271
- if (cloneResult.error) {
11272
- const errorCode = typeof cloneResult.error === "object" && cloneResult.error !== null && "code" in cloneResult.error ? String(cloneResult.error.code) : "";
11273
- if (errorCode === "ETIMEDOUT") {
11274
- throw createExternalTemplateTimeoutError(`cloning GitHub template ${locator.owner}/${locator.repo}`, cloneTimeoutMs);
11275
- }
11276
- throw cloneResult.error;
11681
+ function runGitTemplateCommand(args, label, options = {}) {
11682
+ const timeoutMs = getExternalTemplateTimeoutMs();
11683
+ const result = options.captureOutput ? spawnSync("git", args, {
11684
+ encoding: "utf8",
11685
+ stdio: ["ignore", "pipe", "pipe"],
11686
+ timeout: timeoutMs
11687
+ }) : spawnSync("git", args, {
11688
+ stdio: "ignore",
11689
+ timeout: timeoutMs
11690
+ });
11691
+ if (result.error) {
11692
+ const errorCode = typeof result.error === "object" && result.error !== null && "code" in result.error ? String(result.error.code) : "";
11693
+ if (errorCode === "ETIMEDOUT") {
11694
+ throw createExternalTemplateTimeoutError(label, timeoutMs);
11277
11695
  }
11278
- if (cloneResult.signal === "SIGTERM" || cloneResult.signal === "SIGKILL") {
11279
- throw createExternalTemplateTimeoutError(`cloning GitHub template ${locator.owner}/${locator.repo}`, cloneTimeoutMs);
11696
+ throw result.error;
11697
+ }
11698
+ if (result.signal === "SIGTERM" || result.signal === "SIGKILL") {
11699
+ throw createExternalTemplateTimeoutError(label, timeoutMs);
11700
+ }
11701
+ return result;
11702
+ }
11703
+ function getGitHubTemplateRepositoryUrl(locator) {
11704
+ return `https://github.com/${locator.owner}/${locator.repo}.git`;
11705
+ }
11706
+ function resolveGitHubTemplateDirectory(checkoutDir, locator) {
11707
+ const sourceDir = path17.resolve(checkoutDir, locator.sourcePath);
11708
+ const relativeSourceDir = path17.relative(checkoutDir, sourceDir);
11709
+ if (relativeSourceDir.startsWith("..") || path17.isAbsolute(relativeSourceDir)) {
11710
+ throw new Error("GitHub template path must stay within the cloned repository.");
11711
+ }
11712
+ if (!fs14.existsSync(sourceDir)) {
11713
+ throw new Error(`GitHub template path does not exist: ${locator.sourcePath}`);
11714
+ }
11715
+ return sourceDir;
11716
+ }
11717
+ function cloneGitHubTemplateSource(locator, checkoutDir) {
11718
+ const args = ["clone", "--depth", "1"];
11719
+ if (locator.ref) {
11720
+ args.push("--branch", locator.ref);
11721
+ }
11722
+ args.push(getGitHubTemplateRepositoryUrl(locator), checkoutDir);
11723
+ const cloneResult = runGitTemplateCommand(args, `cloning GitHub template ${locator.owner}/${locator.repo}`);
11724
+ if (cloneResult.status !== 0) {
11725
+ throw new Error(`Failed to clone GitHub template source ${locator.owner}/${locator.repo}.`);
11726
+ }
11727
+ }
11728
+ function readGitHubTemplateHeadRevision(checkoutDir) {
11729
+ const result = runGitTemplateCommand(["-C", checkoutDir, "rev-parse", "HEAD"], "reading GitHub template checkout revision", { captureOutput: true });
11730
+ if (result.status !== 0 || typeof result.stdout !== "string") {
11731
+ return null;
11732
+ }
11733
+ const revision = result.stdout.trim().split(/\s+/u)[0];
11734
+ return /^[0-9a-f]{40}$/iu.test(revision) ? revision.toLowerCase() : null;
11735
+ }
11736
+ function pinGitHubTemplateCacheRevision(locator, checkoutDir, cacheRevision) {
11737
+ const normalizedCacheRevision = cacheRevision.toLowerCase();
11738
+ if (readGitHubTemplateHeadRevision(checkoutDir) === normalizedCacheRevision) {
11739
+ return;
11740
+ }
11741
+ const fetchResult = runGitTemplateCommand(["-C", checkoutDir, "fetch", "--depth", "1", "origin", cacheRevision], `fetching GitHub template revision ${locator.owner}/${locator.repo}`);
11742
+ if (fetchResult.status !== 0) {
11743
+ throw createGitHubTemplateCacheRevisionRaceError(`Failed to fetch GitHub template revision ${cacheRevision} for ${locator.owner}/${locator.repo}.`);
11744
+ }
11745
+ const checkoutResult = runGitTemplateCommand(["-C", checkoutDir, "checkout", "--detach", cacheRevision], `checking out GitHub template revision ${locator.owner}/${locator.repo}`);
11746
+ if (checkoutResult.status !== 0) {
11747
+ throw createGitHubTemplateCacheRevisionRaceError(`Failed to check out GitHub template revision ${cacheRevision} for ${locator.owner}/${locator.repo}.`);
11748
+ }
11749
+ if (readGitHubTemplateHeadRevision(checkoutDir) !== normalizedCacheRevision) {
11750
+ throw createGitHubTemplateCacheRevisionRaceError(`GitHub template checkout did not match resolved revision ${cacheRevision} for ${locator.owner}/${locator.repo}.`);
11751
+ }
11752
+ }
11753
+ function getGitHubTemplateRevisionPatterns(locator) {
11754
+ const ref = locator.ref ?? "HEAD";
11755
+ if (!locator.ref) {
11756
+ return [ref];
11757
+ }
11758
+ if (ref.startsWith("refs/")) {
11759
+ return [ref, `${ref}^{}`];
11760
+ }
11761
+ return [ref, `refs/heads/${ref}`, `refs/tags/${ref}`, `refs/tags/${ref}^{}`];
11762
+ }
11763
+ function pickGitHubTemplateCacheRevision(locator, revisions) {
11764
+ const ref = locator.ref ?? "HEAD";
11765
+ if (!locator.ref) {
11766
+ return revisions[0]?.revision ?? null;
11767
+ }
11768
+ if (!ref.startsWith("refs/")) {
11769
+ const branchRevision = revisions.find((entry) => entry.resolvedRef === `refs/heads/${ref}`);
11770
+ if (branchRevision) {
11771
+ return branchRevision.revision;
11280
11772
  }
11281
- if (cloneResult.status !== 0) {
11282
- throw new Error(`Failed to clone GitHub template source ${locator.owner}/${locator.repo}.`);
11773
+ const peeledTagRevision = revisions.find((entry) => entry.resolvedRef === `refs/tags/${ref}^{}`);
11774
+ if (peeledTagRevision) {
11775
+ return peeledTagRevision.revision;
11283
11776
  }
11284
- const sourceDir = path15.resolve(checkoutDir, locator.sourcePath);
11285
- const relativeSourceDir = path15.relative(checkoutDir, sourceDir);
11286
- if (relativeSourceDir.startsWith("..") || path15.isAbsolute(relativeSourceDir)) {
11287
- throw new Error("GitHub template path must stay within the cloned repository.");
11777
+ const tagRevision = revisions.find((entry) => entry.resolvedRef === `refs/tags/${ref}`);
11778
+ if (tagRevision) {
11779
+ return tagRevision.revision;
11288
11780
  }
11289
- if (!fs13.existsSync(sourceDir)) {
11290
- throw new Error(`GitHub template path does not exist: ${locator.sourcePath}`);
11781
+ }
11782
+ if (ref.startsWith("refs/tags/")) {
11783
+ const peeledRevision = revisions.find((entry) => entry.resolvedRef === `${ref}^{}`);
11784
+ if (peeledRevision) {
11785
+ return peeledRevision.revision;
11786
+ }
11787
+ }
11788
+ const exactRevision = revisions.find((entry) => entry.resolvedRef === ref);
11789
+ return (exactRevision ?? revisions[0])?.revision ?? null;
11790
+ }
11791
+ function resolveGitHubTemplateCacheRevision(locator) {
11792
+ const result = runGitTemplateCommand([
11793
+ "ls-remote",
11794
+ getGitHubTemplateRepositoryUrl(locator),
11795
+ ...getGitHubTemplateRevisionPatterns(locator)
11796
+ ], `checking GitHub template revision ${locator.owner}/${locator.repo}`, { captureOutput: true });
11797
+ if (result.status !== 0 || typeof result.stdout !== "string") {
11798
+ return {
11799
+ lookupUnavailable: true,
11800
+ revision: null
11801
+ };
11802
+ }
11803
+ const revisions = result.stdout.split(`
11804
+ `).map((line) => {
11805
+ const [revision, resolvedRef] = line.trim().split(/\s+/u);
11806
+ if (!/^[0-9a-f]{40}$/iu.test(revision) || !resolvedRef) {
11807
+ return null;
11291
11808
  }
11809
+ return {
11810
+ resolvedRef,
11811
+ revision: revision.toLowerCase()
11812
+ };
11813
+ }).filter((entry) => entry !== null);
11814
+ return {
11815
+ lookupUnavailable: false,
11816
+ revision: pickGitHubTemplateCacheRevision(locator, revisions)
11817
+ };
11818
+ }
11819
+ function getGitHubTemplateCacheMetadata(locator, revision) {
11820
+ return {
11821
+ ...revision ? { revision } : {},
11822
+ owner: locator.owner,
11823
+ ref: locator.ref,
11824
+ repo: locator.repo,
11825
+ sourcePath: locator.sourcePath
11826
+ };
11827
+ }
11828
+ async function reuseGitHubTemplateCacheByMetadata(locator) {
11829
+ const cachedSource = await findReusableExternalTemplateSourceCache({
11830
+ metadata: getGitHubTemplateCacheMetadata(locator),
11831
+ namespace: "github"
11832
+ });
11833
+ if (!cachedSource) {
11834
+ return null;
11835
+ }
11836
+ const sourceDir = resolveGitHubTemplateDirectory(cachedSource.sourceDir, locator);
11837
+ await assertNoSymlinks2(sourceDir);
11838
+ return {
11839
+ blockDir: sourceDir,
11840
+ rootDir: sourceDir
11841
+ };
11842
+ }
11843
+ async function resolveGitHubTemplateSource(locator) {
11844
+ const cacheEnabled = isExternalTemplateCacheEnabled();
11845
+ let cacheRevisionLookupUnavailable = false;
11846
+ let cacheRevision = null;
11847
+ if (cacheEnabled) {
11848
+ try {
11849
+ const resolvedRevision = resolveGitHubTemplateCacheRevision(locator);
11850
+ cacheRevision = resolvedRevision.revision;
11851
+ cacheRevisionLookupUnavailable = resolvedRevision.lookupUnavailable;
11852
+ } catch {
11853
+ cacheRevision = null;
11854
+ cacheRevisionLookupUnavailable = true;
11855
+ }
11856
+ }
11857
+ if (cacheEnabled && !cacheRevision && cacheRevisionLookupUnavailable) {
11858
+ const cachedSource = await reuseGitHubTemplateCacheByMetadata(locator);
11859
+ if (cachedSource) {
11860
+ return cachedSource;
11861
+ }
11862
+ }
11863
+ if (cacheRevision) {
11864
+ const resolvedCacheRevision = cacheRevision;
11865
+ try {
11866
+ const cachedSource = await resolveExternalTemplateSourceCache({
11867
+ keyParts: [
11868
+ "github",
11869
+ locator.owner,
11870
+ locator.repo,
11871
+ locator.sourcePath,
11872
+ locator.ref ?? "",
11873
+ resolvedCacheRevision
11874
+ ],
11875
+ metadata: getGitHubTemplateCacheMetadata(locator, resolvedCacheRevision),
11876
+ namespace: "github"
11877
+ }, async (checkoutDir2) => {
11878
+ cloneGitHubTemplateSource(locator, checkoutDir2);
11879
+ const sourceDir = resolveGitHubTemplateDirectory(checkoutDir2, locator);
11880
+ await assertNoSymlinks2(sourceDir);
11881
+ pinGitHubTemplateCacheRevision(locator, checkoutDir2, resolvedCacheRevision);
11882
+ });
11883
+ if (cachedSource) {
11884
+ const sourceDir = resolveGitHubTemplateDirectory(cachedSource.sourceDir, locator);
11885
+ await assertNoSymlinks2(sourceDir);
11886
+ return {
11887
+ blockDir: sourceDir,
11888
+ rootDir: sourceDir
11889
+ };
11890
+ }
11891
+ } catch (error) {
11892
+ if (!isGitHubTemplateCacheRevisionRaceError(error)) {
11893
+ throw error;
11894
+ }
11895
+ }
11896
+ }
11897
+ const { path: remoteRoot, cleanup } = await createManagedTempRoot("wp-typia-template-source-");
11898
+ const checkoutDir = path17.join(remoteRoot, "source");
11899
+ try {
11900
+ cloneGitHubTemplateSource(locator, checkoutDir);
11901
+ const sourceDir = resolveGitHubTemplateDirectory(checkoutDir, locator);
11292
11902
  await assertNoSymlinks2(sourceDir);
11293
11903
  return {
11294
11904
  blockDir: sourceDir,
@@ -11302,8 +11912,8 @@ async function resolveGitHubTemplateSource(locator) {
11302
11912
  }
11303
11913
  async function resolveTemplateSeed(locator, cwd) {
11304
11914
  if (locator.kind === "path") {
11305
- const sourceDir = path15.resolve(cwd, locator.templatePath);
11306
- if (!fs13.existsSync(sourceDir)) {
11915
+ const sourceDir = path17.resolve(cwd, locator.templatePath);
11916
+ if (!fs14.existsSync(sourceDir)) {
11307
11917
  throw new Error(`Template path does not exist: ${sourceDir}`);
11308
11918
  }
11309
11919
  await assertNoSymlinks2(sourceDir);
@@ -16468,17 +17078,17 @@ async function scaffoldProject({
16468
17078
  phase: "finalize-project",
16469
17079
  title: "Finalizing scaffold output"
16470
17080
  });
16471
- const readmePath = path16.join(projectDir, "README.md");
16472
- if (!fs14.existsSync(readmePath)) {
16473
- await fsp10.writeFile(readmePath, buildReadme(resolvedTemplateId, variables, resolvedPackageManager, {
17081
+ const readmePath = path18.join(projectDir, "README.md");
17082
+ if (!fs15.existsSync(readmePath)) {
17083
+ await fsp11.writeFile(readmePath, buildReadme(resolvedTemplateId, variables, resolvedPackageManager, {
16474
17084
  withMigrationUi: isBuiltInTemplate || isWorkspace ? withMigrationUi : false,
16475
17085
  withTestPreset: isBuiltInTemplate ? withTestPreset : false,
16476
17086
  withWpEnv: isBuiltInTemplate ? withWpEnv : false
16477
17087
  }), "utf8");
16478
17088
  }
16479
- const gitignorePath = path16.join(projectDir, ".gitignore");
16480
- const existingGitignore = fs14.existsSync(gitignorePath) ? await fsp10.readFile(gitignorePath, "utf8") : "";
16481
- await fsp10.writeFile(gitignorePath, mergeTextLines(buildGitignore(), existingGitignore), "utf8");
17089
+ const gitignorePath = path18.join(projectDir, ".gitignore");
17090
+ const existingGitignore = fs15.existsSync(gitignorePath) ? await fsp11.readFile(gitignorePath, "utf8") : "";
17091
+ await fsp11.writeFile(gitignorePath, mergeTextLines(buildGitignore(), existingGitignore), "utf8");
16482
17092
  await normalizePackageJson(projectDir, resolvedPackageManager);
16483
17093
  if (isBuiltInTemplate) {
16484
17094
  const variableGroups = getScaffoldTemplateVariableGroups(variables);
@@ -16559,4 +17169,4 @@ async function resolveOptionalInteractiveExternalLayerId({
16559
17169
 
16560
17170
  export { syncPersistenceRestArtifacts, copyInterpolatedDirectory, listInterpolatedDirectoryOutputs, getPrimaryDevelopmentScript, getOptionalOnboardingSteps, getOptionalOnboardingNote, getOptionalOnboardingShortNote, formatNonEmptyTargetDirectoryError, require_semver2 as require_semver, parseTemplateLocator, resolveExternalTemplateLayers, resolveTemplateSeed, normalizeOptionalCliString, resolveLocalCliPathOption, assertExternalLayerCompositionOptions, assertBuiltInTemplateVariantAllowed, parseAlternateRenderTargets, parseCompoundInnerBlocksPreset, OPTIONAL_WORDPRESS_AI_CLIENT_COMPATIBILITY, REQUIRED_WORKSPACE_ABILITY_COMPATIBILITY, resolveScaffoldCompatibilityPolicy, renderScaffoldCompatibilityConfig, updatePluginHeaderCompatibility, getDefaultAnswers, resolveTemplateId, resolvePackageManagerId, collectScaffoldAnswers, DATA_STORAGE_MODES, PERSISTENCE_POLICIES, isDataStorageMode, isPersistencePolicy, scaffoldProject, resolveOptionalInteractiveExternalLayerId };
16561
17171
 
16562
- //# debugId=45408AA53A2AA42964756E2164756E21
17172
+ //# debugId=EFE0A10933AD252664756E2164756E21