@wp-typia/project-tools 0.24.10 → 0.24.12

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.
Files changed (68) hide show
  1. package/dist/runtime/add/cli-add-block-config.js +7 -15
  2. package/dist/runtime/add/cli-add-block-package-json.d.ts +5 -0
  3. package/dist/runtime/add/cli-add-block-package-json.js +32 -0
  4. package/dist/runtime/add/cli-add-block.js +17 -4
  5. package/dist/runtime/add/cli-add-workspace-admin-view-scaffold.js +1 -5
  6. package/dist/runtime/add/persistence-rest-artifacts.d.ts +32 -7
  7. package/dist/runtime/add/persistence-rest-artifacts.js +41 -15
  8. package/dist/runtime/cli/cli-diagnostics.d.ts +9 -0
  9. package/dist/runtime/cli/cli-diagnostics.js +8 -0
  10. package/dist/runtime/cli/cli-init-package-json.js +5 -1
  11. package/dist/runtime/doctor/cli-doctor-standalone-control-flow.d.ts +38 -0
  12. package/dist/runtime/doctor/cli-doctor-standalone-control-flow.js +365 -0
  13. package/dist/runtime/doctor/cli-doctor-standalone-rest.d.ts +21 -0
  14. package/dist/runtime/doctor/cli-doctor-standalone-rest.js +1373 -0
  15. package/dist/runtime/doctor/cli-doctor-standalone.d.ts +32 -0
  16. package/dist/runtime/doctor/cli-doctor-standalone.js +2613 -0
  17. package/dist/runtime/doctor/cli-doctor-wordpress-version.js +6 -3
  18. package/dist/runtime/doctor/cli-doctor-workspace.d.ts +5 -3
  19. package/dist/runtime/doctor/cli-doctor-workspace.js +27 -3
  20. package/dist/runtime/doctor/cli-doctor.d.ts +4 -2
  21. package/dist/runtime/doctor/cli-doctor.js +4 -2
  22. package/dist/runtime/shared/json-utils.d.ts +7 -0
  23. package/dist/runtime/shared/json-utils.js +10 -0
  24. package/dist/runtime/shared/package-json-types.d.ts +1 -1
  25. package/dist/runtime/shared/package-versions.d.ts +2 -0
  26. package/dist/runtime/shared/package-versions.js +2 -0
  27. package/dist/runtime/shared/php-utils.d.ts +39 -2
  28. package/dist/runtime/shared/php-utils.js +205 -6
  29. package/dist/runtime/templates/block-generator-service-core.d.ts +1 -1
  30. package/dist/runtime/templates/block-generator-service-core.js +9 -3
  31. package/dist/runtime/templates/block-generator-service-spec.d.ts +5 -0
  32. package/dist/runtime/templates/built-in-block-artifact-documents.d.ts +1 -1
  33. package/dist/runtime/templates/built-in-block-artifact-documents.js +1 -1
  34. package/dist/runtime/templates/built-in-block-artifact-types.js +2 -2
  35. package/dist/runtime/templates/built-in-block-artifacts.d.ts +1 -1
  36. package/dist/runtime/templates/built-in-block-artifacts.js +16 -12
  37. package/dist/runtime/templates/built-in-block-attribute-emitters.d.ts +5 -0
  38. package/dist/runtime/templates/built-in-block-attribute-emitters.js +113 -8
  39. package/dist/runtime/templates/built-in-block-attribute-specs.js +4 -9
  40. package/dist/runtime/templates/built-in-block-code-artifacts.js +6 -1
  41. package/dist/runtime/templates/built-in-block-code-templates/compound-persistence.d.ts +2 -2
  42. package/dist/runtime/templates/built-in-block-code-templates/compound-persistence.js +24 -1
  43. package/dist/runtime/templates/built-in-block-code-templates/persistence.d.ts +2 -2
  44. package/dist/runtime/templates/built-in-block-code-templates/persistence.js +22 -1
  45. package/dist/runtime/templates/built-in-block-non-ts-compound-templates.d.ts +2 -2
  46. package/dist/runtime/templates/built-in-block-non-ts-compound-templates.js +6 -2
  47. package/dist/runtime/templates/built-in-block-non-ts-persistence-templates.d.ts +2 -2
  48. package/dist/runtime/templates/built-in-block-non-ts-persistence-templates.js +6 -2
  49. package/dist/runtime/templates/cli-scaffold-emission.d.ts +7 -1
  50. package/dist/runtime/templates/cli-scaffold-emission.js +10 -1
  51. package/dist/runtime/templates/cli-templates.d.ts +47 -0
  52. package/dist/runtime/templates/cli-templates.js +50 -1
  53. package/dist/runtime/templates/local-dev-presets.js +1 -1
  54. package/dist/runtime/templates/scaffold-apply-utils.d.ts +4 -8
  55. package/dist/runtime/templates/scaffold-apply-utils.js +44 -28
  56. package/dist/runtime/templates/scaffold-compiler-artifacts.d.ts +17 -0
  57. package/dist/runtime/templates/scaffold-compiler-artifacts.js +81 -0
  58. package/dist/runtime/templates/scaffold-onboarding.d.ts +5 -0
  59. package/dist/runtime/templates/scaffold-onboarding.js +13 -2
  60. package/dist/runtime/templates/scaffold-template-variable-groups.d.ts +4 -0
  61. package/dist/runtime/templates/scaffold-template-variable-groups.js +7 -0
  62. package/dist/runtime/templates/scaffold.d.ts +3 -1
  63. package/dist/runtime/templates/scaffold.js +2 -1
  64. package/dist/runtime/templates/starter-manifests.js +1 -1
  65. package/package.json +3 -3
  66. package/templates/_shared/compound/core/scripts/add-compound-child.ts.mustache +1 -1
  67. package/templates/_shared/compound/persistence/package.json.mustache +1 -0
  68. package/templates/_shared/persistence/core/package.json.mustache +1 -0
@@ -0,0 +1,365 @@
1
+ import ts from 'typescript';
2
+ /**
3
+ * Check whether a generated sync helper statement is inert until main() runs.
4
+ * Runtime imports are limited to the modules used by that helper; all other
5
+ * imports must be erased by TypeScript.
6
+ */
7
+ export function isAllowedSyncHelperTopLevelStatement(statement, allowedRuntimeImportModules, isAllowedVariableStatement = () => false) {
8
+ if (ts.isImportDeclaration(statement)) {
9
+ if (!ts.isStringLiteral(statement.moduleSpecifier) ||
10
+ !statement.importClause) {
11
+ return false;
12
+ }
13
+ if (statement.importClause.isTypeOnly) {
14
+ return true;
15
+ }
16
+ return allowedRuntimeImportModules.has(statement.moduleSpecifier.text);
17
+ }
18
+ if (ts.isInterfaceDeclaration(statement) ||
19
+ ts.isTypeAliasDeclaration(statement) ||
20
+ ts.isFunctionDeclaration(statement)) {
21
+ return true;
22
+ }
23
+ return (ts.isVariableStatement(statement) &&
24
+ isAllowedVariableStatement(statement));
25
+ }
26
+ /** Require runtime imports to match the generated helper's load-time API. */
27
+ export function hasCanonicalRuntimeImports(sourceFile, expectedImports) {
28
+ const foundDefaults = new Set();
29
+ const foundNamed = new Map();
30
+ for (const statement of sourceFile.statements) {
31
+ if (!ts.isImportDeclaration(statement))
32
+ continue;
33
+ const importClause = statement.importClause;
34
+ if (importClause?.isTypeOnly)
35
+ continue;
36
+ if (!ts.isStringLiteral(statement.moduleSpecifier) || !importClause) {
37
+ return false;
38
+ }
39
+ const moduleName = statement.moduleSpecifier.text;
40
+ const expected = expectedImports.get(moduleName);
41
+ if (!expected)
42
+ return false;
43
+ if (importClause.name) {
44
+ if (expected.defaultBinding !== importClause.name.text ||
45
+ foundDefaults.has(moduleName)) {
46
+ return false;
47
+ }
48
+ foundDefaults.add(moduleName);
49
+ }
50
+ const namedBindings = importClause.namedBindings;
51
+ if (!namedBindings)
52
+ continue;
53
+ if (ts.isNamespaceImport(namedBindings))
54
+ return false;
55
+ const foundForModule = foundNamed.get(moduleName) ?? new Set();
56
+ for (const element of namedBindings.elements) {
57
+ if (element.isTypeOnly)
58
+ continue;
59
+ const importedName = (element.propertyName ?? element.name).text;
60
+ if (!expected.namedBindings?.has(importedName) ||
61
+ foundForModule.has(importedName)) {
62
+ return false;
63
+ }
64
+ foundForModule.add(importedName);
65
+ }
66
+ foundNamed.set(moduleName, foundForModule);
67
+ }
68
+ for (const [moduleName, expected] of expectedImports) {
69
+ if ((expected.defaultBinding !== undefined &&
70
+ !foundDefaults.has(moduleName)) ||
71
+ [...(expected.namedBindings ?? [])].some((binding) => !foundNamed.get(moduleName)?.has(binding))) {
72
+ return false;
73
+ }
74
+ }
75
+ return true;
76
+ }
77
+ /** Find a control-flow completion without crossing a nested function boundary. */
78
+ export function containsCompletion(node, isTerminal) {
79
+ if (ts.isFunctionLike(node)) {
80
+ return false;
81
+ }
82
+ if (isTerminal(node)) {
83
+ return true;
84
+ }
85
+ return (ts.forEachChild(node, (child) => containsCompletion(child, isTerminal) ? true : undefined) ?? false);
86
+ }
87
+ /** Unwrap supported static TypeScript wrappers to reach the underlying expression. */
88
+ export function unwrapStaticExpression(expression) {
89
+ let current = expression;
90
+ while (ts.isParenthesizedExpression(current) ||
91
+ ts.isAsExpression(current) ||
92
+ ts.isTypeAssertionExpression(current) ||
93
+ ts.isSatisfiesExpression(current) ||
94
+ ts.isNonNullExpression(current)) {
95
+ current = current.expression;
96
+ }
97
+ return current;
98
+ }
99
+ /** Validate the generated main().catch() failure boundary. */
100
+ export function isCanonicalSyncMainCatchHandler(rawHandler) {
101
+ const handler = unwrapStaticExpression(rawHandler);
102
+ if ((!ts.isArrowFunction(handler) && !ts.isFunctionExpression(handler)) ||
103
+ (ts.isFunctionExpression(handler) &&
104
+ handler.asteriskToken !== undefined) ||
105
+ handler.parameters.length !== 1 ||
106
+ !ts.isIdentifier(handler.parameters[0].name) ||
107
+ handler.parameters[0].dotDotDotToken !== undefined ||
108
+ handler.parameters[0].initializer !== undefined ||
109
+ !ts.isBlock(handler.body) ||
110
+ handler.body.statements.length !== 2) {
111
+ return false;
112
+ }
113
+ const errorBinding = handler.parameters[0].name.text;
114
+ const logStatement = handler.body.statements[0];
115
+ if (!ts.isExpressionStatement(logStatement)) {
116
+ return false;
117
+ }
118
+ const logCall = unwrapStaticExpression(logStatement.expression);
119
+ if (!ts.isCallExpression(logCall) ||
120
+ !ts.isPropertyAccessExpression(logCall.expression) ||
121
+ !ts.isIdentifier(logCall.expression.expression) ||
122
+ logCall.expression.expression.text !== 'console' ||
123
+ logCall.expression.name.text !== 'error' ||
124
+ logCall.arguments.length !== 2) {
125
+ return false;
126
+ }
127
+ const message = unwrapStaticExpression(logCall.arguments[0]);
128
+ const errorArgument = unwrapStaticExpression(logCall.arguments[1]);
129
+ if (!ts.isStringLiteralLike(message) ||
130
+ !ts.isIdentifier(errorArgument) ||
131
+ errorArgument.text !== errorBinding) {
132
+ return false;
133
+ }
134
+ const exitStatement = handler.body.statements[1];
135
+ if (!ts.isExpressionStatement(exitStatement)) {
136
+ return false;
137
+ }
138
+ const exitCall = unwrapStaticExpression(exitStatement.expression);
139
+ return (ts.isCallExpression(exitCall) &&
140
+ ts.isPropertyAccessExpression(exitCall.expression) &&
141
+ ts.isIdentifier(exitCall.expression.expression) &&
142
+ exitCall.expression.expression.text === 'process' &&
143
+ exitCall.expression.name.text === 'exit' &&
144
+ exitCall.arguments.length === 1 &&
145
+ ts.isNumericLiteral(exitCall.arguments[0]) &&
146
+ exitCall.arguments[0].text === '1');
147
+ }
148
+ function hasUnsafeStaticExpression(node) {
149
+ if (ts.isCallExpression(node) ||
150
+ ts.isNewExpression(node) ||
151
+ ts.isTaggedTemplateExpression(node) ||
152
+ ts.isAwaitExpression(node) ||
153
+ ts.isYieldExpression(node) ||
154
+ ts.isDeleteExpression(node) ||
155
+ ts.isSpreadElement(node) ||
156
+ ts.isSpreadAssignment(node) ||
157
+ ts.isFunctionLike(node) ||
158
+ ts.isClassDeclaration(node) ||
159
+ ts.isClassExpression(node)) {
160
+ return true;
161
+ }
162
+ if ((ts.isPrefixUnaryExpression(node) ||
163
+ ts.isPostfixUnaryExpression(node)) &&
164
+ (node.operator === ts.SyntaxKind.PlusPlusToken ||
165
+ node.operator === ts.SyntaxKind.MinusMinusToken)) {
166
+ return true;
167
+ }
168
+ if (ts.isBinaryExpression(node) &&
169
+ node.operatorToken.kind >= ts.SyntaxKind.FirstAssignment &&
170
+ node.operatorToken.kind <= ts.SyntaxKind.LastAssignment) {
171
+ return true;
172
+ }
173
+ return (ts.forEachChild(node, (child) => hasUnsafeStaticExpression(child) ? true : undefined) ?? false);
174
+ }
175
+ /** Return a side-effect-free `new Error(message)` expression when present. */
176
+ export function getSafeErrorConstruction(rawExpression) {
177
+ const expression = unwrapStaticExpression(rawExpression);
178
+ return ts.isNewExpression(expression) &&
179
+ ts.isIdentifier(expression.expression) &&
180
+ expression.expression.text === 'Error' &&
181
+ expression.arguments?.length === 1 &&
182
+ !hasUnsafeStaticExpression(expression.arguments[0])
183
+ ? expression
184
+ : null;
185
+ }
186
+ /** Validate a side-effect-free `new Error(message)` expression. */
187
+ export function isSafeErrorConstruction(rawExpression) {
188
+ return getSafeErrorConstruction(rawExpression) !== null;
189
+ }
190
+ /** Require the generated parser's terminal unknown-flag failure. */
191
+ export function hasCanonicalUnknownFlagThrow(body, argumentBinding) {
192
+ if (!ts.isBlock(body) || body.statements.length === 0) {
193
+ return false;
194
+ }
195
+ const finalStatement = body.statements[body.statements.length - 1];
196
+ if (!ts.isThrowStatement(finalStatement) || !finalStatement.expression) {
197
+ return false;
198
+ }
199
+ const errorConstruction = getSafeErrorConstruction(finalStatement.expression);
200
+ if (errorConstruction === null)
201
+ return false;
202
+ let referencesArgument = false;
203
+ function visit(node) {
204
+ if (ts.isIdentifier(node) && node.text === argumentBinding) {
205
+ referencesArgument = true;
206
+ return;
207
+ }
208
+ ts.forEachChild(node, visit);
209
+ }
210
+ visit(errorConstruction.arguments[0]);
211
+ return referencesArgument;
212
+ }
213
+ /**
214
+ * Reject executable parser work beyond the generated option assignments.
215
+ * Parser bodies are inspected rather than executed by doctor, so accepting an
216
+ * unrelated call or mutation here would let the real sync command diverge from
217
+ * the replayed options.
218
+ */
219
+ export function hasOnlyCanonicalParserEffects(node, optionsBinding, indexBinding = null) {
220
+ let valid = true;
221
+ function visit(candidate) {
222
+ if (!valid) {
223
+ return;
224
+ }
225
+ if (ts.isCallExpression(candidate) ||
226
+ ts.isTaggedTemplateExpression(candidate) ||
227
+ ts.isAwaitExpression(candidate) ||
228
+ ts.isYieldExpression(candidate) ||
229
+ ts.isDeleteExpression(candidate) ||
230
+ ts.isSpreadElement(candidate) ||
231
+ ts.isSpreadAssignment(candidate) ||
232
+ ts.isFunctionLike(candidate) ||
233
+ ts.isClassDeclaration(candidate) ||
234
+ ts.isClassExpression(candidate)) {
235
+ valid = false;
236
+ return;
237
+ }
238
+ if (ts.isWhileStatement(candidate) ||
239
+ ts.isDoStatement(candidate) ||
240
+ ts.isForStatement(candidate) ||
241
+ ts.isForInStatement(candidate)) {
242
+ valid = false;
243
+ return;
244
+ }
245
+ if (ts.isForOfStatement(candidate)) {
246
+ const expression = unwrapStaticExpression(candidate.expression);
247
+ if (candidate.awaitModifier !== undefined ||
248
+ !ts.isVariableDeclarationList(candidate.initializer) ||
249
+ !(candidate.initializer.flags & ts.NodeFlags.Const) ||
250
+ candidate.initializer.declarations.length !== 1 ||
251
+ !ts.isIdentifier(candidate.initializer.declarations[0].name) ||
252
+ !ts.isArrayLiteralExpression(expression) ||
253
+ expression.elements.length !== 0) {
254
+ valid = false;
255
+ return;
256
+ }
257
+ }
258
+ if (ts.isNewExpression(candidate)) {
259
+ if (!isSafeErrorConstruction(candidate)) {
260
+ valid = false;
261
+ return;
262
+ }
263
+ }
264
+ if (ts.isPrefixUnaryExpression(candidate) ||
265
+ ts.isPostfixUnaryExpression(candidate)) {
266
+ if (candidate.operator === ts.SyntaxKind.PlusPlusToken ||
267
+ candidate.operator === ts.SyntaxKind.MinusMinusToken) {
268
+ valid = false;
269
+ return;
270
+ }
271
+ }
272
+ if (ts.isBinaryExpression(candidate)) {
273
+ const operator = candidate.operatorToken.kind;
274
+ const isAssignment = operator >= ts.SyntaxKind.FirstAssignment &&
275
+ operator <= ts.SyntaxKind.LastAssignment;
276
+ if (isAssignment) {
277
+ const left = unwrapStaticExpression(candidate.left);
278
+ const isOptionsAssignment = operator === ts.SyntaxKind.EqualsToken &&
279
+ ts.isPropertyAccessExpression(left) &&
280
+ ts.isIdentifier(left.expression) &&
281
+ left.expression.text === optionsBinding;
282
+ const isIndexAdvance = indexBinding !== null &&
283
+ operator === ts.SyntaxKind.PlusEqualsToken &&
284
+ ts.isIdentifier(left) &&
285
+ left.text === indexBinding &&
286
+ ts.isNumericLiteral(candidate.right) &&
287
+ candidate.right.text === '1';
288
+ if (!isOptionsAssignment && !isIndexAdvance) {
289
+ valid = false;
290
+ return;
291
+ }
292
+ }
293
+ }
294
+ ts.forEachChild(candidate, visit);
295
+ }
296
+ visit(node);
297
+ return valid;
298
+ }
299
+ /** Count continues that target the generated parser's outer argument loop. */
300
+ export function countOuterParserContinues(node) {
301
+ let count = 0;
302
+ function visit(candidate, loopDepth, nestedLoopLabels) {
303
+ if (ts.isFunctionLike(candidate))
304
+ return;
305
+ if (ts.isContinueStatement(candidate)) {
306
+ if (candidate.label
307
+ ? !nestedLoopLabels.has(candidate.label.text)
308
+ : loopDepth === 0) {
309
+ count += 1;
310
+ }
311
+ return;
312
+ }
313
+ if (ts.isLabeledStatement(candidate)) {
314
+ const labels = new Set(nestedLoopLabels);
315
+ if (ts.isDoStatement(candidate.statement) ||
316
+ ts.isForInStatement(candidate.statement) ||
317
+ ts.isForOfStatement(candidate.statement) ||
318
+ ts.isForStatement(candidate.statement) ||
319
+ ts.isWhileStatement(candidate.statement)) {
320
+ labels.add(candidate.label.text);
321
+ }
322
+ visit(candidate.statement, loopDepth, labels);
323
+ return;
324
+ }
325
+ const nestedLoop = ts.isDoStatement(candidate) ||
326
+ ts.isForInStatement(candidate) ||
327
+ ts.isForOfStatement(candidate) ||
328
+ ts.isForStatement(candidate) ||
329
+ ts.isWhileStatement(candidate);
330
+ ts.forEachChild(candidate, (child) => visit(child, loopDepth + (nestedLoop ? 1 : 0), nestedLoopLabels));
331
+ }
332
+ visit(node, 0, new Set());
333
+ return count;
334
+ }
335
+ /** Detect a static process.exit() call, regardless of its exit code. */
336
+ export function isProcessExitCompletion(node) {
337
+ if (!ts.isCallExpression(node)) {
338
+ return false;
339
+ }
340
+ const target = unwrapStaticExpression(node.expression);
341
+ let receiver = null;
342
+ if (ts.isPropertyAccessExpression(target) && target.name.text === 'exit') {
343
+ receiver = target.expression;
344
+ }
345
+ else if (ts.isElementAccessExpression(target) &&
346
+ target.argumentExpression !== undefined) {
347
+ const property = unwrapStaticExpression(target.argumentExpression);
348
+ if (ts.isStringLiteralLike(property) && property.text === 'exit') {
349
+ receiver = target.expression;
350
+ }
351
+ }
352
+ if (receiver === null) {
353
+ return false;
354
+ }
355
+ const unwrappedReceiver = unwrapStaticExpression(receiver);
356
+ return (ts.isIdentifier(unwrappedReceiver) && unwrappedReceiver.text === 'process');
357
+ }
358
+ /** Check whether a prior statement can terminate the current function. */
359
+ export function hasEarlierAbruptCompletion(statements, statementIndex) {
360
+ return statements
361
+ .slice(0, statementIndex)
362
+ .some((statement) => containsCompletion(statement, (node) => ts.isReturnStatement(node) ||
363
+ ts.isThrowStatement(node) ||
364
+ isProcessExitCompletion(node)));
365
+ }
@@ -0,0 +1,21 @@
1
+ import type { EndpointManifestDefinition } from '@wp-typia/block-runtime/metadata-core';
2
+ import type { GeneratedPackageJson } from '../shared/package-json-types.js';
3
+ export declare const STANDALONE_PERSISTENCE_BLOCK_SCHEMA_ARTIFACTS: {
4
+ readonly jsonSchemaFile: string;
5
+ readonly openApiFile: string;
6
+ };
7
+ /** Parsed persistence REST metadata and any integrity problem found in its sync helper. */
8
+ export interface ParsedStandaloneRestConfig {
9
+ artifactPaths: string[];
10
+ manifest: EndpointManifestDefinition | null;
11
+ problem: string | null;
12
+ requiresRest: boolean;
13
+ }
14
+ type StandaloneMetadataCoreRestModule = Pick<typeof import('@wp-typia/block-runtime/metadata-core'), 'syncEndpointClient' | 'syncRestOpenApi' | 'syncTypeSchemas'>;
15
+ /** Detect whether a damaged project still exposes the generated REST surface. */
16
+ export declare function standaloneProjectRequiresRest(projectDir: string, packageJson: Pick<GeneratedPackageJson, 'dependencies' | 'devDependencies' | 'scripts'>): boolean;
17
+ /** Parse the generated persistence REST contract without executing project code. */
18
+ export declare function parseStandaloneRestConfig(projectDir: string, requiresRest: boolean, sourceTypeName: string | null): ParsedStandaloneRestConfig;
19
+ /** Check every persistence REST artifact through the installed project runtime. */
20
+ export declare function checkStandaloneRestArtifacts(projectDir: string, config: ParsedStandaloneRestConfig, metadataCore: StandaloneMetadataCoreRestModule): Promise<void>;
21
+ export {};