@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.
- package/dist/runtime/ai-feature-artifacts.js +4 -1
- package/dist/runtime/block-generator-service-spec.js +2 -1
- package/dist/runtime/built-in-block-non-ts-basic-artifacts.d.ts +9 -0
- package/dist/runtime/built-in-block-non-ts-basic-artifacts.js +84 -0
- package/dist/runtime/built-in-block-non-ts-compound-artifacts.d.ts +9 -0
- package/dist/runtime/built-in-block-non-ts-compound-artifacts.js +36 -0
- package/dist/runtime/built-in-block-non-ts-compound-templates.d.ts +23 -0
- package/dist/runtime/built-in-block-non-ts-compound-templates.js +453 -0
- package/dist/runtime/built-in-block-non-ts-family-artifacts.d.ts +8 -26
- package/dist/runtime/built-in-block-non-ts-family-artifacts.js +8 -1034
- package/dist/runtime/built-in-block-non-ts-interactivity-artifacts.d.ts +9 -0
- package/dist/runtime/built-in-block-non-ts-interactivity-artifacts.js +83 -0
- package/dist/runtime/built-in-block-non-ts-persistence-artifacts.d.ts +9 -0
- package/dist/runtime/built-in-block-non-ts-persistence-artifacts.js +33 -0
- package/dist/runtime/built-in-block-non-ts-persistence-templates.d.ts +23 -0
- package/dist/runtime/built-in-block-non-ts-persistence-templates.js +395 -0
- package/dist/runtime/cli-add-block-json.js +5 -1
- package/dist/runtime/cli-add-collision.js +8 -0
- package/dist/runtime/cli-add-help.js +14 -10
- package/dist/runtime/cli-add-kind-ids.d.ts +1 -1
- package/dist/runtime/cli-add-kind-ids.js +1 -0
- package/dist/runtime/cli-add-types.d.ts +45 -6
- package/dist/runtime/cli-add-types.js +2 -0
- package/dist/runtime/cli-add-validation.d.ts +7 -0
- package/dist/runtime/cli-add-validation.js +9 -0
- package/dist/runtime/cli-add-workspace-ability-anchors.d.ts +24 -0
- package/dist/runtime/cli-add-workspace-ability-anchors.js +294 -0
- package/dist/runtime/cli-add-workspace-ability-registry.d.ts +10 -0
- package/dist/runtime/cli-add-workspace-ability-registry.js +51 -0
- package/dist/runtime/cli-add-workspace-ability-scaffold.d.ts +1 -1
- package/dist/runtime/cli-add-workspace-ability-scaffold.js +5 -308
- package/dist/runtime/cli-add-workspace-admin-view-scaffold.js +6 -2
- package/dist/runtime/cli-add-workspace-admin-view-templates-core-data.d.ts +34 -0
- package/dist/runtime/cli-add-workspace-admin-view-templates-core-data.js +483 -0
- package/dist/runtime/cli-add-workspace-admin-view-templates-default.d.ts +30 -0
- package/dist/runtime/cli-add-workspace-admin-view-templates-default.js +310 -0
- package/dist/runtime/cli-add-workspace-admin-view-templates-rest.d.ts +25 -0
- package/dist/runtime/cli-add-workspace-admin-view-templates-rest.js +124 -0
- package/dist/runtime/cli-add-workspace-admin-view-templates-settings.d.ts +34 -0
- package/dist/runtime/cli-add-workspace-admin-view-templates-settings.js +370 -0
- package/dist/runtime/cli-add-workspace-admin-view-templates-shared.d.ts +49 -0
- package/dist/runtime/cli-add-workspace-admin-view-templates-shared.js +259 -0
- package/dist/runtime/cli-add-workspace-admin-view-templates.d.ts +18 -27
- package/dist/runtime/cli-add-workspace-admin-view-templates.js +30 -1326
- package/dist/runtime/cli-add-workspace-ai-anchors.d.ts +4 -4
- package/dist/runtime/cli-add-workspace-ai-anchors.js +8 -233
- package/dist/runtime/cli-add-workspace-ai-scaffold.js +4 -2
- package/dist/runtime/cli-add-workspace-ai-source-emitters.d.ts +1 -4
- package/dist/runtime/cli-add-workspace-ai-source-emitters.js +1 -129
- package/dist/runtime/cli-add-workspace-ai-sync-rest-anchors.d.ts +5 -0
- package/dist/runtime/cli-add-workspace-ai-sync-rest-anchors.js +236 -0
- package/dist/runtime/cli-add-workspace-ai-sync-script-source.d.ts +4 -0
- package/dist/runtime/cli-add-workspace-ai-sync-script-source.js +145 -0
- package/dist/runtime/cli-add-workspace-assets.d.ts +6 -63
- package/dist/runtime/cli-add-workspace-assets.js +6 -950
- package/dist/runtime/cli-add-workspace-binding-source-anchors.d.ts +23 -0
- package/dist/runtime/cli-add-workspace-binding-source-anchors.js +112 -0
- package/dist/runtime/cli-add-workspace-binding-source-source-emitters.d.ts +33 -0
- package/dist/runtime/cli-add-workspace-binding-source-source-emitters.js +436 -0
- package/dist/runtime/cli-add-workspace-binding-source-types.d.ts +20 -0
- package/dist/runtime/cli-add-workspace-binding-source-types.js +1 -0
- package/dist/runtime/cli-add-workspace-binding-source.d.ts +40 -0
- package/dist/runtime/cli-add-workspace-binding-source.js +275 -0
- package/dist/runtime/cli-add-workspace-block-style.d.ts +22 -0
- package/dist/runtime/cli-add-workspace-block-style.js +148 -0
- package/dist/runtime/cli-add-workspace-block-transform.d.ts +32 -0
- package/dist/runtime/cli-add-workspace-block-transform.js +197 -0
- package/dist/runtime/cli-add-workspace-contract.js +1 -1
- package/dist/runtime/cli-add-workspace-core-variation.d.ts +20 -0
- package/dist/runtime/cli-add-workspace-core-variation.js +322 -0
- package/dist/runtime/cli-add-workspace-editor-plugin-anchors.d.ts +37 -0
- package/dist/runtime/cli-add-workspace-editor-plugin-anchors.js +206 -0
- package/dist/runtime/cli-add-workspace-editor-plugin-source-emitters.d.ts +47 -0
- package/dist/runtime/cli-add-workspace-editor-plugin-source-emitters.js +219 -0
- package/dist/runtime/cli-add-workspace-editor-plugin.d.ts +22 -0
- package/dist/runtime/cli-add-workspace-editor-plugin.js +78 -0
- package/dist/runtime/cli-add-workspace-hooked-block.d.ts +23 -0
- package/dist/runtime/cli-add-workspace-hooked-block.js +57 -0
- package/dist/runtime/cli-add-workspace-integration-env-files.d.ts +33 -0
- package/dist/runtime/cli-add-workspace-integration-env-files.js +65 -0
- package/dist/runtime/cli-add-workspace-integration-env-package-json.d.ts +38 -0
- package/dist/runtime/cli-add-workspace-integration-env-package-json.js +122 -0
- package/dist/runtime/cli-add-workspace-integration-env-source-emitters.d.ts +44 -0
- package/dist/runtime/cli-add-workspace-integration-env-source-emitters.js +262 -0
- package/dist/runtime/cli-add-workspace-integration-env.d.ts +3 -1
- package/dist/runtime/cli-add-workspace-integration-env.js +10 -313
- package/dist/runtime/cli-add-workspace-pattern-anchors.d.ts +10 -0
- package/dist/runtime/cli-add-workspace-pattern-anchors.js +95 -0
- package/dist/runtime/cli-add-workspace-pattern-options.d.ts +20 -0
- package/dist/runtime/cli-add-workspace-pattern-options.js +113 -0
- package/dist/runtime/cli-add-workspace-pattern-source-emitters.d.ts +20 -0
- package/dist/runtime/cli-add-workspace-pattern-source-emitters.js +57 -0
- package/dist/runtime/cli-add-workspace-pattern.d.ts +42 -0
- package/dist/runtime/cli-add-workspace-pattern.js +99 -0
- package/dist/runtime/cli-add-workspace-post-meta.js +1 -1
- package/dist/runtime/cli-add-workspace-registration-hooks.d.ts +50 -0
- package/dist/runtime/cli-add-workspace-registration-hooks.js +162 -0
- package/dist/runtime/cli-add-workspace-rest-anchors.d.ts +9 -4
- package/dist/runtime/cli-add-workspace-rest-anchors.js +9 -428
- package/dist/runtime/cli-add-workspace-rest-bootstrap-anchors.d.ts +17 -0
- package/dist/runtime/cli-add-workspace-rest-bootstrap-anchors.js +108 -0
- package/dist/runtime/cli-add-workspace-rest-contract-sync-anchors.d.ts +9 -0
- package/dist/runtime/cli-add-workspace-rest-contract-sync-anchors.js +142 -0
- package/dist/runtime/cli-add-workspace-rest-generated-source-emitters.d.ts +51 -0
- package/dist/runtime/cli-add-workspace-rest-generated-source-emitters.js +415 -0
- package/dist/runtime/cli-add-workspace-rest-generated.d.ts +9 -0
- package/dist/runtime/cli-add-workspace-rest-generated.js +160 -0
- package/dist/runtime/cli-add-workspace-rest-manual-source-emitters.d.ts +80 -0
- package/dist/runtime/cli-add-workspace-rest-manual-source-emitters.js +238 -0
- package/dist/runtime/cli-add-workspace-rest-manual.d.ts +8 -0
- package/dist/runtime/cli-add-workspace-rest-manual.js +266 -0
- package/dist/runtime/cli-add-workspace-rest-php-templates.d.ts +18 -0
- package/dist/runtime/cli-add-workspace-rest-php-templates.js +359 -0
- package/dist/runtime/cli-add-workspace-rest-resource-php-routing-template.d.ts +33 -0
- package/dist/runtime/cli-add-workspace-rest-resource-php-routing-template.js +145 -0
- package/dist/runtime/cli-add-workspace-rest-resource-sync-anchors.d.ts +9 -0
- package/dist/runtime/cli-add-workspace-rest-resource-sync-anchors.js +162 -0
- package/dist/runtime/cli-add-workspace-rest-schema-helper-php-template.d.ts +7 -0
- package/dist/runtime/cli-add-workspace-rest-schema-helper-php-template.js +193 -0
- package/dist/runtime/cli-add-workspace-rest-source-emitters.d.ts +5 -91
- package/dist/runtime/cli-add-workspace-rest-source-emitters.js +5 -642
- package/dist/runtime/cli-add-workspace-rest-source-utils.d.ts +17 -0
- package/dist/runtime/cli-add-workspace-rest-source-utils.js +50 -0
- package/dist/runtime/cli-add-workspace-rest-sync-script-shared.d.ts +56 -0
- package/dist/runtime/cli-add-workspace-rest-sync-script-shared.js +122 -0
- package/dist/runtime/cli-add-workspace-rest-types.d.ts +108 -0
- package/dist/runtime/cli-add-workspace-rest-types.js +1 -0
- package/dist/runtime/cli-add-workspace-rest.d.ts +3 -20
- package/dist/runtime/cli-add-workspace-rest.js +33 -788
- package/dist/runtime/cli-add-workspace-variation.d.ts +22 -0
- package/dist/runtime/cli-add-workspace-variation.js +162 -0
- package/dist/runtime/cli-add-workspace.d.ts +42 -107
- package/dist/runtime/cli-add-workspace.js +42 -674
- package/dist/runtime/cli-add.d.ts +3 -3
- package/dist/runtime/cli-add.js +2 -2
- package/dist/runtime/cli-core.d.ts +3 -2
- package/dist/runtime/cli-core.js +2 -2
- package/dist/runtime/cli-diagnostics.d.ts +3 -1
- package/dist/runtime/cli-diagnostics.js +17 -5
- package/dist/runtime/cli-doctor-workspace-bindings.js +63 -1
- package/dist/runtime/cli-doctor-workspace-block-addons.d.ts +12 -0
- package/dist/runtime/cli-doctor-workspace-block-addons.js +162 -0
- package/dist/runtime/cli-doctor-workspace-block-iframe.d.ts +9 -0
- package/dist/runtime/cli-doctor-workspace-block-iframe.js +228 -0
- package/dist/runtime/cli-doctor-workspace-block-metadata.d.ts +11 -0
- package/dist/runtime/cli-doctor-workspace-block-metadata.js +111 -0
- package/dist/runtime/cli-doctor-workspace-blocks.js +6 -424
- package/dist/runtime/cli-doctor-workspace-features-abilities.d.ts +11 -0
- package/dist/runtime/cli-doctor-workspace-features-abilities.js +112 -0
- package/dist/runtime/cli-doctor-workspace-features-admin-views.d.ts +11 -0
- package/dist/runtime/cli-doctor-workspace-features-admin-views.js +128 -0
- package/dist/runtime/cli-doctor-workspace-features-ai.d.ts +11 -0
- package/dist/runtime/cli-doctor-workspace-features-ai.js +57 -0
- package/dist/runtime/cli-doctor-workspace-features-editor-plugins.d.ts +11 -0
- package/dist/runtime/cli-doctor-workspace-features-editor-plugins.js +80 -0
- package/dist/runtime/cli-doctor-workspace-features-post-meta.d.ts +11 -0
- package/dist/runtime/cli-doctor-workspace-features-post-meta.js +77 -0
- package/dist/runtime/cli-doctor-workspace-features-rest.d.ts +11 -0
- package/dist/runtime/cli-doctor-workspace-features-rest.js +120 -0
- package/dist/runtime/cli-doctor-workspace-features.js +14 -487
- package/dist/runtime/cli-doctor.d.ts +54 -3
- package/dist/runtime/cli-doctor.js +92 -10
- package/dist/runtime/cli-help.js +12 -7
- package/dist/runtime/cli-init-package-json.js +4 -2
- package/dist/runtime/cli-prompt.d.ts +16 -2
- package/dist/runtime/cli-prompt.js +29 -12
- package/dist/runtime/cli-scaffold.d.ts +2 -1
- package/dist/runtime/cli-scaffold.js +19 -10
- package/dist/runtime/external-template-guards.js +4 -6
- package/dist/runtime/index.d.ts +6 -3
- package/dist/runtime/index.js +4 -2
- package/dist/runtime/json-utils.d.ts +62 -4
- package/dist/runtime/json-utils.js +78 -4
- package/dist/runtime/local-dev-presets.js +6 -2
- package/dist/runtime/migration-ui-capability.js +4 -1
- package/dist/runtime/migration-utils.js +4 -1
- package/dist/runtime/package-managers.js +6 -1
- package/dist/runtime/package-versions.d.ts +1 -0
- package/dist/runtime/package-versions.js +16 -3
- package/dist/runtime/pattern-catalog.d.ts +122 -0
- package/dist/runtime/pattern-catalog.js +471 -0
- package/dist/runtime/post-meta-binding-fields.d.ts +46 -0
- package/dist/runtime/post-meta-binding-fields.js +135 -0
- package/dist/runtime/scaffold-bootstrap.js +7 -2
- package/dist/runtime/scaffold-package-manager-files.js +5 -1
- package/dist/runtime/scaffold-repository-reference.js +4 -2
- package/dist/runtime/scaffold-template-variables.js +2 -1
- package/dist/runtime/scaffold.d.ts +18 -1
- package/dist/runtime/scaffold.js +55 -2
- package/dist/runtime/temp-roots.js +4 -1
- package/dist/runtime/template-layers.js +4 -1
- package/dist/runtime/template-registry.js +9 -3
- package/dist/runtime/template-source-contracts.d.ts +2 -0
- package/dist/runtime/template-source-normalization.js +2 -1
- package/dist/runtime/template-source-remote.js +18 -5
- package/dist/runtime/template-source-seeds.js +10 -3
- package/dist/runtime/typia-llm-json-schema.d.ts +24 -0
- package/dist/runtime/typia-llm-json-schema.js +33 -0
- package/dist/runtime/typia-llm-openapi-constraints.d.ts +20 -0
- package/dist/runtime/typia-llm-openapi-constraints.js +254 -0
- package/dist/runtime/typia-llm-projection.d.ts +25 -0
- package/dist/runtime/typia-llm-projection.js +58 -0
- package/dist/runtime/typia-llm-render.d.ts +21 -0
- package/dist/runtime/typia-llm-render.js +252 -0
- package/dist/runtime/typia-llm-sync.d.ts +10 -0
- package/dist/runtime/typia-llm-sync.js +63 -0
- package/dist/runtime/typia-llm-types.d.ts +197 -0
- package/dist/runtime/typia-llm-types.js +1 -0
- package/dist/runtime/typia-llm.d.ts +9 -255
- package/dist/runtime/typia-llm.js +5 -634
- package/dist/runtime/workspace-inventory-mutations.js +15 -1
- package/dist/runtime/workspace-inventory-parser-entries.d.ts +17 -0
- package/dist/runtime/workspace-inventory-parser-entries.js +157 -0
- package/dist/runtime/workspace-inventory-parser-validation.d.ts +104 -0
- package/dist/runtime/workspace-inventory-parser-validation.js +34 -0
- package/dist/runtime/workspace-inventory-parser.d.ts +3 -45
- package/dist/runtime/workspace-inventory-parser.js +3 -581
- package/dist/runtime/workspace-inventory-section-descriptors.d.ts +19 -0
- package/dist/runtime/workspace-inventory-section-descriptors.js +443 -0
- package/dist/runtime/workspace-inventory-templates.d.ts +3 -3
- package/dist/runtime/workspace-inventory-templates.js +10 -1
- package/dist/runtime/workspace-inventory-types.d.ts +10 -1
- package/dist/runtime/workspace-project.js +4 -6
- package/package.json +8 -3
- package/templates/_shared/compound/core/scripts/block-config.ts.mustache +22 -0
- package/templates/_shared/compound/core/scripts/sync-types-to-block-json.ts.mustache +103 -2
- package/templates/_shared/compound/core/src/inner-blocks-templates.ts.mustache +13 -0
- package/templates/_shared/compound/persistence/scripts/block-config.ts.mustache +22 -1
|
@@ -8,15 +8,17 @@ export function formatAddHelpText() {
|
|
|
8
8
|
return `Usage:
|
|
9
9
|
wp-typia add admin-view <name> [--source <rest-resource:slug|core-data:kind/name>] [--dry-run]
|
|
10
10
|
wp-typia add block <name> [--template <${ADD_BLOCK_TEMPLATE_IDS.join("|")}>] [--external-layer-source <./path|github:owner/repo/path[#ref]|npm-package>] [--external-layer-id <layer-id>] [--inner-blocks-preset <freeform|ordered|horizontal|locked-structure>] [--alternate-render-targets <email,mjml,plain-text>] [--data-storage <post-meta|custom-table>] [--persistence-policy <authenticated|public>] [--dry-run]
|
|
11
|
-
wp-typia add integration-env <name> [--wp-env] [--service <none|docker-compose>] [--dry-run]
|
|
12
|
-
wp-typia add variation <name>
|
|
13
|
-
wp-typia add
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
wp-typia add integration-env <name> [--wp-env] [--release-zip] [--service <none|docker-compose>] [--dry-run]
|
|
12
|
+
wp-typia add core-variation <block-name> <name> [--dry-run]
|
|
13
|
+
wp-typia add core-variation <name> --block <namespace/block> [--dry-run]
|
|
14
|
+
wp-typia add variation <name> --block <block-slug> [--dry-run]
|
|
15
|
+
wp-typia add style <name> --block <block-slug> [--dry-run]
|
|
16
|
+
wp-typia add transform <name> --from <namespace/block> --to <block-slug|namespace/block-slug> [--dry-run]
|
|
17
|
+
wp-typia add pattern <name> [--scope <full|section>] [--section-role <role>] [--tags <tag,...>] [--thumbnail-url <url>] [--dry-run]
|
|
18
|
+
wp-typia add binding-source <name> [--block <block-slug|namespace/block-slug> --attribute <attribute>] [--from-post-meta|--post-meta <post-meta> [--meta-path <field>]] [--dry-run]
|
|
17
19
|
wp-typia add contract <name> [--type <ExportedTypeName>] [--dry-run]
|
|
18
20
|
wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <${REST_RESOURCE_METHOD_IDS.join(",")}>] [--route-pattern <route-pattern>] [--permission-callback <callback>] [--controller-class <ClassName>] [--controller-extends <BaseClass>] [--dry-run]
|
|
19
|
-
wp-typia add rest-resource <name> --manual [--namespace <vendor/v1>] [--method <GET|POST|PUT|PATCH|DELETE>] [--auth <public|authenticated|public-write-protected>] [--path <route-pattern>] [--query-type <Type>] [--body-type <Type>] [--response-type <Type>] [--dry-run]
|
|
21
|
+
wp-typia add rest-resource <name> --manual [--namespace <vendor/v1>] [--method <GET|POST|PUT|PATCH|DELETE>] [--auth <public|authenticated|public-write-protected>] [--path <route-pattern>|--route-pattern <route-pattern>] [--permission-callback <callback>] [--controller-class <ClassName>] [--controller-extends <BaseClass>] [--query-type <Type>] [--body-type <Type>] [--response-type <Type>] [--secret-field <field>] [--secret-state-field|--secret-has-value-field <field>] [--secret-preserve-on-empty <true|false>] [--dry-run]
|
|
20
22
|
wp-typia add post-meta <name> --post-type <post-type> [--type <ExportedTypeName>] [--meta-key <meta-key>] [--hide-from-rest] [--dry-run]
|
|
21
23
|
wp-typia add ability <name> [--dry-run]
|
|
22
24
|
wp-typia add ai-feature <name> [--namespace <vendor/v1>] [--dry-run]
|
|
@@ -27,21 +29,23 @@ Notes:
|
|
|
27
29
|
\`wp-typia add\` runs only inside official ${WORKSPACE_TEMPLATE_PACKAGE} workspaces scaffolded via \`wp-typia create <project-dir> --template workspace\`.
|
|
28
30
|
Pass \`--dry-run\` to preview the workspace files that would change without writing them.
|
|
29
31
|
Interactive add flows let you choose a template when \`--template\` is omitted; non-interactive runs default to \`basic\`.
|
|
32
|
+
\`add core-variation\` registers editor-side variations for existing core or external blocks without generating block.json or Typia manifests.
|
|
30
33
|
\`add admin-view\` scaffolds an opt-in DataViews-powered WordPress admin screen under \`src/admin-views/\`.
|
|
31
34
|
Pass \`--source rest-resource:<slug>\` to reuse a list-capable REST resource.
|
|
32
35
|
Pass \`--source core-data:postType/post\` or \`--source core-data:taxonomy/category\` to bind a WordPress-owned entity collection.
|
|
33
36
|
Generated admin-view workspaces add \`@wp-typia/dataviews\` and the needed WordPress DataViews packages as opt-in dependencies.
|
|
34
37
|
\`add integration-env\` generates an opt-in local smoke starter under \`scripts/integration-smoke/\`, updates \`.env.example\`, and can add \`@wordpress/env\` plus \`.wp-env.json\` when \`--wp-env\` is passed.
|
|
38
|
+
Pass \`--release-zip\` to add \`release:zip\`, \`release:zip:check\`, and \`qa:check\` scripts for plugin QA packaging.
|
|
35
39
|
Pass \`--service docker-compose\` to include a placeholder local service stack that can be adapted to project-specific dependencies.
|
|
36
40
|
\`query-loop\` is a create-time scaffold family. Use \`wp-typia create <project-dir> --template query-loop\` instead of \`wp-typia add block\`.
|
|
37
41
|
\`add variation\` targets an existing block slug from \`scripts/block-config.ts\`.
|
|
38
42
|
\`add style\` registers a Block Styles option for an existing generated block.
|
|
39
43
|
\`add transform\` adds a block-to-block transform into an existing generated block.
|
|
40
|
-
\`add pattern\` scaffolds a namespaced PHP pattern shell under \`src/patterns
|
|
41
|
-
\`add binding-source\` scaffolds shared PHP and editor registration under \`src/bindings/\`; pass \`--block\` and \`--attribute\` together to declare an end-to-end bindable attribute on an existing generated block.
|
|
44
|
+
\`add pattern\` scaffolds a namespaced PHP pattern shell under \`src/patterns/full/\` or \`src/patterns/sections/\` and records typed catalog metadata in \`PATTERNS\`.
|
|
45
|
+
\`add binding-source\` scaffolds shared PHP and editor registration under \`src/bindings/\`; pass \`--block\` and \`--attribute\` together to declare an end-to-end bindable attribute on an existing generated block. Pass \`--from-post-meta\` or \`--post-meta\` to generate a source backed by a typed post-meta contract; \`--meta-path\` selects one top-level field as the default binding arg.
|
|
42
46
|
\`add contract\` registers a standalone TypeScript wire contract under \`src/contracts/\` and generates a stable JSON Schema artifact without creating PHP route glue.
|
|
43
47
|
\`add rest-resource\` scaffolds plugin-level TypeScript REST contracts under \`src/rest/\` and PHP route glue under \`inc/rest/\`. Use \`--route-pattern\`, \`--permission-callback\`, \`--controller-class\`, and \`--controller-extends\` when an existing WordPress controller or permission model needs to own part of the generated route surface.
|
|
44
|
-
Pass \`--manual\` with \`add rest-resource\` to track an external REST route with typed schemas, OpenAPI, clients, and drift checks without generating PHP route/controller files.
|
|
48
|
+
Pass \`--manual\` with \`add rest-resource\` to track an external/provider REST route with typed schemas, OpenAPI, clients, and drift checks without generating PHP route/controller files. Manual routes may still declare \`--permission-callback\`, \`--controller-class\`, and \`--controller-extends\` as metadata for the route owner. Settings contracts can add \`--secret-field\` with \`--secret-preserve-on-empty\` metadata so generated schemas, clients, and admin forms treat blank secret submissions as preserve-by-default.
|
|
45
49
|
\`add post-meta\` scaffolds a typed post meta contract under \`src/post-meta/\`, generates a schema artifact, and wires \`register_post_meta()\` helpers under \`inc/post-meta/\`.
|
|
46
50
|
\`add ability\` scaffolds typed workflow abilities under \`src/abilities/\` and server registration under \`inc/abilities/\`.
|
|
47
51
|
\`add ai-feature\` scaffolds server-owned AI feature endpoints under \`src/ai-features/\` and PHP route glue under \`inc/ai-features/\`.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Keep this order stable because it drives help output and command metadata.
|
|
6
6
|
*/
|
|
7
|
-
export declare const ADD_KIND_IDS: readonly ["admin-view", "block", "integration-env", "variation", "style", "transform", "pattern", "binding-source", "contract", "rest-resource", "post-meta", "ability", "ai-feature", "hooked-block", "editor-plugin"];
|
|
7
|
+
export declare const ADD_KIND_IDS: readonly ["admin-view", "block", "integration-env", "core-variation", "variation", "style", "transform", "pattern", "binding-source", "contract", "rest-resource", "post-meta", "ability", "ai-feature", "hooked-block", "editor-plugin"];
|
|
8
8
|
/**
|
|
9
9
|
* Union of supported top-level `wp-typia add` kind ids.
|
|
10
10
|
*/
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { PATTERN_CATALOG_SCOPE_IDS, type PatternCatalogScope } from "./pattern-catalog.js";
|
|
1
2
|
export { ADD_KIND_IDS } from "./cli-add-kind-ids.js";
|
|
2
3
|
export type { AddKindId } from "./cli-add-kind-ids.js";
|
|
4
|
+
export { PATTERN_CATALOG_SCOPE_IDS };
|
|
5
|
+
export type { PatternCatalogScope };
|
|
3
6
|
/**
|
|
4
7
|
* Supported plugin-level REST resource methods accepted by
|
|
5
8
|
* `wp-typia add rest-resource --methods`.
|
|
@@ -87,6 +90,18 @@ export interface RunAddVariationCommandOptions {
|
|
|
87
90
|
cwd?: string;
|
|
88
91
|
variationName: string;
|
|
89
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Options for `wp-typia add core-variation`.
|
|
95
|
+
*
|
|
96
|
+
* @property cwd Working directory used to resolve the nearest official workspace.
|
|
97
|
+
* @property targetBlockName Full `namespace/block` name that receives the variation.
|
|
98
|
+
* @property variationName Human-entered variation name normalized into a slug.
|
|
99
|
+
*/
|
|
100
|
+
export interface RunAddCoreVariationCommandOptions {
|
|
101
|
+
cwd?: string;
|
|
102
|
+
targetBlockName: string;
|
|
103
|
+
variationName: string;
|
|
104
|
+
}
|
|
90
105
|
/**
|
|
91
106
|
* Options for `wp-typia add style`.
|
|
92
107
|
*
|
|
@@ -126,8 +141,14 @@ export interface RunAddBlockTransformCommandOptions {
|
|
|
126
141
|
* @property patternName Human-entered pattern name normalized into a slug.
|
|
127
142
|
*/
|
|
128
143
|
export interface RunAddPatternCommandOptions {
|
|
144
|
+
catalogTitle?: string;
|
|
145
|
+
contentFile?: string;
|
|
129
146
|
cwd?: string;
|
|
130
147
|
patternName: string;
|
|
148
|
+
patternScope?: PatternCatalogScope | string;
|
|
149
|
+
sectionRole?: string;
|
|
150
|
+
tags?: readonly string[] | string;
|
|
151
|
+
thumbnailUrl?: string;
|
|
131
152
|
}
|
|
132
153
|
/**
|
|
133
154
|
* Options for `wp-typia add binding-source`.
|
|
@@ -136,12 +157,18 @@ export interface RunAddPatternCommandOptions {
|
|
|
136
157
|
* @property blockName Optional existing workspace block slug or full block name.
|
|
137
158
|
* @property bindingSourceName Human-entered binding source name normalized into a slug.
|
|
138
159
|
* @property cwd Working directory used to resolve the nearest official workspace.
|
|
160
|
+
* @property metaPath Optional top-level post-meta field used as the default
|
|
161
|
+
* source argument when `postMetaName` is provided.
|
|
162
|
+
* @property postMetaName Optional generated post-meta contract slug used to
|
|
163
|
+
* back the binding source with `get_post_meta()`.
|
|
139
164
|
*/
|
|
140
165
|
export interface RunAddBindingSourceCommandOptions {
|
|
141
166
|
attributeName?: string;
|
|
142
167
|
blockName?: string;
|
|
143
168
|
bindingSourceName: string;
|
|
144
169
|
cwd?: string;
|
|
170
|
+
metaPath?: string;
|
|
171
|
+
postMetaName?: string;
|
|
145
172
|
}
|
|
146
173
|
/**
|
|
147
174
|
* Options for `wp-typia add contract`.
|
|
@@ -189,17 +216,17 @@ export interface RunAddPostMetaCommandOptions {
|
|
|
189
216
|
* @property auth Optional auth intent for manual mode. Defaults to public.
|
|
190
217
|
* @property bodyTypeName Optional exported TypeScript body type for manual
|
|
191
218
|
* mode. Defaults to `<PascalName>Request` for write methods.
|
|
192
|
-
* @property controllerClass Optional
|
|
193
|
-
*
|
|
219
|
+
* @property controllerClass Optional REST controller class reference. Generated
|
|
220
|
+
* routes delegate through it; manual/provider routes record it as owner metadata.
|
|
194
221
|
* @property controllerExtends Optional base class for the generated controller
|
|
195
|
-
* wrapper
|
|
222
|
+
* wrapper or declared manual/provider controller owner.
|
|
196
223
|
* @property cwd Working directory used to resolve the nearest official workspace.
|
|
197
224
|
* @property manual Whether to scaffold a type-only external REST contract.
|
|
198
225
|
* @property method HTTP method for manual REST contract mode. Defaults to GET.
|
|
199
226
|
* @property methods Optional comma-separated REST method list.
|
|
200
227
|
* @property namespace Optional REST namespace, defaulting to the workspace namespace.
|
|
201
228
|
* @property permissionCallback Optional PHP callback used for generated REST
|
|
202
|
-
* route permission checks.
|
|
229
|
+
* route permission checks or declared manual/provider route ownership.
|
|
203
230
|
* @property pathPattern Route path pattern for manual mode, relative to the
|
|
204
231
|
* namespace. Defaults to `/<name>`.
|
|
205
232
|
* @property queryTypeName Optional exported TypeScript query type for manual
|
|
@@ -207,10 +234,17 @@ export interface RunAddPostMetaCommandOptions {
|
|
|
207
234
|
* @property restResourceName Human-entered resource name normalized into a slug.
|
|
208
235
|
* @property responseTypeName Optional exported TypeScript response type for
|
|
209
236
|
* manual mode. Defaults to `<PascalName>Response`.
|
|
210
|
-
* @property routePattern Optional generated item route pattern,
|
|
211
|
-
*
|
|
237
|
+
* @property routePattern Optional generated item route pattern, or manual
|
|
238
|
+
* provider-route alias for `pathPattern`, relative to the namespace.
|
|
239
|
+
* Generated mode defaults to `/<name>/item`; manual mode defaults to `/<name>`.
|
|
212
240
|
* @property secretFieldName Optional write-only secret field name for manual
|
|
213
241
|
* settings contracts. Requires a request body.
|
|
242
|
+
* @property secretHasValueFieldName Optional alias for `secretStateFieldName`
|
|
243
|
+
* when the response field is a safe presence indicator.
|
|
244
|
+
* @property secretMaskedResponseFieldName Optional alias for
|
|
245
|
+
* `secretStateFieldName` when the response field represents masked state.
|
|
246
|
+
* @property secretPreserveOnEmpty Whether blank secret submissions should
|
|
247
|
+
* preserve the existing value. Defaults to true when `secretFieldName` is set.
|
|
214
248
|
* @property secretStateFieldName Optional masked response boolean field for
|
|
215
249
|
* `secretFieldName`. Defaults to `has<PascalSecretField>`.
|
|
216
250
|
*/
|
|
@@ -231,6 +265,9 @@ export interface RunAddRestResourceCommandOptions {
|
|
|
231
265
|
responseTypeName?: string;
|
|
232
266
|
routePattern?: string;
|
|
233
267
|
secretFieldName?: string;
|
|
268
|
+
secretHasValueFieldName?: string;
|
|
269
|
+
secretMaskedResponseFieldName?: string;
|
|
270
|
+
secretPreserveOnEmpty?: boolean;
|
|
234
271
|
secretStateFieldName?: string;
|
|
235
272
|
}
|
|
236
273
|
/**
|
|
@@ -310,12 +347,14 @@ export interface RunAddEditorPluginCommandOptions {
|
|
|
310
347
|
* @property integrationEnvName Human-entered environment name that will be
|
|
311
348
|
* normalized into script and documentation paths.
|
|
312
349
|
* @property service Optional local service starter. Defaults to `none`.
|
|
350
|
+
* @property withReleaseZip Whether to add release zip packaging scripts.
|
|
313
351
|
* @property withWpEnv Whether to add a local `@wordpress/env` preset and scripts.
|
|
314
352
|
*/
|
|
315
353
|
export interface RunAddIntegrationEnvCommandOptions {
|
|
316
354
|
cwd?: string;
|
|
317
355
|
integrationEnvName: string;
|
|
318
356
|
service?: string;
|
|
357
|
+
withReleaseZip?: boolean;
|
|
319
358
|
withWpEnv?: boolean;
|
|
320
359
|
}
|
|
321
360
|
/**
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { suggestCloseId } from "./id-suggestions.js";
|
|
2
|
+
import { PATTERN_CATALOG_SCOPE_IDS, } from "./pattern-catalog.js";
|
|
2
3
|
export { ADD_KIND_IDS } from "./cli-add-kind-ids.js";
|
|
4
|
+
export { PATTERN_CATALOG_SCOPE_IDS };
|
|
3
5
|
/**
|
|
4
6
|
* Supported plugin-level REST resource methods accepted by
|
|
5
7
|
* `wp-typia add rest-resource --methods`.
|
|
@@ -110,6 +110,13 @@ export declare function assertValidManualRestContractAuth(auth?: string): Manual
|
|
|
110
110
|
* @returns True when the pattern has no regex groups or uses only `(?P<id>...)`.
|
|
111
111
|
*/
|
|
112
112
|
export declare function isGeneratedRestResourceRoutePatternCompatible(routePattern: string): boolean;
|
|
113
|
+
/**
|
|
114
|
+
* Collect unique WordPress named capture parameters from a REST route pattern.
|
|
115
|
+
*
|
|
116
|
+
* @param routePattern Route pattern relative to the namespace.
|
|
117
|
+
* @returns Capture names in first-seen order.
|
|
118
|
+
*/
|
|
119
|
+
export declare function collectRestRouteNamedCaptureNames(routePattern: string): string[];
|
|
113
120
|
export declare function resolveManualRestContractPathPattern(slug: string, pathPattern?: string): string;
|
|
114
121
|
/**
|
|
115
122
|
* Normalize and validate a generated REST resource item route pattern.
|
|
@@ -332,6 +332,15 @@ export function isGeneratedRestResourceRoutePatternCompatible(routePattern) {
|
|
|
332
332
|
return (!hasUnsupportedCapture &&
|
|
333
333
|
(!hasRegexGroup || (namedCaptures.length === 1 && namedCaptures[0] === "id")));
|
|
334
334
|
}
|
|
335
|
+
/**
|
|
336
|
+
* Collect unique WordPress named capture parameters from a REST route pattern.
|
|
337
|
+
*
|
|
338
|
+
* @param routePattern Route pattern relative to the namespace.
|
|
339
|
+
* @returns Capture names in first-seen order.
|
|
340
|
+
*/
|
|
341
|
+
export function collectRestRouteNamedCaptureNames(routePattern) {
|
|
342
|
+
return Array.from(new Set(Array.from(routePattern.matchAll(REST_ROUTE_NAMED_CAPTURE_PATTERN), (match) => match[1])));
|
|
343
|
+
}
|
|
335
344
|
export function resolveManualRestContractPathPattern(slug, pathPattern) {
|
|
336
345
|
return resolveRestRoutePathPattern({
|
|
337
346
|
defaultPath: `/${slug}`,
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { WorkspaceProject } from "./workspace-project.js";
|
|
2
|
+
/**
|
|
3
|
+
* Ensure the workspace bootstrap loads generated ability PHP modules and
|
|
4
|
+
* enqueues the generated ability editor script module.
|
|
5
|
+
*/
|
|
6
|
+
export declare function ensureAbilityBootstrapAnchors(workspace: WorkspaceProject): Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* Ensure ability package scripts and WordPress ability runtime dependencies
|
|
9
|
+
* are present without downgrading existing compatible ranges.
|
|
10
|
+
*/
|
|
11
|
+
export declare function ensureAbilityPackageScripts(workspace: WorkspaceProject): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Ensure `scripts/sync-project.ts` delegates to the generated ability sync
|
|
14
|
+
* script when present.
|
|
15
|
+
*/
|
|
16
|
+
export declare function ensureAbilitySyncProjectAnchors(workspace: WorkspaceProject): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Ensure the workspace build script includes optional ability client entries.
|
|
19
|
+
*/
|
|
20
|
+
export declare function ensureAbilityBuildScriptAnchors(workspace: WorkspaceProject): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Ensure webpack discovers the optional ability client registry bundle.
|
|
23
|
+
*/
|
|
24
|
+
export declare function ensureAbilityWebpackAnchors(workspace: WorkspaceProject): Promise<void>;
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { promises as fsp } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import semver from "semver";
|
|
4
|
+
import { getWorkspaceBootstrapPath, patchFile, } from "./cli-add-shared.js";
|
|
5
|
+
import { ABILITY_EDITOR_ASSET, ABILITY_EDITOR_SCRIPT, ABILITY_SERVER_GLOB, WP_ABILITIES_SCRIPT_MODULE_ID, WP_CORE_ABILITIES_SCRIPT_MODULE_ID, } from "./cli-add-workspace-ability-types.js";
|
|
6
|
+
import { appendPhpSnippetBeforeClosingTag, insertPhpSnippetBeforeWorkspaceAnchors, } from "./cli-add-workspace-mutation.js";
|
|
7
|
+
import { readJsonFile } from "./json-utils.js";
|
|
8
|
+
import { DEFAULT_WORDPRESS_ABILITIES_VERSION, DEFAULT_WORDPRESS_CORE_ABILITIES_VERSION, } from "./package-versions.js";
|
|
9
|
+
import { findPhpFunctionRange, hasPhpFunctionCall, hasPhpFunctionDefinition, replacePhpFunctionDefinition, } from "./php-utils.js";
|
|
10
|
+
function resolveManagedDependencyVersion(existingVersion, requiredVersion) {
|
|
11
|
+
if (!existingVersion) {
|
|
12
|
+
return requiredVersion;
|
|
13
|
+
}
|
|
14
|
+
const existingMinimum = semver.minVersion(existingVersion);
|
|
15
|
+
const requiredMinimum = semver.minVersion(requiredVersion);
|
|
16
|
+
if (!existingMinimum || !requiredMinimum) {
|
|
17
|
+
return requiredVersion;
|
|
18
|
+
}
|
|
19
|
+
return semver.gte(existingMinimum, requiredMinimum)
|
|
20
|
+
? existingVersion
|
|
21
|
+
: requiredVersion;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Ensure the workspace bootstrap loads generated ability PHP modules and
|
|
25
|
+
* enqueues the generated ability editor script module.
|
|
26
|
+
*/
|
|
27
|
+
export async function ensureAbilityBootstrapAnchors(workspace) {
|
|
28
|
+
const bootstrapPath = getWorkspaceBootstrapPath(workspace);
|
|
29
|
+
await patchFile(bootstrapPath, (source) => {
|
|
30
|
+
let nextSource = source;
|
|
31
|
+
const workspaceBaseName = workspace.packageName.split("/").pop() ?? workspace.packageName;
|
|
32
|
+
const loadFunctionName = `${workspace.workspace.phpPrefix}_load_workflow_abilities`;
|
|
33
|
+
const enqueueFunctionName = `${workspace.workspace.phpPrefix}_enqueue_workflow_abilities`;
|
|
34
|
+
const loadHook = `add_action( 'plugins_loaded', '${loadFunctionName}' );`;
|
|
35
|
+
const adminEnqueueHook = `add_action( 'admin_enqueue_scripts', '${enqueueFunctionName}' );`;
|
|
36
|
+
const editorEnqueueHook = `add_action( 'enqueue_block_editor_assets', '${enqueueFunctionName}' );`;
|
|
37
|
+
const loadFunction = `
|
|
38
|
+
|
|
39
|
+
function ${loadFunctionName}() {
|
|
40
|
+
\tforeach ( glob( __DIR__ . '${ABILITY_SERVER_GLOB}' ) ?: array() as $ability_module ) {
|
|
41
|
+
\t\trequire_once $ability_module;
|
|
42
|
+
\t}
|
|
43
|
+
}
|
|
44
|
+
`;
|
|
45
|
+
const enqueueFunction = `
|
|
46
|
+
|
|
47
|
+
function ${enqueueFunctionName}() {
|
|
48
|
+
\tif ( ! class_exists( 'WP_Ability' ) ) {
|
|
49
|
+
\t\treturn;
|
|
50
|
+
\t}
|
|
51
|
+
|
|
52
|
+
\t$script_path = __DIR__ . '/${ABILITY_EDITOR_SCRIPT}';
|
|
53
|
+
\t$asset_path = __DIR__ . '/${ABILITY_EDITOR_ASSET}';
|
|
54
|
+
|
|
55
|
+
\tif ( ! file_exists( $script_path ) || ! file_exists( $asset_path ) ) {
|
|
56
|
+
\t\treturn;
|
|
57
|
+
\t}
|
|
58
|
+
|
|
59
|
+
\t$asset = require $asset_path;
|
|
60
|
+
\tif ( ! is_array( $asset ) ) {
|
|
61
|
+
\t\t$asset = array();
|
|
62
|
+
\t}
|
|
63
|
+
|
|
64
|
+
\t$dependencies = isset( $asset['dependencies'] ) && is_array( $asset['dependencies'] )
|
|
65
|
+
\t\t? $asset['dependencies']
|
|
66
|
+
\t\t: array();
|
|
67
|
+
|
|
68
|
+
\tforeach ( array( '${WP_CORE_ABILITIES_SCRIPT_MODULE_ID}', '${WP_ABILITIES_SCRIPT_MODULE_ID}' ) as $ability_dependency ) {
|
|
69
|
+
\t\t$has_dependency = false;
|
|
70
|
+
\t\tforeach ( $dependencies as $dependency ) {
|
|
71
|
+
\t\t\t$dependency_id = is_array( $dependency ) && isset( $dependency['id'] )
|
|
72
|
+
\t\t\t\t? $dependency['id']
|
|
73
|
+
\t\t\t\t: $dependency;
|
|
74
|
+
\t\t\tif ( $dependency_id === $ability_dependency ) {
|
|
75
|
+
\t\t\t\t$has_dependency = true;
|
|
76
|
+
\t\t\t\tbreak;
|
|
77
|
+
\t\t\t}
|
|
78
|
+
\t\t}
|
|
79
|
+
\t\tif ( ! $has_dependency ) {
|
|
80
|
+
\t\t\t$dependencies[] = $ability_dependency;
|
|
81
|
+
\t\t}
|
|
82
|
+
\t}
|
|
83
|
+
|
|
84
|
+
\tif ( ! function_exists( 'wp_enqueue_script_module' ) ) {
|
|
85
|
+
\t\treturn;
|
|
86
|
+
\t}
|
|
87
|
+
|
|
88
|
+
\twp_enqueue_script_module(
|
|
89
|
+
\t\t'${workspaceBaseName}-abilities',
|
|
90
|
+
\t\tplugins_url( '${ABILITY_EDITOR_SCRIPT}', __FILE__ ),
|
|
91
|
+
\t\t$dependencies,
|
|
92
|
+
\t\tisset( $asset['version'] ) ? $asset['version'] : filemtime( $script_path )
|
|
93
|
+
\t);
|
|
94
|
+
}
|
|
95
|
+
`;
|
|
96
|
+
if (!hasPhpFunctionDefinition(nextSource, loadFunctionName)) {
|
|
97
|
+
nextSource = insertPhpSnippetBeforeWorkspaceAnchors(nextSource, loadFunction);
|
|
98
|
+
}
|
|
99
|
+
if (!hasPhpFunctionDefinition(nextSource, enqueueFunctionName)) {
|
|
100
|
+
nextSource = insertPhpSnippetBeforeWorkspaceAnchors(nextSource, enqueueFunction);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
const functionRange = findPhpFunctionRange(nextSource, enqueueFunctionName);
|
|
104
|
+
const functionSource = functionRange
|
|
105
|
+
? nextSource.slice(functionRange.start, functionRange.end)
|
|
106
|
+
: "";
|
|
107
|
+
if (!hasPhpFunctionCall(functionSource, "wp_enqueue_script_module")) {
|
|
108
|
+
const replacedSource = replacePhpFunctionDefinition(nextSource, enqueueFunctionName, enqueueFunction, { trimReplacementStart: true });
|
|
109
|
+
if (!replacedSource) {
|
|
110
|
+
throw new Error(`Unable to repair ${path.basename(bootstrapPath)} for ${enqueueFunctionName}.`);
|
|
111
|
+
}
|
|
112
|
+
nextSource = replacedSource;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (!nextSource.includes(loadHook)) {
|
|
116
|
+
nextSource = appendPhpSnippetBeforeClosingTag(nextSource, loadHook);
|
|
117
|
+
}
|
|
118
|
+
if (!nextSource.includes(adminEnqueueHook)) {
|
|
119
|
+
nextSource = appendPhpSnippetBeforeClosingTag(nextSource, adminEnqueueHook);
|
|
120
|
+
}
|
|
121
|
+
if (!nextSource.includes(editorEnqueueHook)) {
|
|
122
|
+
nextSource = appendPhpSnippetBeforeClosingTag(nextSource, editorEnqueueHook);
|
|
123
|
+
}
|
|
124
|
+
return nextSource;
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Ensure ability package scripts and WordPress ability runtime dependencies
|
|
129
|
+
* are present without downgrading existing compatible ranges.
|
|
130
|
+
*/
|
|
131
|
+
export async function ensureAbilityPackageScripts(workspace) {
|
|
132
|
+
const packageJsonPath = path.join(workspace.projectDir, "package.json");
|
|
133
|
+
const packageJson = await readJsonFile(packageJsonPath, {
|
|
134
|
+
context: "workspace package manifest",
|
|
135
|
+
});
|
|
136
|
+
const nextScripts = {
|
|
137
|
+
...(packageJson.scripts ?? {}),
|
|
138
|
+
"sync-abilities": packageJson.scripts?.["sync-abilities"] ?? "tsx scripts/sync-abilities.ts",
|
|
139
|
+
};
|
|
140
|
+
const nextDependencies = {
|
|
141
|
+
...(packageJson.dependencies ?? {}),
|
|
142
|
+
[WP_ABILITIES_SCRIPT_MODULE_ID]: resolveManagedDependencyVersion(packageJson.dependencies?.[WP_ABILITIES_SCRIPT_MODULE_ID], DEFAULT_WORDPRESS_ABILITIES_VERSION),
|
|
143
|
+
[WP_CORE_ABILITIES_SCRIPT_MODULE_ID]: resolveManagedDependencyVersion(packageJson.dependencies?.[WP_CORE_ABILITIES_SCRIPT_MODULE_ID], DEFAULT_WORDPRESS_CORE_ABILITIES_VERSION),
|
|
144
|
+
};
|
|
145
|
+
if (JSON.stringify(nextScripts) === JSON.stringify(packageJson.scripts ?? {}) &&
|
|
146
|
+
JSON.stringify(nextDependencies) ===
|
|
147
|
+
JSON.stringify(packageJson.dependencies ?? {})) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
packageJson.scripts = nextScripts;
|
|
151
|
+
packageJson.dependencies = nextDependencies;
|
|
152
|
+
await fsp.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, "\t")}\n`, "utf8");
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Ensure `scripts/sync-project.ts` delegates to the generated ability sync
|
|
156
|
+
* script when present.
|
|
157
|
+
*/
|
|
158
|
+
export async function ensureAbilitySyncProjectAnchors(workspace) {
|
|
159
|
+
const syncProjectScriptPath = path.join(workspace.projectDir, "scripts", "sync-project.ts");
|
|
160
|
+
await patchFile(syncProjectScriptPath, (source) => {
|
|
161
|
+
let nextSource = source;
|
|
162
|
+
const syncRestConst = "const syncRestScriptPath = path.join( 'scripts', 'sync-rest-contracts.ts' );";
|
|
163
|
+
const syncAbilitiesConst = "const syncAbilitiesScriptPath = path.join( 'scripts', 'sync-abilities.ts' );";
|
|
164
|
+
const syncRestBlockPattern = /if \( fs\.existsSync\( path\.resolve\( process\.cwd\(\), syncRestScriptPath \) \) \) \{\n\s*runSyncScript\( syncRestScriptPath, options \);\n\s*\}/u;
|
|
165
|
+
const syncAbilitiesBlock = [
|
|
166
|
+
"if ( fs.existsSync( path.resolve( process.cwd(), syncAbilitiesScriptPath ) ) ) {",
|
|
167
|
+
"\trunSyncScript( syncAbilitiesScriptPath, options );",
|
|
168
|
+
"}",
|
|
169
|
+
].join("\n");
|
|
170
|
+
if (!nextSource.includes(syncAbilitiesConst)) {
|
|
171
|
+
if (!nextSource.includes(syncRestConst)) {
|
|
172
|
+
throw new Error([
|
|
173
|
+
`ensureAbilitySyncProjectAnchors could not patch ${path.basename(syncProjectScriptPath)}.`,
|
|
174
|
+
"Missing the expected sync-rest script constant in scripts/sync-project.ts.",
|
|
175
|
+
"Restore the generated template or wire sync-abilities manually before retrying.",
|
|
176
|
+
].join(" "));
|
|
177
|
+
}
|
|
178
|
+
nextSource = nextSource.replace(syncRestConst, `${syncRestConst}\n${syncAbilitiesConst}`);
|
|
179
|
+
}
|
|
180
|
+
if (!nextSource.includes("runSyncScript( syncAbilitiesScriptPath, options );")) {
|
|
181
|
+
if (!syncRestBlockPattern.test(nextSource)) {
|
|
182
|
+
throw new Error([
|
|
183
|
+
`ensureAbilitySyncProjectAnchors could not patch ${path.basename(syncProjectScriptPath)}.`,
|
|
184
|
+
"Missing the expected sync-rest invocation block in scripts/sync-project.ts.",
|
|
185
|
+
"Restore the generated template or wire sync-abilities manually before retrying.",
|
|
186
|
+
].join(" "));
|
|
187
|
+
}
|
|
188
|
+
nextSource = nextSource.replace(syncRestBlockPattern, (match) => `${match}\n\n${syncAbilitiesBlock}`);
|
|
189
|
+
}
|
|
190
|
+
return nextSource;
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Ensure the workspace build script includes optional ability client entries.
|
|
195
|
+
*/
|
|
196
|
+
export async function ensureAbilityBuildScriptAnchors(workspace) {
|
|
197
|
+
const buildScriptPath = path.join(workspace.projectDir, "scripts", "build-workspace.mjs");
|
|
198
|
+
await patchFile(buildScriptPath, (source) => {
|
|
199
|
+
let nextSource = source;
|
|
200
|
+
if (/['"]src\/abilities\/index\.(?:ts|js)['"]/u.test(nextSource)) {
|
|
201
|
+
return nextSource;
|
|
202
|
+
}
|
|
203
|
+
const sharedEntriesPattern = /(for\s*\(\s*const\s+relativePath\s+of\s+\[)([\s\S]*?)(\]\s*\)\s*\{)/u;
|
|
204
|
+
const match = nextSource.match(sharedEntriesPattern);
|
|
205
|
+
if (!match ||
|
|
206
|
+
!/['"]src\/bindings\/index\.(?:ts|js)['"]/u.test(match[2]) ||
|
|
207
|
+
!/['"]src\/editor-plugins\/index\.(?:tsx|ts|js)['"]/u.test(match[2])) {
|
|
208
|
+
throw new Error([
|
|
209
|
+
`ensureAbilityBuildScriptAnchors could not patch ${path.basename(buildScriptPath)}.`,
|
|
210
|
+
"Missing the expected shared editor entries array in scripts/build-workspace.mjs.",
|
|
211
|
+
"Restore the generated template or wire abilities/index manually before retrying.",
|
|
212
|
+
].join(" "));
|
|
213
|
+
}
|
|
214
|
+
nextSource = nextSource.replace(sharedEntriesPattern, (fullMatch, sharedEntries) => {
|
|
215
|
+
const missingAbilityEntries = [
|
|
216
|
+
"'src/abilities/index.ts'",
|
|
217
|
+
"'src/abilities/index.js'",
|
|
218
|
+
].filter((entry) => !sharedEntries.includes(entry));
|
|
219
|
+
if (missingAbilityEntries.length === 0) {
|
|
220
|
+
return fullMatch;
|
|
221
|
+
}
|
|
222
|
+
const itemIndent = sharedEntries.match(/\n([ \t]*)['"]/u)?.[1] ?? "\t\t";
|
|
223
|
+
const trimmedEntries = sharedEntries.replace(/\s*$/u, "");
|
|
224
|
+
const trailingWhitespace = sharedEntries.slice(trimmedEntries.length);
|
|
225
|
+
const separator = trimmedEntries.trimEnd().endsWith(",") ? "" : ",";
|
|
226
|
+
const nextEntries = `${trimmedEntries}${separator}` +
|
|
227
|
+
missingAbilityEntries.map((entry) => `\n${itemIndent}${entry},`).join("") +
|
|
228
|
+
trailingWhitespace;
|
|
229
|
+
return fullMatch.replace(sharedEntries, nextEntries);
|
|
230
|
+
});
|
|
231
|
+
return nextSource;
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Ensure webpack discovers the optional ability client registry bundle.
|
|
236
|
+
*/
|
|
237
|
+
export async function ensureAbilityWebpackAnchors(workspace) {
|
|
238
|
+
const webpackConfigPath = path.join(workspace.projectDir, "webpack.config.js");
|
|
239
|
+
await patchFile(webpackConfigPath, (source) => {
|
|
240
|
+
if (/['"]abilities\/index['"]/u.test(source)) {
|
|
241
|
+
return source;
|
|
242
|
+
}
|
|
243
|
+
const optionalModuleReturnPattern = /(function\s+getOptionalModuleEntries\s*\(\)\s*\{[\s\S]*?)(\n\treturn Object\.fromEntries\(\s*entries\s*\);\n\})/u;
|
|
244
|
+
if (optionalModuleReturnPattern.test(source)) {
|
|
245
|
+
return source.replace(optionalModuleReturnPattern, `$1
|
|
246
|
+
|
|
247
|
+
\tfor ( const [ entryName, candidates ] of [
|
|
248
|
+
\t\t[
|
|
249
|
+
\t\t\t'abilities/index',
|
|
250
|
+
\t\t\t[ 'src/abilities/index.ts', 'src/abilities/index.js' ],
|
|
251
|
+
\t\t],
|
|
252
|
+
\t] ) {
|
|
253
|
+
\t\tfor ( const relativePath of candidates ) {
|
|
254
|
+
\t\t\tconst entryPath = path.resolve( process.cwd(), relativePath );
|
|
255
|
+
\t\t\tif ( ! fs.existsSync( entryPath ) ) {
|
|
256
|
+
\t\t\t\tcontinue;
|
|
257
|
+
\t\t\t}
|
|
258
|
+
|
|
259
|
+
\t\t\tentries.push( [ entryName, entryPath ] );
|
|
260
|
+
\t\t\tbreak;
|
|
261
|
+
\t\t}
|
|
262
|
+
\t}$2`);
|
|
263
|
+
}
|
|
264
|
+
const sharedEntriesPattern = /for\s*\(\s*const\s+\[\s*entryName\s*,\s*candidates\s*\]\s+of\s+\[([\s\S]*?)\]\s*\)\s*\{/u;
|
|
265
|
+
const match = source.match(sharedEntriesPattern);
|
|
266
|
+
if (!match ||
|
|
267
|
+
!match[1].includes("bindings/index") ||
|
|
268
|
+
!match[1].includes("editor-plugins/index")) {
|
|
269
|
+
throw new Error([
|
|
270
|
+
`ensureAbilityWebpackAnchors could not patch ${path.basename(webpackConfigPath)}.`,
|
|
271
|
+
"Missing the expected shared editor entries block in webpack.config.js.",
|
|
272
|
+
"Restore the generated template or wire abilities/index manually before retrying.",
|
|
273
|
+
].join(" "));
|
|
274
|
+
}
|
|
275
|
+
return source.replace(sharedEntriesPattern, (fullMatch, sharedEntries) => {
|
|
276
|
+
if (/['"]abilities\/index['"]/u.test(sharedEntries)) {
|
|
277
|
+
return fullMatch;
|
|
278
|
+
}
|
|
279
|
+
const tupleIndent = sharedEntries.match(/\n([ \t]*)\[/u)?.[1] ?? "\t\t";
|
|
280
|
+
const nestedIndent = `${tupleIndent}\t`;
|
|
281
|
+
const trimmedEntries = sharedEntries.replace(/\s*$/u, "");
|
|
282
|
+
const trailingWhitespace = sharedEntries.slice(trimmedEntries.length);
|
|
283
|
+
const separator = trimmedEntries.trimEnd().endsWith(",") ? "" : ",";
|
|
284
|
+
const abilityTuple = [
|
|
285
|
+
`${tupleIndent}[`,
|
|
286
|
+
`${nestedIndent}'abilities/index',`,
|
|
287
|
+
`${nestedIndent}[ 'src/abilities/index.ts', 'src/abilities/index.js' ],`,
|
|
288
|
+
`${tupleIndent}],`,
|
|
289
|
+
].join("\n");
|
|
290
|
+
const nextEntries = `${trimmedEntries}${separator}\n${abilityTuple}` + trailingWhitespace;
|
|
291
|
+
return fullMatch.replace(sharedEntries, nextEntries);
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the workspace ability client registry path, preserving JS registries
|
|
3
|
+
* when older projects already use them.
|
|
4
|
+
*/
|
|
5
|
+
export declare function resolveAbilityRegistryPath(projectDir: string): Promise<string>;
|
|
6
|
+
/**
|
|
7
|
+
* Rewrite the generated ability client registry while preserving existing
|
|
8
|
+
* generated entries and extension-suffixed exports.
|
|
9
|
+
*/
|
|
10
|
+
export declare function writeAbilityRegistry(projectDir: string, abilitySlug: string): Promise<void>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { promises as fsp } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { readOptionalUtf8File, pathExists } from "./fs-async.js";
|
|
4
|
+
import { buildAbilityRegistrySource, } from "./cli-add-workspace-ability-templates.js";
|
|
5
|
+
import { ABILITY_REGISTRY_END_MARKER, ABILITY_REGISTRY_START_MARKER, } from "./cli-add-workspace-ability-types.js";
|
|
6
|
+
import { escapeRegex } from "./php-utils.js";
|
|
7
|
+
import { readWorkspaceInventoryAsync, } from "./workspace-inventory.js";
|
|
8
|
+
/**
|
|
9
|
+
* Resolve the workspace ability client registry path, preserving JS registries
|
|
10
|
+
* when older projects already use them.
|
|
11
|
+
*/
|
|
12
|
+
export async function resolveAbilityRegistryPath(projectDir) {
|
|
13
|
+
const abilitiesDir = path.join(projectDir, "src", "abilities");
|
|
14
|
+
for (const candidatePath of [
|
|
15
|
+
path.join(abilitiesDir, "index.ts"),
|
|
16
|
+
path.join(abilitiesDir, "index.js"),
|
|
17
|
+
]) {
|
|
18
|
+
if (await pathExists(candidatePath)) {
|
|
19
|
+
return candidatePath;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return path.join(abilitiesDir, "index.ts");
|
|
23
|
+
}
|
|
24
|
+
async function readAbilityRegistrySlugs(registryPath) {
|
|
25
|
+
const source = await readOptionalUtf8File(registryPath);
|
|
26
|
+
if (source === null) {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
return Array.from(source.matchAll(/^\s*export\s+\*\s+from\s+['"]\.\/([^/'"]+)\/client(?:\.[cm]?[jt]sx?)?['"];?\s*$/gmu)).map((match) => match[1]);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Rewrite the generated ability client registry while preserving existing
|
|
33
|
+
* generated entries and extension-suffixed exports.
|
|
34
|
+
*/
|
|
35
|
+
export async function writeAbilityRegistry(projectDir, abilitySlug) {
|
|
36
|
+
const abilitiesDir = path.join(projectDir, "src", "abilities");
|
|
37
|
+
const registryPath = await resolveAbilityRegistryPath(projectDir);
|
|
38
|
+
await fsp.mkdir(abilitiesDir, { recursive: true });
|
|
39
|
+
const existingAbilitySlugs = (await readWorkspaceInventoryAsync(projectDir)).abilities.map((entry) => entry.slug);
|
|
40
|
+
const existingRegistrySlugs = await readAbilityRegistrySlugs(registryPath);
|
|
41
|
+
const nextAbilitySlugs = Array.from(new Set([...existingAbilitySlugs, ...existingRegistrySlugs, abilitySlug])).sort();
|
|
42
|
+
const generatedSection = buildAbilityRegistrySource(nextAbilitySlugs);
|
|
43
|
+
const existingSource = (await readOptionalUtf8File(registryPath)) ?? "";
|
|
44
|
+
const generatedSectionPattern = new RegExp(`${escapeRegex(ABILITY_REGISTRY_START_MARKER)}[\\s\\S]*?${escapeRegex(ABILITY_REGISTRY_END_MARKER)}\\n?`, "u");
|
|
45
|
+
const nextSource = existingSource
|
|
46
|
+
? generatedSectionPattern.test(existingSource)
|
|
47
|
+
? existingSource.replace(generatedSectionPattern, generatedSection)
|
|
48
|
+
: `${existingSource.trimEnd()}\n\n${generatedSection}`
|
|
49
|
+
: generatedSection;
|
|
50
|
+
await fsp.writeFile(registryPath, nextSource, "utf8");
|
|
51
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ScaffoldAbilityWorkspaceOptions } from "./cli-add-workspace-ability-types.js";
|
|
2
2
|
/**
|
|
3
3
|
* Write generated workflow ability sources and patch shared workspace anchors.
|
|
4
4
|
*/
|