@wp-typia/project-tools 0.24.11 → 0.24.13
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/add/cli-add-block-config.js +7 -15
- package/dist/runtime/add/cli-add-block-package-json.d.ts +5 -0
- package/dist/runtime/add/cli-add-block-package-json.js +32 -0
- package/dist/runtime/add/cli-add-block.js +17 -4
- package/dist/runtime/add/cli-add-workspace-admin-view-scaffold.js +1 -5
- package/dist/runtime/add/cli-add-workspace-hooked-block.js +15 -20
- package/dist/runtime/add/cli-add-workspace-mutation.d.ts +15 -2
- package/dist/runtime/add/cli-add-workspace-mutation.js +10 -4
- package/dist/runtime/add/persistence-rest-artifacts.d.ts +32 -7
- package/dist/runtime/add/persistence-rest-artifacts.js +41 -15
- package/dist/runtime/cli/cli-diagnostics.d.ts +9 -0
- package/dist/runtime/cli/cli-diagnostics.js +8 -0
- package/dist/runtime/cli/cli-init-package-json.js +5 -1
- package/dist/runtime/doctor/cli-doctor-standalone-control-flow.d.ts +38 -0
- package/dist/runtime/doctor/cli-doctor-standalone-control-flow.js +365 -0
- package/dist/runtime/doctor/cli-doctor-standalone-rest.d.ts +21 -0
- package/dist/runtime/doctor/cli-doctor-standalone-rest.js +1354 -0
- package/dist/runtime/doctor/cli-doctor-standalone-shared.d.ts +24 -0
- package/dist/runtime/doctor/cli-doctor-standalone-shared.js +50 -0
- package/dist/runtime/doctor/cli-doctor-standalone.d.ts +32 -0
- package/dist/runtime/doctor/cli-doctor-standalone.js +2594 -0
- package/dist/runtime/doctor/cli-doctor-workspace.d.ts +5 -3
- package/dist/runtime/doctor/cli-doctor-workspace.js +27 -3
- package/dist/runtime/doctor/cli-doctor.d.ts +4 -2
- package/dist/runtime/doctor/cli-doctor.js +4 -2
- package/dist/runtime/shared/json-utils.d.ts +7 -0
- package/dist/runtime/shared/json-utils.js +10 -0
- package/dist/runtime/shared/package-json-types.d.ts +1 -1
- package/dist/runtime/shared/package-versions.d.ts +2 -0
- package/dist/runtime/shared/package-versions.js +2 -0
- package/dist/runtime/shared/php-utils.d.ts +39 -2
- package/dist/runtime/shared/php-utils.js +205 -6
- package/dist/runtime/templates/block-generator-service-core.d.ts +1 -1
- package/dist/runtime/templates/block-generator-service-core.js +9 -3
- package/dist/runtime/templates/block-generator-service-spec.d.ts +5 -0
- package/dist/runtime/templates/built-in-block-artifact-documents.d.ts +1 -1
- package/dist/runtime/templates/built-in-block-artifact-documents.js +1 -1
- package/dist/runtime/templates/built-in-block-artifact-types.js +2 -2
- package/dist/runtime/templates/built-in-block-artifacts.d.ts +1 -1
- package/dist/runtime/templates/built-in-block-artifacts.js +16 -12
- package/dist/runtime/templates/built-in-block-attribute-emitters.d.ts +5 -0
- package/dist/runtime/templates/built-in-block-attribute-emitters.js +113 -8
- package/dist/runtime/templates/built-in-block-attribute-specs.js +4 -9
- package/dist/runtime/templates/built-in-block-code-artifacts.js +6 -1
- package/dist/runtime/templates/built-in-block-code-templates/compound-persistence.d.ts +2 -2
- package/dist/runtime/templates/built-in-block-code-templates/compound-persistence.js +24 -1
- package/dist/runtime/templates/built-in-block-code-templates/persistence.d.ts +2 -2
- package/dist/runtime/templates/built-in-block-code-templates/persistence.js +22 -1
- package/dist/runtime/templates/built-in-block-non-ts-compound-templates.d.ts +2 -2
- package/dist/runtime/templates/built-in-block-non-ts-compound-templates.js +6 -2
- package/dist/runtime/templates/built-in-block-non-ts-persistence-templates.d.ts +2 -2
- package/dist/runtime/templates/built-in-block-non-ts-persistence-templates.js +6 -2
- package/dist/runtime/templates/cli-scaffold-emission.d.ts +7 -1
- package/dist/runtime/templates/cli-scaffold-emission.js +10 -1
- package/dist/runtime/templates/cli-templates.d.ts +47 -0
- package/dist/runtime/templates/cli-templates.js +50 -1
- package/dist/runtime/templates/local-dev-presets.js +1 -1
- package/dist/runtime/templates/scaffold-apply-utils.d.ts +4 -8
- package/dist/runtime/templates/scaffold-apply-utils.js +44 -28
- package/dist/runtime/templates/scaffold-compiler-artifacts.d.ts +17 -0
- package/dist/runtime/templates/scaffold-compiler-artifacts.js +81 -0
- package/dist/runtime/templates/scaffold-onboarding.d.ts +5 -0
- package/dist/runtime/templates/scaffold-onboarding.js +13 -2
- package/dist/runtime/templates/scaffold-template-variable-groups.d.ts +4 -0
- package/dist/runtime/templates/scaffold-template-variable-groups.js +7 -0
- package/dist/runtime/templates/scaffold.d.ts +3 -1
- package/dist/runtime/templates/scaffold.js +2 -1
- package/dist/runtime/templates/starter-manifests.js +1 -1
- package/package.json +5 -5
- package/templates/_shared/compound/core/scripts/add-compound-child.ts.mustache +1 -1
- package/templates/_shared/compound/persistence/package.json.mustache +1 -0
- package/templates/_shared/persistence/core/package.json.mustache +1 -0
|
@@ -2,6 +2,7 @@ import path from "node:path";
|
|
|
2
2
|
import { SHARED_WORKSPACE_TEMPLATE_ROOT, } from "../templates/template-registry.js";
|
|
3
3
|
import { isCompoundPersistenceEnabled } from "../templates/scaffold-template-variable-groups.js";
|
|
4
4
|
import { quoteTsString, } from "./cli-add-shared.js";
|
|
5
|
+
import { buildPersistenceEndpointManifest } from "./persistence-rest-artifacts.js";
|
|
5
6
|
export function buildServerTemplateRoot(persistencePolicy) {
|
|
6
7
|
return path.join(SHARED_WORKSPACE_TEMPLATE_ROOT, persistencePolicy === "public" ? "persistence-public" : "persistence-auth");
|
|
7
8
|
}
|
|
@@ -15,27 +16,18 @@ function buildSingleBlockConfigEntry(variables) {
|
|
|
15
16
|
].join("\n");
|
|
16
17
|
}
|
|
17
18
|
function buildPersistenceBlockConfigEntry(variables) {
|
|
19
|
+
const contractLines = Object.entries(buildPersistenceEndpointManifest(variables).contracts).flatMap(([contractName, contract]) => [
|
|
20
|
+
`\t\t\t\t${quoteTsString(contractName)}: {`,
|
|
21
|
+
`\t\t\t\t\tsourceTypeName: ${quoteTsString(contract.sourceTypeName)},`,
|
|
22
|
+
"\t\t\t\t},",
|
|
23
|
+
]);
|
|
18
24
|
return [
|
|
19
25
|
"\t{",
|
|
20
26
|
`\t\tapiTypesFile: ${quoteTsString(`src/blocks/${variables.slugKebabCase}/api-types.ts`)},`,
|
|
21
27
|
`\t\tattributeTypeName: ${quoteTsString(`${variables.pascalCase}Attributes`)},`,
|
|
22
28
|
"\t\trestManifest: defineEndpointManifest( {",
|
|
23
29
|
"\t\t\tcontracts: {",
|
|
24
|
-
|
|
25
|
-
`\t\t\t\t\tsourceTypeName: ${quoteTsString(`${variables.pascalCase}BootstrapQuery`)},`,
|
|
26
|
-
"\t\t\t\t},",
|
|
27
|
-
"\t\t\t\t'bootstrap-response': {",
|
|
28
|
-
`\t\t\t\t\tsourceTypeName: ${quoteTsString(`${variables.pascalCase}BootstrapResponse`)},`,
|
|
29
|
-
"\t\t\t\t},",
|
|
30
|
-
"\t\t\t\t'state-query': {",
|
|
31
|
-
`\t\t\t\t\tsourceTypeName: ${quoteTsString(`${variables.pascalCase}StateQuery`)},`,
|
|
32
|
-
"\t\t\t\t},",
|
|
33
|
-
"\t\t\t\t'state-response': {",
|
|
34
|
-
`\t\t\t\t\tsourceTypeName: ${quoteTsString(`${variables.pascalCase}StateResponse`)},`,
|
|
35
|
-
"\t\t\t\t},",
|
|
36
|
-
"\t\t\t\t'write-state-request': {",
|
|
37
|
-
`\t\t\t\t\tsourceTypeName: ${quoteTsString(`${variables.pascalCase}WriteStateRequest`)},`,
|
|
38
|
-
"\t\t\t\t},",
|
|
30
|
+
...contractLines,
|
|
39
31
|
"\t\t\t},",
|
|
40
32
|
"\t\t\tendpoints: [",
|
|
41
33
|
"\t\t\t\t{",
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ensure legacy workspaces can resolve the editor store used by generated
|
|
3
|
+
* persistence blocks. Existing dependency ranges stay authoritative.
|
|
4
|
+
*/
|
|
5
|
+
export declare function ensurePersistentBlockIdentityDependency(projectDir: string, required: boolean): Promise<boolean>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { detectJsonIndent, safeJsonParse } from "../shared/json-utils.js";
|
|
3
|
+
import { DEFAULT_WORDPRESS_DATA_VERSION } from "../shared/package-versions.js";
|
|
4
|
+
import { patchFile } from "./cli-add-shared.js";
|
|
5
|
+
/**
|
|
6
|
+
* Ensure legacy workspaces can resolve the editor store used by generated
|
|
7
|
+
* persistence blocks. Existing dependency ranges stay authoritative.
|
|
8
|
+
*/
|
|
9
|
+
export async function ensurePersistentBlockIdentityDependency(projectDir, required) {
|
|
10
|
+
if (!required) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
const packageJsonPath = path.join(projectDir, "package.json");
|
|
14
|
+
let added = false;
|
|
15
|
+
await patchFile(packageJsonPath, (source) => {
|
|
16
|
+
const packageJson = safeJsonParse(source, {
|
|
17
|
+
context: "workspace package manifest",
|
|
18
|
+
filePath: packageJsonPath,
|
|
19
|
+
});
|
|
20
|
+
if (packageJson.dependencies?.["@wordpress/data"] ||
|
|
21
|
+
packageJson.devDependencies?.["@wordpress/data"]) {
|
|
22
|
+
return source;
|
|
23
|
+
}
|
|
24
|
+
packageJson.dependencies = {
|
|
25
|
+
...(packageJson.dependencies ?? {}),
|
|
26
|
+
"@wordpress/data": DEFAULT_WORDPRESS_DATA_VERSION,
|
|
27
|
+
};
|
|
28
|
+
added = true;
|
|
29
|
+
return `${JSON.stringify(packageJson, null, detectJsonIndent(source))}\n`;
|
|
30
|
+
});
|
|
31
|
+
return added;
|
|
32
|
+
}
|
|
@@ -12,6 +12,7 @@ import { resolveWorkspaceProject, } from "../workspace/workspace-project.js";
|
|
|
12
12
|
import { ADD_BLOCK_TEMPLATE_IDS, buildWorkspacePhpPrefix, isAddBlockTemplateId, patchFile, readOptionalFile, rollbackWorkspaceMutation, snapshotWorkspaceFiles, suggestAddBlockTemplateId, } from "./cli-add-shared.js";
|
|
13
13
|
import { resolveNonEmptyNormalizedBlockSlug, } from "../templates/scaffold-identifiers.js";
|
|
14
14
|
import { buildConfigEntries, buildMigrationBlocks, buildServerTemplateRoot, } from "./cli-add-block-config.js";
|
|
15
|
+
import { ensurePersistentBlockIdentityDependency } from "./cli-add-block-package-json.js";
|
|
15
16
|
import { COMPOUND_SHARED_SUPPORT_FILES, collectLegacyCompoundValidatorPaths, ensureBlockConfigCanAddRestManifests, ensureCompoundWorkspaceSupportFiles, } from "./cli-add-block-legacy-validator.js";
|
|
16
17
|
import { parseTemplateLocator, resolveTemplateSeed, } from "../templates/template-source.js";
|
|
17
18
|
import { resolveExternalTemplateLayers, } from "../templates/template-layers.js";
|
|
@@ -340,6 +341,7 @@ export async function runAddBlockCommand({ alternateRenderTargets, blockName, cw
|
|
|
340
341
|
cleanup: cleanupTempRoot,
|
|
341
342
|
} = await createManagedTempRoot("wp-typia-add-block-"));
|
|
342
343
|
const tempProjectDir = path.join(tempRoot, normalizedSlug);
|
|
344
|
+
const packageJsonPath = path.join(workspace.projectDir, "package.json");
|
|
343
345
|
const blockConfigPath = path.join(workspace.projectDir, "scripts", "block-config.ts");
|
|
344
346
|
const migrationConfigPath = path.join(workspace.projectDir, "src", "migrations", "config.ts");
|
|
345
347
|
const blockPhpPrefix = buildWorkspacePhpPrefix(workspace.workspace.phpPrefix, normalizedSlug);
|
|
@@ -373,6 +375,7 @@ export async function runAddBlockCommand({ alternateRenderTargets, blockName, cw
|
|
|
373
375
|
packageManager: workspace.packageManager,
|
|
374
376
|
persistencePolicy: persistencePolicy,
|
|
375
377
|
projectDir: tempProjectDir,
|
|
378
|
+
seedCompilerArtifacts: false,
|
|
376
379
|
templateId: resolvedTemplateId,
|
|
377
380
|
});
|
|
378
381
|
await assertAddBlockSupportsExternalLayerOutputs({
|
|
@@ -385,8 +388,12 @@ export async function runAddBlockCommand({ alternateRenderTargets, blockName, cw
|
|
|
385
388
|
return scaffoldResult;
|
|
386
389
|
})();
|
|
387
390
|
await assertBlockTargetsDoNotExist(workspace.projectDir, resolvedTemplateId, result.variables);
|
|
391
|
+
const requiresPersistentIdentity = resolvedTemplateId === "persistence" ||
|
|
392
|
+
(resolvedTemplateId === "compound" &&
|
|
393
|
+
isCompoundPersistenceEnabled(result.variables));
|
|
388
394
|
const mutationSnapshot = {
|
|
389
395
|
fileSources: await snapshotWorkspaceFiles([
|
|
396
|
+
packageJsonPath,
|
|
390
397
|
blockConfigPath,
|
|
391
398
|
migrationConfigPath,
|
|
392
399
|
...compoundSupportPaths,
|
|
@@ -398,18 +405,24 @@ export async function runAddBlockCommand({ alternateRenderTargets, blockName, cw
|
|
|
398
405
|
targetPaths: collectWorkspaceBlockPaths(workspace.projectDir, resolvedTemplateId, result.variables),
|
|
399
406
|
};
|
|
400
407
|
try {
|
|
408
|
+
const addedPersistentIdentityDependency = await ensurePersistentBlockIdentityDependency(workspace.projectDir, requiresPersistentIdentity);
|
|
401
409
|
await copyScaffoldedBlockSlice(workspace.projectDir, resolvedTemplateId, tempProjectDir, result.variables, legacyCompoundValidatorPaths);
|
|
402
410
|
await addCollectionImportsForTemplate(workspace.projectDir, resolvedTemplateId, result.variables);
|
|
403
|
-
await appendBlockConfigEntries(workspace.projectDir, buildConfigEntries(resolvedTemplateId, result.variables),
|
|
404
|
-
(resolvedTemplateId === "compound" &&
|
|
405
|
-
isCompoundPersistenceEnabled(result.variables)));
|
|
411
|
+
await appendBlockConfigEntries(workspace.projectDir, buildConfigEntries(resolvedTemplateId, result.variables), requiresPersistentIdentity);
|
|
406
412
|
await syncWorkspaceAddedBlockArtifacts(workspace.projectDir, resolvedTemplateId, result.variables);
|
|
407
413
|
await updateWorkspaceMigrationConfigIfPresent(workspace.projectDir, buildMigrationBlocks(resolvedTemplateId, result.variables));
|
|
408
414
|
return {
|
|
409
415
|
blockSlugs: collectWorkspaceBlockPaths(workspace.projectDir, resolvedTemplateId, result.variables).map((targetPath) => path.basename(targetPath)),
|
|
410
416
|
projectDir: workspace.projectDir,
|
|
411
417
|
templateId: resolvedTemplateId,
|
|
412
|
-
warnings:
|
|
418
|
+
warnings: [
|
|
419
|
+
...result.warnings,
|
|
420
|
+
...(addedPersistentIdentityDependency
|
|
421
|
+
? [
|
|
422
|
+
`Added @wordpress/data for persistent block identities. Run \`${formatInstallCommand(workspace.packageManager)}\` before building the workspace.`,
|
|
423
|
+
]
|
|
424
|
+
: []),
|
|
425
|
+
],
|
|
413
426
|
};
|
|
414
427
|
}
|
|
415
428
|
catch (error) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { promises as fsp } from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { pathExists, readOptionalUtf8File } from '../shared/fs-async.js';
|
|
4
|
-
import { safeJsonParse } from '../shared/json-utils.js';
|
|
4
|
+
import { detectJsonIndent, safeJsonParse, } from '../shared/json-utils.js';
|
|
5
5
|
import { appendWorkspaceInventoryEntries, readWorkspaceInventoryAsync, } from '../workspace/workspace-inventory.js';
|
|
6
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
7
|
import { ADMIN_VIEWS_PHP_GLOB, isAdminViewCoreDataSource, isAdminViewManualSettingsRestResource, } from './cli-add-workspace-admin-view-types.js';
|
|
@@ -10,10 +10,6 @@ import { getWorkspaceBootstrapPath, patchFile, } from './cli-add-shared.js';
|
|
|
10
10
|
import { appendPhpSnippetBeforeClosingTag, executeWorkspaceMutationPlan, insertPhpSnippetBeforeWorkspaceAnchors, } from './cli-add-workspace-mutation.js';
|
|
11
11
|
import { DEFAULT_WORDPRESS_CORE_DATA_VERSION, DEFAULT_WORDPRESS_DATA_VERSION, DEFAULT_WORDPRESS_DATAVIEWS_VERSION, DEFAULT_WP_TYPIA_DATAVIEWS_VERSION, resolveManagedPackageVersionRange, } from '../shared/package-versions.js';
|
|
12
12
|
import { findPhpFunctionRange, hasPhpFunctionDefinition, replacePhpFunctionDefinition, } from '../shared/php-utils.js';
|
|
13
|
-
function detectJsonIndent(source) {
|
|
14
|
-
const indentMatch = /\n([ \t]+)"/u.exec(source);
|
|
15
|
-
return indentMatch?.[1] ?? 2;
|
|
16
|
-
}
|
|
17
13
|
const LEGACY_MANUAL_REST_API_SOURCE_PATTERN = /^\s*export\s+\*\s+from\s+["']\.\/api-client["'];?\s*$/u;
|
|
18
14
|
const MANUAL_REST_API_DIRECT_CALL_EXPORT_PATTERN = /(?:^|\n)\s*export\s+(?:(?:async\s+)?function|const|let|var)\s+callManualRestContract\b/u;
|
|
19
15
|
const MANUAL_REST_API_NAMED_EXPORT_PATTERN = /(?:^|\n)\s*export\s*\{([^}]*)\}/gu;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { promises as fsp } from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { executeWorkspaceMutationPlan } from "./cli-add-workspace-mutation.js";
|
|
4
|
+
import { assertValidHookAnchor, assertValidHookedBlockPosition, getMutableBlockHooks, normalizeBlockSlug, readWorkspaceBlockJson, resolveWorkspaceBlock, } from "./cli-add-shared.js";
|
|
4
5
|
import { readWorkspaceInventoryAsync } from "../workspace/workspace-inventory.js";
|
|
5
6
|
import { resolveWorkspaceProject } from "../workspace/workspace-project.js";
|
|
6
7
|
/**
|
|
@@ -35,23 +36,17 @@ export async function runAddHookedBlockCommand({ anchorBlockName, blockName, cwd
|
|
|
35
36
|
if (Object.prototype.hasOwnProperty.call(blockHooks, resolvedAnchorBlockName)) {
|
|
36
37
|
throw new Error(`${blockJsonRelativePath} already defines a blockHooks entry for "${resolvedAnchorBlockName}".`);
|
|
37
38
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
catch (error) {
|
|
54
|
-
await rollbackWorkspaceMutation(mutationSnapshot);
|
|
55
|
-
throw error;
|
|
56
|
-
}
|
|
39
|
+
return executeWorkspaceMutationPlan({
|
|
40
|
+
filePaths: [blockJsonPath],
|
|
41
|
+
run: async () => {
|
|
42
|
+
blockHooks[resolvedAnchorBlockName] = resolvedPosition;
|
|
43
|
+
await fsp.writeFile(blockJsonPath, JSON.stringify(blockJson, null, "\t"), "utf8");
|
|
44
|
+
return {
|
|
45
|
+
anchorBlockName: resolvedAnchorBlockName,
|
|
46
|
+
blockSlug,
|
|
47
|
+
position: resolvedPosition,
|
|
48
|
+
projectDir: workspace.projectDir,
|
|
49
|
+
};
|
|
50
|
+
},
|
|
51
|
+
});
|
|
57
52
|
}
|
|
@@ -1,10 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
import { type WorkspaceMutationSnapshot } from "./cli-add-shared.js";
|
|
2
|
+
/**
|
|
3
|
+
* Paths captured before a workspace mutation so its filesystem changes can be rolled back.
|
|
4
|
+
*/
|
|
5
|
+
export interface WorkspaceMutationSnapshotPlan {
|
|
2
6
|
/** Files to capture before the mutation starts. Missing files are restored as absent. */
|
|
3
7
|
filePaths: string[];
|
|
4
8
|
/** Snapshot directories created by the mutation, usually migration fixtures. */
|
|
5
9
|
snapshotDirs?: string[];
|
|
6
10
|
/** Created files or directories to remove if the mutation fails. */
|
|
7
11
|
targetPaths?: string[];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A workspace mutation snapshot plan paired with the operation to execute.
|
|
15
|
+
*/
|
|
16
|
+
export interface WorkspaceMutationPlan<TResult> extends WorkspaceMutationSnapshotPlan {
|
|
8
17
|
/** Mutating work to execute after the snapshot is captured. */
|
|
9
18
|
run: () => Promise<TResult>;
|
|
10
19
|
}
|
|
@@ -16,10 +25,14 @@ export declare class WorkspaceMutationRollbackError extends Error {
|
|
|
16
25
|
readonly rollbackError: unknown;
|
|
17
26
|
constructor(mutationError: unknown, rollbackError: unknown);
|
|
18
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Capture the files and paths needed to roll back a workspace add mutation.
|
|
30
|
+
*/
|
|
31
|
+
export declare function createWorkspaceMutationSnapshot({ filePaths, snapshotDirs, targetPaths, }: WorkspaceMutationSnapshotPlan): Promise<WorkspaceMutationSnapshot>;
|
|
19
32
|
/**
|
|
20
33
|
* Execute a workspace add mutation with rollback on any failure.
|
|
21
34
|
*/
|
|
22
|
-
export declare function executeWorkspaceMutationPlan<TResult>(
|
|
35
|
+
export declare function executeWorkspaceMutationPlan<TResult>(plan: WorkspaceMutationPlan<TResult>): Promise<TResult>;
|
|
23
36
|
/**
|
|
24
37
|
* Insert a PHP snippet before the workspace textdomain hook or closing tag.
|
|
25
38
|
*/
|
|
@@ -15,16 +15,22 @@ export class WorkspaceMutationRollbackError extends Error {
|
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
18
|
+
* Capture the files and paths needed to roll back a workspace add mutation.
|
|
19
19
|
*/
|
|
20
|
-
export async function
|
|
21
|
-
|
|
20
|
+
export async function createWorkspaceMutationSnapshot({ filePaths, snapshotDirs = [], targetPaths = [], }) {
|
|
21
|
+
return {
|
|
22
22
|
fileSources: await snapshotWorkspaceFiles(filePaths),
|
|
23
23
|
snapshotDirs: [...snapshotDirs],
|
|
24
24
|
targetPaths: [...targetPaths],
|
|
25
25
|
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Execute a workspace add mutation with rollback on any failure.
|
|
29
|
+
*/
|
|
30
|
+
export async function executeWorkspaceMutationPlan(plan) {
|
|
31
|
+
const mutationSnapshot = await createWorkspaceMutationSnapshot(plan);
|
|
26
32
|
try {
|
|
27
|
-
return await run();
|
|
33
|
+
return await plan.run();
|
|
28
34
|
}
|
|
29
35
|
catch (error) {
|
|
30
36
|
try {
|
|
@@ -6,7 +6,8 @@ interface PersistenceTemplateVariablesLike {
|
|
|
6
6
|
slugKebabCase: string;
|
|
7
7
|
title: string;
|
|
8
8
|
}
|
|
9
|
-
|
|
9
|
+
/** Inputs used to plan and sync one persistence scaffold's REST artifacts. */
|
|
10
|
+
export interface SyncPersistenceRestArtifactsOptions {
|
|
10
11
|
apiTypesFile: string;
|
|
11
12
|
outputDir: string;
|
|
12
13
|
projectDir: string;
|
|
@@ -20,21 +21,21 @@ interface SyncPersistenceRestArtifactsOptions {
|
|
|
20
21
|
* @returns Endpoint manifest covering bootstrap, state read, and state write operations.
|
|
21
22
|
*/
|
|
22
23
|
export declare function buildPersistenceEndpointManifest(variables: PersistenceTemplateVariablesLike): import("@wp-typia/block-runtime/metadata-core").EndpointManifestDefinition<{
|
|
24
|
+
readonly "state-query": {
|
|
25
|
+
readonly sourceTypeName: `${string}StateQuery`;
|
|
26
|
+
};
|
|
23
27
|
readonly "bootstrap-query": {
|
|
24
28
|
readonly sourceTypeName: `${string}BootstrapQuery`;
|
|
25
29
|
};
|
|
30
|
+
readonly "write-state-request": {
|
|
31
|
+
readonly sourceTypeName: `${string}WriteStateRequest`;
|
|
32
|
+
};
|
|
26
33
|
readonly "bootstrap-response": {
|
|
27
34
|
readonly sourceTypeName: `${string}BootstrapResponse`;
|
|
28
35
|
};
|
|
29
|
-
readonly "state-query": {
|
|
30
|
-
readonly sourceTypeName: `${string}StateQuery`;
|
|
31
|
-
};
|
|
32
36
|
readonly "state-response": {
|
|
33
37
|
readonly sourceTypeName: `${string}StateResponse`;
|
|
34
38
|
};
|
|
35
|
-
readonly "write-state-request": {
|
|
36
|
-
readonly sourceTypeName: `${string}WriteStateRequest`;
|
|
37
|
-
};
|
|
38
39
|
}, readonly [{
|
|
39
40
|
readonly auth: "public";
|
|
40
41
|
readonly method: "GET";
|
|
@@ -66,6 +67,30 @@ export declare function buildPersistenceEndpointManifest(variables: PersistenceT
|
|
|
66
67
|
readonly summary: "Read fresh session bootstrap state for the current viewer.";
|
|
67
68
|
readonly tags: readonly [string];
|
|
68
69
|
}]>;
|
|
70
|
+
/** Output paths and metadata for one persistence REST contract schema. */
|
|
71
|
+
export interface PersistenceRestArtifactSchemaPlan {
|
|
72
|
+
jsonSchemaFile: string;
|
|
73
|
+
openApiFile: string;
|
|
74
|
+
openApiInfo: {
|
|
75
|
+
title: string;
|
|
76
|
+
version: string;
|
|
77
|
+
};
|
|
78
|
+
sourceTypeName: string;
|
|
79
|
+
}
|
|
80
|
+
/** Complete compiler-derived output plan for one persistence REST surface. */
|
|
81
|
+
export interface PersistenceRestArtifactPlan {
|
|
82
|
+
clientFile: string;
|
|
83
|
+
manifest: ReturnType<typeof buildPersistenceEndpointManifest>;
|
|
84
|
+
openApiFile: string;
|
|
85
|
+
schemas: PersistenceRestArtifactSchemaPlan[];
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Build the canonical output plan shared by scaffold generation and previews.
|
|
89
|
+
*
|
|
90
|
+
* @param options Scaffold output paths plus persistence template variables.
|
|
91
|
+
* @returns REST schema, aggregate OpenAPI, and client output paths.
|
|
92
|
+
*/
|
|
93
|
+
export declare function buildPersistenceRestArtifactPlan(options: SyncPersistenceRestArtifactsOptions): PersistenceRestArtifactPlan;
|
|
69
94
|
/**
|
|
70
95
|
* Generate the REST-derived persistence artifacts for a scaffolded block.
|
|
71
96
|
*
|
|
@@ -10,21 +10,21 @@ import { defineEndpointManifest, syncEndpointClient, syncRestOpenApi, syncTypeSc
|
|
|
10
10
|
export function buildPersistenceEndpointManifest(variables) {
|
|
11
11
|
return defineEndpointManifest({
|
|
12
12
|
contracts: {
|
|
13
|
+
"state-query": {
|
|
14
|
+
sourceTypeName: `${variables.pascalCase}StateQuery`,
|
|
15
|
+
},
|
|
13
16
|
"bootstrap-query": {
|
|
14
17
|
sourceTypeName: `${variables.pascalCase}BootstrapQuery`,
|
|
15
18
|
},
|
|
19
|
+
"write-state-request": {
|
|
20
|
+
sourceTypeName: `${variables.pascalCase}WriteStateRequest`,
|
|
21
|
+
},
|
|
16
22
|
"bootstrap-response": {
|
|
17
23
|
sourceTypeName: `${variables.pascalCase}BootstrapResponse`,
|
|
18
24
|
},
|
|
19
|
-
"state-query": {
|
|
20
|
-
sourceTypeName: `${variables.pascalCase}StateQuery`,
|
|
21
|
-
},
|
|
22
25
|
"state-response": {
|
|
23
26
|
sourceTypeName: `${variables.pascalCase}StateResponse`,
|
|
24
27
|
},
|
|
25
|
-
"write-state-request": {
|
|
26
|
-
sourceTypeName: `${variables.pascalCase}WriteStateRequest`,
|
|
27
|
-
},
|
|
28
28
|
},
|
|
29
29
|
endpoints: [
|
|
30
30
|
{
|
|
@@ -67,6 +67,29 @@ export function buildPersistenceEndpointManifest(variables) {
|
|
|
67
67
|
},
|
|
68
68
|
});
|
|
69
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Build the canonical output plan shared by scaffold generation and previews.
|
|
72
|
+
*
|
|
73
|
+
* @param options Scaffold output paths plus persistence template variables.
|
|
74
|
+
* @returns REST schema, aggregate OpenAPI, and client output paths.
|
|
75
|
+
*/
|
|
76
|
+
export function buildPersistenceRestArtifactPlan(options) {
|
|
77
|
+
const manifest = buildPersistenceEndpointManifest(options.variables);
|
|
78
|
+
return {
|
|
79
|
+
clientFile: path.join(options.outputDir, "api-client.ts"),
|
|
80
|
+
manifest,
|
|
81
|
+
openApiFile: path.join(options.outputDir, "api.openapi.json"),
|
|
82
|
+
schemas: Object.entries(manifest.contracts).map(([baseName, contract]) => ({
|
|
83
|
+
jsonSchemaFile: path.join(options.outputDir, "api-schemas", `${baseName}.schema.json`),
|
|
84
|
+
openApiFile: path.join(options.outputDir, "api-schemas", `${baseName}.openapi.json`),
|
|
85
|
+
openApiInfo: {
|
|
86
|
+
title: contract.sourceTypeName,
|
|
87
|
+
version: "1.0.0",
|
|
88
|
+
},
|
|
89
|
+
sourceTypeName: contract.sourceTypeName,
|
|
90
|
+
})),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
70
93
|
/**
|
|
71
94
|
* Generate the REST-derived persistence artifacts for a scaffolded block.
|
|
72
95
|
*
|
|
@@ -74,25 +97,28 @@ export function buildPersistenceEndpointManifest(variables) {
|
|
|
74
97
|
* @returns A promise that resolves after schema, OpenAPI, and client files are written.
|
|
75
98
|
*/
|
|
76
99
|
export async function syncPersistenceRestArtifacts({ apiTypesFile, outputDir, projectDir, variables, }) {
|
|
77
|
-
const
|
|
78
|
-
|
|
100
|
+
const plan = buildPersistenceRestArtifactPlan({
|
|
101
|
+
apiTypesFile,
|
|
102
|
+
outputDir,
|
|
103
|
+
projectDir,
|
|
104
|
+
variables,
|
|
105
|
+
});
|
|
106
|
+
for (const schema of plan.schemas) {
|
|
79
107
|
await syncTypeSchemas({
|
|
80
|
-
|
|
81
|
-
openApiFile: path.join(outputDir, "api-schemas", `${baseName}.openapi.json`),
|
|
108
|
+
...schema,
|
|
82
109
|
projectRoot: projectDir,
|
|
83
|
-
sourceTypeName: contract.sourceTypeName,
|
|
84
110
|
typesFile: apiTypesFile,
|
|
85
111
|
});
|
|
86
112
|
}
|
|
87
113
|
await syncRestOpenApi({
|
|
88
|
-
manifest,
|
|
89
|
-
openApiFile:
|
|
114
|
+
manifest: plan.manifest,
|
|
115
|
+
openApiFile: plan.openApiFile,
|
|
90
116
|
projectRoot: projectDir,
|
|
91
117
|
typesFile: apiTypesFile,
|
|
92
118
|
});
|
|
93
119
|
await syncEndpointClient({
|
|
94
|
-
clientFile:
|
|
95
|
-
manifest,
|
|
120
|
+
clientFile: plan.clientFile,
|
|
121
|
+
manifest: plan.manifest,
|
|
96
122
|
projectRoot: projectDir,
|
|
97
123
|
typesFile: apiTypesFile,
|
|
98
124
|
});
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
export interface CliDiagnosticMessage {
|
|
5
5
|
code: CliDiagnosticCode;
|
|
6
6
|
command: string;
|
|
7
|
+
data?: Record<string, unknown>;
|
|
7
8
|
detailLines: string[];
|
|
8
9
|
summary: string;
|
|
9
10
|
}
|
|
@@ -12,6 +13,7 @@ export declare const CLI_DIAGNOSTIC_CODES: {
|
|
|
12
13
|
readonly CONFIGURATION_MISSING: "configuration-missing";
|
|
13
14
|
readonly DEPENDENCIES_NOT_INSTALLED: "dependencies-not-installed";
|
|
14
15
|
readonly DOCTOR_CHECK_FAILED: "doctor-check-failed";
|
|
16
|
+
readonly GENERATED_ARTIFACT_DRIFT: "generated-artifact-drift";
|
|
15
17
|
readonly INVALID_ARGUMENT: "invalid-argument";
|
|
16
18
|
readonly INVALID_COMMAND: "invalid-command";
|
|
17
19
|
readonly MISSING_ARGUMENT: "missing-argument";
|
|
@@ -52,6 +54,10 @@ export declare const CLI_DIAGNOSTIC_CODE_METADATA: {
|
|
|
52
54
|
cause: string;
|
|
53
55
|
recovery: string;
|
|
54
56
|
};
|
|
57
|
+
"generated-artifact-drift": {
|
|
58
|
+
cause: string;
|
|
59
|
+
recovery: string;
|
|
60
|
+
};
|
|
55
61
|
"invalid-argument": {
|
|
56
62
|
cause: string;
|
|
57
63
|
recovery: string;
|
|
@@ -104,6 +110,7 @@ type DoctorCheckLike = {
|
|
|
104
110
|
export declare class CliDiagnosticError extends Error {
|
|
105
111
|
readonly code: CliDiagnosticCode;
|
|
106
112
|
readonly command: string;
|
|
113
|
+
readonly data?: Record<string, unknown>;
|
|
107
114
|
readonly detailLines: string[];
|
|
108
115
|
readonly summary: string;
|
|
109
116
|
constructor(message: CliDiagnosticMessage, options?: ErrorOptions);
|
|
@@ -130,6 +137,7 @@ export declare function createCliDiagnosticCodeError<TCode extends CliDiagnostic
|
|
|
130
137
|
export declare function createCliCommandError(options: {
|
|
131
138
|
command: string;
|
|
132
139
|
code?: CliDiagnosticCode;
|
|
140
|
+
data?: Record<string, unknown>;
|
|
133
141
|
detailLines?: string[];
|
|
134
142
|
error?: unknown;
|
|
135
143
|
summary?: string;
|
|
@@ -142,6 +150,7 @@ export declare function formatCliDiagnosticError(error: unknown): string;
|
|
|
142
150
|
export declare function serializeCliDiagnosticError(error: unknown): {
|
|
143
151
|
code: CliDiagnosticCode;
|
|
144
152
|
command?: string;
|
|
153
|
+
data?: Record<string, unknown>;
|
|
145
154
|
detailLines?: string[];
|
|
146
155
|
kind: "command-execution";
|
|
147
156
|
message: string;
|
|
@@ -3,6 +3,7 @@ export const CLI_DIAGNOSTIC_CODES = {
|
|
|
3
3
|
CONFIGURATION_MISSING: "configuration-missing",
|
|
4
4
|
DEPENDENCIES_NOT_INSTALLED: "dependencies-not-installed",
|
|
5
5
|
DOCTOR_CHECK_FAILED: "doctor-check-failed",
|
|
6
|
+
GENERATED_ARTIFACT_DRIFT: "generated-artifact-drift",
|
|
6
7
|
INVALID_ARGUMENT: "invalid-argument",
|
|
7
8
|
INVALID_COMMAND: "invalid-command",
|
|
8
9
|
MISSING_ARGUMENT: "missing-argument",
|
|
@@ -33,6 +34,10 @@ export const CLI_DIAGNOSTIC_CODE_METADATA = {
|
|
|
33
34
|
cause: "One or more doctor checks reported a failing environment or workspace row.",
|
|
34
35
|
recovery: "Inspect the failed check labels and details, fix the reported drift or missing prerequisite, then rerun `wp-typia doctor`.",
|
|
35
36
|
},
|
|
37
|
+
[CLI_DIAGNOSTIC_CODES.GENERATED_ARTIFACT_DRIFT]: {
|
|
38
|
+
cause: "One or more generated project artifacts are missing or differ from the TypeScript source of truth.",
|
|
39
|
+
recovery: "Run the reported project sync command to regenerate artifacts, then rerun `wp-typia sync --check`.",
|
|
40
|
+
},
|
|
36
41
|
[CLI_DIAGNOSTIC_CODES.INVALID_ARGUMENT]: {
|
|
37
42
|
cause: "An argument was present but did not match the supported value, shape, or project state.",
|
|
38
43
|
recovery: "Correct the argument value using command help or the detail lines, then rerun the command.",
|
|
@@ -182,6 +187,7 @@ export class CliDiagnosticError extends Error {
|
|
|
182
187
|
super(formatCliDiagnosticBlock(message), options);
|
|
183
188
|
this.code = message.code;
|
|
184
189
|
this.command = message.command;
|
|
190
|
+
this.data = message.data ? { ...message.data } : undefined;
|
|
185
191
|
this.detailLines = [...message.detailLines];
|
|
186
192
|
this.name = "CliDiagnosticError";
|
|
187
193
|
this.summary = message.summary;
|
|
@@ -301,6 +307,7 @@ export function createCliCommandError(options) {
|
|
|
301
307
|
return new CliDiagnosticError({
|
|
302
308
|
code,
|
|
303
309
|
command: options.command,
|
|
310
|
+
...(options.data ? { data: options.data } : {}),
|
|
304
311
|
detailLines,
|
|
305
312
|
summary,
|
|
306
313
|
}, options.error instanceof Error ? { cause: options.error } : undefined);
|
|
@@ -325,6 +332,7 @@ export function serializeCliDiagnosticError(error) {
|
|
|
325
332
|
return {
|
|
326
333
|
code: error.code,
|
|
327
334
|
command: error.command,
|
|
335
|
+
...(error.data ? { data: { ...error.data } } : {}),
|
|
328
336
|
detailLines: [...error.detailLines],
|
|
329
337
|
kind: "command-execution",
|
|
330
338
|
message: formatCliDiagnosticBlock({
|
|
@@ -2,7 +2,7 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { CLI_DIAGNOSTIC_CODES, createCliDiagnosticCodeError, } from "./cli-diagnostics.js";
|
|
4
4
|
import { getPackageManager, transformPackageManagerText, } from "../shared/package-managers.js";
|
|
5
|
-
import { getPackageVersions } from "../shared/package-versions.js";
|
|
5
|
+
import { DEFAULT_WORDPRESS_BLOCKS_TYPES_VERSION, DEFAULT_WORDPRESS_BLOCKS_VERSION, getPackageVersions, } from "../shared/package-versions.js";
|
|
6
6
|
import { readJsonFileSync } from "../shared/json-utils.js";
|
|
7
7
|
import { parseWorkspacePackageManagerId } from "../workspace/workspace-project.js";
|
|
8
8
|
const BASE_RETROFIT_SCRIPTS = {
|
|
@@ -12,6 +12,8 @@ const BASE_RETROFIT_SCRIPTS = {
|
|
|
12
12
|
};
|
|
13
13
|
const BASE_RETROFIT_DEV_DEPENDENCIES = [
|
|
14
14
|
"@typia/unplugin",
|
|
15
|
+
"@types/wordpress__blocks",
|
|
16
|
+
"@wordpress/blocks",
|
|
15
17
|
"@wp-typia/block-runtime",
|
|
16
18
|
"@wp-typia/block-types",
|
|
17
19
|
"tsx",
|
|
@@ -72,6 +74,8 @@ function buildRequiredDevDependencyMap() {
|
|
|
72
74
|
const versions = getPackageVersions();
|
|
73
75
|
return {
|
|
74
76
|
"@typia/unplugin": versions.typiaUnpluginPackageVersion,
|
|
77
|
+
"@types/wordpress__blocks": DEFAULT_WORDPRESS_BLOCKS_TYPES_VERSION,
|
|
78
|
+
"@wordpress/blocks": DEFAULT_WORDPRESS_BLOCKS_VERSION,
|
|
75
79
|
"@wp-typia/block-runtime": versions.blockRuntimePackageVersion,
|
|
76
80
|
"@wp-typia/block-types": versions.blockTypesPackageVersion,
|
|
77
81
|
tsx: versions.tsxPackageVersion,
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
export interface CanonicalRuntimeImportShape {
|
|
3
|
+
defaultBinding?: string;
|
|
4
|
+
namedBindings?: ReadonlySet<string>;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Check whether a generated sync helper statement is inert until main() runs.
|
|
8
|
+
* Runtime imports are limited to the modules used by that helper; all other
|
|
9
|
+
* imports must be erased by TypeScript.
|
|
10
|
+
*/
|
|
11
|
+
export declare function isAllowedSyncHelperTopLevelStatement(statement: ts.Statement, allowedRuntimeImportModules: ReadonlySet<string>, isAllowedVariableStatement?: (statement: ts.VariableStatement) => boolean): boolean;
|
|
12
|
+
/** Require runtime imports to match the generated helper's load-time API. */
|
|
13
|
+
export declare function hasCanonicalRuntimeImports(sourceFile: ts.SourceFile, expectedImports: ReadonlyMap<string, CanonicalRuntimeImportShape>): boolean;
|
|
14
|
+
/** Find a control-flow completion without crossing a nested function boundary. */
|
|
15
|
+
export declare function containsCompletion(node: ts.Node, isTerminal: (candidate: ts.Node) => boolean): boolean;
|
|
16
|
+
/** Unwrap supported static TypeScript wrappers to reach the underlying expression. */
|
|
17
|
+
export declare function unwrapStaticExpression(expression: ts.Expression): ts.Expression;
|
|
18
|
+
/** Validate the generated main().catch() failure boundary. */
|
|
19
|
+
export declare function isCanonicalSyncMainCatchHandler(rawHandler: ts.Expression): boolean;
|
|
20
|
+
/** Return a side-effect-free `new Error(message)` expression when present. */
|
|
21
|
+
export declare function getSafeErrorConstruction(rawExpression: ts.Expression): ts.NewExpression | null;
|
|
22
|
+
/** Validate a side-effect-free `new Error(message)` expression. */
|
|
23
|
+
export declare function isSafeErrorConstruction(rawExpression: ts.Expression): boolean;
|
|
24
|
+
/** Require the generated parser's terminal unknown-flag failure. */
|
|
25
|
+
export declare function hasCanonicalUnknownFlagThrow(body: ts.Statement, argumentBinding: string): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Reject executable parser work beyond the generated option assignments.
|
|
28
|
+
* Parser bodies are inspected rather than executed by doctor, so accepting an
|
|
29
|
+
* unrelated call or mutation here would let the real sync command diverge from
|
|
30
|
+
* the replayed options.
|
|
31
|
+
*/
|
|
32
|
+
export declare function hasOnlyCanonicalParserEffects(node: ts.Node, optionsBinding: string, indexBinding?: string | null): boolean;
|
|
33
|
+
/** Count continues that target the generated parser's outer argument loop. */
|
|
34
|
+
export declare function countOuterParserContinues(node: ts.Node): number;
|
|
35
|
+
/** Detect a static process.exit() call, regardless of its exit code. */
|
|
36
|
+
export declare function isProcessExitCompletion(node: ts.Node): boolean;
|
|
37
|
+
/** Check whether a prior statement can terminate the current function. */
|
|
38
|
+
export declare function hasEarlierAbruptCompletion(statements: readonly ts.Statement[], statementIndex: number): boolean;
|