wp-typia 0.19.0 → 0.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +4 -2
  2. package/dist-bunli/.bunli/commands.gen.js +2117 -1465
  3. package/dist-bunli/.bunli/commands.gen.js.map +42 -35
  4. package/dist-bunli/cli-03j0axbt.js +163 -0
  5. package/dist-bunli/cli-03j0axbt.js.map +11 -0
  6. package/dist-bunli/{cli-yw0mq0wq.js → cli-93wd227r.js} +108 -3
  7. package/dist-bunli/cli-93wd227r.js.map +10 -0
  8. package/dist-bunli/{cli-kan7a6db.js → cli-a6dwqnhq.js} +24 -2
  9. package/dist-bunli/cli-a6dwqnhq.js.map +11 -0
  10. package/dist-bunli/{cli-add-j2c81sh1.js → cli-add-gcwww85p.js} +263 -250
  11. package/dist-bunli/cli-add-gcwww85p.js.map +18 -0
  12. package/dist-bunli/{cli-7svz19s1.js → cli-cfx3gm1r.js} +417 -129
  13. package/dist-bunli/{cli-7svz19s1.js.map → cli-cfx3gm1r.js.map} +18 -15
  14. package/dist-bunli/{cli-diagnostics-c65hhyhx.js → cli-diagnostics-e5gxeprp.js} +8 -4
  15. package/dist-bunli/{cli-diagnostics-c65hhyhx.js.map → cli-diagnostics-e5gxeprp.js.map} +1 -1
  16. package/dist-bunli/{cli-doctor-hft0wr0e.js → cli-doctor-qk6fwpds.js} +14 -13
  17. package/dist-bunli/{cli-doctor-hft0wr0e.js.map → cli-doctor-qk6fwpds.js.map} +3 -3
  18. package/dist-bunli/{cli-572d6g4m.js → cli-hv2yedw2.js} +2 -157
  19. package/dist-bunli/{cli-572d6g4m.js.map → cli-hv2yedw2.js.map} +4 -6
  20. package/dist-bunli/cli-mgh3f3k5.js +427 -0
  21. package/dist-bunli/cli-mgh3f3k5.js.map +12 -0
  22. package/dist-bunli/{cli-scaffold-vcg6wem5.js → cli-scaffold-f1bdt68d.js} +9 -7
  23. package/dist-bunli/cli-scaffold-f1bdt68d.js.map +10 -0
  24. package/dist-bunli/cli-t73q5aqz.js +103 -0
  25. package/dist-bunli/cli-t73q5aqz.js.map +10 -0
  26. package/dist-bunli/{cli-templates-4qxszbmc.js → cli-templates-j65r4k9v.js} +1 -1
  27. package/dist-bunli/{cli-wtrvnce5.js → cli-w4r0rr8a.js} +8 -8
  28. package/dist-bunli/cli-w4r0rr8a.js.map +10 -0
  29. package/dist-bunli/cli.js +127 -2863
  30. package/dist-bunli/cli.js.map +5 -56
  31. package/dist-bunli/command-list-66cqt7y8.js +2485 -0
  32. package/dist-bunli/command-list-66cqt7y8.js.map +58 -0
  33. package/dist-bunli/node-cli.js +432 -323
  34. package/dist-bunli/node-cli.js.map +11 -10
  35. package/dist-bunli/{sync-x91y9jtv.js → sync-k2k8svyc.js} +3 -2
  36. package/dist-bunli/{sync-x91y9jtv.js.map → sync-k2k8svyc.js.map} +1 -1
  37. package/package.json +6 -3
  38. package/dist-bunli/cli-add-j2c81sh1.js.map +0 -16
  39. package/dist-bunli/cli-kan7a6db.js.map +0 -11
  40. package/dist-bunli/cli-scaffold-vcg6wem5.js.map +0 -10
  41. package/dist-bunli/cli-wtrvnce5.js.map +0 -10
  42. package/dist-bunli/cli-yw0mq0wq.js.map +0 -10
  43. /package/dist-bunli/{cli-templates-4qxszbmc.js.map → cli-templates-j65r4k9v.js.map} +0 -0
@@ -14,7 +14,7 @@ import {
14
14
  resolveTemplateSeed,
15
15
  scaffoldProject,
16
16
  syncPersistenceRestArtifacts
17
- } from "./cli-7svz19s1.js";
17
+ } from "./cli-cfx3gm1r.js";
18
18
  import {
19
19
  ensureMigrationDirectories,
20
20
  parseMigrationConfig,
@@ -26,10 +26,10 @@ import"./cli-bq2v559b.js";
26
26
  import {
27
27
  formatInstallCommand
28
28
  } from "./cli-1b5jx6j9.js";
29
- import"./cli-wtrvnce5.js";
29
+ import"./cli-w4r0rr8a.js";
30
30
  import {
31
31
  SHARED_WORKSPACE_TEMPLATE_ROOT
32
- } from "./cli-kan7a6db.js";
32
+ } from "./cli-a6dwqnhq.js";
33
33
  import {
34
34
  ADD_BLOCK_TEMPLATE_IDS,
35
35
  ADD_KIND_IDS,
@@ -65,6 +65,9 @@ import {
65
65
  toKebabCase,
66
66
  toTitleCase
67
67
  } from "./cli-rg481yks.js";
68
+ import {
69
+ createManagedTempRoot
70
+ } from "./cli-t73q5aqz.js";
68
71
  import {
69
72
  resolveWorkspaceProject
70
73
  } from "./cli-pd5pqgre.js";
@@ -72,7 +75,6 @@ import"./cli-xnn9xjcy.js";
72
75
  // ../wp-typia-project-tools/src/runtime/cli-add-block.ts
73
76
  import fs2 from "fs";
74
77
  import { promises as fsp2 } from "fs";
75
- import os from "os";
76
78
  import path3 from "path";
77
79
  import {
78
80
  syncBlockMetadata
@@ -652,6 +654,7 @@ async function runAddBlockCommand({
652
654
  selectExternalLayerId
653
655
  });
654
656
  let tempRoot = "";
657
+ let cleanupTempRoot;
655
658
  try {
656
659
  const normalizedSlug = resolveNonEmptyNormalizedBlockSlug({
657
660
  input: blockName,
@@ -659,7 +662,10 @@ async function runAddBlockCommand({
659
662
  usage: "wp-typia add block <name> --template <family>"
660
663
  });
661
664
  const defaults = getDefaultAnswers(normalizedSlug, resolvedTemplateId);
662
- tempRoot = await fsp2.mkdtemp(path3.join(os.tmpdir(), "wp-typia-add-block-"));
665
+ ({
666
+ path: tempRoot,
667
+ cleanup: cleanupTempRoot
668
+ } = await createManagedTempRoot("wp-typia-add-block-"));
663
669
  const tempProjectDir = path3.join(tempRoot, normalizedSlug);
664
670
  const blockConfigPath = path3.join(workspace.projectDir, "scripts", "block-config.ts");
665
671
  const migrationConfigPath = path3.join(workspace.projectDir, "src", "migrations", "config.ts");
@@ -729,16 +735,17 @@ async function runAddBlockCommand({
729
735
  throw error;
730
736
  }
731
737
  } finally {
732
- await resolvedExternalLayerSelection.cleanup?.();
733
- if (tempRoot) {
734
- await fsp2.rm(tempRoot, { force: true, recursive: true });
738
+ try {
739
+ await resolvedExternalLayerSelection.cleanup?.();
740
+ } finally {
741
+ await cleanupTempRoot?.();
735
742
  }
736
743
  }
737
744
  }
738
745
  // ../wp-typia-project-tools/src/runtime/cli-add-workspace.ts
739
746
  import fs4 from "fs";
740
747
  import { promises as fsp5 } from "fs";
741
- import path7 from "path";
748
+ import path8 from "path";
742
749
 
743
750
  // ../wp-typia-project-tools/src/runtime/cli-add-workspace-assets.ts
744
751
  import fs3 from "fs";
@@ -1551,10 +1558,209 @@ async function runAddBindingSourceCommand({
1551
1558
  }
1552
1559
  // ../wp-typia-project-tools/src/runtime/cli-add-workspace-rest.ts
1553
1560
  import { promises as fsp4 } from "fs";
1554
- import path6 from "path";
1561
+ import path7 from "path";
1555
1562
 
1556
- // ../wp-typia-project-tools/src/runtime/rest-resource-artifacts.ts
1563
+ // ../wp-typia-project-tools/src/runtime/cli-add-workspace-rest-anchors.ts
1557
1564
  import path5 from "path";
1565
+ var REST_RESOURCE_SERVER_GLOB = "/inc/rest/*.php";
1566
+ function escapeRegex2(value) {
1567
+ return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
1568
+ }
1569
+ async function ensureRestResourceBootstrapAnchors(workspace) {
1570
+ const bootstrapPath = getWorkspaceBootstrapPath(workspace);
1571
+ await patchFile(bootstrapPath, (source) => {
1572
+ let nextSource = source;
1573
+ const registerFunctionName = `${workspace.workspace.phpPrefix}_register_rest_resources`;
1574
+ const registerHook = `add_action( 'init', '${registerFunctionName}', 20 );`;
1575
+ const registerFunction = `
1576
+
1577
+ function ${registerFunctionName}() {
1578
+ foreach ( glob( __DIR__ . '${REST_RESOURCE_SERVER_GLOB}' ) ?: array() as $rest_resource_module ) {
1579
+ require_once $rest_resource_module;
1580
+ }
1581
+ }
1582
+ `;
1583
+ const insertionAnchors = [
1584
+ /add_action\(\s*["']init["']\s*,\s*["'][^"']+_load_textdomain["']\s*\);\s*\n/u,
1585
+ /\?>\s*$/u
1586
+ ];
1587
+ const hasPhpFunctionDefinition = (functionName) => new RegExp(`function\\s+${escapeRegex2(functionName)}\\s*\\(`, "u").test(nextSource);
1588
+ const insertPhpSnippet = (snippet) => {
1589
+ for (const anchor of insertionAnchors) {
1590
+ const candidate = nextSource.replace(anchor, (match) => `${snippet}
1591
+ ${match}`);
1592
+ if (candidate !== nextSource) {
1593
+ nextSource = candidate;
1594
+ return;
1595
+ }
1596
+ }
1597
+ nextSource = `${nextSource.trimEnd()}
1598
+ ${snippet}
1599
+ `;
1600
+ };
1601
+ const appendPhpSnippet = (snippet) => {
1602
+ const closingTagPattern = /\?>\s*$/u;
1603
+ if (closingTagPattern.test(nextSource)) {
1604
+ nextSource = nextSource.replace(closingTagPattern, `${snippet}
1605
+ ?>`);
1606
+ return;
1607
+ }
1608
+ nextSource = `${nextSource.trimEnd()}
1609
+ ${snippet}
1610
+ `;
1611
+ };
1612
+ if (!hasPhpFunctionDefinition(registerFunctionName)) {
1613
+ insertPhpSnippet(registerFunction);
1614
+ } else if (!nextSource.includes(REST_RESOURCE_SERVER_GLOB)) {
1615
+ throw new Error([
1616
+ `Unable to patch ${path5.basename(bootstrapPath)} in ensureRestResourceBootstrapAnchors.`,
1617
+ `The existing ${registerFunctionName}() definition does not include ${REST_RESOURCE_SERVER_GLOB}.`,
1618
+ "Restore the generated bootstrap shape or wire the REST resource loader manually before retrying."
1619
+ ].join(" "));
1620
+ }
1621
+ if (!nextSource.includes(registerHook)) {
1622
+ appendPhpSnippet(registerHook);
1623
+ }
1624
+ return nextSource;
1625
+ });
1626
+ }
1627
+ function assertSyncRestAnchor(nextSource, target, anchorDescription, hasAnchor, syncRestScriptPath) {
1628
+ if (!nextSource.includes(target) && !hasAnchor) {
1629
+ throw new Error([
1630
+ `ensureRestResourceSyncScriptAnchors could not patch ${path5.basename(syncRestScriptPath)}.`,
1631
+ `Missing expected ${anchorDescription} anchor in scripts/sync-rest-contracts.ts.`,
1632
+ "Restore the generated template or add the REST_RESOURCES wiring manually before retrying."
1633
+ ].join(" "));
1634
+ }
1635
+ }
1636
+ function replaceRequiredSyncRestSource(nextSource, target, anchor, replacement, anchorDescription, syncRestScriptPath) {
1637
+ if (nextSource.includes(target)) {
1638
+ return nextSource;
1639
+ }
1640
+ const hasAnchor = typeof anchor === "string" ? nextSource.includes(anchor) : anchor.test(nextSource);
1641
+ assertSyncRestAnchor(nextSource, target, anchorDescription, hasAnchor, syncRestScriptPath);
1642
+ return nextSource.replace(anchor, replacement);
1643
+ }
1644
+ async function ensureRestResourceSyncScriptAnchors(workspace) {
1645
+ const syncRestScriptPath = path5.join(workspace.projectDir, "scripts", "sync-rest-contracts.ts");
1646
+ await patchFile(syncRestScriptPath, (source) => {
1647
+ let nextSource = source;
1648
+ const importAnchor = "import { BLOCKS, type WorkspaceBlockConfig } from './block-config';";
1649
+ const helperInsertionAnchor = "async function assertTypeArtifactsCurrent";
1650
+ const restBlocksAnchor = "const restBlocks = BLOCKS.filter( isRestEnabledBlock );";
1651
+ const noResourcesPattern = /if \( restBlocks.length === 0 \) \{[\s\S]*?\n\t\treturn;\n\t\}/u;
1652
+ const consoleLogPattern = /\n\tconsole\.log\(\n\t\toptions\.check/u;
1653
+ nextSource = replaceRequiredSyncRestSource(nextSource, "REST_RESOURCES", importAnchor, [
1654
+ "import {",
1655
+ "\tBLOCKS,",
1656
+ "\tREST_RESOURCES,",
1657
+ "\ttype WorkspaceBlockConfig,",
1658
+ "\ttype WorkspaceRestResourceConfig,",
1659
+ "} from './block-config';"
1660
+ ].join(`
1661
+ `), "BLOCKS import", syncRestScriptPath);
1662
+ nextSource = replaceRequiredSyncRestSource(nextSource, "function isWorkspaceRestResource(", helperInsertionAnchor, [
1663
+ "function isWorkspaceRestResource(",
1664
+ "\tresource: WorkspaceRestResourceConfig",
1665
+ "): resource is WorkspaceRestResourceConfig & {",
1666
+ "\tclientFile: string;",
1667
+ "\topenApiFile: string;",
1668
+ "\trestManifest: NonNullable< WorkspaceRestResourceConfig[ 'restManifest' ] >;",
1669
+ "\ttypesFile: string;",
1670
+ "\tvalidatorsFile: string;",
1671
+ "} {",
1672
+ "\treturn (",
1673
+ "\t\ttypeof resource.clientFile === 'string' &&",
1674
+ "\t\ttypeof resource.openApiFile === 'string' &&",
1675
+ "\t\ttypeof resource.typesFile === 'string' &&",
1676
+ "\t\ttypeof resource.validatorsFile === 'string' &&",
1677
+ "\t\ttypeof resource.restManifest === 'object' &&",
1678
+ "\t\tresource.restManifest !== null",
1679
+ "\t);",
1680
+ "}",
1681
+ "",
1682
+ "async function assertTypeArtifactsCurrent"
1683
+ ].join(`
1684
+ `), "type artifact assertion helper", syncRestScriptPath);
1685
+ nextSource = replaceRequiredSyncRestSource(nextSource, "const restResources = REST_RESOURCES.filter( isWorkspaceRestResource );", restBlocksAnchor, [
1686
+ "const restBlocks = BLOCKS.filter( isRestEnabledBlock );",
1687
+ "const restResources = REST_RESOURCES.filter( isWorkspaceRestResource );"
1688
+ ].join(`
1689
+ `), "restBlocks filter", syncRestScriptPath);
1690
+ nextSource = replaceRequiredSyncRestSource(nextSource, "restBlocks.length === 0 && restResources.length === 0", noResourcesPattern, [
1691
+ "if ( restBlocks.length === 0 && restResources.length === 0 ) {",
1692
+ "\t\tconsole.log(",
1693
+ "\t\t\toptions.check",
1694
+ "\t\t\t\t? '\u2139\uFE0F No REST-enabled workspace blocks or plugin-level REST resources are registered yet. `sync-rest --check` is already clean.'",
1695
+ "\t\t\t\t: '\u2139\uFE0F No REST-enabled workspace blocks or plugin-level REST resources are registered yet.'",
1696
+ "\t\t);",
1697
+ "\t\treturn;",
1698
+ "\t}"
1699
+ ].join(`
1700
+ `), "no-resources guard", syncRestScriptPath);
1701
+ nextSource = replaceRequiredSyncRestSource(nextSource, "for ( const resource of restResources ) {", consoleLogPattern, [
1702
+ "",
1703
+ "\tfor ( const resource of restResources ) {",
1704
+ "\t\tconst contracts = resource.restManifest.contracts;",
1705
+ "",
1706
+ "\t\tfor ( const [ baseName, contract ] of Object.entries( contracts ) ) {",
1707
+ "\t\t\tawait syncTypeSchemas(",
1708
+ "\t\t\t\t{",
1709
+ "\t\t\t\t\tjsonSchemaFile: path.join(",
1710
+ "\t\t\t\t\t\tpath.dirname( resource.typesFile ),",
1711
+ "\t\t\t\t\t\t'api-schemas',",
1712
+ "\t\t\t\t\t\t`${ baseName }.schema.json`",
1713
+ "\t\t\t\t\t),",
1714
+ "\t\t\t\t\topenApiFile: path.join(",
1715
+ "\t\t\t\t\t\tpath.dirname( resource.typesFile ),",
1716
+ "\t\t\t\t\t\t'api-schemas',",
1717
+ "\t\t\t\t\t\t`${ baseName }.openapi.json`",
1718
+ "\t\t\t\t\t),",
1719
+ "\t\t\t\t\tsourceTypeName: contract.sourceTypeName,",
1720
+ "\t\t\t\t\ttypesFile: resource.typesFile,",
1721
+ "\t\t\t\t},",
1722
+ "\t\t\t\t{",
1723
+ "\t\t\t\t\tcheck: options.check,",
1724
+ "\t\t\t\t}",
1725
+ "\t\t\t);",
1726
+ "\t\t}",
1727
+ "",
1728
+ "\t\tawait syncRestOpenApi(",
1729
+ "\t\t\t{",
1730
+ "\t\t\t\tmanifest: resource.restManifest,",
1731
+ "\t\t\t\topenApiFile: resource.openApiFile,",
1732
+ "\t\t\t\ttypesFile: resource.typesFile,",
1733
+ "\t\t\t},",
1734
+ "\t\t\t{",
1735
+ "\t\t\t\tcheck: options.check,",
1736
+ "\t\t\t}",
1737
+ "\t\t);",
1738
+ "",
1739
+ "\t\tawait syncEndpointClient(",
1740
+ "\t\t\t{",
1741
+ "\t\t\t\tclientFile: resource.clientFile,",
1742
+ "\t\t\t\tmanifest: resource.restManifest,",
1743
+ "\t\t\t\ttypesFile: resource.typesFile,",
1744
+ "\t\t\t\tvalidatorsFile: resource.validatorsFile,",
1745
+ "\t\t\t},",
1746
+ "\t\t\t{",
1747
+ "\t\t\t\tcheck: options.check,",
1748
+ "\t\t\t}",
1749
+ "\t\t);",
1750
+ "\t}",
1751
+ "",
1752
+ "\tconsole.log(",
1753
+ "\t\toptions.check"
1754
+ ].join(`
1755
+ `), "success log insertion point", syncRestScriptPath);
1756
+ nextSource = nextSource.replace("\u2705 REST contract schemas, portable API clients, and endpoint-aware OpenAPI documents are already up to date with the TypeScript types!", "\u2705 REST contract schemas, portable API clients, and endpoint-aware OpenAPI documents are already up to date for workspace blocks and plugin-level resources!");
1757
+ nextSource = nextSource.replace("\u2705 REST contract schemas, portable API clients, and endpoint-aware OpenAPI documents generated from TypeScript types!", "\u2705 REST contract schemas, portable API clients, and endpoint-aware OpenAPI documents generated for workspace blocks and plugin-level resources!");
1758
+ return nextSource;
1759
+ });
1760
+ }
1761
+
1762
+ // ../wp-typia-project-tools/src/runtime/rest-resource-artifacts.ts
1763
+ import path6 from "path";
1558
1764
  import {
1559
1765
  defineEndpointManifest,
1560
1766
  syncEndpointClient,
@@ -1690,8 +1896,8 @@ async function syncRestResourceArtifacts({
1690
1896
  const manifest = buildRestResourceEndpointManifest(variables, methods);
1691
1897
  for (const [baseName, contract] of Object.entries(manifest.contracts)) {
1692
1898
  await syncTypeSchemas({
1693
- jsonSchemaFile: path5.join(outputDir, "api-schemas", `${baseName}.schema.json`),
1694
- openApiFile: path5.join(outputDir, "api-schemas", `${baseName}.openapi.json`),
1899
+ jsonSchemaFile: path6.join(outputDir, "api-schemas", `${baseName}.schema.json`),
1900
+ openApiFile: path6.join(outputDir, "api-schemas", `${baseName}.openapi.json`),
1695
1901
  projectRoot: projectDir,
1696
1902
  sourceTypeName: contract.sourceTypeName,
1697
1903
  typesFile
@@ -1699,7 +1905,7 @@ async function syncRestResourceArtifacts({
1699
1905
  }
1700
1906
  await syncRestOpenApi({
1701
1907
  manifest,
1702
- openApiFile: path5.join(outputDir, "api.openapi.json"),
1908
+ openApiFile: path6.join(outputDir, "api.openapi.json"),
1703
1909
  projectRoot: projectDir,
1704
1910
  typesFile
1705
1911
  });
@@ -1712,14 +1918,7 @@ async function syncRestResourceArtifacts({
1712
1918
  });
1713
1919
  }
1714
1920
 
1715
- // ../wp-typia-project-tools/src/runtime/cli-add-workspace-rest.ts
1716
- var REST_RESOURCE_SERVER_GLOB = "/inc/rest/*.php";
1717
- function escapeRegex2(value) {
1718
- return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
1719
- }
1720
- function quotePhpString2(value) {
1721
- return `'${value.replace(/\\/gu, "\\\\").replace(/'/gu, "\\'")}'`;
1722
- }
1921
+ // ../wp-typia-project-tools/src/runtime/cli-add-workspace-rest-source-emitters.ts
1723
1922
  function toPascalCaseFromSlug2(slug) {
1724
1923
  return normalizeBlockSlug(slug).split("-").filter(Boolean).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1)).join("");
1725
1924
  }
@@ -1942,21 +2141,7 @@ export function deleteResource( request: ${pascalCase}DeleteQuery ) {
1942
2141
  return callEndpoint( restResourceDeleteEndpoint, request );
1943
2142
  }`);
1944
2143
  }
1945
- return `import {
1946
- callEndpoint,
1947
- resolveRestRouteUrl,
1948
- } from '@wp-typia/rest';
1949
-
1950
- import type {
1951
- ${Array.from(typeImports).sort().join(`,
1952
- `)},
1953
- } from './api-types';
1954
- import {
1955
- ${clientEndpointImports.sort().join(`,
1956
- `)},
1957
- } from './api-client';
1958
- ${writeMethods.length > 0 ? `
1959
- function resolveRestNonce( fallback?: string ): string | undefined {
2144
+ const resolveRestNonceSource = writeMethods.length > 0 ? `function resolveRestNonce( fallback?: string ): string | undefined {
1960
2145
  if ( typeof fallback === 'string' && fallback.length > 0 ) {
1961
2146
  return fallback;
1962
2147
  }
@@ -1976,7 +2161,22 @@ function resolveRestNonce( fallback?: string ): string | undefined {
1976
2161
  ? wpApiSettings.nonce
1977
2162
  : undefined;
1978
2163
  }
1979
- ` : ""}
2164
+
2165
+ ` : "";
2166
+ return `import {
2167
+ callEndpoint,
2168
+ resolveRestRouteUrl,
2169
+ } from '@wp-typia/rest';
2170
+
2171
+ import type {
2172
+ ${Array.from(typeImports).sort().join(`,
2173
+ `)},
2174
+ } from './api-types';
2175
+ import {
2176
+ ${clientEndpointImports.sort().join(`,
2177
+ `)},
2178
+ } from './api-client';
2179
+ ${resolveRestNonceSource}
1980
2180
  ${exportedBindings.join(`
1981
2181
 
1982
2182
  `)}
@@ -2102,6 +2302,11 @@ ${exportedBindings.join(`
2102
2302
  `)}
2103
2303
  `;
2104
2304
  }
2305
+
2306
+ // ../wp-typia-project-tools/src/runtime/cli-add-workspace-rest.ts
2307
+ function quotePhpString2(value) {
2308
+ return `'${value.replace(/\\/gu, "\\\\").replace(/'/gu, "\\'")}'`;
2309
+ }
2105
2310
  function buildRestResourceRouteRegistrations(restResourceSlug, methods, functions) {
2106
2311
  const collectionRoutes = [];
2107
2312
  const itemRoutes = [];
@@ -2519,198 +2724,6 @@ ${routeRegistrations}
2519
2724
  add_action( 'rest_api_init', '${registerRoutesFunctionName}' );
2520
2725
  `;
2521
2726
  }
2522
- async function ensureRestResourceBootstrapAnchors(workspace) {
2523
- const bootstrapPath = getWorkspaceBootstrapPath(workspace);
2524
- await patchFile(bootstrapPath, (source) => {
2525
- let nextSource = source;
2526
- const registerFunctionName = `${workspace.workspace.phpPrefix}_register_rest_resources`;
2527
- const registerHook = `add_action( 'init', '${registerFunctionName}', 20 );`;
2528
- const registerFunction = `
2529
-
2530
- function ${registerFunctionName}() {
2531
- foreach ( glob( __DIR__ . '${REST_RESOURCE_SERVER_GLOB}' ) ?: array() as $rest_resource_module ) {
2532
- require_once $rest_resource_module;
2533
- }
2534
- }
2535
- `;
2536
- const insertionAnchors = [
2537
- /add_action\(\s*["']init["']\s*,\s*["'][^"']+_load_textdomain["']\s*\);\s*\n/u,
2538
- /\?>\s*$/u
2539
- ];
2540
- const hasPhpFunctionDefinition = (functionName) => new RegExp(`function\\s+${escapeRegex2(functionName)}\\s*\\(`, "u").test(nextSource);
2541
- const insertPhpSnippet = (snippet) => {
2542
- for (const anchor of insertionAnchors) {
2543
- const candidate = nextSource.replace(anchor, (match) => `${snippet}
2544
- ${match}`);
2545
- if (candidate !== nextSource) {
2546
- nextSource = candidate;
2547
- return;
2548
- }
2549
- }
2550
- nextSource = `${nextSource.trimEnd()}
2551
- ${snippet}
2552
- `;
2553
- };
2554
- const appendPhpSnippet = (snippet) => {
2555
- const closingTagPattern = /\?>\s*$/u;
2556
- if (closingTagPattern.test(nextSource)) {
2557
- nextSource = nextSource.replace(closingTagPattern, `${snippet}
2558
- ?>`);
2559
- return;
2560
- }
2561
- nextSource = `${nextSource.trimEnd()}
2562
- ${snippet}
2563
- `;
2564
- };
2565
- if (!hasPhpFunctionDefinition(registerFunctionName)) {
2566
- insertPhpSnippet(registerFunction);
2567
- } else if (!nextSource.includes(REST_RESOURCE_SERVER_GLOB)) {
2568
- throw new Error([
2569
- `Unable to patch ${path6.basename(bootstrapPath)} in ensureRestResourceBootstrapAnchors.`,
2570
- `The existing ${registerFunctionName}() definition does not include ${REST_RESOURCE_SERVER_GLOB}.`,
2571
- "Restore the generated bootstrap shape or wire the REST resource loader manually before retrying."
2572
- ].join(" "));
2573
- }
2574
- if (!nextSource.includes(registerHook)) {
2575
- appendPhpSnippet(registerHook);
2576
- }
2577
- return nextSource;
2578
- });
2579
- }
2580
- function assertSyncRestAnchor(nextSource, target, anchorDescription, hasAnchor, syncRestScriptPath) {
2581
- if (!nextSource.includes(target) && !hasAnchor) {
2582
- throw new Error([
2583
- `ensureRestResourceSyncScriptAnchors could not patch ${path6.basename(syncRestScriptPath)}.`,
2584
- `Missing expected ${anchorDescription} anchor in scripts/sync-rest-contracts.ts.`,
2585
- "Restore the generated template or add the REST_RESOURCES wiring manually before retrying."
2586
- ].join(" "));
2587
- }
2588
- }
2589
- function replaceRequiredSyncRestSource(nextSource, target, anchor, replacement, anchorDescription, syncRestScriptPath) {
2590
- if (nextSource.includes(target)) {
2591
- return nextSource;
2592
- }
2593
- const hasAnchor = typeof anchor === "string" ? nextSource.includes(anchor) : anchor.test(nextSource);
2594
- assertSyncRestAnchor(nextSource, target, anchorDescription, hasAnchor, syncRestScriptPath);
2595
- return nextSource.replace(anchor, replacement);
2596
- }
2597
- async function ensureRestResourceSyncScriptAnchors(workspace) {
2598
- const syncRestScriptPath = path6.join(workspace.projectDir, "scripts", "sync-rest-contracts.ts");
2599
- await patchFile(syncRestScriptPath, (source) => {
2600
- let nextSource = source;
2601
- const importAnchor = "import { BLOCKS, type WorkspaceBlockConfig } from './block-config';";
2602
- const helperInsertionAnchor = "async function assertTypeArtifactsCurrent";
2603
- const restBlocksAnchor = "const restBlocks = BLOCKS.filter( isRestEnabledBlock );";
2604
- const noResourcesPattern = /if \( restBlocks.length === 0 \) \{[\s\S]*?\n\t\treturn;\n\t\}/u;
2605
- const consoleLogPattern = /\n\tconsole\.log\(\n\t\toptions\.check/u;
2606
- nextSource = replaceRequiredSyncRestSource(nextSource, "REST_RESOURCES", importAnchor, [
2607
- "import {",
2608
- "\tBLOCKS,",
2609
- "\tREST_RESOURCES,",
2610
- "\ttype WorkspaceBlockConfig,",
2611
- "\ttype WorkspaceRestResourceConfig,",
2612
- "} from './block-config';"
2613
- ].join(`
2614
- `), "BLOCKS import", syncRestScriptPath);
2615
- nextSource = replaceRequiredSyncRestSource(nextSource, "function isWorkspaceRestResource(", helperInsertionAnchor, [
2616
- "function isWorkspaceRestResource(",
2617
- "\tresource: WorkspaceRestResourceConfig",
2618
- "): resource is WorkspaceRestResourceConfig & {",
2619
- "\tclientFile: string;",
2620
- "\topenApiFile: string;",
2621
- "\trestManifest: NonNullable< WorkspaceRestResourceConfig[ 'restManifest' ] >;",
2622
- "\ttypesFile: string;",
2623
- "\tvalidatorsFile: string;",
2624
- "} {",
2625
- "\treturn (",
2626
- "\t\ttypeof resource.clientFile === 'string' &&",
2627
- "\t\ttypeof resource.openApiFile === 'string' &&",
2628
- "\t\ttypeof resource.typesFile === 'string' &&",
2629
- "\t\ttypeof resource.validatorsFile === 'string' &&",
2630
- "\t\ttypeof resource.restManifest === 'object' &&",
2631
- "\t\tresource.restManifest !== null",
2632
- "\t);",
2633
- "}",
2634
- "",
2635
- "async function assertTypeArtifactsCurrent"
2636
- ].join(`
2637
- `), "type artifact assertion helper", syncRestScriptPath);
2638
- nextSource = replaceRequiredSyncRestSource(nextSource, "const restResources = REST_RESOURCES.filter( isWorkspaceRestResource );", restBlocksAnchor, [
2639
- "const restBlocks = BLOCKS.filter( isRestEnabledBlock );",
2640
- "const restResources = REST_RESOURCES.filter( isWorkspaceRestResource );"
2641
- ].join(`
2642
- `), "restBlocks filter", syncRestScriptPath);
2643
- nextSource = replaceRequiredSyncRestSource(nextSource, "restBlocks.length === 0 && restResources.length === 0", noResourcesPattern, [
2644
- "if ( restBlocks.length === 0 && restResources.length === 0 ) {",
2645
- "\t\tconsole.log(",
2646
- "\t\t\toptions.check",
2647
- "\t\t\t\t? '\u2139\uFE0F No REST-enabled workspace blocks or plugin-level REST resources are registered yet. `sync-rest --check` is already clean.'",
2648
- "\t\t\t\t: '\u2139\uFE0F No REST-enabled workspace blocks or plugin-level REST resources are registered yet.'",
2649
- "\t\t);",
2650
- "\t\treturn;",
2651
- "\t}"
2652
- ].join(`
2653
- `), "no-resources guard", syncRestScriptPath);
2654
- nextSource = replaceRequiredSyncRestSource(nextSource, "for ( const resource of restResources ) {", consoleLogPattern, [
2655
- "",
2656
- "\tfor ( const resource of restResources ) {",
2657
- "\t\tconst contracts = resource.restManifest.contracts;",
2658
- "",
2659
- "\t\tfor ( const [ baseName, contract ] of Object.entries( contracts ) ) {",
2660
- "\t\t\tawait syncTypeSchemas(",
2661
- "\t\t\t\t{",
2662
- "\t\t\t\t\tjsonSchemaFile: path.join(",
2663
- "\t\t\t\t\t\tpath.dirname( resource.typesFile ),",
2664
- "\t\t\t\t\t\t'api-schemas',",
2665
- "\t\t\t\t\t\t`${ baseName }.schema.json`",
2666
- "\t\t\t\t\t),",
2667
- "\t\t\t\t\topenApiFile: path.join(",
2668
- "\t\t\t\t\t\tpath.dirname( resource.typesFile ),",
2669
- "\t\t\t\t\t\t'api-schemas',",
2670
- "\t\t\t\t\t\t`${ baseName }.openapi.json`",
2671
- "\t\t\t\t\t),",
2672
- "\t\t\t\t\tsourceTypeName: contract.sourceTypeName,",
2673
- "\t\t\t\t\ttypesFile: resource.typesFile,",
2674
- "\t\t\t\t},",
2675
- "\t\t\t\t{",
2676
- "\t\t\t\t\tcheck: options.check,",
2677
- "\t\t\t\t}",
2678
- "\t\t\t);",
2679
- "\t\t}",
2680
- "",
2681
- "\t\tawait syncRestOpenApi(",
2682
- "\t\t\t{",
2683
- "\t\t\t\tmanifest: resource.restManifest,",
2684
- "\t\t\t\topenApiFile: resource.openApiFile,",
2685
- "\t\t\t\ttypesFile: resource.typesFile,",
2686
- "\t\t\t},",
2687
- "\t\t\t{",
2688
- "\t\t\t\tcheck: options.check,",
2689
- "\t\t\t}",
2690
- "\t\t);",
2691
- "",
2692
- "\t\tawait syncEndpointClient(",
2693
- "\t\t\t{",
2694
- "\t\t\t\tclientFile: resource.clientFile,",
2695
- "\t\t\t\tmanifest: resource.restManifest,",
2696
- "\t\t\t\ttypesFile: resource.typesFile,",
2697
- "\t\t\t\tvalidatorsFile: resource.validatorsFile,",
2698
- "\t\t\t},",
2699
- "\t\t\t{",
2700
- "\t\t\t\tcheck: options.check,",
2701
- "\t\t\t}",
2702
- "\t\t);",
2703
- "\t}",
2704
- "",
2705
- "\tconsole.log(",
2706
- "\t\toptions.check"
2707
- ].join(`
2708
- `), "success log insertion point", syncRestScriptPath);
2709
- nextSource = nextSource.replace("\u2705 REST contract schemas, portable API clients, and endpoint-aware OpenAPI documents are already up to date with the TypeScript types!", "\u2705 REST contract schemas, portable API clients, and endpoint-aware OpenAPI documents are already up to date for workspace blocks and plugin-level resources!");
2710
- nextSource = nextSource.replace("\u2705 REST contract schemas, portable API clients, and endpoint-aware OpenAPI documents generated from TypeScript types!", "\u2705 REST contract schemas, portable API clients, and endpoint-aware OpenAPI documents generated for workspace blocks and plugin-level resources!");
2711
- return nextSource;
2712
- });
2713
- }
2714
2727
  async function runAddRestResourceCommand({
2715
2728
  cwd = process.cwd(),
2716
2729
  methods,
@@ -2723,16 +2736,16 @@ async function runAddRestResourceCommand({
2723
2736
  const resolvedNamespace = resolveRestResourceNamespace(workspace.workspace.namespace, namespace);
2724
2737
  const inventory = readWorkspaceInventory(workspace.projectDir);
2725
2738
  assertRestResourceDoesNotExist(workspace.projectDir, restResourceSlug, inventory);
2726
- const blockConfigPath = path6.join(workspace.projectDir, "scripts", "block-config.ts");
2739
+ const blockConfigPath = path7.join(workspace.projectDir, "scripts", "block-config.ts");
2727
2740
  const bootstrapPath = getWorkspaceBootstrapPath(workspace);
2728
- const syncRestScriptPath = path6.join(workspace.projectDir, "scripts", "sync-rest-contracts.ts");
2729
- const restResourceDir = path6.join(workspace.projectDir, "src", "rest", restResourceSlug);
2730
- const typesFilePath = path6.join(restResourceDir, "api-types.ts");
2731
- const validatorsFilePath = path6.join(restResourceDir, "api-validators.ts");
2732
- const apiFilePath = path6.join(restResourceDir, "api.ts");
2733
- const dataFilePath = path6.join(restResourceDir, "data.ts");
2734
- const clientFilePath = path6.join(restResourceDir, "api-client.ts");
2735
- const phpFilePath = path6.join(workspace.projectDir, "inc", "rest", `${restResourceSlug}.php`);
2741
+ const syncRestScriptPath = path7.join(workspace.projectDir, "scripts", "sync-rest-contracts.ts");
2742
+ const restResourceDir = path7.join(workspace.projectDir, "src", "rest", restResourceSlug);
2743
+ const typesFilePath = path7.join(restResourceDir, "api-types.ts");
2744
+ const validatorsFilePath = path7.join(restResourceDir, "api-validators.ts");
2745
+ const apiFilePath = path7.join(restResourceDir, "api.ts");
2746
+ const dataFilePath = path7.join(restResourceDir, "data.ts");
2747
+ const clientFilePath = path7.join(restResourceDir, "api-client.ts");
2748
+ const phpFilePath = path7.join(workspace.projectDir, "inc", "rest", `${restResourceSlug}.php`);
2736
2749
  const mutationSnapshot = {
2737
2750
  fileSources: await snapshotWorkspaceFiles([
2738
2751
  blockConfigPath,
@@ -2744,7 +2757,7 @@ async function runAddRestResourceCommand({
2744
2757
  };
2745
2758
  try {
2746
2759
  await fsp4.mkdir(restResourceDir, { recursive: true });
2747
- await fsp4.mkdir(path6.dirname(phpFilePath), { recursive: true });
2760
+ await fsp4.mkdir(path7.dirname(phpFilePath), { recursive: true });
2748
2761
  await ensureRestResourceBootstrapAnchors(workspace);
2749
2762
  await ensureRestResourceSyncScriptAnchors(workspace);
2750
2763
  await fsp4.writeFile(typesFilePath, buildRestResourceTypesSource(restResourceSlug, resolvedMethods), "utf8");
@@ -2887,14 +2900,14 @@ ${VARIATIONS_CALL_LINE}
2887
2900
  }
2888
2901
  }
2889
2902
  if (!nextSource.includes(VARIATIONS_CALL_LINE)) {
2890
- throw new Error(`Unable to inject ${VARIATIONS_CALL_LINE} into ${path7.basename(blockIndexPath)}.`);
2903
+ throw new Error(`Unable to inject ${VARIATIONS_CALL_LINE} into ${path8.basename(blockIndexPath)}.`);
2891
2904
  }
2892
2905
  return nextSource;
2893
2906
  });
2894
2907
  }
2895
2908
  async function writeVariationRegistry(projectDir, blockSlug, variationSlug) {
2896
- const variationsDir = path7.join(projectDir, "src", "blocks", blockSlug, "variations");
2897
- const variationsIndexPath = path7.join(variationsDir, "index.ts");
2909
+ const variationsDir = path8.join(projectDir, "src", "blocks", blockSlug, "variations");
2910
+ const variationsIndexPath = path8.join(variationsDir, "index.ts");
2898
2911
  await fsp5.mkdir(variationsDir, { recursive: true });
2899
2912
  const existingVariationSlugs = fs4.readdirSync(variationsDir).filter((entry) => entry.endsWith(".ts") && entry !== "index.ts").map((entry) => entry.replace(/\.ts$/u, ""));
2900
2913
  const nextVariationSlugs = Array.from(new Set([...existingVariationSlugs, variationSlug])).sort();
@@ -2911,11 +2924,11 @@ async function runAddVariationCommand({
2911
2924
  const inventory = readWorkspaceInventory(workspace.projectDir);
2912
2925
  resolveWorkspaceBlock(inventory, blockSlug);
2913
2926
  assertVariationDoesNotExist(workspace.projectDir, blockSlug, variationSlug, inventory);
2914
- const blockConfigPath = path7.join(workspace.projectDir, "scripts", "block-config.ts");
2915
- const blockIndexPath = path7.join(workspace.projectDir, "src", "blocks", blockSlug, "index.tsx");
2916
- const variationsDir = path7.join(workspace.projectDir, "src", "blocks", blockSlug, "variations");
2917
- const variationFilePath = path7.join(variationsDir, `${variationSlug}.ts`);
2918
- const variationsIndexPath = path7.join(variationsDir, "index.ts");
2927
+ const blockConfigPath = path8.join(workspace.projectDir, "scripts", "block-config.ts");
2928
+ const blockIndexPath = path8.join(workspace.projectDir, "src", "blocks", blockSlug, "index.tsx");
2929
+ const variationsDir = path8.join(workspace.projectDir, "src", "blocks", blockSlug, "variations");
2930
+ const variationFilePath = path8.join(variationsDir, `${variationSlug}.ts`);
2931
+ const variationsIndexPath = path8.join(variationsDir, "index.ts");
2919
2932
  const mutationSnapshot = {
2920
2933
  fileSources: await snapshotWorkspaceFiles([
2921
2934
  blockConfigPath,
@@ -2960,7 +2973,7 @@ async function runAddHookedBlockCommand({
2960
2973
  throw new Error("`wp-typia add hooked-block` cannot hook a block relative to its own block name.");
2961
2974
  }
2962
2975
  const { blockJson, blockJsonPath } = readWorkspaceBlockJson(workspace.projectDir, blockSlug);
2963
- const blockJsonRelativePath = path7.relative(workspace.projectDir, blockJsonPath);
2976
+ const blockJsonRelativePath = path8.relative(workspace.projectDir, blockJsonPath);
2964
2977
  const blockHooks = getMutableBlockHooks(blockJson, blockJsonRelativePath);
2965
2978
  if (Object.prototype.hasOwnProperty.call(blockHooks, resolvedAnchorBlockName)) {
2966
2979
  throw new Error(`${blockJsonRelativePath} already defines a blockHooks entry for "${resolvedAnchorBlockName}".`);
@@ -3000,4 +3013,4 @@ export {
3000
3013
  ADD_BLOCK_TEMPLATE_IDS
3001
3014
  };
3002
3015
 
3003
- //# debugId=6BED23CF79FF983364756E2164756E21
3016
+ //# debugId=BD6B18859A84FB8164756E2164756E21