@wp-typia/project-tools 0.23.1 → 0.24.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.
Files changed (152) hide show
  1. package/dist/runtime/built-in-block-non-ts-basic-artifacts.d.ts +9 -0
  2. package/dist/runtime/built-in-block-non-ts-basic-artifacts.js +84 -0
  3. package/dist/runtime/built-in-block-non-ts-compound-artifacts.d.ts +9 -0
  4. package/dist/runtime/built-in-block-non-ts-compound-artifacts.js +36 -0
  5. package/dist/runtime/built-in-block-non-ts-compound-templates.d.ts +23 -0
  6. package/dist/runtime/built-in-block-non-ts-compound-templates.js +453 -0
  7. package/dist/runtime/built-in-block-non-ts-family-artifacts.d.ts +8 -26
  8. package/dist/runtime/built-in-block-non-ts-family-artifacts.js +8 -1034
  9. package/dist/runtime/built-in-block-non-ts-interactivity-artifacts.d.ts +9 -0
  10. package/dist/runtime/built-in-block-non-ts-interactivity-artifacts.js +83 -0
  11. package/dist/runtime/built-in-block-non-ts-persistence-artifacts.d.ts +9 -0
  12. package/dist/runtime/built-in-block-non-ts-persistence-artifacts.js +33 -0
  13. package/dist/runtime/built-in-block-non-ts-persistence-templates.d.ts +23 -0
  14. package/dist/runtime/built-in-block-non-ts-persistence-templates.js +395 -0
  15. package/dist/runtime/cli-add-collision.js +8 -0
  16. package/dist/runtime/cli-add-help.js +10 -7
  17. package/dist/runtime/cli-add-kind-ids.d.ts +1 -1
  18. package/dist/runtime/cli-add-kind-ids.js +1 -0
  19. package/dist/runtime/cli-add-types.d.ts +28 -1
  20. package/dist/runtime/cli-add-types.js +2 -0
  21. package/dist/runtime/cli-add-workspace-ability-anchors.d.ts +24 -0
  22. package/dist/runtime/cli-add-workspace-ability-anchors.js +294 -0
  23. package/dist/runtime/cli-add-workspace-ability-registry.d.ts +10 -0
  24. package/dist/runtime/cli-add-workspace-ability-registry.js +51 -0
  25. package/dist/runtime/cli-add-workspace-ability-scaffold.d.ts +1 -1
  26. package/dist/runtime/cli-add-workspace-ability-scaffold.js +5 -311
  27. package/dist/runtime/cli-add-workspace-admin-view-scaffold.js +1 -1
  28. package/dist/runtime/cli-add-workspace-ai-anchors.d.ts +4 -4
  29. package/dist/runtime/cli-add-workspace-ai-anchors.js +4 -232
  30. package/dist/runtime/cli-add-workspace-ai-scaffold.js +4 -2
  31. package/dist/runtime/cli-add-workspace-ai-source-emitters.d.ts +1 -4
  32. package/dist/runtime/cli-add-workspace-ai-source-emitters.js +1 -145
  33. package/dist/runtime/cli-add-workspace-ai-sync-rest-anchors.d.ts +5 -0
  34. package/dist/runtime/cli-add-workspace-ai-sync-rest-anchors.js +236 -0
  35. package/dist/runtime/cli-add-workspace-ai-sync-script-source.d.ts +4 -0
  36. package/dist/runtime/cli-add-workspace-ai-sync-script-source.js +145 -0
  37. package/dist/runtime/cli-add-workspace-assets.d.ts +6 -63
  38. package/dist/runtime/cli-add-workspace-assets.js +6 -950
  39. package/dist/runtime/cli-add-workspace-binding-source-anchors.d.ts +23 -0
  40. package/dist/runtime/cli-add-workspace-binding-source-anchors.js +112 -0
  41. package/dist/runtime/cli-add-workspace-binding-source-source-emitters.d.ts +33 -0
  42. package/dist/runtime/cli-add-workspace-binding-source-source-emitters.js +436 -0
  43. package/dist/runtime/cli-add-workspace-binding-source-types.d.ts +20 -0
  44. package/dist/runtime/cli-add-workspace-binding-source-types.js +1 -0
  45. package/dist/runtime/cli-add-workspace-binding-source.d.ts +40 -0
  46. package/dist/runtime/cli-add-workspace-binding-source.js +275 -0
  47. package/dist/runtime/cli-add-workspace-block-style.d.ts +22 -0
  48. package/dist/runtime/cli-add-workspace-block-style.js +148 -0
  49. package/dist/runtime/cli-add-workspace-block-transform.d.ts +32 -0
  50. package/dist/runtime/cli-add-workspace-block-transform.js +197 -0
  51. package/dist/runtime/cli-add-workspace-contract.js +1 -1
  52. package/dist/runtime/cli-add-workspace-core-variation.d.ts +20 -0
  53. package/dist/runtime/cli-add-workspace-core-variation.js +322 -0
  54. package/dist/runtime/cli-add-workspace-editor-plugin-anchors.d.ts +37 -0
  55. package/dist/runtime/cli-add-workspace-editor-plugin-anchors.js +206 -0
  56. package/dist/runtime/cli-add-workspace-editor-plugin-source-emitters.d.ts +47 -0
  57. package/dist/runtime/cli-add-workspace-editor-plugin-source-emitters.js +219 -0
  58. package/dist/runtime/cli-add-workspace-editor-plugin.d.ts +22 -0
  59. package/dist/runtime/cli-add-workspace-editor-plugin.js +78 -0
  60. package/dist/runtime/cli-add-workspace-hooked-block.d.ts +23 -0
  61. package/dist/runtime/cli-add-workspace-hooked-block.js +57 -0
  62. package/dist/runtime/cli-add-workspace-integration-env-files.d.ts +33 -0
  63. package/dist/runtime/cli-add-workspace-integration-env-files.js +65 -0
  64. package/dist/runtime/cli-add-workspace-integration-env-package-json.d.ts +38 -0
  65. package/dist/runtime/cli-add-workspace-integration-env-package-json.js +122 -0
  66. package/dist/runtime/cli-add-workspace-integration-env-source-emitters.d.ts +44 -0
  67. package/dist/runtime/cli-add-workspace-integration-env-source-emitters.js +262 -0
  68. package/dist/runtime/cli-add-workspace-integration-env.js +5 -345
  69. package/dist/runtime/cli-add-workspace-pattern-anchors.d.ts +10 -0
  70. package/dist/runtime/cli-add-workspace-pattern-anchors.js +95 -0
  71. package/dist/runtime/cli-add-workspace-pattern-options.d.ts +20 -0
  72. package/dist/runtime/cli-add-workspace-pattern-options.js +113 -0
  73. package/dist/runtime/cli-add-workspace-pattern-source-emitters.d.ts +20 -0
  74. package/dist/runtime/cli-add-workspace-pattern-source-emitters.js +57 -0
  75. package/dist/runtime/cli-add-workspace-pattern.d.ts +42 -0
  76. package/dist/runtime/cli-add-workspace-pattern.js +99 -0
  77. package/dist/runtime/cli-add-workspace-post-meta.js +1 -1
  78. package/dist/runtime/cli-add-workspace-registration-hooks.d.ts +50 -0
  79. package/dist/runtime/cli-add-workspace-registration-hooks.js +162 -0
  80. package/dist/runtime/cli-add-workspace-rest-anchors.d.ts +6 -9
  81. package/dist/runtime/cli-add-workspace-rest-anchors.js +6 -466
  82. package/dist/runtime/cli-add-workspace-rest-bootstrap-anchors.d.ts +17 -0
  83. package/dist/runtime/cli-add-workspace-rest-bootstrap-anchors.js +108 -0
  84. package/dist/runtime/cli-add-workspace-rest-contract-sync-anchors.d.ts +9 -0
  85. package/dist/runtime/cli-add-workspace-rest-contract-sync-anchors.js +142 -0
  86. package/dist/runtime/cli-add-workspace-rest-generated-source-emitters.d.ts +51 -0
  87. package/dist/runtime/cli-add-workspace-rest-generated-source-emitters.js +415 -0
  88. package/dist/runtime/cli-add-workspace-rest-generated.js +5 -3
  89. package/dist/runtime/cli-add-workspace-rest-manual-source-emitters.d.ts +80 -0
  90. package/dist/runtime/cli-add-workspace-rest-manual-source-emitters.js +238 -0
  91. package/dist/runtime/cli-add-workspace-rest-manual.js +3 -16
  92. package/dist/runtime/cli-add-workspace-rest-php-templates.d.ts +1 -7
  93. package/dist/runtime/cli-add-workspace-rest-php-templates.js +3 -322
  94. package/dist/runtime/cli-add-workspace-rest-resource-php-routing-template.d.ts +33 -0
  95. package/dist/runtime/cli-add-workspace-rest-resource-php-routing-template.js +145 -0
  96. package/dist/runtime/cli-add-workspace-rest-resource-sync-anchors.d.ts +9 -0
  97. package/dist/runtime/cli-add-workspace-rest-resource-sync-anchors.js +162 -0
  98. package/dist/runtime/cli-add-workspace-rest-schema-helper-php-template.d.ts +7 -0
  99. package/dist/runtime/cli-add-workspace-rest-schema-helper-php-template.js +193 -0
  100. package/dist/runtime/cli-add-workspace-rest-source-emitters.d.ts +5 -99
  101. package/dist/runtime/cli-add-workspace-rest-source-emitters.js +5 -663
  102. package/dist/runtime/cli-add-workspace-rest-source-utils.d.ts +17 -0
  103. package/dist/runtime/cli-add-workspace-rest-source-utils.js +50 -0
  104. package/dist/runtime/cli-add-workspace-rest-sync-script-shared.d.ts +56 -0
  105. package/dist/runtime/cli-add-workspace-rest-sync-script-shared.js +122 -0
  106. package/dist/runtime/cli-add-workspace-rest-types.d.ts +3 -3
  107. package/dist/runtime/cli-add-workspace-variation.d.ts +22 -0
  108. package/dist/runtime/cli-add-workspace-variation.js +162 -0
  109. package/dist/runtime/cli-add-workspace.d.ts +42 -107
  110. package/dist/runtime/cli-add-workspace.js +42 -674
  111. package/dist/runtime/cli-add.d.ts +3 -3
  112. package/dist/runtime/cli-add.js +2 -2
  113. package/dist/runtime/cli-core.d.ts +2 -1
  114. package/dist/runtime/cli-core.js +1 -1
  115. package/dist/runtime/cli-doctor-workspace-bindings.js +59 -0
  116. package/dist/runtime/cli-doctor-workspace-block-addons.js +33 -5
  117. package/dist/runtime/cli-doctor.d.ts +2 -0
  118. package/dist/runtime/cli-doctor.js +13 -2
  119. package/dist/runtime/cli-help.js +6 -4
  120. package/dist/runtime/index.d.ts +5 -2
  121. package/dist/runtime/index.js +4 -2
  122. package/dist/runtime/local-dev-presets.js +2 -1
  123. package/dist/runtime/package-versions.d.ts +1 -0
  124. package/dist/runtime/package-versions.js +10 -2
  125. package/dist/runtime/pattern-catalog.d.ts +122 -0
  126. package/dist/runtime/pattern-catalog.js +471 -0
  127. package/dist/runtime/post-meta-binding-fields.d.ts +46 -0
  128. package/dist/runtime/post-meta-binding-fields.js +135 -0
  129. package/dist/runtime/typia-llm-json-schema.d.ts +24 -0
  130. package/dist/runtime/typia-llm-json-schema.js +33 -0
  131. package/dist/runtime/typia-llm-openapi-constraints.d.ts +20 -0
  132. package/dist/runtime/typia-llm-openapi-constraints.js +254 -0
  133. package/dist/runtime/typia-llm-projection.d.ts +25 -0
  134. package/dist/runtime/typia-llm-projection.js +58 -0
  135. package/dist/runtime/typia-llm-render.d.ts +21 -0
  136. package/dist/runtime/typia-llm-render.js +252 -0
  137. package/dist/runtime/typia-llm-sync.d.ts +10 -0
  138. package/dist/runtime/typia-llm-sync.js +63 -0
  139. package/dist/runtime/typia-llm-types.d.ts +197 -0
  140. package/dist/runtime/typia-llm-types.js +1 -0
  141. package/dist/runtime/typia-llm.d.ts +9 -255
  142. package/dist/runtime/typia-llm.js +5 -634
  143. package/dist/runtime/workspace-inventory-mutations.js +13 -0
  144. package/dist/runtime/workspace-inventory-section-descriptors.js +9 -1
  145. package/dist/runtime/workspace-inventory-templates.d.ts +2 -2
  146. package/dist/runtime/workspace-inventory-templates.js +9 -1
  147. package/dist/runtime/workspace-inventory-types.d.ts +9 -1
  148. package/package.json +8 -3
  149. package/templates/_shared/compound/core/scripts/block-config.ts.mustache +22 -0
  150. package/templates/_shared/compound/core/scripts/sync-types-to-block-json.ts.mustache +103 -2
  151. package/templates/_shared/compound/core/src/inner-blocks-templates.ts.mustache +13 -0
  152. package/templates/_shared/compound/persistence/scripts/block-config.ts.mustache +22 -1
@@ -1,320 +1,14 @@
1
1
  import { promises as fsp } from "node:fs";
2
2
  import path from "node:path";
3
3
  import { syncTypeSchemas } from "@wp-typia/block-runtime/metadata-core";
4
- import semver from "semver";
5
- import { appendWorkspaceInventoryEntries, readWorkspaceInventoryAsync, } from "./workspace-inventory.js";
6
- import { pathExists, readOptionalUtf8File } from "./fs-async.js";
7
- import { readJsonFile } from "./json-utils.js";
8
- import { buildAbilityClientSource, buildAbilityConfigEntry, buildAbilityConfigSource, buildAbilityDataSource, buildAbilityPhpSource, buildAbilityRegistrySource, buildAbilitySyncScriptSource, buildAbilityTypesSource, } from "./cli-add-workspace-ability-templates.js";
9
- import { ABILITY_EDITOR_ASSET, ABILITY_EDITOR_SCRIPT, ABILITY_REGISTRY_END_MARKER, ABILITY_REGISTRY_START_MARKER, ABILITY_SERVER_GLOB, WP_ABILITIES_SCRIPT_MODULE_ID, WP_CORE_ABILITIES_SCRIPT_MODULE_ID, } from "./cli-add-workspace-ability-types.js";
4
+ import { appendWorkspaceInventoryEntries, } from "./workspace-inventory.js";
5
+ import { ensureAbilityBootstrapAnchors, ensureAbilityBuildScriptAnchors, ensureAbilityPackageScripts, ensureAbilitySyncProjectAnchors, ensureAbilityWebpackAnchors, } from "./cli-add-workspace-ability-anchors.js";
6
+ import { resolveAbilityRegistryPath, writeAbilityRegistry, } from "./cli-add-workspace-ability-registry.js";
7
+ import { buildAbilityClientSource, buildAbilityConfigEntry, buildAbilityConfigSource, buildAbilityDataSource, buildAbilityPhpSource, buildAbilitySyncScriptSource, buildAbilityTypesSource, } from "./cli-add-workspace-ability-templates.js";
10
8
  import { getWorkspaceBootstrapPath, patchFile, } from "./cli-add-shared.js";
11
- import { appendPhpSnippetBeforeClosingTag, executeWorkspaceMutationPlan, insertPhpSnippetBeforeWorkspaceAnchors, } from "./cli-add-workspace-mutation.js";
9
+ import { executeWorkspaceMutationPlan, } from "./cli-add-workspace-mutation.js";
12
10
  import { updatePluginHeaderCompatibility, } from "./scaffold-compatibility.js";
13
- import { DEFAULT_WORDPRESS_ABILITIES_VERSION, DEFAULT_WORDPRESS_CORE_ABILITIES_VERSION, } from "./package-versions.js";
14
- import { escapeRegex, findPhpFunctionRange, hasPhpFunctionCall, hasPhpFunctionDefinition, replacePhpFunctionDefinition, } from "./php-utils.js";
15
11
  import { toPascalCase } from "./string-case.js";
16
- function resolveManagedDependencyVersion(existingVersion, requiredVersion) {
17
- if (!existingVersion) {
18
- return requiredVersion;
19
- }
20
- const existingMinimum = semver.minVersion(existingVersion);
21
- const requiredMinimum = semver.minVersion(requiredVersion);
22
- if (!existingMinimum || !requiredMinimum) {
23
- return requiredVersion;
24
- }
25
- return semver.gte(existingMinimum, requiredMinimum)
26
- ? existingVersion
27
- : requiredVersion;
28
- }
29
- async function resolveAbilityRegistryPath(projectDir) {
30
- const abilitiesDir = path.join(projectDir, "src", "abilities");
31
- for (const candidatePath of [
32
- path.join(abilitiesDir, "index.ts"),
33
- path.join(abilitiesDir, "index.js"),
34
- ]) {
35
- if (await pathExists(candidatePath)) {
36
- return candidatePath;
37
- }
38
- }
39
- return path.join(abilitiesDir, "index.ts");
40
- }
41
- async function readAbilityRegistrySlugs(registryPath) {
42
- const source = await readOptionalUtf8File(registryPath);
43
- if (source === null) {
44
- return [];
45
- }
46
- return Array.from(source.matchAll(/^\s*export\s+\*\s+from\s+['"]\.\/([^/'"]+)\/client(?:\.[cm]?[jt]sx?)?['"];?\s*$/gmu)).map((match) => match[1]);
47
- }
48
- async function writeAbilityRegistry(projectDir, abilitySlug) {
49
- const abilitiesDir = path.join(projectDir, "src", "abilities");
50
- const registryPath = await resolveAbilityRegistryPath(projectDir);
51
- await fsp.mkdir(abilitiesDir, { recursive: true });
52
- const existingAbilitySlugs = (await readWorkspaceInventoryAsync(projectDir)).abilities.map((entry) => entry.slug);
53
- const existingRegistrySlugs = await readAbilityRegistrySlugs(registryPath);
54
- const nextAbilitySlugs = Array.from(new Set([...existingAbilitySlugs, ...existingRegistrySlugs, abilitySlug])).sort();
55
- const generatedSection = buildAbilityRegistrySource(nextAbilitySlugs);
56
- const existingSource = (await readOptionalUtf8File(registryPath)) ?? "";
57
- const generatedSectionPattern = new RegExp(`${escapeRegex(ABILITY_REGISTRY_START_MARKER)}[\\s\\S]*?${escapeRegex(ABILITY_REGISTRY_END_MARKER)}\\n?`, "u");
58
- const nextSource = existingSource
59
- ? generatedSectionPattern.test(existingSource)
60
- ? existingSource.replace(generatedSectionPattern, generatedSection)
61
- : `${existingSource.trimEnd()}\n\n${generatedSection}`
62
- : generatedSection;
63
- await fsp.writeFile(registryPath, nextSource, "utf8");
64
- }
65
- async function ensureAbilityBootstrapAnchors(workspace) {
66
- const bootstrapPath = getWorkspaceBootstrapPath(workspace);
67
- await patchFile(bootstrapPath, (source) => {
68
- let nextSource = source;
69
- const workspaceBaseName = workspace.packageName.split("/").pop() ?? workspace.packageName;
70
- const loadFunctionName = `${workspace.workspace.phpPrefix}_load_workflow_abilities`;
71
- const enqueueFunctionName = `${workspace.workspace.phpPrefix}_enqueue_workflow_abilities`;
72
- const loadHook = `add_action( 'plugins_loaded', '${loadFunctionName}' );`;
73
- const adminEnqueueHook = `add_action( 'admin_enqueue_scripts', '${enqueueFunctionName}' );`;
74
- const editorEnqueueHook = `add_action( 'enqueue_block_editor_assets', '${enqueueFunctionName}' );`;
75
- const loadFunction = `
76
-
77
- function ${loadFunctionName}() {
78
- \tforeach ( glob( __DIR__ . '${ABILITY_SERVER_GLOB}' ) ?: array() as $ability_module ) {
79
- \t\trequire_once $ability_module;
80
- \t}
81
- }
82
- `;
83
- const enqueueFunction = `
84
-
85
- function ${enqueueFunctionName}() {
86
- \tif ( ! class_exists( 'WP_Ability' ) ) {
87
- \t\treturn;
88
- \t}
89
-
90
- \t$script_path = __DIR__ . '/${ABILITY_EDITOR_SCRIPT}';
91
- \t$asset_path = __DIR__ . '/${ABILITY_EDITOR_ASSET}';
92
-
93
- \tif ( ! file_exists( $script_path ) || ! file_exists( $asset_path ) ) {
94
- \t\treturn;
95
- \t}
96
-
97
- \t$asset = require $asset_path;
98
- \tif ( ! is_array( $asset ) ) {
99
- \t\t$asset = array();
100
- \t}
101
-
102
- \t$dependencies = isset( $asset['dependencies'] ) && is_array( $asset['dependencies'] )
103
- \t\t? $asset['dependencies']
104
- \t\t: array();
105
-
106
- \tforeach ( array( '${WP_CORE_ABILITIES_SCRIPT_MODULE_ID}', '${WP_ABILITIES_SCRIPT_MODULE_ID}' ) as $ability_dependency ) {
107
- \t\t$has_dependency = false;
108
- \t\tforeach ( $dependencies as $dependency ) {
109
- \t\t\t$dependency_id = is_array( $dependency ) && isset( $dependency['id'] )
110
- \t\t\t\t? $dependency['id']
111
- \t\t\t\t: $dependency;
112
- \t\t\tif ( $dependency_id === $ability_dependency ) {
113
- \t\t\t\t$has_dependency = true;
114
- \t\t\t\tbreak;
115
- \t\t\t}
116
- \t\t}
117
- \t\tif ( ! $has_dependency ) {
118
- \t\t\t$dependencies[] = $ability_dependency;
119
- \t\t}
120
- \t}
121
-
122
- \tif ( ! function_exists( 'wp_enqueue_script_module' ) ) {
123
- \t\treturn;
124
- \t}
125
-
126
- \twp_enqueue_script_module(
127
- \t\t'${workspaceBaseName}-abilities',
128
- \t\tplugins_url( '${ABILITY_EDITOR_SCRIPT}', __FILE__ ),
129
- \t\t$dependencies,
130
- \t\tisset( $asset['version'] ) ? $asset['version'] : filemtime( $script_path )
131
- \t);
132
- }
133
- `;
134
- if (!hasPhpFunctionDefinition(nextSource, loadFunctionName)) {
135
- nextSource = insertPhpSnippetBeforeWorkspaceAnchors(nextSource, loadFunction);
136
- }
137
- if (!hasPhpFunctionDefinition(nextSource, enqueueFunctionName)) {
138
- nextSource = insertPhpSnippetBeforeWorkspaceAnchors(nextSource, enqueueFunction);
139
- }
140
- else {
141
- const functionRange = findPhpFunctionRange(nextSource, enqueueFunctionName);
142
- const functionSource = functionRange
143
- ? nextSource.slice(functionRange.start, functionRange.end)
144
- : "";
145
- if (!hasPhpFunctionCall(functionSource, "wp_enqueue_script_module")) {
146
- const replacedSource = replacePhpFunctionDefinition(nextSource, enqueueFunctionName, enqueueFunction, { trimReplacementStart: true });
147
- if (!replacedSource) {
148
- throw new Error(`Unable to repair ${path.basename(bootstrapPath)} for ${enqueueFunctionName}.`);
149
- }
150
- nextSource = replacedSource;
151
- }
152
- }
153
- if (!nextSource.includes(loadHook)) {
154
- nextSource = appendPhpSnippetBeforeClosingTag(nextSource, loadHook);
155
- }
156
- if (!nextSource.includes(adminEnqueueHook)) {
157
- nextSource = appendPhpSnippetBeforeClosingTag(nextSource, adminEnqueueHook);
158
- }
159
- if (!nextSource.includes(editorEnqueueHook)) {
160
- nextSource = appendPhpSnippetBeforeClosingTag(nextSource, editorEnqueueHook);
161
- }
162
- return nextSource;
163
- });
164
- }
165
- async function ensureAbilityPackageScripts(workspace) {
166
- const packageJsonPath = path.join(workspace.projectDir, "package.json");
167
- const packageJson = await readJsonFile(packageJsonPath, {
168
- context: "workspace package manifest",
169
- });
170
- const nextScripts = {
171
- ...(packageJson.scripts ?? {}),
172
- "sync-abilities": packageJson.scripts?.["sync-abilities"] ?? "tsx scripts/sync-abilities.ts",
173
- };
174
- const nextDependencies = {
175
- ...(packageJson.dependencies ?? {}),
176
- [WP_ABILITIES_SCRIPT_MODULE_ID]: resolveManagedDependencyVersion(packageJson.dependencies?.[WP_ABILITIES_SCRIPT_MODULE_ID], DEFAULT_WORDPRESS_ABILITIES_VERSION),
177
- [WP_CORE_ABILITIES_SCRIPT_MODULE_ID]: resolveManagedDependencyVersion(packageJson.dependencies?.[WP_CORE_ABILITIES_SCRIPT_MODULE_ID], DEFAULT_WORDPRESS_CORE_ABILITIES_VERSION),
178
- };
179
- if (JSON.stringify(nextScripts) === JSON.stringify(packageJson.scripts ?? {}) &&
180
- JSON.stringify(nextDependencies) === JSON.stringify(packageJson.dependencies ?? {})) {
181
- return;
182
- }
183
- packageJson.scripts = nextScripts;
184
- packageJson.dependencies = nextDependencies;
185
- await fsp.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, "\t")}\n`, "utf8");
186
- }
187
- async function ensureAbilitySyncProjectAnchors(workspace) {
188
- const syncProjectScriptPath = path.join(workspace.projectDir, "scripts", "sync-project.ts");
189
- await patchFile(syncProjectScriptPath, (source) => {
190
- let nextSource = source;
191
- const syncRestConst = "const syncRestScriptPath = path.join( 'scripts', 'sync-rest-contracts.ts' );";
192
- const syncAbilitiesConst = "const syncAbilitiesScriptPath = path.join( 'scripts', 'sync-abilities.ts' );";
193
- const syncRestBlockPattern = /if \( fs\.existsSync\( path\.resolve\( process\.cwd\(\), syncRestScriptPath \) \) \) \{\n\s*runSyncScript\( syncRestScriptPath, options \);\n\s*\}/u;
194
- const syncAbilitiesBlock = [
195
- "if ( fs.existsSync( path.resolve( process.cwd(), syncAbilitiesScriptPath ) ) ) {",
196
- "\trunSyncScript( syncAbilitiesScriptPath, options );",
197
- "}",
198
- ].join("\n");
199
- if (!nextSource.includes(syncAbilitiesConst)) {
200
- if (!nextSource.includes(syncRestConst)) {
201
- throw new Error([
202
- `ensureAbilitySyncProjectAnchors could not patch ${path.basename(syncProjectScriptPath)}.`,
203
- "Missing the expected sync-rest script constant in scripts/sync-project.ts.",
204
- "Restore the generated template or wire sync-abilities manually before retrying.",
205
- ].join(" "));
206
- }
207
- nextSource = nextSource.replace(syncRestConst, `${syncRestConst}\n${syncAbilitiesConst}`);
208
- }
209
- if (!nextSource.includes("runSyncScript( syncAbilitiesScriptPath, options );")) {
210
- if (!syncRestBlockPattern.test(nextSource)) {
211
- throw new Error([
212
- `ensureAbilitySyncProjectAnchors could not patch ${path.basename(syncProjectScriptPath)}.`,
213
- "Missing the expected sync-rest invocation block in scripts/sync-project.ts.",
214
- "Restore the generated template or wire sync-abilities manually before retrying.",
215
- ].join(" "));
216
- }
217
- nextSource = nextSource.replace(syncRestBlockPattern, (match) => `${match}\n\n${syncAbilitiesBlock}`);
218
- }
219
- return nextSource;
220
- });
221
- }
222
- async function ensureAbilityBuildScriptAnchors(workspace) {
223
- const buildScriptPath = path.join(workspace.projectDir, "scripts", "build-workspace.mjs");
224
- await patchFile(buildScriptPath, (source) => {
225
- let nextSource = source;
226
- if (/['"]src\/abilities\/index\.(?:ts|js)['"]/u.test(nextSource)) {
227
- return nextSource;
228
- }
229
- const sharedEntriesPattern = /(for\s*\(\s*const\s+relativePath\s+of\s+\[)([\s\S]*?)(\]\s*\)\s*\{)/u;
230
- const match = nextSource.match(sharedEntriesPattern);
231
- if (!match ||
232
- !/['"]src\/bindings\/index\.(?:ts|js)['"]/u.test(match[2]) ||
233
- !/['"]src\/editor-plugins\/index\.(?:tsx|ts|js)['"]/u.test(match[2])) {
234
- throw new Error([
235
- `ensureAbilityBuildScriptAnchors could not patch ${path.basename(buildScriptPath)}.`,
236
- "Missing the expected shared editor entries array in scripts/build-workspace.mjs.",
237
- "Restore the generated template or wire abilities/index manually before retrying.",
238
- ].join(" "));
239
- }
240
- nextSource = nextSource.replace(sharedEntriesPattern, (fullMatch, sharedEntries) => {
241
- const missingAbilityEntries = [
242
- "'src/abilities/index.ts'",
243
- "'src/abilities/index.js'",
244
- ].filter((entry) => !sharedEntries.includes(entry));
245
- if (missingAbilityEntries.length === 0) {
246
- return fullMatch;
247
- }
248
- const itemIndent = sharedEntries.match(/\n([ \t]*)['"]/u)?.[1] ?? "\t\t";
249
- const trimmedEntries = sharedEntries.replace(/\s*$/u, "");
250
- const trailingWhitespace = sharedEntries.slice(trimmedEntries.length);
251
- const separator = trimmedEntries.trimEnd().endsWith(",") ? "" : ",";
252
- const nextEntries = `${trimmedEntries}${separator}` +
253
- missingAbilityEntries.map((entry) => `\n${itemIndent}${entry},`).join("") +
254
- trailingWhitespace;
255
- return fullMatch.replace(sharedEntries, nextEntries);
256
- });
257
- return nextSource;
258
- });
259
- }
260
- async function ensureAbilityWebpackAnchors(workspace) {
261
- const webpackConfigPath = path.join(workspace.projectDir, "webpack.config.js");
262
- await patchFile(webpackConfigPath, (source) => {
263
- if (/['"]abilities\/index['"]/u.test(source)) {
264
- return source;
265
- }
266
- const optionalModuleReturnPattern = /(function\s+getOptionalModuleEntries\s*\(\)\s*\{[\s\S]*?)(\n\treturn Object\.fromEntries\(\s*entries\s*\);\n\})/u;
267
- if (optionalModuleReturnPattern.test(source)) {
268
- return source.replace(optionalModuleReturnPattern, `$1
269
-
270
- \tfor ( const [ entryName, candidates ] of [
271
- \t\t[
272
- \t\t\t'abilities/index',
273
- \t\t\t[ 'src/abilities/index.ts', 'src/abilities/index.js' ],
274
- \t\t],
275
- \t] ) {
276
- \t\tfor ( const relativePath of candidates ) {
277
- \t\t\tconst entryPath = path.resolve( process.cwd(), relativePath );
278
- \t\t\tif ( ! fs.existsSync( entryPath ) ) {
279
- \t\t\t\tcontinue;
280
- \t\t\t}
281
-
282
- \t\t\tentries.push( [ entryName, entryPath ] );
283
- \t\t\tbreak;
284
- \t\t}
285
- \t}$2`);
286
- }
287
- const sharedEntriesPattern = /for\s*\(\s*const\s+\[\s*entryName\s*,\s*candidates\s*\]\s+of\s+\[([\s\S]*?)\]\s*\)\s*\{/u;
288
- const match = source.match(sharedEntriesPattern);
289
- if (!match ||
290
- !match[1].includes("bindings/index") ||
291
- !match[1].includes("editor-plugins/index")) {
292
- throw new Error([
293
- `ensureAbilityWebpackAnchors could not patch ${path.basename(webpackConfigPath)}.`,
294
- "Missing the expected shared editor entries block in webpack.config.js.",
295
- "Restore the generated template or wire abilities/index manually before retrying.",
296
- ].join(" "));
297
- }
298
- return source.replace(sharedEntriesPattern, (fullMatch, sharedEntries) => {
299
- if (/['"]abilities\/index['"]/u.test(sharedEntries)) {
300
- return fullMatch;
301
- }
302
- const tupleIndent = sharedEntries.match(/\n([ \t]*)\[/u)?.[1] ?? "\t\t";
303
- const nestedIndent = `${tupleIndent}\t`;
304
- const trimmedEntries = sharedEntries.replace(/\s*$/u, "");
305
- const trailingWhitespace = sharedEntries.slice(trimmedEntries.length);
306
- const separator = trimmedEntries.trimEnd().endsWith(",") ? "" : ",";
307
- const abilityTuple = [
308
- `${tupleIndent}[`,
309
- `${nestedIndent}'abilities/index',`,
310
- `${nestedIndent}[ 'src/abilities/index.ts', 'src/abilities/index.js' ],`,
311
- `${tupleIndent}],`,
312
- ].join("\n");
313
- const nextEntries = `${trimmedEntries}${separator}\n${abilityTuple}` + trailingWhitespace;
314
- return fullMatch.replace(sharedEntries, nextEntries);
315
- });
316
- });
317
- }
318
12
  /**
319
13
  * Write generated workflow ability sources and patch shared workspace anchors.
320
14
  */
@@ -5,7 +5,7 @@ import { safeJsonParse } from './json-utils.js';
5
5
  import { appendWorkspaceInventoryEntries, readWorkspaceInventoryAsync, } from './workspace-inventory.js';
6
6
  import { buildAdminViewConfigEntry, buildAdminViewConfigSource, buildAdminViewEntrySource, buildAdminViewPhpSource, buildAdminViewRegistrySource, buildAdminViewScreenSource, buildAdminViewStyleSource, buildAdminViewTypesSource, buildCoreDataAdminViewDataSource, buildCoreDataAdminViewScreenSource, buildDefaultAdminViewDataSource, buildRestAdminViewDataSource, buildRestSettingsAdminViewConfigSource, buildRestSettingsAdminViewDataSource, buildRestSettingsAdminViewScreenSource, buildRestSettingsAdminViewTypesSource, } from './cli-add-workspace-admin-view-templates.js';
7
7
  import { ADMIN_VIEWS_PHP_GLOB, isAdminViewCoreDataSource, isAdminViewManualSettingsRestResource, } from './cli-add-workspace-admin-view-types.js';
8
- import { buildManualRestContractApiSource } from './cli-add-workspace-rest-source-emitters.js';
8
+ import { buildManualRestContractApiSource } from './cli-add-workspace-rest-manual-source-emitters.js';
9
9
  import { getWorkspaceBootstrapPath, patchFile, } from './cli-add-shared.js';
10
10
  import { appendPhpSnippetBeforeClosingTag, executeWorkspaceMutationPlan, insertPhpSnippetBeforeWorkspaceAnchors, } from './cli-add-workspace-mutation.js';
11
11
  import { DEFAULT_WORDPRESS_CORE_DATA_VERSION, DEFAULT_WORDPRESS_DATA_VERSION, DEFAULT_WORDPRESS_DATAVIEWS_VERSION, DEFAULT_WP_TYPIA_DATAVIEWS_VERSION, resolveManagedPackageVersionRange, } from './package-versions.js';
@@ -1,4 +1,8 @@
1
1
  import type { WorkspaceProject } from "./workspace-project.js";
2
+ /**
3
+ * Patch generated sync-rest scripts so AI feature REST artifacts join workspace REST synchronization.
4
+ */
5
+ export { ensureAiFeatureSyncRestAnchors, } from "./cli-add-workspace-ai-sync-rest-anchors.js";
2
6
  /**
3
7
  * Patch the workspace bootstrap file so it loads generated AI feature PHP modules.
4
8
  */
@@ -16,7 +20,3 @@ export declare function ensureAiFeaturePackageScripts(workspace: WorkspaceProjec
16
20
  * Patch `scripts/sync-project.ts` after package scripts so generated workspaces invoke `sync-ai` when present.
17
21
  */
18
22
  export declare function ensureAiFeatureSyncProjectAnchors(workspace: WorkspaceProject): Promise<void>;
19
- /**
20
- * Patch `scripts/sync-rest-contracts.ts` after sync-project wiring so AI feature REST artifacts join the split sync flow.
21
- */
22
- export declare function ensureAiFeatureSyncRestAnchors(workspace: WorkspaceProject): Promise<void>;
@@ -6,6 +6,10 @@ import { appendPhpSnippetBeforeClosingTag, insertPhpSnippetBeforeWorkspaceAnchor
6
6
  import { readJsonFile } from "./json-utils.js";
7
7
  import { hasPhpFunctionDefinition } from "./php-utils.js";
8
8
  const AI_FEATURE_SERVER_GLOB = "/inc/ai-features/*.php";
9
+ /**
10
+ * Patch generated sync-rest scripts so AI feature REST artifacts join workspace REST synchronization.
11
+ */
12
+ export { ensureAiFeatureSyncRestAnchors, } from "./cli-add-workspace-ai-sync-rest-anchors.js";
9
13
  /**
10
14
  * Patch the workspace bootstrap file so it loads generated AI feature PHP modules.
11
15
  */
@@ -112,235 +116,3 @@ export async function ensureAiFeatureSyncProjectAnchors(workspace) {
112
116
  return nextSource;
113
117
  });
114
118
  }
115
- function assertSyncRestAnchor(nextSource, target, anchorDescription, hasAnchor, syncRestScriptPath) {
116
- if (!nextSource.includes(target) && !hasAnchor) {
117
- throw new Error([
118
- `ensureAiFeatureSyncRestAnchors could not patch ${path.basename(syncRestScriptPath)}.`,
119
- `Missing expected ${anchorDescription} anchor in scripts/sync-rest-contracts.ts.`,
120
- "Restore the generated template or add the AI feature wiring manually before retrying.",
121
- ].join(" "));
122
- }
123
- }
124
- function replaceRequiredSyncRestSource(nextSource, target, anchor, replacement, anchorDescription, syncRestScriptPath) {
125
- if (nextSource.includes(target)) {
126
- return nextSource;
127
- }
128
- const hasAnchor = typeof anchor === "string" ? nextSource.includes(anchor) : anchor.test(nextSource);
129
- assertSyncRestAnchor(nextSource, target, anchorDescription, hasAnchor, syncRestScriptPath);
130
- return nextSource.replace(anchor, replacement);
131
- }
132
- function replaceBlockConfigImportForAiFeatures(nextSource, syncRestScriptPath) {
133
- const importPatterns = [
134
- /^import\s*\{\n(?:\t[^\n]*\n)+\} from ["']\.\/block-config["'];?$/mu,
135
- /^import\s*\{[^\n]*\}\s*from\s*["']\.\/block-config["'];?$/mu,
136
- ];
137
- const importMatch = importPatterns.map((pattern) => pattern.exec(nextSource)).find(Boolean) ??
138
- null;
139
- if (!importMatch) {
140
- throw new Error([
141
- `ensureAiFeatureSyncRestAnchors could not patch ${path.basename(syncRestScriptPath)}.`,
142
- "Missing expected workspace inventory import anchor in scripts/sync-rest-contracts.ts.",
143
- "Restore the generated template or add the AI feature wiring manually before retrying.",
144
- ].join(" "));
145
- }
146
- const importSource = importMatch[0];
147
- if (importSource.includes("AI_FEATURES") &&
148
- importSource.includes("WorkspaceAiFeatureConfig")) {
149
- return nextSource;
150
- }
151
- const hasContracts = importSource.includes("CONTRACTS");
152
- const hasContractConfig = importSource.includes("WorkspaceContractConfig");
153
- const hasPostMeta = importSource.includes("POST_META");
154
- const hasPostMetaConfig = importSource.includes("WorkspacePostMetaConfig");
155
- const replacement = [
156
- "import {",
157
- "\tAI_FEATURES,",
158
- "\tBLOCKS,",
159
- ...(hasContracts ? ["\tCONTRACTS,"] : []),
160
- ...(hasPostMeta ? ["\tPOST_META,"] : []),
161
- "\tREST_RESOURCES,",
162
- "\ttype WorkspaceAiFeatureConfig,",
163
- "\ttype WorkspaceBlockConfig,",
164
- ...(hasContractConfig ? ["\ttype WorkspaceContractConfig,"] : []),
165
- ...(hasPostMetaConfig ? ["\ttype WorkspacePostMetaConfig,"] : []),
166
- "\ttype WorkspaceRestResourceConfig,",
167
- "} from './block-config';",
168
- ].join("\n");
169
- return nextSource.replace(importSource, replacement);
170
- }
171
- function replaceAiFeatureSyncSummaryCopy(nextSource, syncRestScriptPath) {
172
- const standaloneSummary = "workspace blocks, standalone contracts, and plugin-level resources";
173
- const standaloneAiSummary = "workspace blocks, standalone contracts, plugin-level resources, and AI features";
174
- const standalonePostMetaSummary = "workspace blocks, standalone contracts, post meta contracts, and plugin-level resources";
175
- const standalonePostMetaAiSummary = "workspace blocks, standalone contracts, post meta contracts, plugin-level resources, and AI features";
176
- const postMetaSummary = "workspace blocks, post meta contracts, and plugin-level resources";
177
- const postMetaAiSummary = "workspace blocks, post meta contracts, plugin-level resources, and AI features";
178
- const restResourceSummary = "workspace blocks and plugin-level resources";
179
- const restResourceAiSummary = "workspace blocks, plugin-level resources, and AI features";
180
- if (nextSource.includes(standalonePostMetaSummary)) {
181
- return nextSource
182
- .split(standalonePostMetaSummary)
183
- .join(standalonePostMetaAiSummary);
184
- }
185
- if (nextSource.includes(standaloneSummary)) {
186
- return nextSource.split(standaloneSummary).join(standaloneAiSummary);
187
- }
188
- if (nextSource.includes(postMetaSummary)) {
189
- return nextSource.split(postMetaSummary).join(postMetaAiSummary);
190
- }
191
- if (nextSource.includes(restResourceSummary)) {
192
- return nextSource.split(restResourceSummary).join(restResourceAiSummary);
193
- }
194
- if (nextSource.includes(standaloneAiSummary) ||
195
- nextSource.includes(standalonePostMetaAiSummary) ||
196
- nextSource.includes(postMetaAiSummary) ||
197
- nextSource.includes(restResourceAiSummary)) {
198
- return nextSource;
199
- }
200
- throw new Error([
201
- `ensureAiFeatureSyncRestAnchors could not patch ${path.basename(syncRestScriptPath)}.`,
202
- "Missing expected sync summary copy anchor in scripts/sync-rest-contracts.ts.",
203
- "Restore the generated template or add the AI feature wiring manually before retrying.",
204
- ].join(" "));
205
- }
206
- function formatNoResourcesSubject(subjects) {
207
- if (subjects.length <= 2) {
208
- return subjects.join(" or ");
209
- }
210
- const lastSubject = subjects[subjects.length - 1];
211
- return `${subjects.slice(0, -1).join(", ")}, or ${lastSubject}`;
212
- }
213
- function buildAiFeatureNoResourcesGuard({ hasPostMeta, hasStandaloneContracts, }) {
214
- const condition = ["restBlocks.length === 0"];
215
- if (hasStandaloneContracts) {
216
- condition[condition.length - 1] = `${condition[condition.length - 1]} &&`;
217
- condition.push("standaloneContracts.length === 0");
218
- }
219
- if (hasPostMeta) {
220
- condition[condition.length - 1] = `${condition[condition.length - 1]} &&`;
221
- condition.push("postMetaContracts.length === 0");
222
- }
223
- condition[condition.length - 1] = `${condition[condition.length - 1]} &&`;
224
- condition.push("restResources.length === 0 &&");
225
- condition.push("aiFeatures.length === 0");
226
- const noResourcesSubject = formatNoResourcesSubject([
227
- "REST-enabled workspace blocks",
228
- ...(hasStandaloneContracts ? ["standalone contracts"] : []),
229
- ...(hasPostMeta ? ["post meta contracts"] : []),
230
- "plugin-level REST resources",
231
- "AI features",
232
- ]);
233
- return [
234
- "if (",
235
- ...condition.map((line) => `\t\t${line}`),
236
- "\t) {",
237
- "\t\tconsole.log(",
238
- "\t\t\toptions.check",
239
- `\t\t\t\t? 'ℹ️ No ${noResourcesSubject} are registered yet. \`sync-rest --check\` is already clean.'`,
240
- `\t\t\t\t: 'ℹ️ No ${noResourcesSubject} are registered yet.'`,
241
- "\t\t);",
242
- "\t\treturn;",
243
- "\t}",
244
- ].join("\n");
245
- }
246
- const NO_RESOURCES_GUARD_PATTERN = /if \(\s*restBlocks\.length === 0(?:\s*&&\s*standaloneContracts\.length === 0)?(?:\s*&&\s*postMetaContracts\.length === 0)?\s*&&\s*restResources\.length === 0(?:\s*&&\s*aiFeatures\.length === 0)?\s*\) \{[\s\S]*?\n\t\treturn;\n\t\}/u;
247
- /**
248
- * Patch `scripts/sync-rest-contracts.ts` after sync-project wiring so AI feature REST artifacts join the split sync flow.
249
- */
250
- export async function ensureAiFeatureSyncRestAnchors(workspace) {
251
- const syncRestScriptPath = path.join(workspace.projectDir, "scripts", "sync-rest-contracts.ts");
252
- await patchFile(syncRestScriptPath, (source) => {
253
- let nextSource = replaceBlockConfigImportForAiFeatures(source, syncRestScriptPath);
254
- const helperInsertionAnchor = "async function assertTypeArtifactsCurrent";
255
- const restResourcesAnchor = "const restResources = REST_RESOURCES.filter( isWorkspaceRestResource );";
256
- const consoleLogPattern = /\n\tconsole\.log\(\n\t\toptions\.check/u;
257
- nextSource = replaceRequiredSyncRestSource(nextSource, "function isWorkspaceAiFeature(", helperInsertionAnchor, [
258
- "function isWorkspaceAiFeature(",
259
- "\tfeature: WorkspaceAiFeatureConfig",
260
- "): feature is WorkspaceAiFeatureConfig & {",
261
- "\taiSchemaFile: string;",
262
- "\tclientFile: string;",
263
- "\topenApiFile: string;",
264
- "\trestManifest: NonNullable< WorkspaceAiFeatureConfig[ 'restManifest' ] >;",
265
- "\ttypesFile: string;",
266
- "\tvalidatorsFile: string;",
267
- "} {",
268
- "\treturn (",
269
- "\t\ttypeof feature.aiSchemaFile === 'string' &&",
270
- "\t\ttypeof feature.clientFile === 'string' &&",
271
- "\t\ttypeof feature.openApiFile === 'string' &&",
272
- "\t\ttypeof feature.typesFile === 'string' &&",
273
- "\t\ttypeof feature.validatorsFile === 'string' &&",
274
- "\t\ttypeof feature.restManifest === 'object' &&",
275
- "\t\tfeature.restManifest !== null",
276
- "\t);",
277
- "}",
278
- "",
279
- "async function assertTypeArtifactsCurrent",
280
- ].join("\n"), "type artifact assertion helper", syncRestScriptPath);
281
- nextSource = replaceRequiredSyncRestSource(nextSource, "const aiFeatures = AI_FEATURES.filter( isWorkspaceAiFeature );", restResourcesAnchor, [
282
- "const restResources = REST_RESOURCES.filter( isWorkspaceRestResource );",
283
- "const aiFeatures = AI_FEATURES.filter( isWorkspaceAiFeature );",
284
- ].join("\n"), "rest resource filter", syncRestScriptPath);
285
- nextSource = replaceRequiredSyncRestSource(nextSource, "aiFeatures.length === 0", NO_RESOURCES_GUARD_PATTERN, buildAiFeatureNoResourcesGuard({
286
- hasPostMeta: nextSource.includes("const postMetaContracts = POST_META.filter( isWorkspacePostMetaContract );"),
287
- hasStandaloneContracts: nextSource.includes("const standaloneContracts = CONTRACTS.filter( isWorkspaceStandaloneContract );"),
288
- }), "no-resources guard", syncRestScriptPath);
289
- nextSource = replaceRequiredSyncRestSource(nextSource, "for ( const feature of aiFeatures ) {", consoleLogPattern, [
290
- "",
291
- "\tfor ( const feature of aiFeatures ) {",
292
- "\t\tconst contracts = feature.restManifest.contracts;",
293
- "",
294
- "\t\tfor ( const [ baseName, contract ] of Object.entries( contracts ) ) {",
295
- "\t\t\tawait syncTypeSchemas(",
296
- "\t\t\t\t{",
297
- "\t\t\t\t\tjsonSchemaFile: path.join(",
298
- "\t\t\t\t\t\tpath.dirname( feature.typesFile ),",
299
- "\t\t\t\t\t\t'api-schemas',",
300
- "\t\t\t\t\t\t`${ baseName }.schema.json`",
301
- "\t\t\t\t\t),",
302
- "\t\t\t\t\topenApiFile: path.join(",
303
- "\t\t\t\t\t\tpath.dirname( feature.typesFile ),",
304
- "\t\t\t\t\t\t'api-schemas',",
305
- "\t\t\t\t\t\t`${ baseName }.openapi.json`",
306
- "\t\t\t\t\t),",
307
- "\t\t\t\t\tsourceTypeName: contract.sourceTypeName,",
308
- "\t\t\t\t\ttypesFile: feature.typesFile,",
309
- "\t\t\t\t},",
310
- "\t\t\t\t{",
311
- "\t\t\t\t\tcheck: options.check,",
312
- "\t\t\t\t}",
313
- "\t\t\t);",
314
- "\t\t}",
315
- "",
316
- "\t\tawait syncRestOpenApi(",
317
- "\t\t\t{",
318
- "\t\t\t\tmanifest: feature.restManifest,",
319
- "\t\t\t\topenApiFile: feature.openApiFile,",
320
- "\t\t\t\ttypesFile: feature.typesFile,",
321
- "\t\t\t},",
322
- "\t\t\t{",
323
- "\t\t\t\tcheck: options.check,",
324
- "\t\t\t}",
325
- "\t\t);",
326
- "",
327
- "\t\tawait syncEndpointClient(",
328
- "\t\t\t{",
329
- "\t\t\t\tclientFile: feature.clientFile,",
330
- "\t\t\t\tmanifest: feature.restManifest,",
331
- "\t\t\t\ttypesFile: feature.typesFile,",
332
- "\t\t\t\tvalidatorsFile: feature.validatorsFile,",
333
- "\t\t\t},",
334
- "\t\t\t{",
335
- "\t\t\t\tcheck: options.check,",
336
- "\t\t\t}",
337
- "\t\t);",
338
- "\t}",
339
- "",
340
- "\tconsole.log(",
341
- "\t\toptions.check",
342
- ].join("\n"), "final sync summary", syncRestScriptPath);
343
- nextSource = replaceAiFeatureSyncSummaryCopy(nextSource, syncRestScriptPath);
344
- return nextSource;
345
- });
346
- }
@@ -1,8 +1,10 @@
1
1
  import { promises as fsp } from "node:fs";
2
2
  import path from "node:path";
3
3
  import { ensureBlockConfigCanAddRestManifests } from "./cli-add-block-legacy-validator.js";
4
- import { buildAiFeatureConfigEntry, buildAiFeatureDataSource, buildAiFeatureSyncScriptSource, buildAiFeatureTypesSource, buildAiFeatureValidatorsSource, buildAiFeatureApiSource, } from "./cli-add-workspace-ai-source-emitters.js";
5
- import { ensureAiFeatureBootstrapAnchors, ensureAiFeaturePackageScripts, ensureAiFeatureSyncProjectAnchors, ensureAiFeatureSyncRestAnchors, } from "./cli-add-workspace-ai-anchors.js";
4
+ import { buildAiFeatureConfigEntry, buildAiFeatureDataSource, buildAiFeatureTypesSource, buildAiFeatureValidatorsSource, buildAiFeatureApiSource, } from "./cli-add-workspace-ai-source-emitters.js";
5
+ import { buildAiFeatureSyncScriptSource, } from "./cli-add-workspace-ai-sync-script-source.js";
6
+ import { ensureAiFeatureBootstrapAnchors, ensureAiFeaturePackageScripts, ensureAiFeatureSyncProjectAnchors, } from "./cli-add-workspace-ai-anchors.js";
7
+ import { ensureAiFeatureSyncRestAnchors, } from "./cli-add-workspace-ai-sync-rest-anchors.js";
6
8
  import { buildAiFeaturePhpSource } from "./cli-add-workspace-ai-templates.js";
7
9
  import { appendWorkspaceInventoryEntries } from "./workspace-inventory.js";
8
10
  import { getWorkspaceBootstrapPath, patchFile, } from "./cli-add-shared.js";
@@ -1,3 +1,4 @@
1
+ export { buildAiFeatureSyncScriptSource, } from "./cli-add-workspace-ai-sync-script-source.js";
1
2
  /**
2
3
  * Build the workspace inventory entry written into `scripts/block-config.ts` for one AI feature.
3
4
  */
@@ -18,7 +19,3 @@ export declare function buildAiFeatureApiSource(aiFeatureSlug: string): string;
18
19
  * Generate React endpoint-mutation hooks for the scaffolded AI feature client wrapper.
19
20
  */
20
21
  export declare function buildAiFeatureDataSource(aiFeatureSlug: string): string;
21
- /**
22
- * Generate the `scripts/sync-ai-features.ts` source that projects AI-safe schemas for workspace features.
23
- */
24
- export declare function buildAiFeatureSyncScriptSource(): string;