@wp-typia/project-tools 0.22.10 → 0.23.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/runtime/ai-feature-artifacts.js +4 -1
- package/dist/runtime/block-generator-service-spec.js +2 -1
- package/dist/runtime/cli-add-block-json.js +5 -1
- package/dist/runtime/cli-add-collision.d.ts +25 -0
- package/dist/runtime/cli-add-collision.js +76 -0
- package/dist/runtime/cli-add-help.js +12 -2
- package/dist/runtime/cli-add-kind-ids.d.ts +1 -1
- package/dist/runtime/cli-add-kind-ids.js +3 -0
- package/dist/runtime/cli-add-types.d.ts +129 -0
- package/dist/runtime/cli-add-types.js +26 -0
- package/dist/runtime/cli-add-validation.d.ts +97 -1
- package/dist/runtime/cli-add-validation.js +313 -1
- package/dist/runtime/cli-add-workspace-ability-scaffold.js +4 -1
- package/dist/runtime/cli-add-workspace-admin-view-scaffold.js +79 -20
- package/dist/runtime/cli-add-workspace-admin-view-source.js +11 -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 +19 -10
- package/dist/runtime/cli-add-workspace-admin-view-templates.js +31 -971
- package/dist/runtime/cli-add-workspace-admin-view-types.d.ts +21 -0
- package/dist/runtime/cli-add-workspace-admin-view-types.js +22 -0
- package/dist/runtime/cli-add-workspace-ai-anchors.js +125 -32
- package/dist/runtime/cli-add-workspace-ai-source-emitters.js +17 -1
- package/dist/runtime/cli-add-workspace-contract-source-emitters.d.ts +15 -0
- package/dist/runtime/cli-add-workspace-contract-source-emitters.js +42 -0
- package/dist/runtime/cli-add-workspace-contract.d.ts +15 -0
- package/dist/runtime/cli-add-workspace-contract.js +65 -0
- package/dist/runtime/cli-add-workspace-integration-env.d.ts +26 -0
- package/dist/runtime/cli-add-workspace-integration-env.js +428 -0
- package/dist/runtime/cli-add-workspace-post-meta-anchors.d.ts +23 -0
- package/dist/runtime/cli-add-workspace-post-meta-anchors.js +244 -0
- package/dist/runtime/cli-add-workspace-post-meta-source-emitters.d.ts +63 -0
- package/dist/runtime/cli-add-workspace-post-meta-source-emitters.js +179 -0
- package/dist/runtime/cli-add-workspace-post-meta.d.ts +15 -0
- package/dist/runtime/cli-add-workspace-post-meta.js +107 -0
- package/dist/runtime/cli-add-workspace-rest-anchors.d.ts +9 -0
- package/dist/runtime/cli-add-workspace-rest-anchors.js +326 -21
- package/dist/runtime/cli-add-workspace-rest-generated.d.ts +9 -0
- package/dist/runtime/cli-add-workspace-rest-generated.js +158 -0
- package/dist/runtime/cli-add-workspace-rest-manual.d.ts +8 -0
- package/dist/runtime/cli-add-workspace-rest-manual.js +279 -0
- package/dist/runtime/cli-add-workspace-rest-php-templates.d.ts +24 -0
- package/dist/runtime/cli-add-workspace-rest-php-templates.js +678 -0
- package/dist/runtime/cli-add-workspace-rest-source-emitters.d.ts +98 -2
- package/dist/runtime/cli-add-workspace-rest-source-emitters.js +323 -29
- 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 -7
- package/dist/runtime/cli-add-workspace-rest.js +34 -481
- package/dist/runtime/cli-add-workspace.d.ts +15 -0
- package/dist/runtime/cli-add-workspace.js +15 -0
- package/dist/runtime/cli-add.d.ts +1 -1
- package/dist/runtime/cli-add.js +1 -1
- package/dist/runtime/cli-core.d.ts +3 -2
- package/dist/runtime/cli-core.js +3 -2
- package/dist/runtime/cli-diagnostics.d.ts +3 -1
- package/dist/runtime/cli-diagnostics.js +17 -5
- package/dist/runtime/cli-doctor-environment.js +1 -3
- package/dist/runtime/cli-doctor-workspace-bindings.js +4 -1
- package/dist/runtime/cli-doctor-workspace-block-addons.d.ts +12 -0
- package/dist/runtime/cli-doctor-workspace-block-addons.js +134 -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 -369
- package/dist/runtime/cli-doctor-workspace-package.d.ts +25 -3
- package/dist/runtime/cli-doctor-workspace-package.js +35 -13
- package/dist/runtime/cli-doctor-workspace-shared.d.ts +2 -0
- package/dist/runtime/cli-doctor-workspace-shared.js +2 -0
- package/dist/runtime/cli-doctor-workspace.js +8 -3
- package/dist/runtime/cli-doctor.d.ts +52 -3
- package/dist/runtime/cli-doctor.js +79 -8
- package/dist/runtime/cli-help.js +10 -0
- package/dist/runtime/cli-init-package-json.js +4 -2
- package/dist/runtime/cli-init-templates.js +11 -1
- 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/contract-artifacts.d.ts +14 -0
- package/dist/runtime/contract-artifacts.js +15 -0
- package/dist/runtime/external-template-guards.js +4 -6
- package/dist/runtime/index.d.ts +2 -2
- package/dist/runtime/index.js +1 -1
- package/dist/runtime/json-utils.d.ts +62 -4
- package/dist/runtime/json-utils.js +78 -4
- package/dist/runtime/local-dev-presets.js +4 -1
- 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.js +6 -1
- package/dist/runtime/rest-resource-artifacts.d.ts +57 -1
- package/dist/runtime/rest-resource-artifacts.js +97 -1
- 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-render.d.ts +1 -1
- package/dist/runtime/template-render.js +1 -1
- package/dist/runtime/template-source-cache-markers.d.ts +37 -0
- package/dist/runtime/template-source-cache-markers.js +125 -0
- package/dist/runtime/template-source-cache.d.ts +1 -4
- package/dist/runtime/template-source-cache.js +16 -122
- package/dist/runtime/template-source-contracts.d.ts +2 -0
- package/dist/runtime/template-source-external.d.ts +4 -2
- package/dist/runtime/template-source-external.js +4 -2
- package/dist/runtime/template-source-normalization.js +2 -1
- package/dist/runtime/template-source-remote.d.ts +8 -4
- package/dist/runtime/template-source-remote.js +26 -9
- package/dist/runtime/template-source-seeds.js +10 -3
- package/dist/runtime/workspace-inventory-mutations.js +54 -4
- 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 -44
- package/dist/runtime/workspace-inventory-parser.js +7 -464
- package/dist/runtime/workspace-inventory-read.d.ts +9 -2
- package/dist/runtime/workspace-inventory-read.js +9 -2
- package/dist/runtime/workspace-inventory-section-descriptors.d.ts +19 -0
- package/dist/runtime/workspace-inventory-section-descriptors.js +435 -0
- package/dist/runtime/workspace-inventory-templates.d.ts +16 -1
- package/dist/runtime/workspace-inventory-templates.js +75 -4
- package/dist/runtime/workspace-inventory-types.d.ts +52 -2
- package/dist/runtime/workspace-inventory.d.ts +2 -2
- package/dist/runtime/workspace-inventory.js +1 -1
- package/dist/runtime/workspace-project.js +4 -6
- package/package.json +2 -2
|
@@ -1,11 +1,101 @@
|
|
|
1
1
|
import { HOOKED_BLOCK_ANCHOR_PATTERN, HOOKED_BLOCK_POSITION_IDS, } from "./hooked-blocks.js";
|
|
2
2
|
import { toSnakeCase, } from "./string-case.js";
|
|
3
|
-
import { ADD_BLOCK_TEMPLATE_IDS, EDITOR_PLUGIN_SLOT_IDS, REST_RESOURCE_METHOD_IDS, resolveEditorPluginSlotAlias, } from "./cli-add-types.js";
|
|
3
|
+
import { ADD_BLOCK_TEMPLATE_IDS, EDITOR_PLUGIN_SLOT_IDS, INTEGRATION_ENV_SERVICE_IDS, MANUAL_REST_CONTRACT_AUTH_IDS, MANUAL_REST_CONTRACT_HTTP_METHOD_IDS, REST_RESOURCE_METHOD_IDS, resolveEditorPluginSlotAlias, } from "./cli-add-types.js";
|
|
4
4
|
const WORKSPACE_GENERATED_SLUG_PATTERN = /^[a-z][a-z0-9-]*$/;
|
|
5
|
+
const WORDPRESS_POST_TYPE_PATTERN = /^[a-z0-9_][a-z0-9_-]*$/u;
|
|
6
|
+
const TYPESCRIPT_IDENTIFIER_PATTERN = /^[A-Za-z_$][A-Za-z0-9_$]*$/u;
|
|
7
|
+
const TYPESCRIPT_RESERVED_IDENTIFIERS = new Set([
|
|
8
|
+
"abstract",
|
|
9
|
+
"any",
|
|
10
|
+
"as",
|
|
11
|
+
"asserts",
|
|
12
|
+
"async",
|
|
13
|
+
"await",
|
|
14
|
+
"bigint",
|
|
15
|
+
"boolean",
|
|
16
|
+
"break",
|
|
17
|
+
"case",
|
|
18
|
+
"catch",
|
|
19
|
+
"class",
|
|
20
|
+
"const",
|
|
21
|
+
"constructor",
|
|
22
|
+
"continue",
|
|
23
|
+
"debugger",
|
|
24
|
+
"declare",
|
|
25
|
+
"default",
|
|
26
|
+
"delete",
|
|
27
|
+
"do",
|
|
28
|
+
"else",
|
|
29
|
+
"enum",
|
|
30
|
+
"export",
|
|
31
|
+
"extends",
|
|
32
|
+
"false",
|
|
33
|
+
"finally",
|
|
34
|
+
"for",
|
|
35
|
+
"from",
|
|
36
|
+
"function",
|
|
37
|
+
"get",
|
|
38
|
+
"global",
|
|
39
|
+
"if",
|
|
40
|
+
"implements",
|
|
41
|
+
"import",
|
|
42
|
+
"in",
|
|
43
|
+
"infer",
|
|
44
|
+
"instanceof",
|
|
45
|
+
"interface",
|
|
46
|
+
"intrinsic",
|
|
47
|
+
"is",
|
|
48
|
+
"keyof",
|
|
49
|
+
"let",
|
|
50
|
+
"module",
|
|
51
|
+
"namespace",
|
|
52
|
+
"never",
|
|
53
|
+
"new",
|
|
54
|
+
"null",
|
|
55
|
+
"number",
|
|
56
|
+
"object",
|
|
57
|
+
"of",
|
|
58
|
+
"out",
|
|
59
|
+
"override",
|
|
60
|
+
"package",
|
|
61
|
+
"private",
|
|
62
|
+
"protected",
|
|
63
|
+
"public",
|
|
64
|
+
"readonly",
|
|
65
|
+
"require",
|
|
66
|
+
"return",
|
|
67
|
+
"satisfies",
|
|
68
|
+
"set",
|
|
69
|
+
"static",
|
|
70
|
+
"string",
|
|
71
|
+
"super",
|
|
72
|
+
"switch",
|
|
73
|
+
"symbol",
|
|
74
|
+
"this",
|
|
75
|
+
"throw",
|
|
76
|
+
"true",
|
|
77
|
+
"try",
|
|
78
|
+
"type",
|
|
79
|
+
"typeof",
|
|
80
|
+
"undefined",
|
|
81
|
+
"unique",
|
|
82
|
+
"unknown",
|
|
83
|
+
"using",
|
|
84
|
+
"var",
|
|
85
|
+
"void",
|
|
86
|
+
"while",
|
|
87
|
+
"with",
|
|
88
|
+
"yield",
|
|
89
|
+
]);
|
|
5
90
|
/**
|
|
6
91
|
* Namespace format accepted by plugin-level REST resources.
|
|
7
92
|
*/
|
|
8
93
|
export const REST_RESOURCE_NAMESPACE_PATTERN = /^[a-z][a-z0-9-]*(?:\/[a-z0-9-]+)+$/u;
|
|
94
|
+
const PHP_IDENTIFIER_PATTERN = "[A-Za-z_][A-Za-z0-9_]*";
|
|
95
|
+
const PHP_QUALIFIED_NAME_PATTERN = new RegExp(`^\\\\?${PHP_IDENTIFIER_PATTERN}(?:\\\\${PHP_IDENTIFIER_PATTERN})*$`, "u");
|
|
96
|
+
const PHP_CALLBACK_REFERENCE_PATTERN = new RegExp(`^\\\\?${PHP_IDENTIFIER_PATTERN}(?:\\\\${PHP_IDENTIFIER_PATTERN})*(?:::${PHP_IDENTIFIER_PATTERN})?$`, "u");
|
|
97
|
+
const REST_ROUTE_NAMED_CAPTURE_PATTERN = /\(\?P<([A-Za-z_][A-Za-z0-9_]*)>/gu;
|
|
98
|
+
const REST_ROUTE_UNSUPPORTED_CAPTURE_PATTERN = /\((?!\?(?:P<[A-Za-z_][A-Za-z0-9_]*>|:))/u;
|
|
9
99
|
/**
|
|
10
100
|
* Validate a normalized workspace-generated slug.
|
|
11
101
|
*
|
|
@@ -24,6 +114,28 @@ export function assertValidGeneratedSlug(label, slug, usage) {
|
|
|
24
114
|
}
|
|
25
115
|
return slug;
|
|
26
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* Validate a source type name used by generated schema artifact workflows.
|
|
119
|
+
*
|
|
120
|
+
* @param label Human-readable field label used in error messages.
|
|
121
|
+
* @param value TypeScript identifier candidate from CLI input or defaults.
|
|
122
|
+
* @param usage CLI usage hint shown when the identifier is empty.
|
|
123
|
+
* @returns The trimmed, validated TypeScript identifier.
|
|
124
|
+
* @throws {Error} When the value is empty or not a TypeScript identifier.
|
|
125
|
+
*/
|
|
126
|
+
export function assertValidTypeScriptIdentifier(label, value, usage) {
|
|
127
|
+
const trimmed = value.trim();
|
|
128
|
+
if (!trimmed) {
|
|
129
|
+
throw new Error(`${label} is required. Use \`${usage}\`.`);
|
|
130
|
+
}
|
|
131
|
+
if (!TYPESCRIPT_IDENTIFIER_PATTERN.test(trimmed)) {
|
|
132
|
+
throw new Error(`${label} must be a valid TypeScript identifier, such as ExternalRetrieveResponse.`);
|
|
133
|
+
}
|
|
134
|
+
if (TYPESCRIPT_RESERVED_IDENTIFIERS.has(trimmed)) {
|
|
135
|
+
throw new Error(`${label} must not be a reserved TypeScript keyword, such as ${trimmed}.`);
|
|
136
|
+
}
|
|
137
|
+
return trimmed;
|
|
138
|
+
}
|
|
27
139
|
/**
|
|
28
140
|
* Validate a REST resource namespace.
|
|
29
141
|
*
|
|
@@ -52,6 +164,44 @@ export function assertValidRestResourceNamespace(namespace) {
|
|
|
52
164
|
export function resolveRestResourceNamespace(workspaceNamespace, namespace) {
|
|
53
165
|
return assertValidRestResourceNamespace(namespace ?? `${workspaceNamespace}/v1`);
|
|
54
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* Validate a WordPress post type key used as post-meta scope.
|
|
169
|
+
*
|
|
170
|
+
* @param postType Raw post type key from CLI input.
|
|
171
|
+
* @returns The trimmed post type key.
|
|
172
|
+
* @throws {Error} When the key is empty or contains unsupported characters.
|
|
173
|
+
*/
|
|
174
|
+
export function assertValidPostMetaPostType(postType) {
|
|
175
|
+
const trimmed = postType.trim();
|
|
176
|
+
if (!trimmed) {
|
|
177
|
+
throw new Error("`wp-typia add post-meta` requires --post-type <post-type>.");
|
|
178
|
+
}
|
|
179
|
+
if (trimmed.length > 20) {
|
|
180
|
+
throw new Error("Post meta post type must be 20 characters or fewer.");
|
|
181
|
+
}
|
|
182
|
+
if (!WORDPRESS_POST_TYPE_PATTERN.test(trimmed)) {
|
|
183
|
+
throw new Error("Post meta post type must use a WordPress post type key such as `post` or `example_post_type`.");
|
|
184
|
+
}
|
|
185
|
+
return trimmed;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Resolve a post-meta key from explicit input or the workspace slug default.
|
|
189
|
+
*
|
|
190
|
+
* @param options Optional explicit meta key plus workspace prefix and slug.
|
|
191
|
+
* @returns A validated post-meta key.
|
|
192
|
+
* @throws {Error} When the key is empty or contains whitespace/control characters.
|
|
193
|
+
*/
|
|
194
|
+
export function resolvePostMetaKey({ metaKey, phpPrefix, slug, }) {
|
|
195
|
+
const resolvedMetaKey = metaKey ?? `_${toSnakeCase(`${phpPrefix}_${slug}`)}`;
|
|
196
|
+
const trimmed = resolvedMetaKey.trim();
|
|
197
|
+
if (!trimmed) {
|
|
198
|
+
throw new Error("Post meta key cannot be empty.");
|
|
199
|
+
}
|
|
200
|
+
if (/[\p{Cc}\s]/u.test(trimmed)) {
|
|
201
|
+
throw new Error("Post meta key must not contain whitespace or control characters.");
|
|
202
|
+
}
|
|
203
|
+
return trimmed;
|
|
204
|
+
}
|
|
55
205
|
/**
|
|
56
206
|
* Parse and validate REST resource method ids from a comma-separated list.
|
|
57
207
|
*
|
|
@@ -73,6 +223,154 @@ export function assertValidRestResourceMethods(methods) {
|
|
|
73
223
|
}
|
|
74
224
|
return normalizedMethods;
|
|
75
225
|
}
|
|
226
|
+
/**
|
|
227
|
+
* Validate a PHP callable reference supplied to generated REST route metadata.
|
|
228
|
+
*
|
|
229
|
+
* @param label Human-readable field label for errors.
|
|
230
|
+
* @param callback Optional PHP function or `ClassName::method` callback string.
|
|
231
|
+
* @returns The trimmed callback when present.
|
|
232
|
+
* @throws {Error} When the callback cannot be emitted as a safe PHP callable string.
|
|
233
|
+
*/
|
|
234
|
+
export function resolveOptionalPhpCallbackReference(label, callback) {
|
|
235
|
+
if (callback == null) {
|
|
236
|
+
return undefined;
|
|
237
|
+
}
|
|
238
|
+
const trimmed = callback.trim();
|
|
239
|
+
if (!trimmed) {
|
|
240
|
+
throw new Error(`${label} cannot be empty.`);
|
|
241
|
+
}
|
|
242
|
+
if (!PHP_CALLBACK_REFERENCE_PATTERN.test(trimmed)) {
|
|
243
|
+
throw new Error(`${label} must be a PHP function reference or ClassName::method callback.`);
|
|
244
|
+
}
|
|
245
|
+
return trimmed;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Validate a PHP class reference used by generated REST controller wrappers.
|
|
249
|
+
*
|
|
250
|
+
* @param label Human-readable field label for errors.
|
|
251
|
+
* @param classReference Optional PHP class name.
|
|
252
|
+
* @returns The trimmed class reference when present.
|
|
253
|
+
* @throws {Error} When the class reference cannot be emitted safely.
|
|
254
|
+
*/
|
|
255
|
+
export function resolveOptionalPhpClassReference(label, classReference) {
|
|
256
|
+
if (classReference == null) {
|
|
257
|
+
return undefined;
|
|
258
|
+
}
|
|
259
|
+
const trimmed = classReference.trim();
|
|
260
|
+
if (!trimmed) {
|
|
261
|
+
throw new Error(`${label} cannot be empty.`);
|
|
262
|
+
}
|
|
263
|
+
if (!PHP_QUALIFIED_NAME_PATTERN.test(trimmed)) {
|
|
264
|
+
throw new Error(`${label} must be a PHP class reference such as Demo_Rest_Controller or Vendor\\Plugin\\Controller.`);
|
|
265
|
+
}
|
|
266
|
+
return trimmed;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Normalize and validate the HTTP method used by a manual REST contract.
|
|
270
|
+
*
|
|
271
|
+
* @param method Optional method input. Defaults to GET.
|
|
272
|
+
* @returns A canonical uppercase HTTP method.
|
|
273
|
+
* @throws {Error} When the method is unsupported.
|
|
274
|
+
*/
|
|
275
|
+
export function assertValidManualRestContractHttpMethod(method = "GET") {
|
|
276
|
+
const normalized = method.trim().toUpperCase();
|
|
277
|
+
if (MANUAL_REST_CONTRACT_HTTP_METHOD_IDS.includes(normalized)) {
|
|
278
|
+
return normalized;
|
|
279
|
+
}
|
|
280
|
+
throw new Error(`Manual REST contract method must be one of: ${MANUAL_REST_CONTRACT_HTTP_METHOD_IDS.join(", ")}.`);
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Normalize and validate the auth intent used by a manual REST contract.
|
|
284
|
+
*
|
|
285
|
+
* @param auth Optional auth intent input. Defaults to public.
|
|
286
|
+
* @returns A canonical auth intent.
|
|
287
|
+
* @throws {Error} When the auth intent is unsupported.
|
|
288
|
+
*/
|
|
289
|
+
export function assertValidManualRestContractAuth(auth = "public") {
|
|
290
|
+
const normalized = auth.trim().toLowerCase();
|
|
291
|
+
if (MANUAL_REST_CONTRACT_AUTH_IDS.includes(normalized)) {
|
|
292
|
+
return normalized;
|
|
293
|
+
}
|
|
294
|
+
throw new Error(`Manual REST contract auth must be one of: ${MANUAL_REST_CONTRACT_AUTH_IDS.join(", ")}.`);
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Normalize and validate a manual REST contract route path pattern.
|
|
298
|
+
*
|
|
299
|
+
* @param slug Generated contract slug used for the default route path.
|
|
300
|
+
* @param pathPattern Optional route path pattern, relative to the namespace.
|
|
301
|
+
* @returns A route pattern with a leading slash.
|
|
302
|
+
* @throws {Error} When the path pattern is empty or clearly not a route path.
|
|
303
|
+
*/
|
|
304
|
+
function resolveRestRoutePathPattern(options) {
|
|
305
|
+
const explicitPath = typeof options.pathPattern === "string" ? options.pathPattern.trim() : undefined;
|
|
306
|
+
if (explicitPath === "") {
|
|
307
|
+
throw new Error(options.emptyMessage);
|
|
308
|
+
}
|
|
309
|
+
const trimmed = explicitPath ?? options.defaultPath;
|
|
310
|
+
if (/^https?:\/\//iu.test(trimmed)) {
|
|
311
|
+
throw new Error(`${options.label} must be a route pattern relative to the namespace, not an absolute URL.`);
|
|
312
|
+
}
|
|
313
|
+
const withLeadingSlash = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
314
|
+
if (!withLeadingSlash || withLeadingSlash === "/") {
|
|
315
|
+
throw new Error(options.emptyMessage);
|
|
316
|
+
}
|
|
317
|
+
if (/\s/u.test(withLeadingSlash)) {
|
|
318
|
+
throw new Error(`${options.label} must not contain whitespace.`);
|
|
319
|
+
}
|
|
320
|
+
return withLeadingSlash;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Check whether a generated REST item route keeps the generated `id` contract aligned.
|
|
324
|
+
*
|
|
325
|
+
* @param routePattern Route pattern relative to the namespace.
|
|
326
|
+
* @returns True when the pattern has no regex groups or uses only `(?P<id>...)`.
|
|
327
|
+
*/
|
|
328
|
+
export function isGeneratedRestResourceRoutePatternCompatible(routePattern) {
|
|
329
|
+
const namedCaptures = Array.from(routePattern.matchAll(REST_ROUTE_NAMED_CAPTURE_PATTERN), (match) => match[1]);
|
|
330
|
+
const hasRegexGroup = routePattern.includes("(");
|
|
331
|
+
const hasUnsupportedCapture = REST_ROUTE_UNSUPPORTED_CAPTURE_PATTERN.test(routePattern);
|
|
332
|
+
return (!hasUnsupportedCapture &&
|
|
333
|
+
(!hasRegexGroup || (namedCaptures.length === 1 && namedCaptures[0] === "id")));
|
|
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
|
+
}
|
|
344
|
+
export function resolveManualRestContractPathPattern(slug, pathPattern) {
|
|
345
|
+
return resolveRestRoutePathPattern({
|
|
346
|
+
defaultPath: `/${slug}`,
|
|
347
|
+
emptyMessage: "Manual REST contract path is required. Use `--path <route-pattern>` such as `/external-record/(?P<id>[\\d]+)`.",
|
|
348
|
+
label: "Manual REST contract path",
|
|
349
|
+
pathPattern,
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Normalize and validate a generated REST resource item route pattern.
|
|
354
|
+
*
|
|
355
|
+
* @param slug Generated resource slug used for the default item route path.
|
|
356
|
+
* @param routePattern Optional route path pattern, relative to the namespace.
|
|
357
|
+
* @returns A route pattern with a leading slash.
|
|
358
|
+
* @throws {Error} When the route pattern is empty or clearly not a route path.
|
|
359
|
+
*/
|
|
360
|
+
export function resolveGeneratedRestResourceRoutePattern(slug, routePattern) {
|
|
361
|
+
const resolvedRoutePattern = resolveRestRoutePathPattern({
|
|
362
|
+
defaultPath: `/${slug}/item`,
|
|
363
|
+
emptyMessage: "Generated REST resource route pattern is required. Use `--route-pattern <route-pattern>` such as `/records/(?P<id>[\\d]+)`.",
|
|
364
|
+
label: "Generated REST resource route pattern",
|
|
365
|
+
pathPattern: routePattern,
|
|
366
|
+
});
|
|
367
|
+
const hasExplicitRoutePattern = typeof routePattern === "string" && routePattern.trim().length > 0;
|
|
368
|
+
if (hasExplicitRoutePattern &&
|
|
369
|
+
!isGeneratedRestResourceRoutePatternCompatible(resolvedRoutePattern)) {
|
|
370
|
+
throw new Error("Generated REST resource route pattern must use only an `(?P<id>...)` named capture when using regex groups.");
|
|
371
|
+
}
|
|
372
|
+
return resolvedRoutePattern;
|
|
373
|
+
}
|
|
76
374
|
/**
|
|
77
375
|
* Validate a hooked block insertion position.
|
|
78
376
|
*
|
|
@@ -145,3 +443,17 @@ export function assertValidEditorPluginSlot(slot = "sidebar") {
|
|
|
145
443
|
}
|
|
146
444
|
throw new Error(`Editor plugin slot must be one of: ${EDITOR_PLUGIN_SLOT_IDS.join(", ")}. Legacy aliases: PluginSidebar, PluginDocumentSettingPanel.`);
|
|
147
445
|
}
|
|
446
|
+
/**
|
|
447
|
+
* Validate and normalize the optional integration environment service starter.
|
|
448
|
+
*
|
|
449
|
+
* @param service Optional service starter id. Defaults to `none`.
|
|
450
|
+
* @returns The canonical integration environment service id.
|
|
451
|
+
* @throws {Error} When the service starter is unsupported.
|
|
452
|
+
*/
|
|
453
|
+
export function assertValidIntegrationEnvService(service = "none") {
|
|
454
|
+
const trimmed = service.trim();
|
|
455
|
+
if (INTEGRATION_ENV_SERVICE_IDS.includes(trimmed)) {
|
|
456
|
+
return trimmed;
|
|
457
|
+
}
|
|
458
|
+
throw new Error(`Integration environment service must be one of: ${INTEGRATION_ENV_SERVICE_IDS.join(", ")}.`);
|
|
459
|
+
}
|
|
@@ -4,6 +4,7 @@ import { syncTypeSchemas } from "@wp-typia/block-runtime/metadata-core";
|
|
|
4
4
|
import semver from "semver";
|
|
5
5
|
import { appendWorkspaceInventoryEntries, readWorkspaceInventoryAsync, } from "./workspace-inventory.js";
|
|
6
6
|
import { pathExists, readOptionalUtf8File } from "./fs-async.js";
|
|
7
|
+
import { readJsonFile } from "./json-utils.js";
|
|
7
8
|
import { buildAbilityClientSource, buildAbilityConfigEntry, buildAbilityConfigSource, buildAbilityDataSource, buildAbilityPhpSource, buildAbilityRegistrySource, buildAbilitySyncScriptSource, buildAbilityTypesSource, } from "./cli-add-workspace-ability-templates.js";
|
|
8
9
|
import { ABILITY_EDITOR_ASSET, ABILITY_EDITOR_SCRIPT, ABILITY_REGISTRY_END_MARKER, ABILITY_REGISTRY_START_MARKER, ABILITY_SERVER_GLOB, WP_ABILITIES_SCRIPT_MODULE_ID, WP_CORE_ABILITIES_SCRIPT_MODULE_ID, } from "./cli-add-workspace-ability-types.js";
|
|
9
10
|
import { getWorkspaceBootstrapPath, patchFile, } from "./cli-add-shared.js";
|
|
@@ -163,7 +164,9 @@ function ${enqueueFunctionName}() {
|
|
|
163
164
|
}
|
|
164
165
|
async function ensureAbilityPackageScripts(workspace) {
|
|
165
166
|
const packageJsonPath = path.join(workspace.projectDir, "package.json");
|
|
166
|
-
const packageJson =
|
|
167
|
+
const packageJson = await readJsonFile(packageJsonPath, {
|
|
168
|
+
context: "workspace package manifest",
|
|
169
|
+
});
|
|
167
170
|
const nextScripts = {
|
|
168
171
|
...(packageJson.scripts ?? {}),
|
|
169
172
|
"sync-abilities": packageJson.scripts?.["sync-abilities"] ?? "tsx scripts/sync-abilities.ts",
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { promises as fsp } from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { pathExists, readOptionalUtf8File } from './fs-async.js';
|
|
4
|
+
import { safeJsonParse } from './json-utils.js';
|
|
4
5
|
import { appendWorkspaceInventoryEntries, readWorkspaceInventoryAsync, } from './workspace-inventory.js';
|
|
5
|
-
import { buildAdminViewConfigEntry, buildAdminViewConfigSource, buildAdminViewEntrySource, buildAdminViewPhpSource, buildAdminViewRegistrySource, buildAdminViewScreenSource, buildAdminViewStyleSource, buildAdminViewTypesSource, buildCoreDataAdminViewDataSource, buildCoreDataAdminViewScreenSource, buildDefaultAdminViewDataSource, buildRestAdminViewDataSource, } from './cli-add-workspace-admin-view-templates.js';
|
|
6
|
-
import { ADMIN_VIEWS_PHP_GLOB, isAdminViewCoreDataSource, } from './cli-add-workspace-admin-view-types.js';
|
|
6
|
+
import { buildAdminViewConfigEntry, buildAdminViewConfigSource, buildAdminViewEntrySource, buildAdminViewPhpSource, buildAdminViewRegistrySource, buildAdminViewScreenSource, buildAdminViewStyleSource, buildAdminViewTypesSource, buildCoreDataAdminViewDataSource, buildCoreDataAdminViewScreenSource, buildDefaultAdminViewDataSource, buildRestAdminViewDataSource, buildRestSettingsAdminViewConfigSource, buildRestSettingsAdminViewDataSource, buildRestSettingsAdminViewScreenSource, buildRestSettingsAdminViewTypesSource, } from './cli-add-workspace-admin-view-templates.js';
|
|
7
|
+
import { ADMIN_VIEWS_PHP_GLOB, isAdminViewCoreDataSource, isAdminViewManualSettingsRestResource, } from './cli-add-workspace-admin-view-types.js';
|
|
8
|
+
import { buildManualRestContractApiSource } from './cli-add-workspace-rest-source-emitters.js';
|
|
7
9
|
import { getWorkspaceBootstrapPath, patchFile, } from './cli-add-shared.js';
|
|
8
10
|
import { appendPhpSnippetBeforeClosingTag, executeWorkspaceMutationPlan, insertPhpSnippetBeforeWorkspaceAnchors, } from './cli-add-workspace-mutation.js';
|
|
9
11
|
import { DEFAULT_WORDPRESS_CORE_DATA_VERSION, DEFAULT_WORDPRESS_DATA_VERSION, DEFAULT_WORDPRESS_DATAVIEWS_VERSION, DEFAULT_WP_TYPIA_DATAVIEWS_VERSION, resolveManagedPackageVersionRange, } from './package-versions.js';
|
|
@@ -12,7 +14,34 @@ function detectJsonIndent(source) {
|
|
|
12
14
|
const indentMatch = /\n([ \t]+)"/u.exec(source);
|
|
13
15
|
return indentMatch?.[1] ?? 2;
|
|
14
16
|
}
|
|
15
|
-
|
|
17
|
+
const LEGACY_MANUAL_REST_API_SOURCE_PATTERN = /^\s*export\s+\*\s+from\s+["']\.\/api-client["'];?\s*$/u;
|
|
18
|
+
const MANUAL_REST_API_DIRECT_CALL_EXPORT_PATTERN = /(?:^|\n)\s*export\s+(?:(?:async\s+)?function|const|let|var)\s+callManualRestContract\b/u;
|
|
19
|
+
const MANUAL_REST_API_NAMED_EXPORT_PATTERN = /(?:^|\n)\s*export\s*\{([^}]*)\}/gu;
|
|
20
|
+
function hasManualRestContractCallerExport(apiSource) {
|
|
21
|
+
if (MANUAL_REST_API_DIRECT_CALL_EXPORT_PATTERN.test(apiSource)) {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
return Array.from(apiSource.matchAll(MANUAL_REST_API_NAMED_EXPORT_PATTERN)).some((match) => match[1].split(',').some((specifier) => {
|
|
25
|
+
const [localName, exportedName] = specifier.trim().split(/\s+as\s+/u);
|
|
26
|
+
return (exportedName ?? localName)?.trim() === 'callManualRestContract';
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
async function ensureManualSettingsRestApiShim(workspace, restResource) {
|
|
30
|
+
const apiPath = path.join(workspace.projectDir, restResource.apiFile);
|
|
31
|
+
const apiSource = await fsp.readFile(apiPath, 'utf8');
|
|
32
|
+
if (hasManualRestContractCallerExport(apiSource)) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (!LEGACY_MANUAL_REST_API_SOURCE_PATTERN.test(apiSource)) {
|
|
36
|
+
throw new Error(`Manual REST resource source "${restResource.slug}" must export callManualRestContract from ${restResource.apiFile}. Restore the generated manual REST api.ts or update it before scaffolding a settings admin view.`);
|
|
37
|
+
}
|
|
38
|
+
await fsp.writeFile(apiPath, buildManualRestContractApiSource({
|
|
39
|
+
bodyTypeName: restResource.bodyTypeName,
|
|
40
|
+
queryTypeName: restResource.queryTypeName,
|
|
41
|
+
restResourceSlug: restResource.slug,
|
|
42
|
+
}), 'utf8');
|
|
43
|
+
}
|
|
44
|
+
async function ensureAdminViewPackageDependencies(workspace, adminViewSource, restResource) {
|
|
16
45
|
const packageJsonPath = path.join(workspace.projectDir, 'package.json');
|
|
17
46
|
const wpTypiaDataViewsVersion = resolveManagedPackageVersionRange({
|
|
18
47
|
fallback: DEFAULT_WP_TYPIA_DATAVIEWS_VERSION,
|
|
@@ -32,7 +61,11 @@ async function ensureAdminViewPackageDependencies(workspace, adminViewSource) {
|
|
|
32
61
|
packageName: '@wordpress/data',
|
|
33
62
|
});
|
|
34
63
|
await patchFile(packageJsonPath, (source) => {
|
|
35
|
-
const packageJson =
|
|
64
|
+
const packageJson = safeJsonParse(source, {
|
|
65
|
+
context: 'admin view package manifest',
|
|
66
|
+
filePath: packageJsonPath,
|
|
67
|
+
});
|
|
68
|
+
const needsDataViews = !isAdminViewManualSettingsRestResource(restResource);
|
|
36
69
|
const coreDataDependencies = isAdminViewCoreDataSource(adminViewSource)
|
|
37
70
|
? {
|
|
38
71
|
'@wordpress/core-data': packageJson.dependencies?.['@wordpress/core-data'] ??
|
|
@@ -43,14 +76,22 @@ async function ensureAdminViewPackageDependencies(workspace, adminViewSource) {
|
|
|
43
76
|
: {};
|
|
44
77
|
const nextDependencies = {
|
|
45
78
|
...(packageJson.dependencies ?? {}),
|
|
46
|
-
|
|
47
|
-
|
|
79
|
+
...(needsDataViews
|
|
80
|
+
? {
|
|
81
|
+
'@wordpress/dataviews': packageJson.dependencies?.['@wordpress/dataviews'] ??
|
|
82
|
+
wordpressDataViewsVersion,
|
|
83
|
+
}
|
|
84
|
+
: {}),
|
|
48
85
|
...coreDataDependencies,
|
|
49
86
|
};
|
|
50
87
|
const nextDevDependencies = {
|
|
51
88
|
...(packageJson.devDependencies ?? {}),
|
|
52
|
-
|
|
53
|
-
|
|
89
|
+
...(needsDataViews
|
|
90
|
+
? {
|
|
91
|
+
'@wp-typia/dataviews': packageJson.devDependencies?.['@wp-typia/dataviews'] ??
|
|
92
|
+
wpTypiaDataViewsVersion,
|
|
93
|
+
}
|
|
94
|
+
: {}),
|
|
54
95
|
};
|
|
55
96
|
if (JSON.stringify(nextDependencies) ===
|
|
56
97
|
JSON.stringify(packageJson.dependencies ?? {}) &&
|
|
@@ -193,6 +234,10 @@ export async function scaffoldAdminViewWorkspace(options) {
|
|
|
193
234
|
const webpackConfigPath = path.join(workspace.projectDir, 'webpack.config.js');
|
|
194
235
|
const adminViewsIndexPath = await resolveAdminViewRegistryPath(workspace.projectDir);
|
|
195
236
|
const adminViewDir = path.join(workspace.projectDir, 'src', 'admin-views', adminViewSlug);
|
|
237
|
+
const manualSettingsRestResource = isAdminViewManualSettingsRestResource(restResource) ? restResource : undefined;
|
|
238
|
+
const manualSettingsRestApiPath = manualSettingsRestResource
|
|
239
|
+
? path.join(workspace.projectDir, manualSettingsRestResource.apiFile)
|
|
240
|
+
: undefined;
|
|
196
241
|
const adminViewPhpPath = path.join(workspace.projectDir, 'inc', 'admin-views', `${adminViewSlug}.php`);
|
|
197
242
|
await executeWorkspaceMutationPlan({
|
|
198
243
|
filePaths: [
|
|
@@ -202,26 +247,40 @@ export async function scaffoldAdminViewWorkspace(options) {
|
|
|
202
247
|
buildScriptPath,
|
|
203
248
|
packageJsonPath,
|
|
204
249
|
webpackConfigPath,
|
|
250
|
+
...(manualSettingsRestApiPath ? [manualSettingsRestApiPath] : []),
|
|
205
251
|
],
|
|
206
252
|
targetPaths: [adminViewDir, adminViewPhpPath],
|
|
207
253
|
run: async () => {
|
|
208
254
|
await fsp.mkdir(adminViewDir, { recursive: true });
|
|
209
255
|
await fsp.mkdir(path.dirname(adminViewPhpPath), { recursive: true });
|
|
210
|
-
await ensureAdminViewPackageDependencies(workspace, parsedSource);
|
|
256
|
+
await ensureAdminViewPackageDependencies(workspace, parsedSource, restResource);
|
|
211
257
|
await ensureAdminViewBootstrapAnchors(workspace);
|
|
212
258
|
await ensureAdminViewBuildScriptAnchors(workspace);
|
|
213
259
|
await ensureAdminViewWebpackAnchors(workspace);
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
260
|
+
if (manualSettingsRestResource) {
|
|
261
|
+
await ensureManualSettingsRestApiShim(workspace, manualSettingsRestResource);
|
|
262
|
+
}
|
|
263
|
+
await fsp.writeFile(path.join(adminViewDir, 'types.ts'), manualSettingsRestResource
|
|
264
|
+
? buildRestSettingsAdminViewTypesSource(adminViewSlug, manualSettingsRestResource)
|
|
265
|
+
: buildAdminViewTypesSource(adminViewSlug, restResource, coreDataSource), 'utf8');
|
|
266
|
+
await fsp.writeFile(path.join(adminViewDir, 'config.ts'), manualSettingsRestResource
|
|
267
|
+
? buildRestSettingsAdminViewConfigSource(adminViewSlug, workspace.workspace.textDomain, manualSettingsRestResource)
|
|
268
|
+
: buildAdminViewConfigSource(adminViewSlug, workspace.workspace.textDomain, parsedSource, restResource), 'utf8');
|
|
269
|
+
await fsp.writeFile(path.join(adminViewDir, 'data.ts'), manualSettingsRestResource
|
|
270
|
+
? buildRestSettingsAdminViewDataSource(adminViewSlug, manualSettingsRestResource)
|
|
271
|
+
: coreDataSource
|
|
272
|
+
? buildCoreDataAdminViewDataSource(adminViewSlug, coreDataSource)
|
|
273
|
+
: restResource
|
|
274
|
+
? buildRestAdminViewDataSource(adminViewSlug, restResource)
|
|
275
|
+
: buildDefaultAdminViewDataSource(adminViewSlug), 'utf8');
|
|
276
|
+
await fsp.writeFile(path.join(adminViewDir, 'Screen.tsx'), manualSettingsRestResource
|
|
277
|
+
? buildRestSettingsAdminViewScreenSource(adminViewSlug, workspace.workspace.textDomain)
|
|
278
|
+
: coreDataSource
|
|
279
|
+
? buildCoreDataAdminViewScreenSource(adminViewSlug, workspace.workspace.textDomain)
|
|
280
|
+
: buildAdminViewScreenSource(adminViewSlug, workspace.workspace.textDomain), 'utf8');
|
|
281
|
+
await fsp.writeFile(path.join(adminViewDir, 'index.tsx'), buildAdminViewEntrySource(adminViewSlug, {
|
|
282
|
+
includeDataViewsStyle: !manualSettingsRestResource,
|
|
283
|
+
}), 'utf8');
|
|
225
284
|
await fsp.writeFile(path.join(adminViewDir, 'style.scss'), buildAdminViewStyleSource(), 'utf8');
|
|
226
285
|
await fsp.writeFile(adminViewPhpPath, buildAdminViewPhpSource(adminViewSlug, workspace), 'utf8');
|
|
227
286
|
await writeAdminViewRegistry(workspace.projectDir, adminViewSlug);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { assertValidGeneratedSlug } from './cli-add-shared.js';
|
|
2
|
-
import { ADMIN_VIEW_CORE_DATA_ENTITY_KIND_IDS, ADMIN_VIEW_CORE_DATA_ENTITY_NAME_PATTERN, ADMIN_VIEW_CORE_DATA_ENTITY_SEGMENT_PATTERN, ADMIN_VIEW_CORE_DATA_SOURCE_KIND, ADMIN_VIEW_REST_SOURCE_KIND, ADMIN_VIEW_SOURCE_USAGE, isAdminViewCoreDataSource, isAdminViewRestResourceSource, } from './cli-add-workspace-admin-view-types.js';
|
|
2
|
+
import { ADMIN_VIEW_CORE_DATA_ENTITY_KIND_IDS, ADMIN_VIEW_CORE_DATA_ENTITY_NAME_PATTERN, ADMIN_VIEW_CORE_DATA_ENTITY_SEGMENT_PATTERN, ADMIN_VIEW_CORE_DATA_SOURCE_KIND, ADMIN_VIEW_REST_SOURCE_KIND, ADMIN_VIEW_SOURCE_USAGE, hasAdminViewManualSettingsRouteParameters, isAdminViewCoreDataSource, isAdminViewManualSettingsRestResource, isAdminViewRestResourceSource, } from './cli-add-workspace-admin-view-types.js';
|
|
3
3
|
/**
|
|
4
4
|
* Assert that admin-view package dependencies are available before file writes.
|
|
5
5
|
*
|
|
@@ -75,8 +75,17 @@ export function resolveRestResourceSource(restResources, source) {
|
|
|
75
75
|
if (!restResource) {
|
|
76
76
|
throw new Error(`Unknown REST resource source "${source.slug}". Choose one of: ${restResources.map((entry) => entry.slug).join(', ') || '<none>'}.`);
|
|
77
77
|
}
|
|
78
|
+
if (isAdminViewManualSettingsRestResource(restResource)) {
|
|
79
|
+
if (hasAdminViewManualSettingsRouteParameters(restResource)) {
|
|
80
|
+
throw new Error(`REST resource source "${source.slug}" uses route parameters or regex groups and cannot scaffold a singleton admin settings form. Use a manual REST contract without path parameters or build a custom admin UI.`);
|
|
81
|
+
}
|
|
82
|
+
return restResource;
|
|
83
|
+
}
|
|
84
|
+
if (restResource.mode === 'manual') {
|
|
85
|
+
throw new Error(`REST resource source "${source.slug}" must define a request body type before it can scaffold an admin settings form.`);
|
|
86
|
+
}
|
|
78
87
|
if (!restResource.methods.includes('list')) {
|
|
79
|
-
throw new Error(`REST resource source "${source.slug}" must include the list method for DataViews pagination.`);
|
|
88
|
+
throw new Error(`REST resource source "${source.slug}" must include the list method for DataViews pagination or be a manual settings contract with a body type.`);
|
|
80
89
|
}
|
|
81
90
|
return restResource;
|
|
82
91
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type AdminViewCoreDataSource } from './cli-add-workspace-admin-view-types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Builds TypeScript item and dataset types for a core-data-backed admin view.
|
|
4
|
+
*
|
|
5
|
+
* @param adminViewSlug - Admin-view slug used to derive generated type names.
|
|
6
|
+
* @param coreDataSource - WordPress core-data entity source for the admin view.
|
|
7
|
+
* @returns Generated TypeScript source for core-data admin-view types.
|
|
8
|
+
*/
|
|
9
|
+
export declare function buildCoreDataAdminViewTypesSource(adminViewSlug: string, coreDataSource: AdminViewCoreDataSource): string;
|
|
10
|
+
/**
|
|
11
|
+
* Builds a DataViews config module for a core-data-backed admin view.
|
|
12
|
+
*
|
|
13
|
+
* @param adminViewSlug - Admin-view slug used to derive generated identifiers.
|
|
14
|
+
* @param textDomain - WordPress i18n text domain for generated labels.
|
|
15
|
+
* @param coreDataSource - WordPress core-data entity source for field selection.
|
|
16
|
+
* @returns Generated TypeScript source for the core-data DataViews config.
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildCoreDataAdminViewConfigSource(adminViewSlug: string, textDomain: string, coreDataSource: AdminViewCoreDataSource): string;
|
|
19
|
+
/**
|
|
20
|
+
* Builds data hooks for loading records from the WordPress core-data store.
|
|
21
|
+
*
|
|
22
|
+
* @param adminViewSlug - Admin-view slug used to derive generated identifiers.
|
|
23
|
+
* @param coreDataSource - WordPress core-data entity source for generated hooks.
|
|
24
|
+
* @returns Generated TypeScript source for core-data data access.
|
|
25
|
+
*/
|
|
26
|
+
export declare function buildCoreDataAdminViewDataSource(adminViewSlug: string, coreDataSource: AdminViewCoreDataSource): string;
|
|
27
|
+
/**
|
|
28
|
+
* Builds the React screen module for a core-data-backed admin view.
|
|
29
|
+
*
|
|
30
|
+
* @param adminViewSlug - Admin-view slug used to derive generated identifiers.
|
|
31
|
+
* @param textDomain - WordPress i18n text domain for generated labels.
|
|
32
|
+
* @returns Generated TSX source for the core-data admin-view screen.
|
|
33
|
+
*/
|
|
34
|
+
export declare function buildCoreDataAdminViewScreenSource(adminViewSlug: string, textDomain: string): string;
|