@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
|
@@ -22,6 +22,27 @@ export interface AdminViewCoreDataSource {
|
|
|
22
22
|
}
|
|
23
23
|
export type AdminViewSource = AdminViewCoreDataSource | AdminViewRestResourceSource;
|
|
24
24
|
export type AdminViewRestResource = WorkspaceRestResourceInventoryEntry;
|
|
25
|
+
/**
|
|
26
|
+
* Manual REST resource metadata required to scaffold a typed admin settings
|
|
27
|
+
* screen. The type narrows a workspace REST inventory entry to manual
|
|
28
|
+
* contracts that expose request body, query, and response type names.
|
|
29
|
+
*/
|
|
30
|
+
export type AdminViewManualSettingsRestResource = AdminViewRestResource & {
|
|
31
|
+
bodyTypeName: string;
|
|
32
|
+
mode: 'manual';
|
|
33
|
+
queryTypeName: string;
|
|
34
|
+
responseTypeName: string;
|
|
35
|
+
};
|
|
25
36
|
export declare function isAdminViewCoreDataSource(source: AdminViewSource | undefined): source is AdminViewCoreDataSource;
|
|
26
37
|
export declare function isAdminViewRestResourceSource(source: AdminViewSource | undefined): source is AdminViewRestResourceSource;
|
|
38
|
+
/**
|
|
39
|
+
* Return whether a REST inventory entry has the manual contract shape required
|
|
40
|
+
* by generated settings screens.
|
|
41
|
+
*/
|
|
42
|
+
export declare function isAdminViewManualSettingsRestResource(restResource: AdminViewRestResource | undefined): restResource is AdminViewManualSettingsRestResource;
|
|
43
|
+
/**
|
|
44
|
+
* Return whether a REST inventory entry uses route regex groups that a
|
|
45
|
+
* generated singleton settings screen cannot satisfy with path input.
|
|
46
|
+
*/
|
|
47
|
+
export declare function hasAdminViewManualSettingsRouteParameters(restResource: AdminViewRestResource | undefined): boolean;
|
|
27
48
|
export declare function formatAdminViewSourceLocator(source: AdminViewSource): string;
|
|
@@ -12,12 +12,34 @@ export const ADMIN_VIEWS_ASSET = 'build/admin-views/index.asset.php';
|
|
|
12
12
|
export const ADMIN_VIEWS_STYLE = 'build/admin-views/style-index.css';
|
|
13
13
|
export const ADMIN_VIEWS_STYLE_RTL = 'build/admin-views/style-index-rtl.css';
|
|
14
14
|
export const ADMIN_VIEWS_PHP_GLOB = '/inc/admin-views/*.php';
|
|
15
|
+
const ADMIN_VIEW_MANUAL_REST_ROUTE_PARAMETER_PATTERN = /(?:^|[^\\])\(/u;
|
|
15
16
|
export function isAdminViewCoreDataSource(source) {
|
|
16
17
|
return source?.kind === ADMIN_VIEW_CORE_DATA_SOURCE_KIND;
|
|
17
18
|
}
|
|
18
19
|
export function isAdminViewRestResourceSource(source) {
|
|
19
20
|
return source?.kind === ADMIN_VIEW_REST_SOURCE_KIND;
|
|
20
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Return whether a REST inventory entry has the manual contract shape required
|
|
24
|
+
* by generated settings screens.
|
|
25
|
+
*/
|
|
26
|
+
export function isAdminViewManualSettingsRestResource(restResource) {
|
|
27
|
+
return (restResource?.mode === 'manual' &&
|
|
28
|
+
typeof restResource.bodyTypeName === 'string' &&
|
|
29
|
+
restResource.bodyTypeName.trim().length > 0 &&
|
|
30
|
+
typeof restResource.queryTypeName === 'string' &&
|
|
31
|
+
restResource.queryTypeName.trim().length > 0 &&
|
|
32
|
+
typeof restResource.responseTypeName === 'string' &&
|
|
33
|
+
restResource.responseTypeName.trim().length > 0);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Return whether a REST inventory entry uses route regex groups that a
|
|
37
|
+
* generated singleton settings screen cannot satisfy with path input.
|
|
38
|
+
*/
|
|
39
|
+
export function hasAdminViewManualSettingsRouteParameters(restResource) {
|
|
40
|
+
return [restResource?.pathPattern, restResource?.routePattern].some((pattern) => typeof pattern === 'string' &&
|
|
41
|
+
ADMIN_VIEW_MANUAL_REST_ROUTE_PARAMETER_PATTERN.test(pattern));
|
|
42
|
+
}
|
|
21
43
|
export function formatAdminViewSourceLocator(source) {
|
|
22
44
|
if (isAdminViewCoreDataSource(source)) {
|
|
23
45
|
return `${source.kind}:${source.entityKind}/${source.entityName}`;
|
|
@@ -3,6 +3,7 @@ import path from "node:path";
|
|
|
3
3
|
import { getPackageVersions } from "./package-versions.js";
|
|
4
4
|
import { getWorkspaceBootstrapPath, patchFile, } from "./cli-add-shared.js";
|
|
5
5
|
import { appendPhpSnippetBeforeClosingTag, insertPhpSnippetBeforeWorkspaceAnchors, } from "./cli-add-workspace-mutation.js";
|
|
6
|
+
import { readJsonFile } from "./json-utils.js";
|
|
6
7
|
import { hasPhpFunctionDefinition } from "./php-utils.js";
|
|
7
8
|
const AI_FEATURE_SERVER_GLOB = "/inc/ai-features/*.php";
|
|
8
9
|
/**
|
|
@@ -43,7 +44,9 @@ function ${registerFunctionName}() {
|
|
|
43
44
|
*/
|
|
44
45
|
export async function ensureAiFeaturePackageScripts(workspace) {
|
|
45
46
|
const packageJsonPath = path.join(workspace.projectDir, "package.json");
|
|
46
|
-
const packageJson =
|
|
47
|
+
const packageJson = await readJsonFile(packageJsonPath, {
|
|
48
|
+
context: "workspace package manifest",
|
|
49
|
+
});
|
|
47
50
|
const nextScripts = {
|
|
48
51
|
...(packageJson.scripts ?? {}),
|
|
49
52
|
"sync-ai": packageJson.scripts?.["sync-ai"] ?? "tsx scripts/sync-ai-features.ts",
|
|
@@ -126,35 +129,131 @@ function replaceRequiredSyncRestSource(nextSource, target, anchor, replacement,
|
|
|
126
129
|
assertSyncRestAnchor(nextSource, target, anchorDescription, hasAnchor, syncRestScriptPath);
|
|
127
130
|
return nextSource.replace(anchor, replacement);
|
|
128
131
|
}
|
|
132
|
+
function replaceBlockConfigImportForAiFeatures(nextSource, syncRestScriptPath) {
|
|
133
|
+
const importPatterns = [
|
|
134
|
+
/^import\s*\{\n(?:\t[^\n]*\n)+\} from ["']\.\/block-config["'];?$/mu,
|
|
135
|
+
/^import\s*\{[^\n]*\}\s*from\s*["']\.\/block-config["'];?$/mu,
|
|
136
|
+
];
|
|
137
|
+
const importMatch = importPatterns.map((pattern) => pattern.exec(nextSource)).find(Boolean) ??
|
|
138
|
+
null;
|
|
139
|
+
if (!importMatch) {
|
|
140
|
+
throw new Error([
|
|
141
|
+
`ensureAiFeatureSyncRestAnchors could not patch ${path.basename(syncRestScriptPath)}.`,
|
|
142
|
+
"Missing expected workspace inventory import anchor in scripts/sync-rest-contracts.ts.",
|
|
143
|
+
"Restore the generated template or add the AI feature wiring manually before retrying.",
|
|
144
|
+
].join(" "));
|
|
145
|
+
}
|
|
146
|
+
const importSource = importMatch[0];
|
|
147
|
+
if (importSource.includes("AI_FEATURES") &&
|
|
148
|
+
importSource.includes("WorkspaceAiFeatureConfig")) {
|
|
149
|
+
return nextSource;
|
|
150
|
+
}
|
|
151
|
+
const hasContracts = importSource.includes("CONTRACTS");
|
|
152
|
+
const hasContractConfig = importSource.includes("WorkspaceContractConfig");
|
|
153
|
+
const hasPostMeta = importSource.includes("POST_META");
|
|
154
|
+
const hasPostMetaConfig = importSource.includes("WorkspacePostMetaConfig");
|
|
155
|
+
const replacement = [
|
|
156
|
+
"import {",
|
|
157
|
+
"\tAI_FEATURES,",
|
|
158
|
+
"\tBLOCKS,",
|
|
159
|
+
...(hasContracts ? ["\tCONTRACTS,"] : []),
|
|
160
|
+
...(hasPostMeta ? ["\tPOST_META,"] : []),
|
|
161
|
+
"\tREST_RESOURCES,",
|
|
162
|
+
"\ttype WorkspaceAiFeatureConfig,",
|
|
163
|
+
"\ttype WorkspaceBlockConfig,",
|
|
164
|
+
...(hasContractConfig ? ["\ttype WorkspaceContractConfig,"] : []),
|
|
165
|
+
...(hasPostMetaConfig ? ["\ttype WorkspacePostMetaConfig,"] : []),
|
|
166
|
+
"\ttype WorkspaceRestResourceConfig,",
|
|
167
|
+
"} from './block-config';",
|
|
168
|
+
].join("\n");
|
|
169
|
+
return nextSource.replace(importSource, replacement);
|
|
170
|
+
}
|
|
171
|
+
function replaceAiFeatureSyncSummaryCopy(nextSource, syncRestScriptPath) {
|
|
172
|
+
const standaloneSummary = "workspace blocks, standalone contracts, and plugin-level resources";
|
|
173
|
+
const standaloneAiSummary = "workspace blocks, standalone contracts, plugin-level resources, and AI features";
|
|
174
|
+
const standalonePostMetaSummary = "workspace blocks, standalone contracts, post meta contracts, and plugin-level resources";
|
|
175
|
+
const standalonePostMetaAiSummary = "workspace blocks, standalone contracts, post meta contracts, plugin-level resources, and AI features";
|
|
176
|
+
const postMetaSummary = "workspace blocks, post meta contracts, and plugin-level resources";
|
|
177
|
+
const postMetaAiSummary = "workspace blocks, post meta contracts, plugin-level resources, and AI features";
|
|
178
|
+
const restResourceSummary = "workspace blocks and plugin-level resources";
|
|
179
|
+
const restResourceAiSummary = "workspace blocks, plugin-level resources, and AI features";
|
|
180
|
+
if (nextSource.includes(standalonePostMetaSummary)) {
|
|
181
|
+
return nextSource
|
|
182
|
+
.split(standalonePostMetaSummary)
|
|
183
|
+
.join(standalonePostMetaAiSummary);
|
|
184
|
+
}
|
|
185
|
+
if (nextSource.includes(standaloneSummary)) {
|
|
186
|
+
return nextSource.split(standaloneSummary).join(standaloneAiSummary);
|
|
187
|
+
}
|
|
188
|
+
if (nextSource.includes(postMetaSummary)) {
|
|
189
|
+
return nextSource.split(postMetaSummary).join(postMetaAiSummary);
|
|
190
|
+
}
|
|
191
|
+
if (nextSource.includes(restResourceSummary)) {
|
|
192
|
+
return nextSource.split(restResourceSummary).join(restResourceAiSummary);
|
|
193
|
+
}
|
|
194
|
+
if (nextSource.includes(standaloneAiSummary) ||
|
|
195
|
+
nextSource.includes(standalonePostMetaAiSummary) ||
|
|
196
|
+
nextSource.includes(postMetaAiSummary) ||
|
|
197
|
+
nextSource.includes(restResourceAiSummary)) {
|
|
198
|
+
return nextSource;
|
|
199
|
+
}
|
|
200
|
+
throw new Error([
|
|
201
|
+
`ensureAiFeatureSyncRestAnchors could not patch ${path.basename(syncRestScriptPath)}.`,
|
|
202
|
+
"Missing expected sync summary copy anchor in scripts/sync-rest-contracts.ts.",
|
|
203
|
+
"Restore the generated template or add the AI feature wiring manually before retrying.",
|
|
204
|
+
].join(" "));
|
|
205
|
+
}
|
|
206
|
+
function formatNoResourcesSubject(subjects) {
|
|
207
|
+
if (subjects.length <= 2) {
|
|
208
|
+
return subjects.join(" or ");
|
|
209
|
+
}
|
|
210
|
+
const lastSubject = subjects[subjects.length - 1];
|
|
211
|
+
return `${subjects.slice(0, -1).join(", ")}, or ${lastSubject}`;
|
|
212
|
+
}
|
|
213
|
+
function buildAiFeatureNoResourcesGuard({ hasPostMeta, hasStandaloneContracts, }) {
|
|
214
|
+
const condition = ["restBlocks.length === 0"];
|
|
215
|
+
if (hasStandaloneContracts) {
|
|
216
|
+
condition[condition.length - 1] = `${condition[condition.length - 1]} &&`;
|
|
217
|
+
condition.push("standaloneContracts.length === 0");
|
|
218
|
+
}
|
|
219
|
+
if (hasPostMeta) {
|
|
220
|
+
condition[condition.length - 1] = `${condition[condition.length - 1]} &&`;
|
|
221
|
+
condition.push("postMetaContracts.length === 0");
|
|
222
|
+
}
|
|
223
|
+
condition[condition.length - 1] = `${condition[condition.length - 1]} &&`;
|
|
224
|
+
condition.push("restResources.length === 0 &&");
|
|
225
|
+
condition.push("aiFeatures.length === 0");
|
|
226
|
+
const noResourcesSubject = formatNoResourcesSubject([
|
|
227
|
+
"REST-enabled workspace blocks",
|
|
228
|
+
...(hasStandaloneContracts ? ["standalone contracts"] : []),
|
|
229
|
+
...(hasPostMeta ? ["post meta contracts"] : []),
|
|
230
|
+
"plugin-level REST resources",
|
|
231
|
+
"AI features",
|
|
232
|
+
]);
|
|
233
|
+
return [
|
|
234
|
+
"if (",
|
|
235
|
+
...condition.map((line) => `\t\t${line}`),
|
|
236
|
+
"\t) {",
|
|
237
|
+
"\t\tconsole.log(",
|
|
238
|
+
"\t\t\toptions.check",
|
|
239
|
+
`\t\t\t\t? 'ℹ️ No ${noResourcesSubject} are registered yet. \`sync-rest --check\` is already clean.'`,
|
|
240
|
+
`\t\t\t\t: 'ℹ️ No ${noResourcesSubject} are registered yet.'`,
|
|
241
|
+
"\t\t);",
|
|
242
|
+
"\t\treturn;",
|
|
243
|
+
"\t}",
|
|
244
|
+
].join("\n");
|
|
245
|
+
}
|
|
246
|
+
const NO_RESOURCES_GUARD_PATTERN = /if \(\s*restBlocks\.length === 0(?:\s*&&\s*standaloneContracts\.length === 0)?(?:\s*&&\s*postMetaContracts\.length === 0)?\s*&&\s*restResources\.length === 0(?:\s*&&\s*aiFeatures\.length === 0)?\s*\) \{[\s\S]*?\n\t\treturn;\n\t\}/u;
|
|
129
247
|
/**
|
|
130
248
|
* Patch `scripts/sync-rest-contracts.ts` after sync-project wiring so AI feature REST artifacts join the split sync flow.
|
|
131
249
|
*/
|
|
132
250
|
export async function ensureAiFeatureSyncRestAnchors(workspace) {
|
|
133
251
|
const syncRestScriptPath = path.join(workspace.projectDir, "scripts", "sync-rest-contracts.ts");
|
|
134
252
|
await patchFile(syncRestScriptPath, (source) => {
|
|
135
|
-
let nextSource = source;
|
|
136
|
-
const importAnchor = [
|
|
137
|
-
"import {",
|
|
138
|
-
"\tBLOCKS,",
|
|
139
|
-
"\tREST_RESOURCES,",
|
|
140
|
-
"\ttype WorkspaceBlockConfig,",
|
|
141
|
-
"\ttype WorkspaceRestResourceConfig,",
|
|
142
|
-
"} from './block-config';",
|
|
143
|
-
].join("\n");
|
|
253
|
+
let nextSource = replaceBlockConfigImportForAiFeatures(source, syncRestScriptPath);
|
|
144
254
|
const helperInsertionAnchor = "async function assertTypeArtifactsCurrent";
|
|
145
255
|
const restResourcesAnchor = "const restResources = REST_RESOURCES.filter( isWorkspaceRestResource );";
|
|
146
|
-
const noResourcesPattern = /if \( restBlocks.length === 0 && restResources.length === 0 \) \{[\s\S]*?\n\t\treturn;\n\t\}/u;
|
|
147
256
|
const consoleLogPattern = /\n\tconsole\.log\(\n\t\toptions\.check/u;
|
|
148
|
-
nextSource = replaceRequiredSyncRestSource(nextSource, "AI_FEATURES", importAnchor, [
|
|
149
|
-
"import {",
|
|
150
|
-
"\tAI_FEATURES,",
|
|
151
|
-
"\tBLOCKS,",
|
|
152
|
-
"\tREST_RESOURCES,",
|
|
153
|
-
"\ttype WorkspaceAiFeatureConfig,",
|
|
154
|
-
"\ttype WorkspaceBlockConfig,",
|
|
155
|
-
"\ttype WorkspaceRestResourceConfig,",
|
|
156
|
-
"} from './block-config';",
|
|
157
|
-
].join("\n"), "workspace inventory import", syncRestScriptPath);
|
|
158
257
|
nextSource = replaceRequiredSyncRestSource(nextSource, "function isWorkspaceAiFeature(", helperInsertionAnchor, [
|
|
159
258
|
"function isWorkspaceAiFeature(",
|
|
160
259
|
"\tfeature: WorkspaceAiFeatureConfig",
|
|
@@ -183,16 +282,10 @@ export async function ensureAiFeatureSyncRestAnchors(workspace) {
|
|
|
183
282
|
"const restResources = REST_RESOURCES.filter( isWorkspaceRestResource );",
|
|
184
283
|
"const aiFeatures = AI_FEATURES.filter( isWorkspaceAiFeature );",
|
|
185
284
|
].join("\n"), "rest resource filter", syncRestScriptPath);
|
|
186
|
-
nextSource = replaceRequiredSyncRestSource(nextSource, "
|
|
187
|
-
|
|
188
|
-
"
|
|
189
|
-
|
|
190
|
-
"\t\t\t\t? 'ℹ️ No REST-enabled workspace blocks, plugin-level REST resources, or AI features are registered yet. `sync-rest --check` is already clean.'",
|
|
191
|
-
"\t\t\t\t: 'ℹ️ No REST-enabled workspace blocks, plugin-level REST resources, or AI features are registered yet.'",
|
|
192
|
-
"\t\t);",
|
|
193
|
-
"\t\treturn;",
|
|
194
|
-
"\t}",
|
|
195
|
-
].join("\n"), "no-resources guard", syncRestScriptPath);
|
|
285
|
+
nextSource = replaceRequiredSyncRestSource(nextSource, "aiFeatures.length === 0", NO_RESOURCES_GUARD_PATTERN, buildAiFeatureNoResourcesGuard({
|
|
286
|
+
hasPostMeta: nextSource.includes("const postMetaContracts = POST_META.filter( isWorkspacePostMetaContract );"),
|
|
287
|
+
hasStandaloneContracts: nextSource.includes("const standaloneContracts = CONTRACTS.filter( isWorkspaceStandaloneContract );"),
|
|
288
|
+
}), "no-resources guard", syncRestScriptPath);
|
|
196
289
|
nextSource = replaceRequiredSyncRestSource(nextSource, "for ( const feature of aiFeatures ) {", consoleLogPattern, [
|
|
197
290
|
"",
|
|
198
291
|
"\tfor ( const feature of aiFeatures ) {",
|
|
@@ -247,7 +340,7 @@ export async function ensureAiFeatureSyncRestAnchors(workspace) {
|
|
|
247
340
|
"\tconsole.log(",
|
|
248
341
|
"\t\toptions.check",
|
|
249
342
|
].join("\n"), "final sync summary", syncRestScriptPath);
|
|
250
|
-
nextSource =
|
|
343
|
+
nextSource = replaceAiFeatureSyncSummaryCopy(nextSource, syncRestScriptPath);
|
|
251
344
|
return nextSource;
|
|
252
345
|
});
|
|
253
346
|
}
|
|
@@ -397,7 +397,23 @@ async function reconcileGeneratedArtifact( options: {
|
|
|
397
397
|
}
|
|
398
398
|
|
|
399
399
|
async function loadJsonDocument( filePath: string ) {
|
|
400
|
-
\
|
|
400
|
+
\tlet source: string;
|
|
401
|
+
\ttry {
|
|
402
|
+
\t\tsource = await readFile( filePath, 'utf8' );
|
|
403
|
+
\t} catch ( error ) {
|
|
404
|
+
\t\tthrow new Error(
|
|
405
|
+
\t\t\t\`Failed to read AI schema document at \${ filePath }: \${ error instanceof Error ? error.message : String( error ) }\`
|
|
406
|
+
\t\t);
|
|
407
|
+
\t}
|
|
408
|
+
|
|
409
|
+
\tlet decoded: unknown;
|
|
410
|
+
\ttry {
|
|
411
|
+
\t\tdecoded = JSON.parse( source ) as unknown;
|
|
412
|
+
\t} catch ( error ) {
|
|
413
|
+
\t\tthrow new Error(
|
|
414
|
+
\t\t\t\`Failed to parse AI schema document at \${ filePath }: \${ error instanceof Error ? error.message : String( error ) }\`
|
|
415
|
+
\t\t);
|
|
416
|
+
\t}
|
|
401
417
|
\tif ( ! decoded || typeof decoded !== 'object' || Array.isArray( decoded ) ) {
|
|
402
418
|
\t\tthrow new Error( \`Expected \${ filePath } to decode to a JSON object.\` );
|
|
403
419
|
\t}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render one `CONTRACTS` inventory entry for `scripts/block-config.ts`.
|
|
3
|
+
*
|
|
4
|
+
* @param contractSlug Stable kebab-case contract id.
|
|
5
|
+
* @param sourceTypeName Exported TypeScript type/interface used for schema generation.
|
|
6
|
+
*/
|
|
7
|
+
export declare function buildContractConfigEntry(contractSlug: string, sourceTypeName: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* Render a small starter TypeScript contract that users can replace with their
|
|
10
|
+
* real external route, smoke-test, or PHP integration payload shape.
|
|
11
|
+
*
|
|
12
|
+
* @param contractSlug Stable kebab-case contract id.
|
|
13
|
+
* @param sourceTypeName Exported TypeScript type/interface used for schema generation.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildContractTypesSource(contractSlug: string, sourceTypeName: string): string;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { quoteTsString, } from "./cli-add-shared.js";
|
|
2
|
+
import { toTitleCase } from "./string-case.js";
|
|
3
|
+
/**
|
|
4
|
+
* Render one `CONTRACTS` inventory entry for `scripts/block-config.ts`.
|
|
5
|
+
*
|
|
6
|
+
* @param contractSlug Stable kebab-case contract id.
|
|
7
|
+
* @param sourceTypeName Exported TypeScript type/interface used for schema generation.
|
|
8
|
+
*/
|
|
9
|
+
export function buildContractConfigEntry(contractSlug, sourceTypeName) {
|
|
10
|
+
return [
|
|
11
|
+
"\t{",
|
|
12
|
+
`\t\tschemaFile: ${quoteTsString(`src/contracts/${contractSlug}.schema.json`)},`,
|
|
13
|
+
`\t\tslug: ${quoteTsString(contractSlug)},`,
|
|
14
|
+
`\t\tsourceTypeName: ${quoteTsString(sourceTypeName)},`,
|
|
15
|
+
`\t\ttypesFile: ${quoteTsString(`src/contracts/${contractSlug}.ts`)},`,
|
|
16
|
+
"\t},",
|
|
17
|
+
].join("\n");
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Render a small starter TypeScript contract that users can replace with their
|
|
21
|
+
* real external route, smoke-test, or PHP integration payload shape.
|
|
22
|
+
*
|
|
23
|
+
* @param contractSlug Stable kebab-case contract id.
|
|
24
|
+
* @param sourceTypeName Exported TypeScript type/interface used for schema generation.
|
|
25
|
+
*/
|
|
26
|
+
export function buildContractTypesSource(contractSlug, sourceTypeName) {
|
|
27
|
+
const title = toTitleCase(contractSlug);
|
|
28
|
+
return `/**
|
|
29
|
+
* ${title} is a standalone wire contract.
|
|
30
|
+
*
|
|
31
|
+
* It does not register a WordPress REST route. Edit this type, then run
|
|
32
|
+
* \`wp-typia sync-rest\` or \`wp-typia sync\` to refresh the JSON Schema
|
|
33
|
+
* artifact referenced from scripts/block-config.ts.
|
|
34
|
+
*/
|
|
35
|
+
export interface ${sourceTypeName} {
|
|
36
|
+
\tid: string;
|
|
37
|
+
\tstatus: 'pending' | 'ready';
|
|
38
|
+
\tupdatedAt: string;
|
|
39
|
+
\tmessage?: string;
|
|
40
|
+
}
|
|
41
|
+
`;
|
|
42
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type RunAddContractCommandOptions } from "./cli-add-shared.js";
|
|
2
|
+
/**
|
|
3
|
+
* Scaffold a standalone TypeScript wire contract and synchronize its JSON
|
|
4
|
+
* Schema artifact without generating PHP route glue.
|
|
5
|
+
*
|
|
6
|
+
* @param options Command options for the standalone contract workflow.
|
|
7
|
+
* @returns Resolved scaffold metadata for the created contract.
|
|
8
|
+
*/
|
|
9
|
+
export declare function runAddContractCommand({ contractName, cwd, typeName, }: RunAddContractCommandOptions): Promise<{
|
|
10
|
+
contractSlug: string;
|
|
11
|
+
projectDir: string;
|
|
12
|
+
schemaFile: string;
|
|
13
|
+
sourceTypeName: string;
|
|
14
|
+
typesFile: string;
|
|
15
|
+
}>;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { promises as fsp } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { pathExists } from "./fs-async.js";
|
|
4
|
+
import { assertContractDoesNotExist, assertValidGeneratedSlug, assertValidTypeScriptIdentifier, normalizeBlockSlug, } from "./cli-add-shared.js";
|
|
5
|
+
import { executeWorkspaceMutationPlan } from "./cli-add-workspace-mutation.js";
|
|
6
|
+
import { ensureContractSyncScriptAnchors } from "./cli-add-workspace-rest-anchors.js";
|
|
7
|
+
import { buildContractConfigEntry, buildContractTypesSource, } from "./cli-add-workspace-contract-source-emitters.js";
|
|
8
|
+
import { syncStandaloneContractArtifacts } from "./contract-artifacts.js";
|
|
9
|
+
import { toPascalCase } from "./string-case.js";
|
|
10
|
+
import { appendWorkspaceInventoryEntries, readWorkspaceInventoryAsync, } from "./workspace-inventory.js";
|
|
11
|
+
import { resolveWorkspaceProject } from "./workspace-project.js";
|
|
12
|
+
const ADD_CONTRACT_USAGE = "wp-typia add contract <name> [--type <ExportedTypeName>]";
|
|
13
|
+
/**
|
|
14
|
+
* Scaffold a standalone TypeScript wire contract and synchronize its JSON
|
|
15
|
+
* Schema artifact without generating PHP route glue.
|
|
16
|
+
*
|
|
17
|
+
* @param options Command options for the standalone contract workflow.
|
|
18
|
+
* @returns Resolved scaffold metadata for the created contract.
|
|
19
|
+
*/
|
|
20
|
+
export async function runAddContractCommand({ contractName, cwd = process.cwd(), typeName, }) {
|
|
21
|
+
const workspace = resolveWorkspaceProject(cwd);
|
|
22
|
+
const contractSlug = assertValidGeneratedSlug("Contract name", normalizeBlockSlug(contractName), ADD_CONTRACT_USAGE);
|
|
23
|
+
const sourceTypeName = assertValidTypeScriptIdentifier("Contract type", typeName ?? toPascalCase(contractSlug), ADD_CONTRACT_USAGE);
|
|
24
|
+
const inventory = await readWorkspaceInventoryAsync(workspace.projectDir);
|
|
25
|
+
assertContractDoesNotExist(workspace.projectDir, contractSlug, inventory);
|
|
26
|
+
const blockConfigPath = path.join(workspace.projectDir, "scripts", "block-config.ts");
|
|
27
|
+
const syncRestScriptPath = path.join(workspace.projectDir, "scripts", "sync-rest-contracts.ts");
|
|
28
|
+
const contractDir = path.join(workspace.projectDir, "src", "contracts");
|
|
29
|
+
const typesFile = `src/contracts/${contractSlug}.ts`;
|
|
30
|
+
const schemaFile = `src/contracts/${contractSlug}.schema.json`;
|
|
31
|
+
const typesFilePath = path.join(workspace.projectDir, typesFile);
|
|
32
|
+
const schemaFilePath = path.join(workspace.projectDir, schemaFile);
|
|
33
|
+
const contractDirExisted = await pathExists(contractDir);
|
|
34
|
+
return executeWorkspaceMutationPlan({
|
|
35
|
+
filePaths: [blockConfigPath, syncRestScriptPath],
|
|
36
|
+
targetPaths: [
|
|
37
|
+
typesFilePath,
|
|
38
|
+
schemaFilePath,
|
|
39
|
+
...(contractDirExisted ? [] : [contractDir]),
|
|
40
|
+
],
|
|
41
|
+
run: async () => {
|
|
42
|
+
await fsp.mkdir(contractDir, { recursive: true });
|
|
43
|
+
await ensureContractSyncScriptAnchors(workspace);
|
|
44
|
+
await fsp.writeFile(typesFilePath, buildContractTypesSource(contractSlug, sourceTypeName), "utf8");
|
|
45
|
+
await syncStandaloneContractArtifacts({
|
|
46
|
+
projectDir: workspace.projectDir,
|
|
47
|
+
schemaFile,
|
|
48
|
+
sourceTypeName,
|
|
49
|
+
typesFile,
|
|
50
|
+
});
|
|
51
|
+
await appendWorkspaceInventoryEntries(workspace.projectDir, {
|
|
52
|
+
contractEntries: [
|
|
53
|
+
buildContractConfigEntry(contractSlug, sourceTypeName),
|
|
54
|
+
],
|
|
55
|
+
});
|
|
56
|
+
return {
|
|
57
|
+
contractSlug,
|
|
58
|
+
projectDir: workspace.projectDir,
|
|
59
|
+
schemaFile,
|
|
60
|
+
sourceTypeName,
|
|
61
|
+
typesFile,
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type IntegrationEnvServiceId, type RunAddIntegrationEnvCommandOptions } from "./cli-add-shared.js";
|
|
2
|
+
/**
|
|
3
|
+
* Runtime result returned after adding an integration environment starter.
|
|
4
|
+
*
|
|
5
|
+
* @property integrationEnvSlug Normalized slug used for generated script and
|
|
6
|
+
* documentation paths.
|
|
7
|
+
* @property projectDir Absolute official workspace directory that was updated.
|
|
8
|
+
* @property service Canonical local service starter id selected for the scaffold.
|
|
9
|
+
* @property warnings Optional non-fatal preservation notices for existing files
|
|
10
|
+
* or scripts.
|
|
11
|
+
* @property withReleaseZip Whether release zip packaging scripts were added.
|
|
12
|
+
* @property withWpEnv Whether the generated scaffold included the wp-env preset.
|
|
13
|
+
*/
|
|
14
|
+
export interface RunAddIntegrationEnvCommandResult {
|
|
15
|
+
integrationEnvSlug: string;
|
|
16
|
+
projectDir: string;
|
|
17
|
+
service: IntegrationEnvServiceId;
|
|
18
|
+
warnings?: string[];
|
|
19
|
+
withReleaseZip: boolean;
|
|
20
|
+
withWpEnv: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Add an opt-in local WordPress integration environment starter to an official
|
|
24
|
+
* workspace.
|
|
25
|
+
*/
|
|
26
|
+
export declare function runAddIntegrationEnvCommand({ cwd, integrationEnvName, service, withReleaseZip, withWpEnv, }: RunAddIntegrationEnvCommandOptions): Promise<RunAddIntegrationEnvCommandResult>;
|