@wp-typia/project-tools 0.23.0 → 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-help.js +4 -3
- package/dist/runtime/cli-add-types.d.ts +18 -6
- 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-scaffold.js +4 -1
- package/dist/runtime/cli-add-workspace-admin-view-scaffold.js +5 -1
- 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.js +4 -1
- package/dist/runtime/cli-add-workspace-ai-source-emitters.js +17 -1
- package/dist/runtime/cli-add-workspace-integration-env.d.ts +3 -1
- package/dist/runtime/cli-add-workspace-integration-env.js +42 -5
- package/dist/runtime/cli-add-workspace-rest-anchors.d.ts +8 -0
- package/dist/runtime/cli-add-workspace-rest-anchors.js +41 -0
- 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 +8 -0
- package/dist/runtime/cli-add-workspace-rest-source-emitters.js +25 -4
- 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-core.d.ts +1 -1
- package/dist/runtime/cli-core.js +1 -1
- 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 +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 -487
- package/dist/runtime/cli-doctor.d.ts +52 -3
- package/dist/runtime/cli-doctor.js +79 -8
- package/dist/runtime/cli-help.js +6 -3
- 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 +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/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/workspace-inventory-mutations.js +2 -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 +435 -0
- package/dist/runtime/workspace-inventory-templates.d.ts +1 -1
- package/dist/runtime/workspace-inventory-templates.js +1 -0
- package/dist/runtime/workspace-inventory-types.d.ts +1 -0
- package/dist/runtime/workspace-project.js +4 -6
- package/package.json +2 -2
|
@@ -1,529 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { ensureRestResourceBootstrapAnchors, ensureRestResourceSyncScriptAnchors, } from "./cli-add-workspace-rest-anchors.js";
|
|
6
|
-
import { buildManualRestContractApiSource, buildManualRestContractConfigEntry, buildManualRestContractTypesSource, buildManualRestContractValidatorsSource, buildRestResourceApiSource, buildRestResourceConfigEntry, buildRestResourceDataSource, buildRestResourceTypesSource, buildRestResourceValidatorsSource, } from "./cli-add-workspace-rest-source-emitters.js";
|
|
7
|
-
import { quotePhpString } from "./php-utils.js";
|
|
8
|
-
import { syncManualRestContractArtifacts, syncRestResourceArtifacts, } from "./rest-resource-artifacts.js";
|
|
9
|
-
import { toPascalCase, toTitleCase } from "./string-case.js";
|
|
10
|
-
import { appendWorkspaceInventoryEntries, readWorkspaceInventoryAsync, } from "./workspace-inventory.js";
|
|
1
|
+
import { assertRestResourceDoesNotExist, assertValidGeneratedSlug, normalizeBlockSlug, resolveRestResourceNamespace, } from "./cli-add-shared.js";
|
|
2
|
+
import { scaffoldGeneratedRestResource } from "./cli-add-workspace-rest-generated.js";
|
|
3
|
+
import { scaffoldManualRestContract } from "./cli-add-workspace-rest-manual.js";
|
|
4
|
+
import { readWorkspaceInventoryAsync } from "./workspace-inventory.js";
|
|
11
5
|
import { resolveWorkspaceProject } from "./workspace-project.js";
|
|
12
|
-
const MANUAL_REST_REQUEST_BODY_FIELD_NAMES = new Set(["payload", "comment"]);
|
|
13
|
-
const MANUAL_REST_RESPONSE_FIELD_NAMES = new Set([
|
|
14
|
-
"id",
|
|
15
|
-
"status",
|
|
16
|
-
"message",
|
|
17
|
-
"updatedAt",
|
|
18
|
-
]);
|
|
19
|
-
function buildRestResourceRouteRegistrations(restResourceSlug, methods, functions, options) {
|
|
20
|
-
const collectionRoutes = [];
|
|
21
|
-
const itemRoutes = [];
|
|
22
|
-
const readPermissionCallback = options.permissionCallback
|
|
23
|
-
? quotePhpString(options.permissionCallback)
|
|
24
|
-
: quotePhpString("__return_true");
|
|
25
|
-
const writePermissionCallback = options.permissionCallback
|
|
26
|
-
? quotePhpString(options.permissionCallback)
|
|
27
|
-
: options.controllerVariableName
|
|
28
|
-
? `array( ${options.controllerVariableName}, 'can_manage_rest_resource' )`
|
|
29
|
-
: quotePhpString(functions.canWriteFunctionName);
|
|
30
|
-
const buildRouteCallback = (functionName, methodName) => options.controllerVariableName
|
|
31
|
-
? `array( ${options.controllerVariableName}, '${methodName}' )`
|
|
32
|
-
: quotePhpString(functionName);
|
|
33
|
-
if (methods.includes("list")) {
|
|
34
|
-
collectionRoutes.push(`\t\tarray(
|
|
35
|
-
\t\t\t'methods' => WP_REST_Server::READABLE,
|
|
36
|
-
\t\t\t'callback' => ${buildRouteCallback(functions.listHandlerName, "list_items")},
|
|
37
|
-
\t\t\t'permission_callback' => ${readPermissionCallback},
|
|
38
|
-
\t\t)`);
|
|
39
|
-
}
|
|
40
|
-
if (methods.includes("create")) {
|
|
41
|
-
collectionRoutes.push(`\t\tarray(
|
|
42
|
-
\t\t\t'methods' => WP_REST_Server::CREATABLE,
|
|
43
|
-
\t\t\t'callback' => ${buildRouteCallback(functions.createHandlerName, "create_item")},
|
|
44
|
-
\t\t\t'permission_callback' => ${writePermissionCallback},
|
|
45
|
-
\t\t)`);
|
|
46
|
-
}
|
|
47
|
-
if (methods.includes("read")) {
|
|
48
|
-
itemRoutes.push(`\t\tarray(
|
|
49
|
-
\t\t\t'methods' => WP_REST_Server::READABLE,
|
|
50
|
-
\t\t\t'callback' => ${buildRouteCallback(functions.readHandlerName, "read_item")},
|
|
51
|
-
\t\t\t'permission_callback' => ${readPermissionCallback},
|
|
52
|
-
\t\t)`);
|
|
53
|
-
}
|
|
54
|
-
if (methods.includes("update")) {
|
|
55
|
-
itemRoutes.push(`\t\tarray(
|
|
56
|
-
\t\t\t'methods' => WP_REST_Server::EDITABLE,
|
|
57
|
-
\t\t\t'callback' => ${buildRouteCallback(functions.updateHandlerName, "update_item")},
|
|
58
|
-
\t\t\t'permission_callback' => ${writePermissionCallback},
|
|
59
|
-
\t\t)`);
|
|
60
|
-
}
|
|
61
|
-
if (methods.includes("delete")) {
|
|
62
|
-
itemRoutes.push(`\t\tarray(
|
|
63
|
-
\t\t\t'methods' => WP_REST_Server::DELETABLE,
|
|
64
|
-
\t\t\t'callback' => ${buildRouteCallback(functions.deleteHandlerName, "delete_item")},
|
|
65
|
-
\t\t\t'permission_callback' => ${writePermissionCallback},
|
|
66
|
-
\t\t)`);
|
|
67
|
-
}
|
|
68
|
-
const registrations = [];
|
|
69
|
-
if (collectionRoutes.length > 0) {
|
|
70
|
-
registrations.push(`\tregister_rest_route(
|
|
71
|
-
\t\t$namespace,
|
|
72
|
-
\t\t'/${restResourceSlug}',
|
|
73
|
-
\t\tarray(
|
|
74
|
-
${collectionRoutes.join(",\n")}
|
|
75
|
-
\t\t)
|
|
76
|
-
\t);`);
|
|
77
|
-
}
|
|
78
|
-
if (itemRoutes.length > 0) {
|
|
79
|
-
registrations.push(`\tregister_rest_route(
|
|
80
|
-
\t\t$namespace,
|
|
81
|
-
\t\t${quotePhpString(options.routePattern)},
|
|
82
|
-
\t\tarray(
|
|
83
|
-
${itemRoutes.join(",\n")}
|
|
84
|
-
\t\t)
|
|
85
|
-
\t);`);
|
|
86
|
-
}
|
|
87
|
-
return registrations.join("\n\n");
|
|
88
|
-
}
|
|
89
|
-
function normalizeGlobalPhpClassName(classReference) {
|
|
90
|
-
const normalized = classReference.startsWith("\\")
|
|
91
|
-
? classReference.slice(1)
|
|
92
|
-
: classReference;
|
|
93
|
-
return /^[A-Za-z_][A-Za-z0-9_]*$/u.test(normalized) ? normalized : undefined;
|
|
94
|
-
}
|
|
95
|
-
function toPhpClassConstantReference(classReference) {
|
|
96
|
-
const normalized = classReference.startsWith("\\")
|
|
97
|
-
? classReference
|
|
98
|
-
: `\\${classReference}`;
|
|
99
|
-
return `${normalized}::class`;
|
|
100
|
-
}
|
|
101
|
-
function buildRestResourceControllerClassSource(options) {
|
|
102
|
-
const controllerClassName = normalizeGlobalPhpClassName(options.controllerClass);
|
|
103
|
-
if (!controllerClassName) {
|
|
104
|
-
return "";
|
|
105
|
-
}
|
|
106
|
-
const extendsClause = options.controllerExtends
|
|
107
|
-
? ` extends ${options.controllerExtends.startsWith("\\") ? options.controllerExtends : `\\${options.controllerExtends}`}`
|
|
108
|
-
: "";
|
|
109
|
-
return `
|
|
110
|
-
if ( ! class_exists( ${quotePhpString(controllerClassName)} ) ) {
|
|
111
|
-
\tclass ${controllerClassName}${extendsClause} {
|
|
112
|
-
\t\tpublic function can_manage_rest_resource() {
|
|
113
|
-
\t\t\treturn ${options.functions.canWriteFunctionName}();
|
|
114
|
-
\t\t}
|
|
115
|
-
|
|
116
|
-
\t\tpublic function list_items( WP_REST_Request $request ) {
|
|
117
|
-
\t\t\treturn ${options.functions.listHandlerName}( $request );
|
|
118
|
-
\t\t}
|
|
119
|
-
|
|
120
|
-
\t\tpublic function read_item( WP_REST_Request $request ) {
|
|
121
|
-
\t\t\treturn ${options.functions.readHandlerName}( $request );
|
|
122
|
-
\t\t}
|
|
123
|
-
|
|
124
|
-
\t\tpublic function create_item( WP_REST_Request $request ) {
|
|
125
|
-
\t\t\treturn ${options.functions.createHandlerName}( $request );
|
|
126
|
-
\t\t}
|
|
127
|
-
|
|
128
|
-
\t\tpublic function update_item( WP_REST_Request $request ) {
|
|
129
|
-
\t\t\treturn ${options.functions.updateHandlerName}( $request );
|
|
130
|
-
\t\t}
|
|
131
|
-
|
|
132
|
-
\t\tpublic function delete_item( WP_REST_Request $request ) {
|
|
133
|
-
\t\t\treturn ${options.functions.deleteHandlerName}( $request );
|
|
134
|
-
\t\t}
|
|
135
|
-
\t}
|
|
136
|
-
}
|
|
137
|
-
`;
|
|
138
|
-
}
|
|
139
|
-
function buildRestResourcePhpSource(restResourceSlug, namespace, phpPrefix, textDomain, methods, options) {
|
|
140
|
-
const restResourceTitle = toTitleCase(restResourceSlug);
|
|
141
|
-
const restResourcePhpId = restResourceSlug.replace(/-/g, "_");
|
|
142
|
-
const canWriteFunctionName = `${phpPrefix}_${restResourcePhpId}_can_manage_rest_resource`;
|
|
143
|
-
const getItemsFunctionName = `${phpPrefix}_${restResourcePhpId}_get_rest_resource_items`;
|
|
144
|
-
const loadSchemaFunctionName = `${phpPrefix}_${restResourcePhpId}_load_rest_resource_schema`;
|
|
145
|
-
const normalizeSchemaFunctionName = `${phpPrefix}_${restResourcePhpId}_sanitize_rest_resource_schema`;
|
|
146
|
-
const validatePayloadFunctionName = `${phpPrefix}_${restResourcePhpId}_validate_rest_resource_payload`;
|
|
147
|
-
const normalizeItemFunctionName = `${phpPrefix}_${restResourcePhpId}_normalize_rest_resource_item`;
|
|
148
|
-
const saveItemsFunctionName = `${phpPrefix}_${restResourcePhpId}_save_rest_resource_items`;
|
|
149
|
-
const getOptionNameFunctionName = `${phpPrefix}_${restResourcePhpId}_get_rest_resource_option_name`;
|
|
150
|
-
const listHandlerName = `${phpPrefix}_${restResourcePhpId}_handle_list_rest_resource`;
|
|
151
|
-
const readHandlerName = `${phpPrefix}_${restResourcePhpId}_handle_read_rest_resource`;
|
|
152
|
-
const createHandlerName = `${phpPrefix}_${restResourcePhpId}_handle_create_rest_resource`;
|
|
153
|
-
const updateHandlerName = `${phpPrefix}_${restResourcePhpId}_handle_update_rest_resource`;
|
|
154
|
-
const deleteHandlerName = `${phpPrefix}_${restResourcePhpId}_handle_delete_rest_resource`;
|
|
155
|
-
const registerRoutesFunctionName = `${phpPrefix}_${restResourcePhpId}_register_rest_routes`;
|
|
156
|
-
const controllerVariableName = options.controllerClass ? "$controller" : undefined;
|
|
157
|
-
const routeRegistrations = buildRestResourceRouteRegistrations(restResourceSlug, methods, {
|
|
158
|
-
canWriteFunctionName,
|
|
159
|
-
createHandlerName,
|
|
160
|
-
deleteHandlerName,
|
|
161
|
-
listHandlerName,
|
|
162
|
-
readHandlerName,
|
|
163
|
-
updateHandlerName,
|
|
164
|
-
}, {
|
|
165
|
-
...(controllerVariableName ? { controllerVariableName } : {}),
|
|
166
|
-
...(options.permissionCallback
|
|
167
|
-
? { permissionCallback: options.permissionCallback }
|
|
168
|
-
: {}),
|
|
169
|
-
routePattern: options.routePattern,
|
|
170
|
-
});
|
|
171
|
-
const controllerClassSource = options.controllerClass
|
|
172
|
-
? buildRestResourceControllerClassSource({
|
|
173
|
-
controllerClass: options.controllerClass,
|
|
174
|
-
...(options.controllerExtends
|
|
175
|
-
? { controllerExtends: options.controllerExtends }
|
|
176
|
-
: {}),
|
|
177
|
-
functions: {
|
|
178
|
-
canWriteFunctionName,
|
|
179
|
-
createHandlerName,
|
|
180
|
-
deleteHandlerName,
|
|
181
|
-
listHandlerName,
|
|
182
|
-
readHandlerName,
|
|
183
|
-
updateHandlerName,
|
|
184
|
-
},
|
|
185
|
-
})
|
|
186
|
-
: "";
|
|
187
|
-
const controllerBootstrapSource = options.controllerClass
|
|
188
|
-
? `\t\t$controller_class = ${toPhpClassConstantReference(options.controllerClass)};
|
|
189
|
-
\t\tif ( ! class_exists( $controller_class ) ) {
|
|
190
|
-
\t\t\treturn;
|
|
191
|
-
\t\t}
|
|
192
|
-
\t\t$controller = new $controller_class();
|
|
193
|
-
|
|
194
|
-
`
|
|
195
|
-
: "";
|
|
196
|
-
return `<?php
|
|
197
|
-
if ( ! defined( 'ABSPATH' ) ) {
|
|
198
|
-
\treturn;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
if ( ! function_exists( '${getOptionNameFunctionName}' ) ) {
|
|
202
|
-
\tfunction ${getOptionNameFunctionName}() {
|
|
203
|
-
\t\treturn ${quotePhpString(`${phpPrefix}_${restResourcePhpId}_rest_resource_items`)};
|
|
204
|
-
\t}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
if ( ! function_exists( '${normalizeItemFunctionName}' ) ) {
|
|
208
|
-
\tfunction ${normalizeItemFunctionName}( array $item ) {
|
|
209
|
-
\t\treturn array(
|
|
210
|
-
\t\t\t'id' => isset( $item['id'] ) ? (int) $item['id'] : 0,
|
|
211
|
-
\t\t\t'title' => isset( $item['title'] ) ? (string) $item['title'] : '',
|
|
212
|
-
\t\t\t'content' => isset( $item['content'] ) ? (string) $item['content'] : '',
|
|
213
|
-
\t\t\t'status' => isset( $item['status'] ) && 'published' === $item['status'] ? 'published' : 'draft',
|
|
214
|
-
\t\t\t'updatedAt' => isset( $item['updatedAt'] ) ? (string) $item['updatedAt'] : gmdate( 'c' ),
|
|
215
|
-
\t\t);
|
|
216
|
-
\t}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
if ( ! function_exists( '${getItemsFunctionName}' ) ) {
|
|
220
|
-
\tfunction ${getItemsFunctionName}() {
|
|
221
|
-
\t\t$seed_items = array(
|
|
222
|
-
\t\t\tarray(
|
|
223
|
-
\t\t\t\t'id' => 1,
|
|
224
|
-
\t\t\t\t'title' => ${quotePhpString(`${restResourceTitle} Starter`)},
|
|
225
|
-
\t\t\t\t'content' => ${quotePhpString(`Replace this seeded ${restResourceTitle.toLowerCase()} content with your plugin data source.`)},
|
|
226
|
-
\t\t\t\t'status' => 'draft',
|
|
227
|
-
\t\t\t\t'updatedAt' => '2026-01-01T00:00:00Z',
|
|
228
|
-
\t\t\t),
|
|
229
|
-
\t\t);
|
|
230
|
-
\t\t$items = get_option( ${getOptionNameFunctionName}(), $seed_items );
|
|
231
|
-
|
|
232
|
-
\t\tif ( ! is_array( $items ) ) {
|
|
233
|
-
\t\t\t$items = $seed_items;
|
|
234
|
-
\t\t}
|
|
235
|
-
|
|
236
|
-
\t\treturn array_values(
|
|
237
|
-
\t\t\tarray_map(
|
|
238
|
-
\t\t\t\t'${normalizeItemFunctionName}',
|
|
239
|
-
\t\t\t\tarray_filter(
|
|
240
|
-
\t\t\t\t\t$items,
|
|
241
|
-
\t\t\t\t\t'is_array'
|
|
242
|
-
\t\t\t\t)
|
|
243
|
-
\t\t\t)
|
|
244
|
-
\t\t);
|
|
245
|
-
\t}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
if ( ! function_exists( '${saveItemsFunctionName}' ) ) {
|
|
249
|
-
\tfunction ${saveItemsFunctionName}( array $items ) {
|
|
250
|
-
\t\tupdate_option(
|
|
251
|
-
\t\t\t${getOptionNameFunctionName}(),
|
|
252
|
-
\t\t\tarray_values(
|
|
253
|
-
\t\t\t\tarray_map(
|
|
254
|
-
\t\t\t\t\t'${normalizeItemFunctionName}',
|
|
255
|
-
\t\t\t\t\t$items
|
|
256
|
-
\t\t\t\t)
|
|
257
|
-
\t\t\t),
|
|
258
|
-
\t\t\tfalse
|
|
259
|
-
\t\t);
|
|
260
|
-
\t}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
if ( ! function_exists( '${loadSchemaFunctionName}' ) ) {
|
|
264
|
-
\tfunction ${loadSchemaFunctionName}( $schema_name ) {
|
|
265
|
-
\t\t$project_root = dirname( __DIR__, 2 );
|
|
266
|
-
\t\t$schema_path = $project_root . '/src/rest/${restResourceSlug}/api-schemas/' . $schema_name . '.schema.json';
|
|
267
|
-
\t\tif ( ! file_exists( $schema_path ) ) {
|
|
268
|
-
\t\t\treturn null;
|
|
269
|
-
\t\t}
|
|
270
|
-
|
|
271
|
-
\t\t$decoded = json_decode( file_get_contents( $schema_path ), true );
|
|
272
|
-
\t\treturn is_array( $decoded ) ? $decoded : null;
|
|
273
|
-
\t}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
if ( ! function_exists( '${normalizeSchemaFunctionName}' ) ) {
|
|
277
|
-
\tfunction ${normalizeSchemaFunctionName}( $schema ) {
|
|
278
|
-
\t\tif ( ! is_array( $schema ) ) {
|
|
279
|
-
\t\t\treturn $schema;
|
|
280
|
-
\t\t}
|
|
281
|
-
|
|
282
|
-
\t\tunset( $schema['$schema'], $schema['title'] );
|
|
283
|
-
|
|
284
|
-
\t\tif ( isset( $schema['properties'] ) && is_array( $schema['properties'] ) ) {
|
|
285
|
-
\t\t\tforeach ( $schema['properties'] as $key => $property_schema ) {
|
|
286
|
-
\t\t\t\t$schema['properties'][ $key ] = ${normalizeSchemaFunctionName}( $property_schema );
|
|
287
|
-
\t\t\t}
|
|
288
|
-
\t\t}
|
|
289
|
-
|
|
290
|
-
\t\tif ( isset( $schema['items'] ) && is_array( $schema['items'] ) ) {
|
|
291
|
-
\t\t\t$schema['items'] = ${normalizeSchemaFunctionName}( $schema['items'] );
|
|
292
|
-
\t\t}
|
|
293
|
-
|
|
294
|
-
\t\treturn $schema;
|
|
295
|
-
\t}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
if ( ! function_exists( '${validatePayloadFunctionName}' ) ) {
|
|
299
|
-
\tfunction ${validatePayloadFunctionName}( $value, $schema_name, $param_name ) {
|
|
300
|
-
\t\t$schema = ${loadSchemaFunctionName}( $schema_name );
|
|
301
|
-
\t\tif ( ! is_array( $schema ) ) {
|
|
302
|
-
\t\t\treturn new WP_Error( 'missing_schema', 'Missing REST schema.', array( 'status' => 500 ) );
|
|
303
|
-
\t\t}
|
|
304
|
-
|
|
305
|
-
\t\t$rest_schema = ${normalizeSchemaFunctionName}( $schema );
|
|
306
|
-
\t\t$validation = rest_validate_value_from_schema( $value, $rest_schema, $param_name );
|
|
307
|
-
\t\tif ( is_wp_error( $validation ) ) {
|
|
308
|
-
\t\t\treturn $validation;
|
|
309
|
-
\t\t}
|
|
310
|
-
|
|
311
|
-
\t\treturn rest_sanitize_value_from_schema( $value, $rest_schema, $param_name );
|
|
312
|
-
\t}
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
if ( ! function_exists( '${canWriteFunctionName}' ) ) {
|
|
316
|
-
\tfunction ${canWriteFunctionName}() {
|
|
317
|
-
\t\treturn current_user_can( 'edit_posts' );
|
|
318
|
-
\t}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
if ( ! function_exists( '${listHandlerName}' ) ) {
|
|
322
|
-
\tfunction ${listHandlerName}( WP_REST_Request $request ) {
|
|
323
|
-
\t\t$payload_input = array();
|
|
324
|
-
\t\t$page = $request->get_param( 'page' );
|
|
325
|
-
\t\t$per_page = $request->get_param( 'perPage' );
|
|
326
|
-
\t\t$search = $request->get_param( 'search' );
|
|
327
|
-
|
|
328
|
-
\t\tif ( null !== $page ) {
|
|
329
|
-
\t\t\t$payload_input['page'] = $page;
|
|
330
|
-
\t\t}
|
|
331
|
-
\t\tif ( null !== $per_page ) {
|
|
332
|
-
\t\t\t$payload_input['perPage'] = $per_page;
|
|
333
|
-
\t\t}
|
|
334
|
-
\t\tif ( null !== $search ) {
|
|
335
|
-
\t\t\t$payload_input['search'] = $search;
|
|
336
|
-
\t\t}
|
|
337
|
-
|
|
338
|
-
\t\t$payload = ${validatePayloadFunctionName}(
|
|
339
|
-
\t\t\t$payload_input,
|
|
340
|
-
\t\t\t'list-query',
|
|
341
|
-
\t\t\t'query'
|
|
342
|
-
\t\t);
|
|
343
|
-
|
|
344
|
-
\t\tif ( is_wp_error( $payload ) ) {
|
|
345
|
-
\t\t\treturn $payload;
|
|
346
|
-
\t\t}
|
|
347
|
-
|
|
348
|
-
\t\t$page = isset( $payload['page'] ) ? max( 1, (int) $payload['page'] ) : 1;
|
|
349
|
-
\t\t$per_page = isset( $payload['perPage'] ) ? min( 50, max( 1, (int) $payload['perPage'] ) ) : 10;
|
|
350
|
-
\t\t$search = isset( $payload['search'] ) ? strtolower( (string) $payload['search'] ) : '';
|
|
351
|
-
\t\t$items = ${getItemsFunctionName}();
|
|
352
|
-
|
|
353
|
-
\t\tif ( '' !== $search ) {
|
|
354
|
-
\t\t\t$items = array_values(
|
|
355
|
-
\t\t\t\tarray_filter(
|
|
356
|
-
\t\t\t\t\t$items,
|
|
357
|
-
\t\t\t\t\tstatic function ( $item ) use ( $search ) {
|
|
358
|
-
\t\t\t\t\t\treturn false !== strpos( strtolower( (string) ( $item['title'] ?? '' ) ), $search ) ||
|
|
359
|
-
\t\t\t\t\t\t\tfalse !== strpos( strtolower( (string) ( $item['content'] ?? '' ) ), $search );
|
|
360
|
-
\t\t\t\t\t}
|
|
361
|
-
\t\t\t\t)
|
|
362
|
-
\t\t\t);
|
|
363
|
-
\t\t}
|
|
364
|
-
|
|
365
|
-
\t\t$total = count( $items );
|
|
366
|
-
\t\t$items = array_slice( $items, ( $page - 1 ) * $per_page, $per_page );
|
|
367
|
-
|
|
368
|
-
\t\treturn rest_ensure_response(
|
|
369
|
-
\t\t\tarray(
|
|
370
|
-
\t\t\t\t'items' => $items,
|
|
371
|
-
\t\t\t\t'page' => $page,
|
|
372
|
-
\t\t\t\t'perPage' => $per_page,
|
|
373
|
-
\t\t\t\t'total' => $total,
|
|
374
|
-
\t\t\t)
|
|
375
|
-
\t\t);
|
|
376
|
-
\t}
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
if ( ! function_exists( '${readHandlerName}' ) ) {
|
|
380
|
-
\tfunction ${readHandlerName}( WP_REST_Request $request ) {
|
|
381
|
-
\t\t$payload = ${validatePayloadFunctionName}(
|
|
382
|
-
\t\t\tarray(
|
|
383
|
-
\t\t\t\t'id' => $request->get_param( 'id' ),
|
|
384
|
-
\t\t\t),
|
|
385
|
-
\t\t\t'read-query',
|
|
386
|
-
\t\t\t'query'
|
|
387
|
-
\t\t);
|
|
388
|
-
|
|
389
|
-
\t\tif ( is_wp_error( $payload ) ) {
|
|
390
|
-
\t\t\treturn $payload;
|
|
391
|
-
\t\t}
|
|
392
|
-
|
|
393
|
-
\t\tforeach ( ${getItemsFunctionName}() as $item ) {
|
|
394
|
-
\t\t\tif ( (int) $item['id'] === (int) $payload['id'] ) {
|
|
395
|
-
\t\t\t\treturn rest_ensure_response( $item );
|
|
396
|
-
\t\t\t}
|
|
397
|
-
\t\t}
|
|
398
|
-
|
|
399
|
-
\t\treturn new WP_Error( 'rest_not_found', 'Resource not found.', array( 'status' => 404 ) );
|
|
400
|
-
\t}
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
if ( ! function_exists( '${createHandlerName}' ) ) {
|
|
404
|
-
\tfunction ${createHandlerName}( WP_REST_Request $request ) {
|
|
405
|
-
\t\t$payload = ${validatePayloadFunctionName}( $request->get_json_params(), 'create-request', 'body' );
|
|
406
|
-
\t\tif ( is_wp_error( $payload ) ) {
|
|
407
|
-
\t\t\treturn $payload;
|
|
408
|
-
\t\t}
|
|
409
|
-
|
|
410
|
-
\t\t$items = ${getItemsFunctionName}();
|
|
411
|
-
\t\t$next_id = 1;
|
|
412
|
-
\t\tforeach ( $items as $item ) {
|
|
413
|
-
\t\t\t$next_id = max( $next_id, (int) $item['id'] + 1 );
|
|
414
|
-
\t\t}
|
|
415
|
-
|
|
416
|
-
\t\t$record = ${normalizeItemFunctionName}(
|
|
417
|
-
\t\t\tarray(
|
|
418
|
-
\t\t\t\t'id' => $next_id,
|
|
419
|
-
\t\t\t\t'title' => (string) $payload['title'],
|
|
420
|
-
\t\t\t\t'content' => isset( $payload['content'] ) ? (string) $payload['content'] : '',
|
|
421
|
-
\t\t\t\t'status' => isset( $payload['status'] ) ? (string) $payload['status'] : 'draft',
|
|
422
|
-
\t\t\t\t'updatedAt' => gmdate( 'c' ),
|
|
423
|
-
\t\t\t)
|
|
424
|
-
\t\t);
|
|
425
|
-
|
|
426
|
-
\t\t$items[] = $record;
|
|
427
|
-
\t\t${saveItemsFunctionName}( $items );
|
|
428
|
-
|
|
429
|
-
\t\treturn rest_ensure_response( $record );
|
|
430
|
-
\t}
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
if ( ! function_exists( '${updateHandlerName}' ) ) {
|
|
434
|
-
\tfunction ${updateHandlerName}( WP_REST_Request $request ) {
|
|
435
|
-
\t\t$query = ${validatePayloadFunctionName}(
|
|
436
|
-
\t\t\tarray(
|
|
437
|
-
\t\t\t\t'id' => $request->get_param( 'id' ),
|
|
438
|
-
\t\t\t),
|
|
439
|
-
\t\t\t'update-query',
|
|
440
|
-
\t\t\t'query'
|
|
441
|
-
\t\t);
|
|
442
|
-
\t\tif ( is_wp_error( $query ) ) {
|
|
443
|
-
\t\t\treturn $query;
|
|
444
|
-
\t\t}
|
|
445
|
-
|
|
446
|
-
\t\t$payload = ${validatePayloadFunctionName}( $request->get_json_params(), 'update-request', 'body' );
|
|
447
|
-
\t\tif ( is_wp_error( $payload ) ) {
|
|
448
|
-
\t\t\treturn $payload;
|
|
449
|
-
\t\t}
|
|
450
|
-
|
|
451
|
-
\t\t$items = ${getItemsFunctionName}();
|
|
452
|
-
\t\tforeach ( $items as $index => $item ) {
|
|
453
|
-
\t\t\tif ( (int) $item['id'] !== (int) $query['id'] ) {
|
|
454
|
-
\t\t\t\tcontinue;
|
|
455
|
-
\t\t\t}
|
|
456
|
-
|
|
457
|
-
\t\t\t$items[ $index ] = ${normalizeItemFunctionName}(
|
|
458
|
-
\t\t\t\tarray(
|
|
459
|
-
\t\t\t\t\t'id' => $item['id'],
|
|
460
|
-
\t\t\t\t\t'title' => isset( $payload['title'] ) ? (string) $payload['title'] : (string) $item['title'],
|
|
461
|
-
\t\t\t\t\t'content' => array_key_exists( 'content', $payload ) ? (string) $payload['content'] : (string) $item['content'],
|
|
462
|
-
\t\t\t\t\t'status' => isset( $payload['status'] ) ? (string) $payload['status'] : (string) $item['status'],
|
|
463
|
-
\t\t\t\t\t'updatedAt' => gmdate( 'c' ),
|
|
464
|
-
\t\t\t\t)
|
|
465
|
-
\t\t\t);
|
|
466
|
-
|
|
467
|
-
\t\t\t${saveItemsFunctionName}( $items );
|
|
468
|
-
\t\t\treturn rest_ensure_response( $items[ $index ] );
|
|
469
|
-
\t\t}
|
|
470
|
-
|
|
471
|
-
\t\treturn new WP_Error( 'rest_not_found', 'Resource not found.', array( 'status' => 404 ) );
|
|
472
|
-
\t}
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
if ( ! function_exists( '${deleteHandlerName}' ) ) {
|
|
476
|
-
\tfunction ${deleteHandlerName}( WP_REST_Request $request ) {
|
|
477
|
-
\t\t$query = ${validatePayloadFunctionName}(
|
|
478
|
-
\t\t\tarray(
|
|
479
|
-
\t\t\t\t'id' => $request->get_param( 'id' ),
|
|
480
|
-
\t\t\t),
|
|
481
|
-
\t\t\t'delete-query',
|
|
482
|
-
\t\t\t'query'
|
|
483
|
-
\t\t);
|
|
484
|
-
\t\tif ( is_wp_error( $query ) ) {
|
|
485
|
-
\t\t\treturn $query;
|
|
486
|
-
\t\t}
|
|
487
|
-
|
|
488
|
-
\t\t$items = ${getItemsFunctionName}();
|
|
489
|
-
\t\t$filtered = array_values(
|
|
490
|
-
\t\t\tarray_filter(
|
|
491
|
-
\t\t\t\t$items,
|
|
492
|
-
\t\t\t\tstatic function ( $item ) use ( $query ) {
|
|
493
|
-
\t\t\t\t\treturn (int) $item['id'] !== (int) $query['id'];
|
|
494
|
-
\t\t\t\t}
|
|
495
|
-
\t\t\t)
|
|
496
|
-
\t\t);
|
|
497
|
-
\t\t$was_deleted = count( $filtered ) !== count( $items );
|
|
498
|
-
|
|
499
|
-
\t\tif ( ! $was_deleted ) {
|
|
500
|
-
\t\t\treturn new WP_Error( 'rest_not_found', 'Resource not found.', array( 'status' => 404 ) );
|
|
501
|
-
\t\t}
|
|
502
|
-
|
|
503
|
-
\t\t${saveItemsFunctionName}( $filtered );
|
|
504
|
-
|
|
505
|
-
\t\treturn rest_ensure_response(
|
|
506
|
-
\t\t\tarray(
|
|
507
|
-
\t\t\t\t'deleted' => true,
|
|
508
|
-
\t\t\t\t'id' => (int) $query['id'],
|
|
509
|
-
\t\t\t)
|
|
510
|
-
\t\t);
|
|
511
|
-
\t}
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
${controllerClassSource}
|
|
515
|
-
if ( ! function_exists( '${registerRoutesFunctionName}' ) ) {
|
|
516
|
-
\tfunction ${registerRoutesFunctionName}() {
|
|
517
|
-
\t\t$namespace = ${quotePhpString(namespace)};
|
|
518
|
-
|
|
519
|
-
${controllerBootstrapSource}
|
|
520
|
-
${routeRegistrations}
|
|
521
|
-
\t}
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
add_action( 'rest_api_init', '${registerRoutesFunctionName}' );
|
|
525
|
-
`;
|
|
526
|
-
}
|
|
527
6
|
/**
|
|
528
7
|
* Scaffold a workspace-level REST resource and synchronize its generated
|
|
529
8
|
* TypeScript and PHP artifacts.
|
|
@@ -531,276 +10,42 @@ add_action( 'rest_api_init', '${registerRoutesFunctionName}' );
|
|
|
531
10
|
* @param options Command options for the REST resource scaffold workflow.
|
|
532
11
|
* @returns Resolved scaffold metadata for the created REST resource.
|
|
533
12
|
*/
|
|
534
|
-
export async function runAddRestResourceCommand({ auth, bodyTypeName, controllerClass, controllerExtends, cwd = process.cwd(), manual, method, methods, namespace, permissionCallback, pathPattern, queryTypeName, restResourceName, responseTypeName, routePattern, secretFieldName, secretStateFieldName, }) {
|
|
13
|
+
export async function runAddRestResourceCommand({ auth, bodyTypeName, controllerClass, controllerExtends, cwd = process.cwd(), manual, method, methods, namespace, permissionCallback, pathPattern, queryTypeName, restResourceName, responseTypeName, routePattern, secretFieldName, secretHasValueFieldName, secretMaskedResponseFieldName, secretPreserveOnEmpty, secretStateFieldName, }) {
|
|
535
14
|
const workspace = resolveWorkspaceProject(cwd);
|
|
536
15
|
const restResourceSlug = assertValidGeneratedSlug("REST resource name", normalizeBlockSlug(restResourceName), "wp-typia add rest-resource <name> [--namespace <vendor/v1>] [--methods <list,read,create>]");
|
|
537
16
|
const resolvedNamespace = resolveRestResourceNamespace(workspace.workspace.namespace, namespace);
|
|
538
17
|
const inventory = await readWorkspaceInventoryAsync(workspace.projectDir);
|
|
539
18
|
assertRestResourceDoesNotExist(workspace.projectDir, restResourceSlug, inventory);
|
|
540
|
-
const blockConfigPath = path.join(workspace.projectDir, "scripts", "block-config.ts");
|
|
541
|
-
const syncRestScriptPath = path.join(workspace.projectDir, "scripts", "sync-rest-contracts.ts");
|
|
542
|
-
const restResourceDir = path.join(workspace.projectDir, "src", "rest", restResourceSlug);
|
|
543
|
-
const typesFilePath = path.join(restResourceDir, "api-types.ts");
|
|
544
|
-
const validatorsFilePath = path.join(restResourceDir, "api-validators.ts");
|
|
545
|
-
const apiFilePath = path.join(restResourceDir, "api.ts");
|
|
546
19
|
if (manual) {
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
const resolvedPathPattern = resolveManualRestContractPathPattern(restResourceSlug, pathPattern);
|
|
554
|
-
const resolvedQueryTypeName = assertValidTypeScriptIdentifier("Manual REST contract query type", queryTypeName ?? `${pascalCase}Query`, "wp-typia add rest-resource <name> --manual [--query-type <ExportedQueryType>]");
|
|
555
|
-
const resolvedResponseTypeName = assertValidTypeScriptIdentifier("Manual REST contract response type", responseTypeName ?? `${pascalCase}Response`, "wp-typia add rest-resource <name> --manual [--response-type <ExportedResponseType>]");
|
|
556
|
-
const defaultsToBody = bodyTypeName == null && ["PATCH", "POST", "PUT"].includes(resolvedMethod);
|
|
557
|
-
const resolvedBodyTypeName = bodyTypeName != null || defaultsToBody
|
|
558
|
-
? assertValidTypeScriptIdentifier("Manual REST contract body type", bodyTypeName ?? `${pascalCase}Request`, "wp-typia add rest-resource <name> --manual [--body-type <ExportedBodyType>]")
|
|
559
|
-
: undefined;
|
|
560
|
-
if (resolvedMethod === "GET" && resolvedBodyTypeName) {
|
|
561
|
-
throw new Error("Manual REST contract GET routes cannot define a body type. Remove --body-type or use POST, PUT, or PATCH.");
|
|
562
|
-
}
|
|
563
|
-
if (secretStateFieldName && !secretFieldName) {
|
|
564
|
-
throw new Error("Manual REST contract --secret-state-field requires --secret-field.");
|
|
565
|
-
}
|
|
566
|
-
if (secretFieldName && !resolvedBodyTypeName) {
|
|
567
|
-
throw new Error("Manual REST contract secret fields require a request body. Use POST, PUT, or PATCH so a request body is generated.");
|
|
568
|
-
}
|
|
569
|
-
const resolvedSecretFieldName = secretFieldName
|
|
570
|
-
? assertValidTypeScriptIdentifier("Manual REST contract secret field", secretFieldName, "wp-typia add rest-resource <name> --manual --method POST --secret-field <field>")
|
|
571
|
-
: undefined;
|
|
572
|
-
const resolvedSecretStateFieldName = resolvedSecretFieldName
|
|
573
|
-
? assertValidTypeScriptIdentifier("Manual REST contract secret state field", secretStateFieldName ?? `has${toPascalCase(resolvedSecretFieldName)}`, "wp-typia add rest-resource <name> --manual --method POST --secret-state-field <field>")
|
|
574
|
-
: undefined;
|
|
575
|
-
if (resolvedSecretFieldName &&
|
|
576
|
-
MANUAL_REST_REQUEST_BODY_FIELD_NAMES.has(resolvedSecretFieldName)) {
|
|
577
|
-
throw new Error(`Manual REST contract secret field must not reuse scaffolded request body fields: ${Array.from(MANUAL_REST_REQUEST_BODY_FIELD_NAMES).join(", ")}.`);
|
|
578
|
-
}
|
|
579
|
-
if (resolvedSecretStateFieldName &&
|
|
580
|
-
MANUAL_REST_RESPONSE_FIELD_NAMES.has(resolvedSecretStateFieldName)) {
|
|
581
|
-
throw new Error(`Manual REST contract secret state field must not reuse scaffolded response fields: ${Array.from(MANUAL_REST_RESPONSE_FIELD_NAMES).join(", ")}.`);
|
|
582
|
-
}
|
|
583
|
-
if (resolvedSecretFieldName &&
|
|
584
|
-
resolvedSecretStateFieldName &&
|
|
585
|
-
resolvedSecretFieldName === resolvedSecretStateFieldName) {
|
|
586
|
-
throw new Error("Manual REST contract secret state field must be different from the raw secret field.");
|
|
587
|
-
}
|
|
588
|
-
const manualTypeNames = [
|
|
589
|
-
resolvedQueryTypeName,
|
|
590
|
-
resolvedResponseTypeName,
|
|
591
|
-
resolvedBodyTypeName,
|
|
592
|
-
].filter((value) => value != null);
|
|
593
|
-
const duplicateManualTypeNames = manualTypeNames.filter((name, index) => manualTypeNames.indexOf(name) !== index);
|
|
594
|
-
if (duplicateManualTypeNames.length > 0) {
|
|
595
|
-
throw new Error(`Manual REST contract type names must be unique: ${Array.from(new Set(duplicateManualTypeNames)).join(", ")}. Use distinct --query-type, --body-type, and --response-type values.`);
|
|
596
|
-
}
|
|
597
|
-
const mutationSnapshot = {
|
|
598
|
-
fileSources: await snapshotWorkspaceFiles([
|
|
599
|
-
blockConfigPath,
|
|
600
|
-
syncRestScriptPath,
|
|
601
|
-
]),
|
|
602
|
-
snapshotDirs: [],
|
|
603
|
-
targetPaths: [restResourceDir],
|
|
604
|
-
};
|
|
605
|
-
try {
|
|
606
|
-
await fsp.mkdir(restResourceDir, { recursive: true });
|
|
607
|
-
await ensureRestResourceSyncScriptAnchors(workspace);
|
|
608
|
-
await fsp.writeFile(typesFilePath, buildManualRestContractTypesSource({
|
|
609
|
-
...(resolvedBodyTypeName
|
|
610
|
-
? { bodyTypeName: resolvedBodyTypeName }
|
|
611
|
-
: {}),
|
|
612
|
-
queryTypeName: resolvedQueryTypeName,
|
|
613
|
-
responseTypeName: resolvedResponseTypeName,
|
|
614
|
-
restResourceSlug,
|
|
615
|
-
...(resolvedSecretFieldName
|
|
616
|
-
? { secretFieldName: resolvedSecretFieldName }
|
|
617
|
-
: {}),
|
|
618
|
-
...(resolvedSecretStateFieldName
|
|
619
|
-
? { secretStateFieldName: resolvedSecretStateFieldName }
|
|
620
|
-
: {}),
|
|
621
|
-
}), "utf8");
|
|
622
|
-
await fsp.writeFile(validatorsFilePath, buildManualRestContractValidatorsSource({
|
|
623
|
-
...(resolvedBodyTypeName
|
|
624
|
-
? { bodyTypeName: resolvedBodyTypeName }
|
|
625
|
-
: {}),
|
|
626
|
-
queryTypeName: resolvedQueryTypeName,
|
|
627
|
-
responseTypeName: resolvedResponseTypeName,
|
|
628
|
-
}), "utf8");
|
|
629
|
-
await fsp.writeFile(apiFilePath, buildManualRestContractApiSource({
|
|
630
|
-
...(resolvedBodyTypeName
|
|
631
|
-
? { bodyTypeName: resolvedBodyTypeName }
|
|
632
|
-
: {}),
|
|
633
|
-
queryTypeName: resolvedQueryTypeName,
|
|
634
|
-
restResourceSlug,
|
|
635
|
-
}), "utf8");
|
|
636
|
-
await syncManualRestContractArtifacts({
|
|
637
|
-
clientFile: `src/rest/${restResourceSlug}/api-client.ts`,
|
|
638
|
-
outputDir: restResourceDir,
|
|
639
|
-
projectDir: workspace.projectDir,
|
|
640
|
-
typesFile: `src/rest/${restResourceSlug}/api-types.ts`,
|
|
641
|
-
validatorsFile: `src/rest/${restResourceSlug}/api-validators.ts`,
|
|
642
|
-
variables: {
|
|
643
|
-
auth: resolvedAuth,
|
|
644
|
-
...(resolvedBodyTypeName
|
|
645
|
-
? { bodyTypeName: resolvedBodyTypeName }
|
|
646
|
-
: {}),
|
|
647
|
-
method: resolvedMethod,
|
|
648
|
-
namespace: resolvedNamespace,
|
|
649
|
-
pascalCase,
|
|
650
|
-
pathPattern: resolvedPathPattern,
|
|
651
|
-
queryTypeName: resolvedQueryTypeName,
|
|
652
|
-
responseTypeName: resolvedResponseTypeName,
|
|
653
|
-
slugKebabCase: restResourceSlug,
|
|
654
|
-
title: toTitleCase(restResourceSlug),
|
|
655
|
-
},
|
|
656
|
-
});
|
|
657
|
-
await appendWorkspaceInventoryEntries(workspace.projectDir, {
|
|
658
|
-
restResourceEntries: [
|
|
659
|
-
buildManualRestContractConfigEntry({
|
|
660
|
-
auth: resolvedAuth,
|
|
661
|
-
...(resolvedBodyTypeName
|
|
662
|
-
? { bodyTypeName: resolvedBodyTypeName }
|
|
663
|
-
: {}),
|
|
664
|
-
method: resolvedMethod,
|
|
665
|
-
namespace: resolvedNamespace,
|
|
666
|
-
pathPattern: resolvedPathPattern,
|
|
667
|
-
queryTypeName: resolvedQueryTypeName,
|
|
668
|
-
responseTypeName: resolvedResponseTypeName,
|
|
669
|
-
restResourceSlug,
|
|
670
|
-
...(resolvedSecretFieldName
|
|
671
|
-
? { secretFieldName: resolvedSecretFieldName }
|
|
672
|
-
: {}),
|
|
673
|
-
...(resolvedSecretStateFieldName
|
|
674
|
-
? { secretStateFieldName: resolvedSecretStateFieldName }
|
|
675
|
-
: {}),
|
|
676
|
-
}),
|
|
677
|
-
],
|
|
678
|
-
transformSource: ensureBlockConfigCanAddRestManifests,
|
|
679
|
-
});
|
|
680
|
-
return {
|
|
681
|
-
auth: resolvedAuth,
|
|
682
|
-
...(resolvedBodyTypeName
|
|
683
|
-
? { bodyTypeName: resolvedBodyTypeName }
|
|
684
|
-
: {}),
|
|
685
|
-
method: resolvedMethod,
|
|
686
|
-
methods: [],
|
|
687
|
-
mode: "manual",
|
|
688
|
-
namespace: resolvedNamespace,
|
|
689
|
-
pathPattern: resolvedPathPattern,
|
|
690
|
-
projectDir: workspace.projectDir,
|
|
691
|
-
queryTypeName: resolvedQueryTypeName,
|
|
692
|
-
restResourceSlug,
|
|
693
|
-
responseTypeName: resolvedResponseTypeName,
|
|
694
|
-
...(resolvedSecretFieldName
|
|
695
|
-
? { secretFieldName: resolvedSecretFieldName }
|
|
696
|
-
: {}),
|
|
697
|
-
...(resolvedSecretStateFieldName
|
|
698
|
-
? { secretStateFieldName: resolvedSecretStateFieldName }
|
|
699
|
-
: {}),
|
|
700
|
-
};
|
|
701
|
-
}
|
|
702
|
-
catch (error) {
|
|
703
|
-
await rollbackWorkspaceMutation(mutationSnapshot);
|
|
704
|
-
throw error;
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
const resolvedMethods = assertValidRestResourceMethods(methods);
|
|
708
|
-
const resolvedRoutePattern = resolveGeneratedRestResourceRoutePattern(restResourceSlug, routePattern);
|
|
709
|
-
const hasCustomRoutePattern = typeof routePattern === "string" && routePattern.trim().length > 0;
|
|
710
|
-
const resolvedPermissionCallback = resolveOptionalPhpCallbackReference("Generated REST resource permission callback", permissionCallback);
|
|
711
|
-
const resolvedControllerClass = resolveOptionalPhpClassReference("Generated REST resource controller class", controllerClass);
|
|
712
|
-
const resolvedControllerExtends = resolveOptionalPhpClassReference("Generated REST resource controller base class", controllerExtends);
|
|
713
|
-
if (resolvedControllerExtends && !resolvedControllerClass) {
|
|
714
|
-
throw new Error("Generated REST resource controller base class requires --controller-class.");
|
|
715
|
-
}
|
|
716
|
-
const bootstrapPath = getWorkspaceBootstrapPath(workspace);
|
|
717
|
-
const dataFilePath = path.join(restResourceDir, "data.ts");
|
|
718
|
-
const phpFilePath = path.join(workspace.projectDir, "inc", "rest", `${restResourceSlug}.php`);
|
|
719
|
-
const mutationSnapshot = {
|
|
720
|
-
fileSources: await snapshotWorkspaceFiles([
|
|
721
|
-
blockConfigPath,
|
|
722
|
-
bootstrapPath,
|
|
723
|
-
syncRestScriptPath,
|
|
724
|
-
]),
|
|
725
|
-
snapshotDirs: [],
|
|
726
|
-
targetPaths: [restResourceDir, phpFilePath],
|
|
727
|
-
};
|
|
728
|
-
try {
|
|
729
|
-
await fsp.mkdir(restResourceDir, { recursive: true });
|
|
730
|
-
await fsp.mkdir(path.dirname(phpFilePath), { recursive: true });
|
|
731
|
-
await ensureRestResourceBootstrapAnchors(workspace);
|
|
732
|
-
await ensureRestResourceSyncScriptAnchors(workspace);
|
|
733
|
-
await fsp.writeFile(typesFilePath, buildRestResourceTypesSource(restResourceSlug, resolvedMethods), "utf8");
|
|
734
|
-
await fsp.writeFile(validatorsFilePath, buildRestResourceValidatorsSource(restResourceSlug, resolvedMethods), "utf8");
|
|
735
|
-
await fsp.writeFile(apiFilePath, buildRestResourceApiSource(restResourceSlug, resolvedMethods), "utf8");
|
|
736
|
-
await fsp.writeFile(dataFilePath, buildRestResourceDataSource(restResourceSlug, resolvedMethods), "utf8");
|
|
737
|
-
await fsp.writeFile(phpFilePath, buildRestResourcePhpSource(restResourceSlug, resolvedNamespace, workspace.workspace.phpPrefix, workspace.workspace.textDomain, resolvedMethods, {
|
|
738
|
-
...(resolvedControllerClass
|
|
739
|
-
? { controllerClass: resolvedControllerClass }
|
|
740
|
-
: {}),
|
|
741
|
-
...(resolvedControllerExtends
|
|
742
|
-
? { controllerExtends: resolvedControllerExtends }
|
|
743
|
-
: {}),
|
|
744
|
-
...(resolvedPermissionCallback
|
|
745
|
-
? { permissionCallback: resolvedPermissionCallback }
|
|
746
|
-
: {}),
|
|
747
|
-
routePattern: resolvedRoutePattern,
|
|
748
|
-
}), "utf8");
|
|
749
|
-
await syncRestResourceArtifacts({
|
|
750
|
-
clientFile: `src/rest/${restResourceSlug}/api-client.ts`,
|
|
751
|
-
methods: resolvedMethods,
|
|
752
|
-
outputDir: restResourceDir,
|
|
753
|
-
projectDir: workspace.projectDir,
|
|
754
|
-
typesFile: `src/rest/${restResourceSlug}/api-types.ts`,
|
|
755
|
-
validatorsFile: `src/rest/${restResourceSlug}/api-validators.ts`,
|
|
756
|
-
variables: {
|
|
757
|
-
namespace: resolvedNamespace,
|
|
758
|
-
pascalCase: toPascalCase(restResourceSlug),
|
|
759
|
-
...(hasCustomRoutePattern ? { routePattern: resolvedRoutePattern } : {}),
|
|
760
|
-
slugKebabCase: restResourceSlug,
|
|
761
|
-
title: toTitleCase(restResourceSlug),
|
|
762
|
-
},
|
|
763
|
-
});
|
|
764
|
-
await appendWorkspaceInventoryEntries(workspace.projectDir, {
|
|
765
|
-
restResourceEntries: [
|
|
766
|
-
buildRestResourceConfigEntry({
|
|
767
|
-
...(resolvedControllerClass
|
|
768
|
-
? { controllerClass: resolvedControllerClass }
|
|
769
|
-
: {}),
|
|
770
|
-
...(resolvedControllerExtends
|
|
771
|
-
? { controllerExtends: resolvedControllerExtends }
|
|
772
|
-
: {}),
|
|
773
|
-
methods: resolvedMethods,
|
|
774
|
-
namespace: resolvedNamespace,
|
|
775
|
-
...(resolvedPermissionCallback
|
|
776
|
-
? { permissionCallback: resolvedPermissionCallback }
|
|
777
|
-
: {}),
|
|
778
|
-
restResourceSlug,
|
|
779
|
-
...(hasCustomRoutePattern ? { routePattern: resolvedRoutePattern } : {}),
|
|
780
|
-
}),
|
|
781
|
-
],
|
|
782
|
-
transformSource: ensureBlockConfigCanAddRestManifests,
|
|
783
|
-
});
|
|
784
|
-
return {
|
|
785
|
-
...(resolvedControllerClass
|
|
786
|
-
? { controllerClass: resolvedControllerClass }
|
|
787
|
-
: {}),
|
|
788
|
-
...(resolvedControllerExtends
|
|
789
|
-
? { controllerExtends: resolvedControllerExtends }
|
|
790
|
-
: {}),
|
|
791
|
-
methods: resolvedMethods,
|
|
792
|
-
mode: "generated",
|
|
20
|
+
return scaffoldManualRestContract({
|
|
21
|
+
auth,
|
|
22
|
+
bodyTypeName,
|
|
23
|
+
controllerClass,
|
|
24
|
+
controllerExtends,
|
|
25
|
+
method,
|
|
793
26
|
namespace: resolvedNamespace,
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
27
|
+
pathPattern,
|
|
28
|
+
permissionCallback,
|
|
29
|
+
queryTypeName,
|
|
30
|
+
responseTypeName,
|
|
798
31
|
restResourceSlug,
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
32
|
+
routePattern,
|
|
33
|
+
secretFieldName,
|
|
34
|
+
secretHasValueFieldName,
|
|
35
|
+
secretMaskedResponseFieldName,
|
|
36
|
+
secretPreserveOnEmpty,
|
|
37
|
+
secretStateFieldName,
|
|
38
|
+
workspace,
|
|
39
|
+
});
|
|
805
40
|
}
|
|
41
|
+
return scaffoldGeneratedRestResource({
|
|
42
|
+
controllerClass,
|
|
43
|
+
controllerExtends,
|
|
44
|
+
methods,
|
|
45
|
+
namespace: resolvedNamespace,
|
|
46
|
+
permissionCallback,
|
|
47
|
+
restResourceSlug,
|
|
48
|
+
routePattern,
|
|
49
|
+
workspace,
|
|
50
|
+
});
|
|
806
51
|
}
|