@wp-typia/project-tools 0.23.0 → 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 (228) hide show
  1. package/dist/runtime/ai-feature-artifacts.js +4 -1
  2. package/dist/runtime/block-generator-service-spec.js +2 -1
  3. package/dist/runtime/built-in-block-non-ts-basic-artifacts.d.ts +9 -0
  4. package/dist/runtime/built-in-block-non-ts-basic-artifacts.js +84 -0
  5. package/dist/runtime/built-in-block-non-ts-compound-artifacts.d.ts +9 -0
  6. package/dist/runtime/built-in-block-non-ts-compound-artifacts.js +36 -0
  7. package/dist/runtime/built-in-block-non-ts-compound-templates.d.ts +23 -0
  8. package/dist/runtime/built-in-block-non-ts-compound-templates.js +453 -0
  9. package/dist/runtime/built-in-block-non-ts-family-artifacts.d.ts +8 -26
  10. package/dist/runtime/built-in-block-non-ts-family-artifacts.js +8 -1034
  11. package/dist/runtime/built-in-block-non-ts-interactivity-artifacts.d.ts +9 -0
  12. package/dist/runtime/built-in-block-non-ts-interactivity-artifacts.js +83 -0
  13. package/dist/runtime/built-in-block-non-ts-persistence-artifacts.d.ts +9 -0
  14. package/dist/runtime/built-in-block-non-ts-persistence-artifacts.js +33 -0
  15. package/dist/runtime/built-in-block-non-ts-persistence-templates.d.ts +23 -0
  16. package/dist/runtime/built-in-block-non-ts-persistence-templates.js +395 -0
  17. package/dist/runtime/cli-add-block-json.js +5 -1
  18. package/dist/runtime/cli-add-collision.js +8 -0
  19. package/dist/runtime/cli-add-help.js +14 -10
  20. package/dist/runtime/cli-add-kind-ids.d.ts +1 -1
  21. package/dist/runtime/cli-add-kind-ids.js +1 -0
  22. package/dist/runtime/cli-add-types.d.ts +45 -6
  23. package/dist/runtime/cli-add-types.js +2 -0
  24. package/dist/runtime/cli-add-validation.d.ts +7 -0
  25. package/dist/runtime/cli-add-validation.js +9 -0
  26. package/dist/runtime/cli-add-workspace-ability-anchors.d.ts +24 -0
  27. package/dist/runtime/cli-add-workspace-ability-anchors.js +294 -0
  28. package/dist/runtime/cli-add-workspace-ability-registry.d.ts +10 -0
  29. package/dist/runtime/cli-add-workspace-ability-registry.js +51 -0
  30. package/dist/runtime/cli-add-workspace-ability-scaffold.d.ts +1 -1
  31. package/dist/runtime/cli-add-workspace-ability-scaffold.js +5 -308
  32. package/dist/runtime/cli-add-workspace-admin-view-scaffold.js +6 -2
  33. package/dist/runtime/cli-add-workspace-admin-view-templates-core-data.d.ts +34 -0
  34. package/dist/runtime/cli-add-workspace-admin-view-templates-core-data.js +483 -0
  35. package/dist/runtime/cli-add-workspace-admin-view-templates-default.d.ts +30 -0
  36. package/dist/runtime/cli-add-workspace-admin-view-templates-default.js +310 -0
  37. package/dist/runtime/cli-add-workspace-admin-view-templates-rest.d.ts +25 -0
  38. package/dist/runtime/cli-add-workspace-admin-view-templates-rest.js +124 -0
  39. package/dist/runtime/cli-add-workspace-admin-view-templates-settings.d.ts +34 -0
  40. package/dist/runtime/cli-add-workspace-admin-view-templates-settings.js +370 -0
  41. package/dist/runtime/cli-add-workspace-admin-view-templates-shared.d.ts +49 -0
  42. package/dist/runtime/cli-add-workspace-admin-view-templates-shared.js +259 -0
  43. package/dist/runtime/cli-add-workspace-admin-view-templates.d.ts +18 -27
  44. package/dist/runtime/cli-add-workspace-admin-view-templates.js +30 -1326
  45. package/dist/runtime/cli-add-workspace-ai-anchors.d.ts +4 -4
  46. package/dist/runtime/cli-add-workspace-ai-anchors.js +8 -233
  47. package/dist/runtime/cli-add-workspace-ai-scaffold.js +4 -2
  48. package/dist/runtime/cli-add-workspace-ai-source-emitters.d.ts +1 -4
  49. package/dist/runtime/cli-add-workspace-ai-source-emitters.js +1 -129
  50. package/dist/runtime/cli-add-workspace-ai-sync-rest-anchors.d.ts +5 -0
  51. package/dist/runtime/cli-add-workspace-ai-sync-rest-anchors.js +236 -0
  52. package/dist/runtime/cli-add-workspace-ai-sync-script-source.d.ts +4 -0
  53. package/dist/runtime/cli-add-workspace-ai-sync-script-source.js +145 -0
  54. package/dist/runtime/cli-add-workspace-assets.d.ts +6 -63
  55. package/dist/runtime/cli-add-workspace-assets.js +6 -950
  56. package/dist/runtime/cli-add-workspace-binding-source-anchors.d.ts +23 -0
  57. package/dist/runtime/cli-add-workspace-binding-source-anchors.js +112 -0
  58. package/dist/runtime/cli-add-workspace-binding-source-source-emitters.d.ts +33 -0
  59. package/dist/runtime/cli-add-workspace-binding-source-source-emitters.js +436 -0
  60. package/dist/runtime/cli-add-workspace-binding-source-types.d.ts +20 -0
  61. package/dist/runtime/cli-add-workspace-binding-source-types.js +1 -0
  62. package/dist/runtime/cli-add-workspace-binding-source.d.ts +40 -0
  63. package/dist/runtime/cli-add-workspace-binding-source.js +275 -0
  64. package/dist/runtime/cli-add-workspace-block-style.d.ts +22 -0
  65. package/dist/runtime/cli-add-workspace-block-style.js +148 -0
  66. package/dist/runtime/cli-add-workspace-block-transform.d.ts +32 -0
  67. package/dist/runtime/cli-add-workspace-block-transform.js +197 -0
  68. package/dist/runtime/cli-add-workspace-contract.js +1 -1
  69. package/dist/runtime/cli-add-workspace-core-variation.d.ts +20 -0
  70. package/dist/runtime/cli-add-workspace-core-variation.js +322 -0
  71. package/dist/runtime/cli-add-workspace-editor-plugin-anchors.d.ts +37 -0
  72. package/dist/runtime/cli-add-workspace-editor-plugin-anchors.js +206 -0
  73. package/dist/runtime/cli-add-workspace-editor-plugin-source-emitters.d.ts +47 -0
  74. package/dist/runtime/cli-add-workspace-editor-plugin-source-emitters.js +219 -0
  75. package/dist/runtime/cli-add-workspace-editor-plugin.d.ts +22 -0
  76. package/dist/runtime/cli-add-workspace-editor-plugin.js +78 -0
  77. package/dist/runtime/cli-add-workspace-hooked-block.d.ts +23 -0
  78. package/dist/runtime/cli-add-workspace-hooked-block.js +57 -0
  79. package/dist/runtime/cli-add-workspace-integration-env-files.d.ts +33 -0
  80. package/dist/runtime/cli-add-workspace-integration-env-files.js +65 -0
  81. package/dist/runtime/cli-add-workspace-integration-env-package-json.d.ts +38 -0
  82. package/dist/runtime/cli-add-workspace-integration-env-package-json.js +122 -0
  83. package/dist/runtime/cli-add-workspace-integration-env-source-emitters.d.ts +44 -0
  84. package/dist/runtime/cli-add-workspace-integration-env-source-emitters.js +262 -0
  85. package/dist/runtime/cli-add-workspace-integration-env.d.ts +3 -1
  86. package/dist/runtime/cli-add-workspace-integration-env.js +10 -313
  87. package/dist/runtime/cli-add-workspace-pattern-anchors.d.ts +10 -0
  88. package/dist/runtime/cli-add-workspace-pattern-anchors.js +95 -0
  89. package/dist/runtime/cli-add-workspace-pattern-options.d.ts +20 -0
  90. package/dist/runtime/cli-add-workspace-pattern-options.js +113 -0
  91. package/dist/runtime/cli-add-workspace-pattern-source-emitters.d.ts +20 -0
  92. package/dist/runtime/cli-add-workspace-pattern-source-emitters.js +57 -0
  93. package/dist/runtime/cli-add-workspace-pattern.d.ts +42 -0
  94. package/dist/runtime/cli-add-workspace-pattern.js +99 -0
  95. package/dist/runtime/cli-add-workspace-post-meta.js +1 -1
  96. package/dist/runtime/cli-add-workspace-registration-hooks.d.ts +50 -0
  97. package/dist/runtime/cli-add-workspace-registration-hooks.js +162 -0
  98. package/dist/runtime/cli-add-workspace-rest-anchors.d.ts +9 -4
  99. package/dist/runtime/cli-add-workspace-rest-anchors.js +9 -428
  100. package/dist/runtime/cli-add-workspace-rest-bootstrap-anchors.d.ts +17 -0
  101. package/dist/runtime/cli-add-workspace-rest-bootstrap-anchors.js +108 -0
  102. package/dist/runtime/cli-add-workspace-rest-contract-sync-anchors.d.ts +9 -0
  103. package/dist/runtime/cli-add-workspace-rest-contract-sync-anchors.js +142 -0
  104. package/dist/runtime/cli-add-workspace-rest-generated-source-emitters.d.ts +51 -0
  105. package/dist/runtime/cli-add-workspace-rest-generated-source-emitters.js +415 -0
  106. package/dist/runtime/cli-add-workspace-rest-generated.d.ts +9 -0
  107. package/dist/runtime/cli-add-workspace-rest-generated.js +160 -0
  108. package/dist/runtime/cli-add-workspace-rest-manual-source-emitters.d.ts +80 -0
  109. package/dist/runtime/cli-add-workspace-rest-manual-source-emitters.js +238 -0
  110. package/dist/runtime/cli-add-workspace-rest-manual.d.ts +8 -0
  111. package/dist/runtime/cli-add-workspace-rest-manual.js +266 -0
  112. package/dist/runtime/cli-add-workspace-rest-php-templates.d.ts +18 -0
  113. package/dist/runtime/cli-add-workspace-rest-php-templates.js +359 -0
  114. package/dist/runtime/cli-add-workspace-rest-resource-php-routing-template.d.ts +33 -0
  115. package/dist/runtime/cli-add-workspace-rest-resource-php-routing-template.js +145 -0
  116. package/dist/runtime/cli-add-workspace-rest-resource-sync-anchors.d.ts +9 -0
  117. package/dist/runtime/cli-add-workspace-rest-resource-sync-anchors.js +162 -0
  118. package/dist/runtime/cli-add-workspace-rest-schema-helper-php-template.d.ts +7 -0
  119. package/dist/runtime/cli-add-workspace-rest-schema-helper-php-template.js +193 -0
  120. package/dist/runtime/cli-add-workspace-rest-source-emitters.d.ts +5 -91
  121. package/dist/runtime/cli-add-workspace-rest-source-emitters.js +5 -642
  122. package/dist/runtime/cli-add-workspace-rest-source-utils.d.ts +17 -0
  123. package/dist/runtime/cli-add-workspace-rest-source-utils.js +50 -0
  124. package/dist/runtime/cli-add-workspace-rest-sync-script-shared.d.ts +56 -0
  125. package/dist/runtime/cli-add-workspace-rest-sync-script-shared.js +122 -0
  126. package/dist/runtime/cli-add-workspace-rest-types.d.ts +108 -0
  127. package/dist/runtime/cli-add-workspace-rest-types.js +1 -0
  128. package/dist/runtime/cli-add-workspace-rest.d.ts +3 -20
  129. package/dist/runtime/cli-add-workspace-rest.js +33 -788
  130. package/dist/runtime/cli-add-workspace-variation.d.ts +22 -0
  131. package/dist/runtime/cli-add-workspace-variation.js +162 -0
  132. package/dist/runtime/cli-add-workspace.d.ts +42 -107
  133. package/dist/runtime/cli-add-workspace.js +42 -674
  134. package/dist/runtime/cli-add.d.ts +3 -3
  135. package/dist/runtime/cli-add.js +2 -2
  136. package/dist/runtime/cli-core.d.ts +3 -2
  137. package/dist/runtime/cli-core.js +2 -2
  138. package/dist/runtime/cli-diagnostics.d.ts +3 -1
  139. package/dist/runtime/cli-diagnostics.js +17 -5
  140. package/dist/runtime/cli-doctor-workspace-bindings.js +63 -1
  141. package/dist/runtime/cli-doctor-workspace-block-addons.d.ts +12 -0
  142. package/dist/runtime/cli-doctor-workspace-block-addons.js +162 -0
  143. package/dist/runtime/cli-doctor-workspace-block-iframe.d.ts +9 -0
  144. package/dist/runtime/cli-doctor-workspace-block-iframe.js +228 -0
  145. package/dist/runtime/cli-doctor-workspace-block-metadata.d.ts +11 -0
  146. package/dist/runtime/cli-doctor-workspace-block-metadata.js +111 -0
  147. package/dist/runtime/cli-doctor-workspace-blocks.js +6 -424
  148. package/dist/runtime/cli-doctor-workspace-features-abilities.d.ts +11 -0
  149. package/dist/runtime/cli-doctor-workspace-features-abilities.js +112 -0
  150. package/dist/runtime/cli-doctor-workspace-features-admin-views.d.ts +11 -0
  151. package/dist/runtime/cli-doctor-workspace-features-admin-views.js +128 -0
  152. package/dist/runtime/cli-doctor-workspace-features-ai.d.ts +11 -0
  153. package/dist/runtime/cli-doctor-workspace-features-ai.js +57 -0
  154. package/dist/runtime/cli-doctor-workspace-features-editor-plugins.d.ts +11 -0
  155. package/dist/runtime/cli-doctor-workspace-features-editor-plugins.js +80 -0
  156. package/dist/runtime/cli-doctor-workspace-features-post-meta.d.ts +11 -0
  157. package/dist/runtime/cli-doctor-workspace-features-post-meta.js +77 -0
  158. package/dist/runtime/cli-doctor-workspace-features-rest.d.ts +11 -0
  159. package/dist/runtime/cli-doctor-workspace-features-rest.js +120 -0
  160. package/dist/runtime/cli-doctor-workspace-features.js +14 -487
  161. package/dist/runtime/cli-doctor.d.ts +54 -3
  162. package/dist/runtime/cli-doctor.js +92 -10
  163. package/dist/runtime/cli-help.js +12 -7
  164. package/dist/runtime/cli-init-package-json.js +4 -2
  165. package/dist/runtime/cli-prompt.d.ts +16 -2
  166. package/dist/runtime/cli-prompt.js +29 -12
  167. package/dist/runtime/cli-scaffold.d.ts +2 -1
  168. package/dist/runtime/cli-scaffold.js +19 -10
  169. package/dist/runtime/external-template-guards.js +4 -6
  170. package/dist/runtime/index.d.ts +6 -3
  171. package/dist/runtime/index.js +4 -2
  172. package/dist/runtime/json-utils.d.ts +62 -4
  173. package/dist/runtime/json-utils.js +78 -4
  174. package/dist/runtime/local-dev-presets.js +6 -2
  175. package/dist/runtime/migration-ui-capability.js +4 -1
  176. package/dist/runtime/migration-utils.js +4 -1
  177. package/dist/runtime/package-managers.js +6 -1
  178. package/dist/runtime/package-versions.d.ts +1 -0
  179. package/dist/runtime/package-versions.js +16 -3
  180. package/dist/runtime/pattern-catalog.d.ts +122 -0
  181. package/dist/runtime/pattern-catalog.js +471 -0
  182. package/dist/runtime/post-meta-binding-fields.d.ts +46 -0
  183. package/dist/runtime/post-meta-binding-fields.js +135 -0
  184. package/dist/runtime/scaffold-bootstrap.js +7 -2
  185. package/dist/runtime/scaffold-package-manager-files.js +5 -1
  186. package/dist/runtime/scaffold-repository-reference.js +4 -2
  187. package/dist/runtime/scaffold-template-variables.js +2 -1
  188. package/dist/runtime/scaffold.d.ts +18 -1
  189. package/dist/runtime/scaffold.js +55 -2
  190. package/dist/runtime/temp-roots.js +4 -1
  191. package/dist/runtime/template-layers.js +4 -1
  192. package/dist/runtime/template-registry.js +9 -3
  193. package/dist/runtime/template-source-contracts.d.ts +2 -0
  194. package/dist/runtime/template-source-normalization.js +2 -1
  195. package/dist/runtime/template-source-remote.js +18 -5
  196. package/dist/runtime/template-source-seeds.js +10 -3
  197. package/dist/runtime/typia-llm-json-schema.d.ts +24 -0
  198. package/dist/runtime/typia-llm-json-schema.js +33 -0
  199. package/dist/runtime/typia-llm-openapi-constraints.d.ts +20 -0
  200. package/dist/runtime/typia-llm-openapi-constraints.js +254 -0
  201. package/dist/runtime/typia-llm-projection.d.ts +25 -0
  202. package/dist/runtime/typia-llm-projection.js +58 -0
  203. package/dist/runtime/typia-llm-render.d.ts +21 -0
  204. package/dist/runtime/typia-llm-render.js +252 -0
  205. package/dist/runtime/typia-llm-sync.d.ts +10 -0
  206. package/dist/runtime/typia-llm-sync.js +63 -0
  207. package/dist/runtime/typia-llm-types.d.ts +197 -0
  208. package/dist/runtime/typia-llm-types.js +1 -0
  209. package/dist/runtime/typia-llm.d.ts +9 -255
  210. package/dist/runtime/typia-llm.js +5 -634
  211. package/dist/runtime/workspace-inventory-mutations.js +15 -1
  212. package/dist/runtime/workspace-inventory-parser-entries.d.ts +17 -0
  213. package/dist/runtime/workspace-inventory-parser-entries.js +157 -0
  214. package/dist/runtime/workspace-inventory-parser-validation.d.ts +104 -0
  215. package/dist/runtime/workspace-inventory-parser-validation.js +34 -0
  216. package/dist/runtime/workspace-inventory-parser.d.ts +3 -45
  217. package/dist/runtime/workspace-inventory-parser.js +3 -581
  218. package/dist/runtime/workspace-inventory-section-descriptors.d.ts +19 -0
  219. package/dist/runtime/workspace-inventory-section-descriptors.js +443 -0
  220. package/dist/runtime/workspace-inventory-templates.d.ts +3 -3
  221. package/dist/runtime/workspace-inventory-templates.js +10 -1
  222. package/dist/runtime/workspace-inventory-types.d.ts +10 -1
  223. package/dist/runtime/workspace-project.js +4 -6
  224. package/package.json +8 -3
  225. package/templates/_shared/compound/core/scripts/block-config.ts.mustache +22 -0
  226. package/templates/_shared/compound/core/scripts/sync-types-to-block-json.ts.mustache +103 -2
  227. package/templates/_shared/compound/core/src/inner-blocks-templates.ts.mustache +13 -0
  228. package/templates/_shared/compound/persistence/scripts/block-config.ts.mustache +22 -1
@@ -0,0 +1,23 @@
1
+ import type { WorkspaceProject } from "./workspace-project.js";
2
+ /**
3
+ * Ensure the workspace bootstrap loads binding-source PHP and editor bundles.
4
+ *
5
+ * @param workspace Official workspace metadata used to locate and patch the bootstrap file.
6
+ * @returns A promise that resolves after the bootstrap anchors are present.
7
+ */
8
+ export declare function ensureBindingSourceBootstrapAnchors(workspace: WorkspaceProject): Promise<void>;
9
+ /**
10
+ * Resolve the binding-source editor registry path, preferring existing TypeScript or JavaScript registries.
11
+ *
12
+ * @param projectDir Workspace root directory to inspect.
13
+ * @returns A promise for the registry path to read or write.
14
+ */
15
+ export declare function resolveBindingSourceRegistryPath(projectDir: string): Promise<string>;
16
+ /**
17
+ * Rewrite the binding-source editor registry with the requested source slug included.
18
+ *
19
+ * @param projectDir Workspace root directory that owns `src/bindings`.
20
+ * @param bindingSourceSlug Binding source slug that must be imported by the registry.
21
+ * @returns A promise that resolves after the registry has been written.
22
+ */
23
+ export declare function writeBindingSourceRegistry(projectDir: string, bindingSourceSlug: string): Promise<void>;
@@ -0,0 +1,112 @@
1
+ import { promises as fsp } from "node:fs";
2
+ import path from "node:path";
3
+ import { getWorkspaceBootstrapPath, patchFile, } from "./cli-add-shared.js";
4
+ import { appendPhpSnippetBeforeClosingTag, insertPhpSnippetBeforeWorkspaceAnchors, } from "./cli-add-workspace-mutation.js";
5
+ import { pathExists } from "./fs-async.js";
6
+ import { hasPhpFunctionDefinition } from "./php-utils.js";
7
+ const BINDING_SOURCE_SERVER_GLOB = "/src/bindings/*/server.php";
8
+ const BINDING_SOURCE_EDITOR_SCRIPT = "build/bindings/index.js";
9
+ const BINDING_SOURCE_EDITOR_ASSET = "build/bindings/index.asset.php";
10
+ function buildBindingSourceIndexSource(bindingSourceSlugs) {
11
+ const importLines = bindingSourceSlugs
12
+ .map((bindingSourceSlug) => `import './${bindingSourceSlug}/editor';`)
13
+ .join("\n");
14
+ return `${importLines}${importLines ? "\n\n" : ""}// wp-typia add binding-source entries\n`;
15
+ }
16
+ /**
17
+ * Ensure the workspace bootstrap loads binding-source PHP and editor bundles.
18
+ *
19
+ * @param workspace Official workspace metadata used to locate and patch the bootstrap file.
20
+ * @returns A promise that resolves after the bootstrap anchors are present.
21
+ */
22
+ export async function ensureBindingSourceBootstrapAnchors(workspace) {
23
+ const bootstrapPath = getWorkspaceBootstrapPath(workspace);
24
+ await patchFile(bootstrapPath, (source) => {
25
+ let nextSource = source;
26
+ const workspaceBaseName = workspace.packageName.split("/").pop() ?? workspace.packageName;
27
+ const bindingRegistrationFunctionName = `${workspace.workspace.phpPrefix}_register_binding_sources`;
28
+ const bindingEditorEnqueueFunctionName = `${workspace.workspace.phpPrefix}_enqueue_binding_sources_editor`;
29
+ const bindingRegistrationHook = `add_action( 'init', '${bindingRegistrationFunctionName}', 20 );`;
30
+ const bindingEditorEnqueueHook = `add_action( 'enqueue_block_editor_assets', '${bindingEditorEnqueueFunctionName}' );`;
31
+ const bindingRegistrationFunction = `
32
+
33
+ function ${bindingRegistrationFunctionName}() {
34
+ \tforeach ( glob( __DIR__ . '${BINDING_SOURCE_SERVER_GLOB}' ) ?: array() as $binding_source_module ) {
35
+ \t\trequire_once $binding_source_module;
36
+ \t}
37
+ }
38
+ `;
39
+ const bindingEditorEnqueueFunction = `
40
+
41
+ function ${bindingEditorEnqueueFunctionName}() {
42
+ \t$script_path = __DIR__ . '/${BINDING_SOURCE_EDITOR_SCRIPT}';
43
+ \t$asset_path = __DIR__ . '/${BINDING_SOURCE_EDITOR_ASSET}';
44
+
45
+ \tif ( ! file_exists( $script_path ) || ! file_exists( $asset_path ) ) {
46
+ \t\treturn;
47
+ \t}
48
+
49
+ \t$asset = require $asset_path;
50
+ \tif ( ! is_array( $asset ) ) {
51
+ \t\t$asset = array();
52
+ \t}
53
+
54
+ \twp_enqueue_script(
55
+ \t\t'${workspaceBaseName}-binding-sources',
56
+ \t\tplugins_url( '${BINDING_SOURCE_EDITOR_SCRIPT}', __FILE__ ),
57
+ \t\tisset( $asset['dependencies'] ) && is_array( $asset['dependencies'] ) ? $asset['dependencies'] : array(),
58
+ \t\tisset( $asset['version'] ) ? $asset['version'] : filemtime( $script_path ),
59
+ \t\ttrue
60
+ \t);
61
+ }
62
+ `;
63
+ if (!hasPhpFunctionDefinition(nextSource, bindingRegistrationFunctionName)) {
64
+ nextSource = insertPhpSnippetBeforeWorkspaceAnchors(nextSource, bindingRegistrationFunction);
65
+ }
66
+ if (!hasPhpFunctionDefinition(nextSource, bindingEditorEnqueueFunctionName)) {
67
+ nextSource = insertPhpSnippetBeforeWorkspaceAnchors(nextSource, bindingEditorEnqueueFunction);
68
+ }
69
+ if (!nextSource.includes(bindingRegistrationHook)) {
70
+ nextSource = appendPhpSnippetBeforeClosingTag(nextSource, bindingRegistrationHook);
71
+ }
72
+ if (!nextSource.includes(bindingEditorEnqueueHook)) {
73
+ nextSource = appendPhpSnippetBeforeClosingTag(nextSource, bindingEditorEnqueueHook);
74
+ }
75
+ return nextSource;
76
+ });
77
+ }
78
+ /**
79
+ * Resolve the binding-source editor registry path, preferring existing TypeScript or JavaScript registries.
80
+ *
81
+ * @param projectDir Workspace root directory to inspect.
82
+ * @returns A promise for the registry path to read or write.
83
+ */
84
+ export async function resolveBindingSourceRegistryPath(projectDir) {
85
+ const bindingsDir = path.join(projectDir, "src", "bindings");
86
+ for (const candidatePath of [
87
+ path.join(bindingsDir, "index.ts"),
88
+ path.join(bindingsDir, "index.js"),
89
+ ]) {
90
+ if (await pathExists(candidatePath)) {
91
+ return candidatePath;
92
+ }
93
+ }
94
+ return path.join(bindingsDir, "index.ts");
95
+ }
96
+ /**
97
+ * Rewrite the binding-source editor registry with the requested source slug included.
98
+ *
99
+ * @param projectDir Workspace root directory that owns `src/bindings`.
100
+ * @param bindingSourceSlug Binding source slug that must be imported by the registry.
101
+ * @returns A promise that resolves after the registry has been written.
102
+ */
103
+ export async function writeBindingSourceRegistry(projectDir, bindingSourceSlug) {
104
+ const bindingsDir = path.join(projectDir, "src", "bindings");
105
+ const bindingsIndexPath = await resolveBindingSourceRegistryPath(projectDir);
106
+ await fsp.mkdir(bindingsDir, { recursive: true });
107
+ const existingBindingSourceSlugs = (await fsp.readdir(bindingsDir, { withFileTypes: true }))
108
+ .filter((entry) => entry.isDirectory())
109
+ .map((entry) => entry.name);
110
+ const nextBindingSourceSlugs = Array.from(new Set([...existingBindingSourceSlugs, bindingSourceSlug])).sort();
111
+ await fsp.writeFile(bindingsIndexPath, buildBindingSourceIndexSource(nextBindingSourceSlugs), "utf8");
112
+ }
@@ -0,0 +1,33 @@
1
+ import type { BindingPostMetaSource, BindingTarget } from "./cli-add-workspace-binding-source-types.js";
2
+ /**
3
+ * Render one `scripts/block-config.ts` binding-source inventory entry.
4
+ *
5
+ * @param bindingSourceSlug Normalized binding-source slug.
6
+ * @param target Optional block attribute target wired to the binding source.
7
+ * @param postMeta Optional post-meta contract backing this binding source.
8
+ * @returns TypeScript source for the inventory entry.
9
+ */
10
+ export declare function buildBindingSourceConfigEntry(bindingSourceSlug: string, target?: BindingTarget, postMeta?: BindingPostMetaSource): string;
11
+ /**
12
+ * Render the PHP registration module for a generated binding source.
13
+ *
14
+ * @param bindingSourceSlug Normalized binding-source slug.
15
+ * @param phpPrefix Workspace PHP function prefix.
16
+ * @param namespace Workspace block namespace.
17
+ * @param textDomain Workspace text domain used for labels.
18
+ * @param target Optional block attribute target wired to the binding source.
19
+ * @param postMeta Optional post-meta contract backing this binding source.
20
+ * @returns PHP source for `src/bindings/<slug>/server.php`.
21
+ */
22
+ export declare function buildBindingSourceServerSource(bindingSourceSlug: string, phpPrefix: string, namespace: string, textDomain: string, target?: BindingTarget, postMeta?: BindingPostMetaSource): string;
23
+ /**
24
+ * Render the editor registration module for a generated binding source.
25
+ *
26
+ * @param bindingSourceSlug Normalized binding-source slug.
27
+ * @param namespace Workspace block namespace.
28
+ * @param textDomain Workspace text domain used for labels.
29
+ * @param target Optional block attribute target wired to the binding source.
30
+ * @param postMeta Optional post-meta contract backing this binding source.
31
+ * @returns TypeScript source for `src/bindings/<slug>/editor.ts`.
32
+ */
33
+ export declare function buildBindingSourceEditorSource(bindingSourceSlug: string, namespace: string, textDomain: string, target?: BindingTarget, postMeta?: BindingPostMetaSource): string;
@@ -0,0 +1,436 @@
1
+ import { quoteTsString } from "./cli-add-shared.js";
2
+ import { quotePhpString } from "./php-utils.js";
3
+ import { toTitleCase } from "./string-case.js";
4
+ /**
5
+ * Render one `scripts/block-config.ts` binding-source inventory entry.
6
+ *
7
+ * @param bindingSourceSlug Normalized binding-source slug.
8
+ * @param target Optional block attribute target wired to the binding source.
9
+ * @param postMeta Optional post-meta contract backing this binding source.
10
+ * @returns TypeScript source for the inventory entry.
11
+ */
12
+ export function buildBindingSourceConfigEntry(bindingSourceSlug, target, postMeta) {
13
+ return [
14
+ "\t{",
15
+ ...(target ? [`\t\tattribute: ${quoteTsString(target.attributeName)},`] : []),
16
+ ...(target ? [`\t\tblock: ${quoteTsString(target.blockSlug)},`] : []),
17
+ `\t\teditorFile: ${quoteTsString(`src/bindings/${bindingSourceSlug}/editor.ts`)},`,
18
+ ...(postMeta ? [`\t\tmetaPath: ${quoteTsString(postMeta.metaPath)},`] : []),
19
+ ...(postMeta ? [`\t\tpostMeta: ${quoteTsString(postMeta.postMetaSlug)},`] : []),
20
+ `\t\tserverFile: ${quoteTsString(`src/bindings/${bindingSourceSlug}/server.php`)},`,
21
+ `\t\tslug: ${quoteTsString(bindingSourceSlug)},`,
22
+ "\t},",
23
+ ].join("\n");
24
+ }
25
+ function buildPhpStringList(values) {
26
+ if (values.length === 0) {
27
+ return "array()";
28
+ }
29
+ return `array( ${values.map((value) => quotePhpString(value)).join(", ")} )`;
30
+ }
31
+ function buildBindingPostMetaServerSource(options) {
32
+ const bindingSourceTitle = toTitleCase(options.bindingSourceSlug);
33
+ const bindingSourcePhpId = options.bindingSourceSlug.replace(/-/g, "_");
34
+ const functionPrefix = `${options.phpPrefix}_${bindingSourcePhpId}`;
35
+ const fieldsFunctionName = `${functionPrefix}_post_meta_binding_fields`;
36
+ const canReadFunctionName = `${functionPrefix}_can_read_post_meta`;
37
+ const resolveFunctionName = `${functionPrefix}_resolve_binding_source_value`;
38
+ const supportedAttributesFunctionName = `${functionPrefix}_supported_binding_attributes`;
39
+ const fieldNames = options.postMeta.fields.map((field) => field.name);
40
+ const supportedAttributesSource = options.target
41
+ ? `
42
+ if ( ! function_exists( '${supportedAttributesFunctionName}' ) ) {
43
+ \tfunction ${supportedAttributesFunctionName}( array $supported_attributes ) : array {
44
+ \t\tif ( ! in_array( ${quotePhpString(options.target.attributeName)}, $supported_attributes, true ) ) {
45
+ \t\t\t$supported_attributes[] = ${quotePhpString(options.target.attributeName)};
46
+ \t\t}
47
+
48
+ \t\treturn $supported_attributes;
49
+ \t}
50
+ }
51
+ `
52
+ : "";
53
+ const supportedAttributesHook = options.target
54
+ ? `
55
+ if ( function_exists( '${supportedAttributesFunctionName}' ) ) {
56
+ \tadd_filter(
57
+ \t\t${quotePhpString(`block_bindings_supported_attributes_${options.namespace}/${options.target.blockSlug}`)},
58
+ \t\t${quotePhpString(supportedAttributesFunctionName)}
59
+ \t);
60
+ }
61
+ `
62
+ : "";
63
+ return `<?php
64
+ if ( ! defined( 'ABSPATH' ) ) {
65
+ \treturn;
66
+ }
67
+
68
+ if ( ! function_exists( 'register_block_bindings_source' ) ) {
69
+ \treturn;
70
+ }
71
+
72
+ if ( ! function_exists( '${fieldsFunctionName}' ) ) {
73
+ \tfunction ${fieldsFunctionName}() : array {
74
+ \t\t$schema_file = dirname( __DIR__, 3 ) . '/${options.postMeta.schemaFile}';
75
+ \t\tif ( file_exists( $schema_file ) ) {
76
+ \t\t\t$schema = json_decode( (string) file_get_contents( $schema_file ), true );
77
+ \t\t\tif ( is_array( $schema ) && isset( $schema['properties'] ) && is_array( $schema['properties'] ) ) {
78
+ \t\t\t\treturn array_values( array_filter( array_keys( $schema['properties'] ), 'is_string' ) );
79
+ \t\t\t}
80
+ \t\t}
81
+
82
+ \t\treturn ${buildPhpStringList(fieldNames)};
83
+ \t}
84
+ }
85
+
86
+ if ( ! function_exists( '${canReadFunctionName}' ) ) {
87
+ \tfunction ${canReadFunctionName}( int $post_id ) : bool {
88
+ \t\t$post = get_post( $post_id );
89
+ \t\tif ( ! $post ) {
90
+ \t\t\treturn false;
91
+ \t\t}
92
+ \t\t$post_type = is_string( $post->post_type ) ? $post->post_type : '';
93
+ \t\tif ( '' === $post_type ) {
94
+ \t\t\treturn false;
95
+ \t\t}
96
+ \t\tif ( ( ! is_post_publicly_viewable( $post ) && ! current_user_can( 'read_post', $post_id ) ) || post_password_required( $post ) ) {
97
+ \t\t\treturn false;
98
+ \t\t}
99
+
100
+ \t\t$meta_keys = get_registered_meta_keys( 'post', $post_type );
101
+ \t\t$meta_keys = array_merge( $meta_keys, get_registered_meta_keys( 'post', '' ) );
102
+
103
+ \t\treturn ! empty( $meta_keys[ ${quotePhpString(options.postMeta.metaKey)} ]['show_in_rest'] );
104
+ \t}
105
+ }
106
+
107
+ if ( ! function_exists( '${resolveFunctionName}' ) ) {
108
+ \tfunction ${resolveFunctionName}( array $source_args, $block_instance = null, $attribute_name = null ) {
109
+ \t\tunset( $attribute_name );
110
+
111
+ \t\t$field = isset( $source_args['field'] ) && is_string( $source_args['field'] )
112
+ \t\t\t? $source_args['field']
113
+ \t\t\t: ${quotePhpString(options.postMeta.metaPath)};
114
+ \t\tif ( ! in_array( $field, ${fieldsFunctionName}(), true ) ) {
115
+ \t\t\treturn null;
116
+ \t\t}
117
+
118
+ \t\t$post_id = 0;
119
+ \t\tif (
120
+ \t\t\tis_object( $block_instance ) &&
121
+ \t\t\tproperty_exists( $block_instance, 'context' ) &&
122
+ \t\t\tis_array( $block_instance->context ) &&
123
+ \t\t\tisset( $block_instance->context['postId'] )
124
+ \t\t) {
125
+ \t\t\t$post_id = absint( $block_instance->context['postId'] );
126
+ \t\t}
127
+ \t\tif ( ! $post_id || ! ${canReadFunctionName}( $post_id ) ) {
128
+ \t\t\treturn null;
129
+ \t\t}
130
+
131
+ \t\t$value = null;
132
+ \t\tif ( $post_id ) {
133
+ \t\t\t$meta = get_post_meta( $post_id, ${quotePhpString(options.postMeta.metaKey)}, true );
134
+ \t\t\tif ( is_array( $meta ) && array_key_exists( $field, $meta ) ) {
135
+ \t\t\t\t$value = $meta[ $field ];
136
+ \t\t\t}
137
+ \t\t}
138
+ \t\tif ( null === $value ) {
139
+ \t\t\treturn null;
140
+ \t\t}
141
+
142
+ \t\treturn $value;
143
+ \t}
144
+ }
145
+ ${supportedAttributesSource}
146
+
147
+ register_block_bindings_source(
148
+ \t${quotePhpString(`${options.namespace}/${options.bindingSourceSlug}`)},
149
+ \tarray(
150
+ \t\t'label' => __( ${quotePhpString(bindingSourceTitle)}, ${quotePhpString(options.textDomain)} ),
151
+ \t\t'get_value_callback' => ${quotePhpString(resolveFunctionName)},
152
+ \t\t'uses_context' => array( 'postId', 'postType' ),
153
+ \t)
154
+ );
155
+ ${supportedAttributesHook}`;
156
+ }
157
+ /**
158
+ * Render the PHP registration module for a generated binding source.
159
+ *
160
+ * @param bindingSourceSlug Normalized binding-source slug.
161
+ * @param phpPrefix Workspace PHP function prefix.
162
+ * @param namespace Workspace block namespace.
163
+ * @param textDomain Workspace text domain used for labels.
164
+ * @param target Optional block attribute target wired to the binding source.
165
+ * @param postMeta Optional post-meta contract backing this binding source.
166
+ * @returns PHP source for `src/bindings/<slug>/server.php`.
167
+ */
168
+ export function buildBindingSourceServerSource(bindingSourceSlug, phpPrefix, namespace, textDomain, target, postMeta) {
169
+ if (postMeta) {
170
+ return buildBindingPostMetaServerSource({
171
+ bindingSourceSlug,
172
+ namespace,
173
+ phpPrefix,
174
+ postMeta,
175
+ target,
176
+ textDomain,
177
+ });
178
+ }
179
+ const bindingSourceTitle = toTitleCase(bindingSourceSlug);
180
+ const bindingSourcePhpId = bindingSourceSlug.replace(/-/g, "_");
181
+ const bindingSourceValueFunctionName = `${phpPrefix}_${bindingSourcePhpId}_binding_source_values`;
182
+ const bindingSourceResolveFunctionName = `${phpPrefix}_${bindingSourcePhpId}_resolve_binding_source_value`;
183
+ const bindingSourceSupportedAttributesFunctionName = `${phpPrefix}_${bindingSourcePhpId}_supported_binding_attributes`;
184
+ const starterValue = `${bindingSourceTitle} starter value`;
185
+ const supportedAttributesSource = target
186
+ ? `
187
+ if ( ! function_exists( '${bindingSourceSupportedAttributesFunctionName}' ) ) {
188
+ \tfunction ${bindingSourceSupportedAttributesFunctionName}( array $supported_attributes ) : array {
189
+ \t\tif ( ! in_array( ${quotePhpString(target.attributeName)}, $supported_attributes, true ) ) {
190
+ \t\t\t$supported_attributes[] = ${quotePhpString(target.attributeName)};
191
+ \t\t}
192
+
193
+ \t\treturn $supported_attributes;
194
+ \t}
195
+ }
196
+ `
197
+ : "";
198
+ const supportedAttributesHook = target
199
+ ? `
200
+ if ( function_exists( '${bindingSourceSupportedAttributesFunctionName}' ) ) {
201
+ \tadd_filter(
202
+ \t\t${quotePhpString(`block_bindings_supported_attributes_${namespace}/${target.blockSlug}`)},
203
+ \t\t${quotePhpString(bindingSourceSupportedAttributesFunctionName)}
204
+ \t);
205
+ }
206
+ `
207
+ : "";
208
+ return `<?php
209
+ if ( ! defined( 'ABSPATH' ) ) {
210
+ \treturn;
211
+ }
212
+
213
+ if ( ! function_exists( 'register_block_bindings_source' ) ) {
214
+ \treturn;
215
+ }
216
+
217
+ if ( ! function_exists( '${bindingSourceValueFunctionName}' ) ) {
218
+ \tfunction ${bindingSourceValueFunctionName}() : array {
219
+ \t\treturn array(
220
+ \t\t\t${quotePhpString(bindingSourceSlug)} => ${quotePhpString(starterValue)},
221
+ \t\t);
222
+ \t}
223
+ }
224
+
225
+ if ( ! function_exists( '${bindingSourceResolveFunctionName}' ) ) {
226
+ \tfunction ${bindingSourceResolveFunctionName}( array $source_args ) : string {
227
+ \t\t$field = isset( $source_args['field'] ) && is_string( $source_args['field'] )
228
+ \t\t\t? $source_args['field']
229
+ \t\t\t: '${bindingSourceSlug}';
230
+ \t\t$binding_source_values = ${bindingSourceValueFunctionName}();
231
+ \t\t$value = $binding_source_values[ $field ] ?? '';
232
+
233
+ \t\treturn is_string( $value ) ? $value : '';
234
+ \t}
235
+ }
236
+ ${supportedAttributesSource}
237
+
238
+ register_block_bindings_source(
239
+ \t${quotePhpString(`${namespace}/${bindingSourceSlug}`)},
240
+ \tarray(
241
+ \t\t'label' => __( ${quotePhpString(bindingSourceTitle)}, ${quotePhpString(textDomain)} ),
242
+ \t\t'get_value_callback' => ${quotePhpString(bindingSourceResolveFunctionName)},
243
+ \t)
244
+ );
245
+ ${supportedAttributesHook}`;
246
+ }
247
+ function buildTsPostMetaPreviewValue(field) {
248
+ switch (field.schemaType) {
249
+ case "array":
250
+ return "[]";
251
+ case "boolean":
252
+ return field.fallbackValue === "true" ? "true" : "false";
253
+ case "integer":
254
+ case "number": {
255
+ const value = Number(field.fallbackValue);
256
+ return Number.isFinite(value) ? String(value) : "0";
257
+ }
258
+ case "object":
259
+ return "{}";
260
+ default:
261
+ return quoteTsString(field.fallbackValue);
262
+ }
263
+ }
264
+ function buildTsPostMetaFieldEntries(fields, textDomain) {
265
+ return fields
266
+ .map((field) => [
267
+ "\t{",
268
+ `\t\tfallbackValue: ${quoteTsString(field.fallbackValue)},`,
269
+ `\t\tlabel: __( ${quoteTsString(field.label)}, ${quoteTsString(textDomain)} ),`,
270
+ `\t\tname: ${quoteTsString(field.name)},`,
271
+ `\t\tpreviewValue: ${buildTsPostMetaPreviewValue(field)},`,
272
+ `\t\trequired: ${field.required ? "true" : "false"},`,
273
+ `\t\tschemaType: ${quoteTsString(field.schemaType)},`,
274
+ "\t},",
275
+ ].join("\n"))
276
+ .join("\n");
277
+ }
278
+ function buildBindingPostMetaEditorSource(options) {
279
+ const bindingSourceTitle = toTitleCase(options.bindingSourceSlug);
280
+ const bindingSourceName = `${options.namespace}/${options.bindingSourceSlug}`;
281
+ const targetSource = options.target
282
+ ? `
283
+ export const BINDING_SOURCE_TARGET = {
284
+ \tattribute: ${quoteTsString(options.target.attributeName)},
285
+ \tblock: ${quoteTsString(`${options.namespace}/${options.target.blockSlug}`)},
286
+ \tfield: ${quoteTsString(options.postMeta.metaPath)},
287
+ \tsource: ${quoteTsString(bindingSourceName)},
288
+ } as const;
289
+ `
290
+ : "";
291
+ return `import { registerBlockBindingsSource } from '@wordpress/blocks';
292
+ import { __ } from '@wordpress/i18n';
293
+
294
+ interface BindingSourceRegistration {
295
+ \targs?: {
296
+ \t\tfield?: string;
297
+ \t};
298
+ }
299
+
300
+ export const POST_META_BINDING_SOURCE = {
301
+ \tmetaKey: ${quoteTsString(options.postMeta.metaKey)},
302
+ \tpostMeta: ${quoteTsString(options.postMeta.postMetaSlug)},
303
+ \tpostType: ${quoteTsString(options.postMeta.postType)},
304
+ \tschemaFile: ${quoteTsString(options.postMeta.schemaFile)},
305
+ \tsourceTypeName: ${quoteTsString(options.postMeta.sourceTypeName)},
306
+ } as const;
307
+
308
+ const POST_META_BINDING_FIELDS = [
309
+ ${buildTsPostMetaFieldEntries(options.postMeta.fields, options.textDomain)}
310
+ ] as const;
311
+
312
+ const POST_META_PREVIEW_VALUES: Record<string, unknown> = Object.fromEntries(
313
+ \tPOST_META_BINDING_FIELDS.map( ( field ) => [
314
+ \t\tfield.name,
315
+ \t\tfield.previewValue,
316
+ \t] )
317
+ );
318
+ ${targetSource}
319
+
320
+ function resolveBindingFieldType( schemaType: string ): string {
321
+ \treturn schemaType === 'unknown' ? 'string' : schemaType;
322
+ }
323
+
324
+ function resolveBindingSourceValue( field: string ): unknown {
325
+ \treturn POST_META_PREVIEW_VALUES[ field ] ?? '';
326
+ }
327
+
328
+ registerBlockBindingsSource( {
329
+ \tname: ${quoteTsString(bindingSourceName)},
330
+ \tlabel: __( ${quoteTsString(bindingSourceTitle)}, ${quoteTsString(options.textDomain)} ),
331
+ \tgetFieldsList() {
332
+ \t\treturn POST_META_BINDING_FIELDS.map( ( field ) => ( {
333
+ \t\t\tlabel: field.label,
334
+ \t\t\ttype: resolveBindingFieldType( field.schemaType ),
335
+ \t\t\targs: {
336
+ \t\t\t\tfield: field.name,
337
+ \t\t\t},
338
+ \t\t} ) );
339
+ \t},
340
+ \tgetValues( { bindings } ) {
341
+ \t\tconst values: Record<string, unknown> = {};
342
+ \t\tfor ( const [ attributeName, binding ] of Object.entries(
343
+ \t\t\tbindings as Record<string, BindingSourceRegistration>
344
+ \t\t) ) {
345
+ \t\t\tconst field =
346
+ \t\t\t\ttypeof binding?.args?.field === 'string'
347
+ \t\t\t\t\t? binding.args.field
348
+ \t\t\t\t\t: ${quoteTsString(options.postMeta.metaPath)};
349
+ \t\t\tvalues[ attributeName ] = resolveBindingSourceValue( field );
350
+ \t\t}
351
+ \t\treturn values;
352
+ \t},
353
+ } );
354
+ `;
355
+ }
356
+ /**
357
+ * Render the editor registration module for a generated binding source.
358
+ *
359
+ * @param bindingSourceSlug Normalized binding-source slug.
360
+ * @param namespace Workspace block namespace.
361
+ * @param textDomain Workspace text domain used for labels.
362
+ * @param target Optional block attribute target wired to the binding source.
363
+ * @param postMeta Optional post-meta contract backing this binding source.
364
+ * @returns TypeScript source for `src/bindings/<slug>/editor.ts`.
365
+ */
366
+ export function buildBindingSourceEditorSource(bindingSourceSlug, namespace, textDomain, target, postMeta) {
367
+ if (postMeta) {
368
+ return buildBindingPostMetaEditorSource({
369
+ bindingSourceSlug,
370
+ namespace,
371
+ postMeta,
372
+ target,
373
+ textDomain,
374
+ });
375
+ }
376
+ const bindingSourceTitle = toTitleCase(bindingSourceSlug);
377
+ const starterValue = `${bindingSourceTitle} starter value`;
378
+ const bindingSourceName = `${namespace}/${bindingSourceSlug}`;
379
+ const targetSource = target
380
+ ? `
381
+ export const BINDING_SOURCE_TARGET = {
382
+ \tattribute: ${quoteTsString(target.attributeName)},
383
+ \tblock: ${quoteTsString(`${namespace}/${target.blockSlug}`)},
384
+ \tfield: ${quoteTsString(bindingSourceSlug)},
385
+ \tsource: ${quoteTsString(bindingSourceName)},
386
+ } as const;
387
+ `
388
+ : "";
389
+ return `import { registerBlockBindingsSource } from '@wordpress/blocks';
390
+ import { __ } from '@wordpress/i18n';
391
+
392
+ interface BindingSourceRegistration {
393
+ \targs?: {
394
+ \t\tfield?: string;
395
+ \t};
396
+ }
397
+
398
+ const BINDING_SOURCE_VALUES: Record<string, string> = {
399
+ \t${quoteTsString(bindingSourceSlug)}: ${quoteTsString(starterValue)},
400
+ };
401
+ ${targetSource}
402
+
403
+ function resolveBindingSourceValue( field: string ): string {
404
+ \treturn BINDING_SOURCE_VALUES[ field ] ?? '';
405
+ }
406
+
407
+ registerBlockBindingsSource( {
408
+ \tname: ${quoteTsString(bindingSourceName)},
409
+ \tlabel: __( ${quoteTsString(bindingSourceTitle)}, ${quoteTsString(textDomain)} ),
410
+ \tgetFieldsList() {
411
+ \t\treturn [
412
+ \t\t\t{
413
+ \t\t\t\tlabel: __( ${quoteTsString(bindingSourceTitle)}, ${quoteTsString(textDomain)} ),
414
+ \t\t\t\ttype: 'string',
415
+ \t\t\t\targs: {
416
+ \t\t\t\t\tfield: ${quoteTsString(bindingSourceSlug)},
417
+ \t\t\t\t},
418
+ \t\t\t},
419
+ \t\t];
420
+ \t},
421
+ \tgetValues( { bindings } ) {
422
+ \t\tconst values: Record<string, string> = {};
423
+ \t\tfor ( const [ attributeName, binding ] of Object.entries(
424
+ \t\t\tbindings as Record<string, BindingSourceRegistration>
425
+ \t\t) ) {
426
+ \t\t\tconst field =
427
+ \t\t\t\ttypeof binding?.args?.field === 'string'
428
+ \t\t\t\t\t? binding.args.field
429
+ \t\t\t\t\t: ${quoteTsString(bindingSourceSlug)};
430
+ \t\t\tvalues[ attributeName ] = resolveBindingSourceValue( field );
431
+ \t\t}
432
+ \t\treturn values;
433
+ \t},
434
+ } );
435
+ `;
436
+ }
@@ -0,0 +1,20 @@
1
+ import type { PostMetaBindingField } from "./post-meta-binding-fields.js";
2
+ /**
3
+ * Target block attribute that should receive generated binding-source wiring.
4
+ */
5
+ export type BindingTarget = {
6
+ attributeName: string;
7
+ blockSlug: string;
8
+ };
9
+ /**
10
+ * Resolved post-meta contract data used to generate a binding source.
11
+ */
12
+ export type BindingPostMetaSource = {
13
+ fields: PostMetaBindingField[];
14
+ metaKey: string;
15
+ metaPath: string;
16
+ postMetaSlug: string;
17
+ postType: string;
18
+ schemaFile: string;
19
+ sourceTypeName: string;
20
+ };
@@ -0,0 +1,40 @@
1
+ import { type RunAddBindingSourceCommandOptions } from "./cli-add-shared.js";
2
+ /**
3
+ * Add one block binding source scaffold to an official workspace project.
4
+ *
5
+ * @param options Command options for the binding-source scaffold workflow.
6
+ * @param options.attributeName Optional generated block attribute to declare as
7
+ * bindable. Must be provided together with `blockName`.
8
+ * @param options.blockName Optional generated block slug or full block name to
9
+ * receive the bindable attribute wiring. Must be provided together with
10
+ * `attributeName`.
11
+ * @param options.bindingSourceName Human-entered binding source name that will
12
+ * be normalized and validated before files are written.
13
+ * @param options.cwd Working directory used to resolve the nearest official
14
+ * workspace. Defaults to `process.cwd()`.
15
+ * @param options.metaPath Optional top-level post-meta field used as the
16
+ * binding source's default `field` arg. Requires `postMetaName`.
17
+ * @param options.postMetaName Optional generated post-meta contract slug used
18
+ * to back the binding source with `get_post_meta()`.
19
+ * @returns A promise that resolves with the normalized `bindingSourceSlug` and
20
+ * owning `projectDir` after the server/editor files, optional target block
21
+ * metadata, and inventory entry have been written successfully. Post-meta
22
+ * backed results additionally include `metaKey`, `metaPath`, `postMetaSlug`,
23
+ * `postType`, and `schemaFile`.
24
+ * @throws {Error} When the command is run outside an official workspace, when
25
+ * the slug is invalid, when a binding target is incomplete or unknown, or when
26
+ * a conflicting file or inventory entry exists. Post-meta backed runs also
27
+ * throw when the referenced contract or requested top-level field cannot be
28
+ * resolved.
29
+ */
30
+ export declare function runAddBindingSourceCommand({ attributeName, bindingSourceName, blockName, cwd, metaPath, postMetaName, }: RunAddBindingSourceCommandOptions): Promise<{
31
+ attributeName?: string;
32
+ bindingSourceSlug: string;
33
+ blockSlug?: string;
34
+ metaKey?: string;
35
+ metaPath?: string;
36
+ postMetaSlug?: string;
37
+ postType?: string;
38
+ projectDir: string;
39
+ schemaFile?: string;
40
+ }>;