@wp-typia/project-tools 0.22.5 → 0.22.6
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-capability.js +20 -0
- package/dist/runtime/cli-add-block.js +16 -11
- package/dist/runtime/cli-add-collision.js +213 -136
- package/dist/runtime/cli-add-help.js +1 -1
- package/dist/runtime/cli-add-kind-ids.d.ts +11 -0
- package/dist/runtime/cli-add-kind-ids.js +20 -0
- package/dist/runtime/cli-add-types.d.ts +2 -8
- package/dist/runtime/cli-add-types.js +1 -17
- package/dist/runtime/cli-add-workspace-ability-scaffold.d.ts +3 -1
- package/dist/runtime/cli-add-workspace-ability-scaffold.js +22 -5
- package/dist/runtime/cli-add-workspace-ability.d.ts +4 -0
- package/dist/runtime/cli-add-workspace-ability.js +5 -1
- package/dist/runtime/cli-add-workspace-admin-view-source.d.ts +7 -0
- package/dist/runtime/cli-add-workspace-admin-view-source.js +9 -10
- package/dist/runtime/cli-add-workspace-admin-view-types.d.ts +0 -2
- package/dist/runtime/cli-add-workspace-admin-view-types.js +0 -3
- package/dist/runtime/cli-add-workspace-ai-scaffold.js +14 -6
- package/dist/runtime/cli-doctor-workspace-bindings.js +2 -3
- package/dist/runtime/cli-doctor-workspace-blocks.js +2 -3
- package/dist/runtime/cli-doctor-workspace-features.js +6 -11
- package/dist/runtime/cli-doctor-workspace-shared.d.ts +8 -0
- package/dist/runtime/cli-doctor-workspace-shared.js +10 -0
- package/dist/runtime/cli-help.js +1 -1
- package/dist/runtime/cli-init-apply.d.ts +15 -0
- package/dist/runtime/cli-init-apply.js +99 -0
- package/dist/runtime/cli-init-package-json.d.ts +19 -0
- package/dist/runtime/cli-init-package-json.js +191 -0
- package/dist/runtime/cli-init-plan.d.ts +39 -0
- package/dist/runtime/cli-init-plan.js +375 -0
- package/dist/runtime/cli-init-templates.d.ts +27 -0
- package/dist/runtime/cli-init-templates.js +244 -0
- package/dist/runtime/cli-init-types.d.ts +84 -0
- package/dist/runtime/cli-init-types.js +3 -0
- package/dist/runtime/cli-init.d.ts +4 -100
- package/dist/runtime/cli-init.js +6 -878
- package/dist/runtime/fs-async.d.ts +28 -0
- package/dist/runtime/fs-async.js +53 -0
- package/dist/runtime/package-managers.js +1 -1
- package/dist/runtime/php-utils.d.ts +16 -0
- package/dist/runtime/php-utils.js +321 -1
- package/dist/runtime/scaffold-apply-utils.js +10 -20
- package/dist/runtime/scaffold-bootstrap.js +6 -8
- package/dist/runtime/scaffold-compatibility.d.ts +15 -3
- package/dist/runtime/scaffold-compatibility.js +42 -11
- package/dist/runtime/scaffold-documents.js +12 -0
- package/dist/runtime/scaffold-package-manager-files.js +4 -3
- package/dist/runtime/string-case.d.ts +5 -0
- package/dist/runtime/string-case.js +52 -2
- package/dist/runtime/template-source-cache.d.ts +19 -0
- package/dist/runtime/template-source-cache.js +164 -28
- package/dist/runtime/template-source-external.d.ts +7 -0
- package/dist/runtime/template-source-external.js +22 -5
- package/dist/runtime/template-source-normalization.d.ts +1 -1
- package/dist/runtime/template-source-normalization.js +12 -12
- package/dist/runtime/template-source-remote.d.ts +14 -0
- package/dist/runtime/template-source-remote.js +91 -15
- package/dist/runtime/template-source.js +35 -25
- package/dist/runtime/typia-llm.js +7 -0
- package/dist/runtime/version-floor.js +8 -2
- package/dist/runtime/workspace-inventory.d.ts +16 -14
- package/dist/runtime/workspace-inventory.js +58 -14
- package/package.json +6 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/// <reference path="./external-template-modules.d.ts" />
|
|
2
|
-
import fs from 'node:fs';
|
|
3
2
|
import path from 'node:path';
|
|
4
3
|
import { loadExternalTemplateLayerManifest } from './template-layers.js';
|
|
5
4
|
import { getPackageVersions } from './package-versions.js';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
5
|
+
import { findExternalTemplateEntry } from './template-source-external.js';
|
|
6
|
+
import { getTemplateProjectTypeAsync } from './template-source-remote.js';
|
|
7
|
+
import { pathExists } from './fs-async.js';
|
|
8
8
|
export { renderCreateBlockExternalTemplate } from './template-source-external.js';
|
|
9
|
-
export { getTemplateProjectType, getDefaultCategory, normalizeCreateBlockSubset, normalizeWpTypiaTemplateSeed, } from './template-source-remote.js';
|
|
9
|
+
export { getTemplateProjectType, getTemplateProjectTypeAsync, getDefaultCategory, getDefaultCategoryAsync, normalizeCreateBlockSubset, normalizeWpTypiaTemplateSeed, } from './template-source-remote.js';
|
|
10
10
|
export function getTemplateVariableContext(variables) {
|
|
11
11
|
const { apiClientPackageVersion, blockRuntimePackageVersion, blockTypesPackageVersion, projectToolsPackageVersion, restPackageVersion, } = getPackageVersions();
|
|
12
12
|
return {
|
|
@@ -27,29 +27,29 @@ export function getTemplateVariableContext(variables) {
|
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
29
|
export async function detectTemplateSourceFormat(sourceDir) {
|
|
30
|
-
if (
|
|
30
|
+
if (await pathExists(path.join(sourceDir, 'package.json.mustache'))) {
|
|
31
31
|
return 'wp-typia';
|
|
32
32
|
}
|
|
33
33
|
if (await loadExternalTemplateLayerManifest(sourceDir)) {
|
|
34
34
|
throw new Error(`Template source at ${sourceDir} is an external layer package. External layers currently compose only through built-in scaffolds via the runtime API, not as standalone template ids.`);
|
|
35
35
|
}
|
|
36
|
-
if (
|
|
36
|
+
if (await findExternalTemplateEntry(sourceDir)) {
|
|
37
37
|
return 'create-block-external';
|
|
38
38
|
}
|
|
39
|
-
if (
|
|
39
|
+
if ((await getTemplateProjectTypeAsync(sourceDir)) !== null) {
|
|
40
40
|
return 'wp-typia';
|
|
41
41
|
}
|
|
42
|
-
const sourceRoot =
|
|
42
|
+
const sourceRoot = await pathExists(path.join(sourceDir, 'src'))
|
|
43
43
|
? path.join(sourceDir, 'src')
|
|
44
44
|
: sourceDir;
|
|
45
45
|
const blockJsonCandidates = [
|
|
46
46
|
path.join(sourceDir, 'block.json'),
|
|
47
47
|
path.join(sourceRoot, 'block.json'),
|
|
48
48
|
];
|
|
49
|
-
const hasBlockJson = blockJsonCandidates.
|
|
50
|
-
const hasIndexFile = ['index.js', 'index.jsx', 'index.ts', 'index.tsx'].
|
|
51
|
-
const hasEditFile = ['edit.js', 'edit.jsx', 'edit.ts', 'edit.tsx'].
|
|
52
|
-
const hasSaveFile = ['save.js', 'save.jsx', 'save.ts', 'save.tsx'].
|
|
49
|
+
const hasBlockJson = (await Promise.all(blockJsonCandidates.map((candidate) => pathExists(candidate)))).some(Boolean);
|
|
50
|
+
const hasIndexFile = (await Promise.all(['index.js', 'index.jsx', 'index.ts', 'index.tsx'].map((filename) => pathExists(path.join(sourceRoot, filename))))).some(Boolean);
|
|
51
|
+
const hasEditFile = (await Promise.all(['edit.js', 'edit.jsx', 'edit.ts', 'edit.tsx'].map((filename) => pathExists(path.join(sourceRoot, filename))))).some(Boolean);
|
|
52
|
+
const hasSaveFile = (await Promise.all(['save.js', 'save.jsx', 'save.ts', 'save.tsx'].map((filename) => pathExists(path.join(sourceRoot, filename))))).some(Boolean);
|
|
53
53
|
if (hasBlockJson && hasIndexFile && hasEditFile && hasSaveFile) {
|
|
54
54
|
return 'create-block-subset';
|
|
55
55
|
}
|
|
@@ -6,11 +6,25 @@ import type { ResolvedTemplateSource, SeedSource, TemplateVariableContext } from
|
|
|
6
6
|
* @returns The declared block category, or "widgets" when detection fails.
|
|
7
7
|
*/
|
|
8
8
|
export declare function getDefaultCategory(sourceDir: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Read a remote block source and return its default block category asynchronously.
|
|
11
|
+
*
|
|
12
|
+
* @param sourceDir Block source directory that may contain a block.json file.
|
|
13
|
+
* @returns The declared block category, or "widgets" when detection fails.
|
|
14
|
+
*/
|
|
15
|
+
export declare function getDefaultCategoryAsync(sourceDir: string): Promise<string>;
|
|
9
16
|
/**
|
|
10
17
|
* Read `wpTypia.projectType` from a rendered or source template package
|
|
11
18
|
* manifest and return it when present.
|
|
12
19
|
*/
|
|
13
20
|
export declare function getTemplateProjectType(sourceDir: string): string | null;
|
|
21
|
+
/**
|
|
22
|
+
* Read `wpTypia.projectType` from template metadata asynchronously.
|
|
23
|
+
*
|
|
24
|
+
* @param sourceDir Template source directory to inspect.
|
|
25
|
+
* @returns The project type when present, otherwise `null`.
|
|
26
|
+
*/
|
|
27
|
+
export declare function getTemplateProjectTypeAsync(sourceDir: string): Promise<string | null>;
|
|
14
28
|
/**
|
|
15
29
|
* Copy a wp-typia seed into a normalized temporary template directory.
|
|
16
30
|
*
|
|
@@ -5,6 +5,7 @@ import { assertExternalTemplateFileSize, getExternalTemplatePackageJsonMaxBytes,
|
|
|
5
5
|
import { getBuiltInTemplateLayerDirs, isOmittableBuiltInTemplateLayerDir, } from './template-builtins.js';
|
|
6
6
|
import { copyRawDirectory } from './template-render.js';
|
|
7
7
|
import { createManagedTempRoot } from './temp-roots.js';
|
|
8
|
+
import { pathExists } from './fs-async.js';
|
|
8
9
|
async function cleanupSeedRootPair(cleanup, seedCleanup) {
|
|
9
10
|
let cleanupError;
|
|
10
11
|
try {
|
|
@@ -43,6 +44,18 @@ function readRemoteBlockJson(blockDir) {
|
|
|
43
44
|
}
|
|
44
45
|
throw new Error(`Unable to locate block.json in ${blockDir}`);
|
|
45
46
|
}
|
|
47
|
+
async function readRemoteBlockJsonAsync(blockDir) {
|
|
48
|
+
const sourceRoot = await getSeedSourceRoot(blockDir);
|
|
49
|
+
for (const candidate of [
|
|
50
|
+
path.join(blockDir, 'block.json'),
|
|
51
|
+
path.join(sourceRoot, 'block.json'),
|
|
52
|
+
]) {
|
|
53
|
+
if (await pathExists(candidate)) {
|
|
54
|
+
return JSON.parse(await fsp.readFile(candidate, 'utf8'));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
throw new Error(`Unable to locate block.json in ${blockDir}`);
|
|
58
|
+
}
|
|
46
59
|
/**
|
|
47
60
|
* Read a remote block source and return its default block category.
|
|
48
61
|
*
|
|
@@ -58,6 +71,21 @@ export function getDefaultCategory(sourceDir) {
|
|
|
58
71
|
return 'widgets';
|
|
59
72
|
}
|
|
60
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Read a remote block source and return its default block category asynchronously.
|
|
76
|
+
*
|
|
77
|
+
* @param sourceDir Block source directory that may contain a block.json file.
|
|
78
|
+
* @returns The declared block category, or "widgets" when detection fails.
|
|
79
|
+
*/
|
|
80
|
+
export async function getDefaultCategoryAsync(sourceDir) {
|
|
81
|
+
try {
|
|
82
|
+
const blockJson = await readRemoteBlockJsonAsync(sourceDir);
|
|
83
|
+
return getDefaultCategoryFromBlockJson(blockJson);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return 'widgets';
|
|
87
|
+
}
|
|
88
|
+
}
|
|
61
89
|
function readTemplatePackageJson(sourceDir) {
|
|
62
90
|
for (const candidate of [
|
|
63
91
|
path.join(sourceDir, 'package.json.mustache'),
|
|
@@ -83,6 +111,31 @@ function readTemplatePackageJson(sourceDir) {
|
|
|
83
111
|
}
|
|
84
112
|
return null;
|
|
85
113
|
}
|
|
114
|
+
async function readTemplatePackageJsonAsync(sourceDir) {
|
|
115
|
+
for (const candidate of [
|
|
116
|
+
path.join(sourceDir, 'package.json.mustache'),
|
|
117
|
+
path.join(sourceDir, 'package.json'),
|
|
118
|
+
]) {
|
|
119
|
+
if (!(await pathExists(candidate))) {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
try {
|
|
123
|
+
assertExternalTemplateFileSize(candidate, {
|
|
124
|
+
label: `Template metadata file "${candidate}"`,
|
|
125
|
+
maxBytes: getExternalTemplatePackageJsonMaxBytes(),
|
|
126
|
+
});
|
|
127
|
+
return {
|
|
128
|
+
packageJson: JSON.parse(await fsp.readFile(candidate, 'utf8')),
|
|
129
|
+
sourcePath: candidate,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
const message = error instanceof Error ? error.message : 'Unknown parse failure';
|
|
134
|
+
throw new Error(`Failed to parse template metadata file "${candidate}": ${message}`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
86
139
|
/**
|
|
87
140
|
* Read `wpTypia.projectType` from a rendered or source template package
|
|
88
141
|
* manifest and return it when present.
|
|
@@ -101,6 +154,26 @@ export function getTemplateProjectType(sourceDir) {
|
|
|
101
154
|
}
|
|
102
155
|
return projectType;
|
|
103
156
|
}
|
|
157
|
+
/**
|
|
158
|
+
* Read `wpTypia.projectType` from template metadata asynchronously.
|
|
159
|
+
*
|
|
160
|
+
* @param sourceDir Template source directory to inspect.
|
|
161
|
+
* @returns The project type when present, otherwise `null`.
|
|
162
|
+
*/
|
|
163
|
+
export async function getTemplateProjectTypeAsync(sourceDir) {
|
|
164
|
+
const packageJsonEntry = await readTemplatePackageJsonAsync(sourceDir);
|
|
165
|
+
if (!packageJsonEntry) {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
const projectType = packageJsonEntry.packageJson.wpTypia?.projectType;
|
|
169
|
+
if (projectType === undefined) {
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
if (typeof projectType !== 'string' || projectType.trim().length === 0) {
|
|
173
|
+
throw new Error(`Template metadata file "${packageJsonEntry.sourcePath}" defines wpTypia.projectType, but it must be a non-empty string.`);
|
|
174
|
+
}
|
|
175
|
+
return projectType;
|
|
176
|
+
}
|
|
104
177
|
/**
|
|
105
178
|
* Copy a wp-typia seed into a normalized temporary template directory.
|
|
106
179
|
*
|
|
@@ -119,7 +192,7 @@ export async function normalizeWpTypiaTemplateSeed(seed) {
|
|
|
119
192
|
fs.existsSync(mustacheVariantPath));
|
|
120
193
|
},
|
|
121
194
|
});
|
|
122
|
-
if (seed.assetsDir &&
|
|
195
|
+
if (seed.assetsDir && (await pathExists(seed.assetsDir))) {
|
|
123
196
|
await fsp.cp(seed.assetsDir, path.join(normalizedDir, 'assets'), {
|
|
124
197
|
recursive: true,
|
|
125
198
|
force: true,
|
|
@@ -268,17 +341,17 @@ async function patchRemotePackageJson(templateDir, needsInteractivity) {
|
|
|
268
341
|
}
|
|
269
342
|
await fsp.writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`, 'utf8');
|
|
270
343
|
}
|
|
271
|
-
function getSeedSourceRoot(blockDir) {
|
|
272
|
-
return
|
|
344
|
+
async function getSeedSourceRoot(blockDir) {
|
|
345
|
+
return (await pathExists(path.join(blockDir, 'src')))
|
|
273
346
|
? path.join(blockDir, 'src')
|
|
274
347
|
: blockDir;
|
|
275
348
|
}
|
|
276
|
-
function findSeedRenderPhp(seed) {
|
|
349
|
+
async function findSeedRenderPhp(seed) {
|
|
277
350
|
for (const candidate of [
|
|
278
351
|
path.join(seed.blockDir, 'render.php'),
|
|
279
352
|
path.join(seed.rootDir, 'render.php'),
|
|
280
353
|
]) {
|
|
281
|
-
if (
|
|
354
|
+
if (await pathExists(candidate)) {
|
|
282
355
|
return candidate;
|
|
283
356
|
}
|
|
284
357
|
}
|
|
@@ -331,11 +404,11 @@ export async function normalizeCreateBlockSubset(seed, context) {
|
|
|
331
404
|
const { path: tempRoot, cleanup } = await createManagedTempRoot('wp-typia-remote-template-');
|
|
332
405
|
try {
|
|
333
406
|
const templateDir = path.join(tempRoot, 'template');
|
|
334
|
-
const blockJson =
|
|
335
|
-
const sourceRoot = getSeedSourceRoot(seed.blockDir);
|
|
407
|
+
const blockJson = await readRemoteBlockJsonAsync(seed.blockDir);
|
|
408
|
+
const sourceRoot = await getSeedSourceRoot(seed.blockDir);
|
|
336
409
|
await fsp.mkdir(templateDir, { recursive: true });
|
|
337
410
|
for (const layerDir of getBuiltInTemplateLayerDirs('basic')) {
|
|
338
|
-
if (!
|
|
411
|
+
if (!(await pathExists(layerDir))) {
|
|
339
412
|
if (isOmittableBuiltInTemplateLayerDir('basic', layerDir)) {
|
|
340
413
|
continue;
|
|
341
414
|
}
|
|
@@ -351,11 +424,11 @@ export async function normalizeCreateBlockSubset(seed, context) {
|
|
|
351
424
|
recursive: true,
|
|
352
425
|
force: true,
|
|
353
426
|
});
|
|
354
|
-
const remoteRenderPath = findSeedRenderPhp(seed);
|
|
427
|
+
const remoteRenderPath = await findSeedRenderPhp(seed);
|
|
355
428
|
if (remoteRenderPath) {
|
|
356
429
|
await fsp.copyFile(remoteRenderPath, path.join(templateDir, 'render.php'));
|
|
357
430
|
}
|
|
358
|
-
if (seed.assetsDir &&
|
|
431
|
+
if (seed.assetsDir && (await pathExists(seed.assetsDir))) {
|
|
359
432
|
await fsp.cp(seed.assetsDir, path.join(templateDir, 'assets'), {
|
|
360
433
|
recursive: true,
|
|
361
434
|
force: true,
|
|
@@ -366,11 +439,14 @@ export async function normalizeCreateBlockSubset(seed, context) {
|
|
|
366
439
|
await rewriteBlockJsonImports(path.join(templateDir, 'src'));
|
|
367
440
|
const needsInteractivity = typeof blockJson.viewScriptModule === 'string' ||
|
|
368
441
|
typeof blockJson.viewScript === 'string' ||
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
442
|
+
(await Promise.all([
|
|
443
|
+
'view.js',
|
|
444
|
+
'view.jsx',
|
|
445
|
+
'view.ts',
|
|
446
|
+
'view.tsx',
|
|
447
|
+
'interactivity.js',
|
|
448
|
+
'interactivity.ts',
|
|
449
|
+
].map((filename) => pathExists(path.join(templateDir, 'src', filename))))).some(Boolean);
|
|
374
450
|
await patchRemotePackageJson(templateDir, needsInteractivity);
|
|
375
451
|
return {
|
|
376
452
|
id: 'remote:create-block-subset',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { OFFICIAL_WORKSPACE_TEMPLATE_PACKAGE, isBuiltInTemplateId, } from './template-registry.js';
|
|
2
2
|
import { resolveBuiltInTemplateSource } from './template-builtins.js';
|
|
3
3
|
import { parseTemplateLocator, } from './template-source-locators.js';
|
|
4
|
-
import { detectTemplateSourceFormat,
|
|
4
|
+
import { detectTemplateSourceFormat, getTemplateProjectTypeAsync, getDefaultCategoryAsync, getTemplateVariableContext, normalizeCreateBlockSubset, normalizeWpTypiaTemplateSeed, renderCreateBlockExternalTemplate, } from './template-source-normalization.js';
|
|
5
5
|
import { isOfficialWorkspaceTemplateSeed, resolveTemplateSeed, } from './template-source-seeds.js';
|
|
6
6
|
import { assertBuiltInTemplateVariantAllowed, } from './cli-validation.js';
|
|
7
7
|
import { getScaffoldTemplateVariableGroups } from './scaffold-template-variable-groups.js';
|
|
@@ -36,10 +36,10 @@ export async function resolveTemplateSource(templateId, cwd, variables, variant)
|
|
|
36
36
|
throw new Error(`--variant is only supported for official external template configs. Received variant "${variant}" for "${templateId}".`);
|
|
37
37
|
}
|
|
38
38
|
normalizedSeed = await normalizeWpTypiaTemplateSeed(seed);
|
|
39
|
-
const supportsMigrationUi =
|
|
39
|
+
const supportsMigrationUi = (await getTemplateProjectTypeAsync(seed.blockDir)) === 'workspace';
|
|
40
40
|
return {
|
|
41
41
|
id: templateId,
|
|
42
|
-
defaultCategory:
|
|
42
|
+
defaultCategory: await getDefaultCategoryAsync(seed.blockDir),
|
|
43
43
|
description: 'A remote wp-typia template source',
|
|
44
44
|
features: ['Remote source', 'wp-typia format'],
|
|
45
45
|
format,
|
|
@@ -62,28 +62,38 @@ export async function resolveTemplateSource(templateId, cwd, variables, variant)
|
|
|
62
62
|
(await detectTemplateSourceFormat(normalizedSeed.blockDir));
|
|
63
63
|
if (renderedFormat === 'wp-typia') {
|
|
64
64
|
const normalized = await normalizeWpTypiaTemplateSeed(normalizedSeed);
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
65
|
+
try {
|
|
66
|
+
const [projectType, defaultCategory] = await Promise.all([
|
|
67
|
+
getTemplateProjectTypeAsync(normalizedSeed.blockDir),
|
|
68
|
+
getDefaultCategoryAsync(normalizedSeed.blockDir),
|
|
69
|
+
]);
|
|
70
|
+
const supportsMigrationUi = projectType === 'workspace';
|
|
71
|
+
return {
|
|
72
|
+
cleanup: async () => {
|
|
73
|
+
await normalized.cleanup?.();
|
|
74
|
+
await seed.cleanup?.();
|
|
75
|
+
},
|
|
76
|
+
defaultCategory,
|
|
77
|
+
description: 'A wp-typia scaffold normalized from an official external template config',
|
|
78
|
+
features: [
|
|
79
|
+
'Remote source',
|
|
80
|
+
'official external template',
|
|
81
|
+
'wp-typia format',
|
|
82
|
+
...(supportsMigrationUi ? ['workspace-capable scaffold'] : []),
|
|
83
|
+
],
|
|
84
|
+
format,
|
|
85
|
+
id: 'remote:create-block-external',
|
|
86
|
+
isOfficialWorkspaceTemplate,
|
|
87
|
+
selectedVariant: normalizedSeed.selectedVariant ?? null,
|
|
88
|
+
supportsMigrationUi,
|
|
89
|
+
templateDir: normalized.blockDir,
|
|
90
|
+
warnings: normalizedSeed.warnings ?? [],
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
await normalized.cleanup?.();
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
87
97
|
}
|
|
88
98
|
const normalized = await normalizeCreateBlockSubset(normalizedSeed, context);
|
|
89
99
|
return {
|
|
@@ -164,6 +164,13 @@ function collectOpenApiSeenReferences(schema, seenReferences) {
|
|
|
164
164
|
}
|
|
165
165
|
return new Set([...seenReferences, reference]);
|
|
166
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* Copy constraint-oriented JSON Schema keywords from `source` into `target`.
|
|
169
|
+
*
|
|
170
|
+
* This helper intentionally mutates and returns `target` so nested OpenAPI
|
|
171
|
+
* constraint restoration can preserve the projected typia.llm schema shape.
|
|
172
|
+
* Callers that need immutable behavior should clone the target before calling.
|
|
173
|
+
*/
|
|
167
174
|
function mergeJsonSchemaConstraintProperties(document, target, source, seenReferences = new Set()) {
|
|
168
175
|
const nextSeenReferences = collectOpenApiSeenReferences(source, seenReferences);
|
|
169
176
|
const resolvedSource = resolveOpenApiSchemaObject(document, source, seenReferences);
|
|
@@ -46,10 +46,16 @@ export function compareVersionFloors(left, right) {
|
|
|
46
46
|
* @returns The higher defined floor, or undefined when neither value exists.
|
|
47
47
|
*/
|
|
48
48
|
export function pickHigherVersionFloor(current, candidate) {
|
|
49
|
-
if (
|
|
49
|
+
if (current !== undefined) {
|
|
50
|
+
parseVersionFloorParts(current);
|
|
51
|
+
}
|
|
52
|
+
if (candidate !== undefined) {
|
|
53
|
+
parseVersionFloorParts(candidate);
|
|
54
|
+
}
|
|
55
|
+
if (candidate === undefined) {
|
|
50
56
|
return current;
|
|
51
57
|
}
|
|
52
|
-
if (
|
|
58
|
+
if (current === undefined) {
|
|
53
59
|
return candidate;
|
|
54
60
|
}
|
|
55
61
|
return compareVersionFloors(current, candidate) >= 0 ? current : candidate;
|
|
@@ -156,6 +156,20 @@ export declare const ADMIN_VIEW_CONFIG_ENTRY_MARKER = "\t// wp-typia add admin-v
|
|
|
156
156
|
* Marker used to append generated editor-plugin entries into `EDITOR_PLUGINS`.
|
|
157
157
|
*/
|
|
158
158
|
export declare const EDITOR_PLUGIN_CONFIG_ENTRY_MARKER = "\t// wp-typia add editor-plugin entries";
|
|
159
|
+
type WorkspaceInventoryUpdateOptions = {
|
|
160
|
+
abilityEntries?: string[];
|
|
161
|
+
adminViewEntries?: string[];
|
|
162
|
+
aiFeatureEntries?: string[];
|
|
163
|
+
blockEntries?: string[];
|
|
164
|
+
blockStyleEntries?: string[];
|
|
165
|
+
blockTransformEntries?: string[];
|
|
166
|
+
bindingSourceEntries?: string[];
|
|
167
|
+
editorPluginEntries?: string[];
|
|
168
|
+
patternEntries?: string[];
|
|
169
|
+
restResourceEntries?: string[];
|
|
170
|
+
transformSource?: (source: string) => string;
|
|
171
|
+
variationEntries?: string[];
|
|
172
|
+
};
|
|
159
173
|
/**
|
|
160
174
|
* Parse workspace inventory entries from the source of `scripts/block-config.ts`.
|
|
161
175
|
*
|
|
@@ -199,20 +213,7 @@ export declare function getWorkspaceBlockSelectOptions(projectDir: string): Arra
|
|
|
199
213
|
* @param options Entry lists plus an optional source transformer.
|
|
200
214
|
* @returns Updated source text with all requested inventory entries appended.
|
|
201
215
|
*/
|
|
202
|
-
export declare function updateWorkspaceInventorySource(source: string,
|
|
203
|
-
abilityEntries?: string[];
|
|
204
|
-
adminViewEntries?: string[];
|
|
205
|
-
aiFeatureEntries?: string[];
|
|
206
|
-
blockEntries?: string[];
|
|
207
|
-
blockStyleEntries?: string[];
|
|
208
|
-
blockTransformEntries?: string[];
|
|
209
|
-
bindingSourceEntries?: string[];
|
|
210
|
-
editorPluginEntries?: string[];
|
|
211
|
-
patternEntries?: string[];
|
|
212
|
-
restResourceEntries?: string[];
|
|
213
|
-
transformSource?: (source: string) => string;
|
|
214
|
-
variationEntries?: string[];
|
|
215
|
-
}): string;
|
|
216
|
+
export declare function updateWorkspaceInventorySource(source: string, options?: WorkspaceInventoryUpdateOptions): string;
|
|
216
217
|
/**
|
|
217
218
|
* Append new entries to the canonical workspace inventory file on disk.
|
|
218
219
|
*
|
|
@@ -222,3 +223,4 @@ export declare function updateWorkspaceInventorySource(source: string, { blockEn
|
|
|
222
223
|
* @returns Resolves once `scripts/block-config.ts` has been updated if needed.
|
|
223
224
|
*/
|
|
224
225
|
export declare function appendWorkspaceInventoryEntries(projectDir: string, options: Parameters<typeof updateWorkspaceInventorySource>[1]): Promise<void>;
|
|
226
|
+
export {};
|
|
@@ -206,6 +206,10 @@ export const EDITOR_PLUGINS: WorkspaceEditorPluginConfig[] = [
|
|
|
206
206
|
];
|
|
207
207
|
`;
|
|
208
208
|
const BLOCK_INVENTORY_SECTION = {
|
|
209
|
+
append: {
|
|
210
|
+
marker: BLOCK_CONFIG_ENTRY_MARKER,
|
|
211
|
+
optionKey: "blockEntries",
|
|
212
|
+
},
|
|
209
213
|
parse: {
|
|
210
214
|
entriesKey: "blocks",
|
|
211
215
|
entry: defineInventoryEntryParser({
|
|
@@ -224,6 +228,10 @@ const BLOCK_INVENTORY_SECTION = {
|
|
|
224
228
|
};
|
|
225
229
|
const INVENTORY_SECTIONS = [
|
|
226
230
|
{
|
|
231
|
+
append: {
|
|
232
|
+
marker: VARIATION_CONFIG_ENTRY_MARKER,
|
|
233
|
+
optionKey: "variationEntries",
|
|
234
|
+
},
|
|
227
235
|
interface: {
|
|
228
236
|
name: "WorkspaceVariationConfig",
|
|
229
237
|
section: VARIATIONS_INTERFACE_SECTION,
|
|
@@ -246,6 +254,10 @@ const INVENTORY_SECTIONS = [
|
|
|
246
254
|
},
|
|
247
255
|
},
|
|
248
256
|
{
|
|
257
|
+
append: {
|
|
258
|
+
marker: BLOCK_STYLE_CONFIG_ENTRY_MARKER,
|
|
259
|
+
optionKey: "blockStyleEntries",
|
|
260
|
+
},
|
|
249
261
|
interface: {
|
|
250
262
|
name: "WorkspaceBlockStyleConfig",
|
|
251
263
|
section: BLOCK_STYLES_INTERFACE_SECTION,
|
|
@@ -268,6 +280,10 @@ const INVENTORY_SECTIONS = [
|
|
|
268
280
|
},
|
|
269
281
|
},
|
|
270
282
|
{
|
|
283
|
+
append: {
|
|
284
|
+
marker: BLOCK_TRANSFORM_CONFIG_ENTRY_MARKER,
|
|
285
|
+
optionKey: "blockTransformEntries",
|
|
286
|
+
},
|
|
271
287
|
interface: {
|
|
272
288
|
name: "WorkspaceBlockTransformConfig",
|
|
273
289
|
section: BLOCK_TRANSFORMS_INTERFACE_SECTION,
|
|
@@ -292,6 +308,10 @@ const INVENTORY_SECTIONS = [
|
|
|
292
308
|
},
|
|
293
309
|
},
|
|
294
310
|
{
|
|
311
|
+
append: {
|
|
312
|
+
marker: PATTERN_CONFIG_ENTRY_MARKER,
|
|
313
|
+
optionKey: "patternEntries",
|
|
314
|
+
},
|
|
295
315
|
interface: {
|
|
296
316
|
name: "WorkspacePatternConfig",
|
|
297
317
|
section: PATTERNS_INTERFACE_SECTION,
|
|
@@ -313,6 +333,10 @@ const INVENTORY_SECTIONS = [
|
|
|
313
333
|
},
|
|
314
334
|
},
|
|
315
335
|
{
|
|
336
|
+
append: {
|
|
337
|
+
marker: BINDING_SOURCE_CONFIG_ENTRY_MARKER,
|
|
338
|
+
optionKey: "bindingSourceEntries",
|
|
339
|
+
},
|
|
316
340
|
interface: {
|
|
317
341
|
name: "WorkspaceBindingSourceConfig",
|
|
318
342
|
section: BINDING_SOURCES_INTERFACE_SECTION,
|
|
@@ -337,6 +361,10 @@ const INVENTORY_SECTIONS = [
|
|
|
337
361
|
},
|
|
338
362
|
},
|
|
339
363
|
{
|
|
364
|
+
append: {
|
|
365
|
+
marker: REST_RESOURCE_CONFIG_ENTRY_MARKER,
|
|
366
|
+
optionKey: "restResourceEntries",
|
|
367
|
+
},
|
|
340
368
|
interface: {
|
|
341
369
|
name: "WorkspaceRestResourceConfig",
|
|
342
370
|
section: REST_RESOURCES_INTERFACE_SECTION,
|
|
@@ -377,6 +405,10 @@ const INVENTORY_SECTIONS = [
|
|
|
377
405
|
},
|
|
378
406
|
},
|
|
379
407
|
{
|
|
408
|
+
append: {
|
|
409
|
+
marker: ABILITY_CONFIG_ENTRY_MARKER,
|
|
410
|
+
optionKey: "abilityEntries",
|
|
411
|
+
},
|
|
380
412
|
interface: {
|
|
381
413
|
name: "WorkspaceAbilityConfig",
|
|
382
414
|
section: ABILITIES_INTERFACE_SECTION,
|
|
@@ -406,6 +438,10 @@ const INVENTORY_SECTIONS = [
|
|
|
406
438
|
},
|
|
407
439
|
},
|
|
408
440
|
{
|
|
441
|
+
append: {
|
|
442
|
+
marker: AI_FEATURE_CONFIG_ENTRY_MARKER,
|
|
443
|
+
optionKey: "aiFeatureEntries",
|
|
444
|
+
},
|
|
409
445
|
interface: {
|
|
410
446
|
name: "WorkspaceAiFeatureConfig",
|
|
411
447
|
section: AI_FEATURES_INTERFACE_SECTION,
|
|
@@ -435,6 +471,10 @@ const INVENTORY_SECTIONS = [
|
|
|
435
471
|
},
|
|
436
472
|
},
|
|
437
473
|
{
|
|
474
|
+
append: {
|
|
475
|
+
marker: ADMIN_VIEW_CONFIG_ENTRY_MARKER,
|
|
476
|
+
optionKey: "adminViewEntries",
|
|
477
|
+
},
|
|
438
478
|
interface: {
|
|
439
479
|
name: "WorkspaceAdminViewConfig",
|
|
440
480
|
section: ADMIN_VIEWS_INTERFACE_SECTION,
|
|
@@ -458,6 +498,10 @@ const INVENTORY_SECTIONS = [
|
|
|
458
498
|
},
|
|
459
499
|
},
|
|
460
500
|
{
|
|
501
|
+
append: {
|
|
502
|
+
marker: EDITOR_PLUGIN_CONFIG_ENTRY_MARKER,
|
|
503
|
+
optionKey: "editorPluginEntries",
|
|
504
|
+
},
|
|
461
505
|
interface: {
|
|
462
506
|
name: "WorkspaceEditorPluginConfig",
|
|
463
507
|
section: EDITOR_PLUGINS_INTERFACE_SECTION,
|
|
@@ -731,6 +775,16 @@ function appendEntriesAtMarker(source, marker, entries) {
|
|
|
731
775
|
}
|
|
732
776
|
return source.replace(marker, `${entries.join("\n")}\n${marker}`);
|
|
733
777
|
}
|
|
778
|
+
function appendInventorySectionEntries(source, options) {
|
|
779
|
+
let nextSource = source;
|
|
780
|
+
for (const section of [BLOCK_INVENTORY_SECTION, ...INVENTORY_SECTIONS]) {
|
|
781
|
+
if (!section.append) {
|
|
782
|
+
continue;
|
|
783
|
+
}
|
|
784
|
+
nextSource = appendEntriesAtMarker(nextSource, section.append.marker, options[section.append.optionKey] ?? []);
|
|
785
|
+
}
|
|
786
|
+
return nextSource;
|
|
787
|
+
}
|
|
734
788
|
function ensureInterfaceField(source, interfaceName, fieldName, fieldSource) {
|
|
735
789
|
const interfacePattern = new RegExp(`(export\\s+interface\\s+${escapeRegex(interfaceName)}\\s*\\{\\r?\\n)([\\s\\S]*?)(\\r?\\n\\})`, "u");
|
|
736
790
|
return source.replace(interfacePattern, (match, start, body, end) => {
|
|
@@ -789,28 +843,18 @@ function normalizeInterfaceFieldBlock(source, interfaceName, fieldName, fieldSou
|
|
|
789
843
|
* @param options Entry lists plus an optional source transformer.
|
|
790
844
|
* @returns Updated source text with all requested inventory entries appended.
|
|
791
845
|
*/
|
|
792
|
-
export function updateWorkspaceInventorySource(source,
|
|
846
|
+
export function updateWorkspaceInventorySource(source, options = {}) {
|
|
793
847
|
let nextSource = ensureWorkspaceInventorySections(source);
|
|
794
|
-
if (transformSource) {
|
|
795
|
-
nextSource = transformSource(nextSource);
|
|
848
|
+
if (options.transformSource) {
|
|
849
|
+
nextSource = options.transformSource(nextSource);
|
|
796
850
|
}
|
|
797
|
-
nextSource =
|
|
798
|
-
nextSource = appendEntriesAtMarker(nextSource, VARIATION_CONFIG_ENTRY_MARKER, variationEntries);
|
|
799
|
-
nextSource = appendEntriesAtMarker(nextSource, BLOCK_STYLE_CONFIG_ENTRY_MARKER, blockStyleEntries);
|
|
800
|
-
nextSource = appendEntriesAtMarker(nextSource, BLOCK_TRANSFORM_CONFIG_ENTRY_MARKER, blockTransformEntries);
|
|
801
|
-
nextSource = appendEntriesAtMarker(nextSource, PATTERN_CONFIG_ENTRY_MARKER, patternEntries);
|
|
802
|
-
nextSource = appendEntriesAtMarker(nextSource, BINDING_SOURCE_CONFIG_ENTRY_MARKER, bindingSourceEntries);
|
|
803
|
-
nextSource = appendEntriesAtMarker(nextSource, REST_RESOURCE_CONFIG_ENTRY_MARKER, restResourceEntries);
|
|
804
|
-
nextSource = appendEntriesAtMarker(nextSource, ABILITY_CONFIG_ENTRY_MARKER, abilityEntries);
|
|
805
|
-
nextSource = appendEntriesAtMarker(nextSource, AI_FEATURE_CONFIG_ENTRY_MARKER, aiFeatureEntries);
|
|
806
|
-
nextSource = appendEntriesAtMarker(nextSource, ADMIN_VIEW_CONFIG_ENTRY_MARKER, adminViewEntries);
|
|
851
|
+
nextSource = appendInventorySectionEntries(nextSource, options);
|
|
807
852
|
nextSource = ensureInterfaceField(nextSource, "WorkspaceBindingSourceConfig", "attribute", "\tattribute?: string;");
|
|
808
853
|
nextSource = ensureInterfaceField(nextSource, "WorkspaceBindingSourceConfig", "block", "\tblock?: string;");
|
|
809
854
|
nextSource = ensureInterfaceField(nextSource, "WorkspaceAbilityConfig", "compatibility", WORKSPACE_COMPATIBILITY_CONFIG_FIELD);
|
|
810
855
|
nextSource = normalizeInterfaceFieldBlock(nextSource, "WorkspaceAbilityConfig", "compatibility", WORKSPACE_COMPATIBILITY_CONFIG_FIELD, ["optionalFeatureIds: string[];", "requiredFeatureIds: string[];"]);
|
|
811
856
|
nextSource = ensureInterfaceField(nextSource, "WorkspaceAiFeatureConfig", "compatibility", WORKSPACE_COMPATIBILITY_CONFIG_FIELD);
|
|
812
857
|
nextSource = normalizeInterfaceFieldBlock(nextSource, "WorkspaceAiFeatureConfig", "compatibility", WORKSPACE_COMPATIBILITY_CONFIG_FIELD, ["optionalFeatureIds: string[];", "requiredFeatureIds: string[];"]);
|
|
813
|
-
nextSource = appendEntriesAtMarker(nextSource, EDITOR_PLUGIN_CONFIG_ENTRY_MARKER, editorPluginEntries);
|
|
814
858
|
return nextSource;
|
|
815
859
|
}
|
|
816
860
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wp-typia/project-tools",
|
|
3
|
-
"version": "0.22.
|
|
3
|
+
"version": "0.22.6",
|
|
4
4
|
"description": "Project orchestration and programmatic tooling for wp-typia",
|
|
5
5
|
"packageManager": "bun@1.3.11",
|
|
6
6
|
"type": "module",
|
|
@@ -17,6 +17,11 @@
|
|
|
17
17
|
"import": "./dist/runtime/cli-add.js",
|
|
18
18
|
"default": "./dist/runtime/cli-add.js"
|
|
19
19
|
},
|
|
20
|
+
"./cli-add-kind-ids": {
|
|
21
|
+
"types": "./dist/runtime/cli-add-kind-ids.d.ts",
|
|
22
|
+
"import": "./dist/runtime/cli-add-kind-ids.js",
|
|
23
|
+
"default": "./dist/runtime/cli-add-kind-ids.js"
|
|
24
|
+
},
|
|
20
25
|
"./cli-diagnostics": {
|
|
21
26
|
"types": "./dist/runtime/cli-diagnostics.d.ts",
|
|
22
27
|
"import": "./dist/runtime/cli-diagnostics.js",
|