@wp-typia/project-tools 0.15.1 → 0.15.2

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.
@@ -1,10 +1,7 @@
1
1
  /**
2
- * Create a deep clone of a JSON-serializable value.
3
- *
4
- * @param value JSON-compatible data to clone.
5
- * @returns A deep-cloned copy created with `JSON.parse(JSON.stringify(...))`.
6
- *
7
- * Values that are not JSON-serializable, such as functions, `undefined`,
8
- * `BigInt`, class instances, and `Date` objects, are not preserved faithfully.
2
+ * Re-exports JSON cloning helpers from `@wp-typia/block-runtime`.
3
+ * This adapter keeps the existing project-tools module path stable while the
4
+ * runtime implementation now lives in block-runtime.
5
+ * @module
9
6
  */
10
- export declare function cloneJsonValue<T>(value: T): T;
7
+ export * from "@wp-typia/block-runtime/json-utils";
@@ -1,12 +1,7 @@
1
1
  /**
2
- * Create a deep clone of a JSON-serializable value.
3
- *
4
- * @param value JSON-compatible data to clone.
5
- * @returns A deep-cloned copy created with `JSON.parse(JSON.stringify(...))`.
6
- *
7
- * Values that are not JSON-serializable, such as functions, `undefined`,
8
- * `BigInt`, class instances, and `Date` objects, are not preserved faithfully.
2
+ * Re-exports JSON cloning helpers from `@wp-typia/block-runtime`.
3
+ * This adapter keeps the existing project-tools module path stable while the
4
+ * runtime implementation now lives in block-runtime.
5
+ * @module
9
6
  */
10
- export function cloneJsonValue(value) {
11
- return JSON.parse(JSON.stringify(value));
12
- }
7
+ export * from "@wp-typia/block-runtime/json-utils";
@@ -1,11 +1,7 @@
1
- import ts from "typescript";
2
- export interface AnalysisContext {
3
- allowedExternalPackages: Set<string>;
4
- checker: ts.TypeChecker;
5
- packageNameCache: Map<string, string | null>;
6
- projectRoot: string;
7
- program: ts.Program;
8
- recursionGuard: Set<string>;
9
- }
10
- export declare function getTaggedSyncBlockMetadataFailureCode(error: Error): "typescript-diagnostic" | undefined;
11
- export declare function createAnalysisContext(projectRoot: string, typesFilePath: string): AnalysisContext;
1
+ /**
2
+ * Re-exports metadata analysis helpers from `@wp-typia/block-runtime`.
3
+ * This adapter preserves the public project-tools module path while sharing
4
+ * the runtime implementation with block-runtime.
5
+ * @module
6
+ */
7
+ export * from "@wp-typia/block-runtime/metadata-analysis";
@@ -1,285 +1,7 @@
1
- import { createHash } from "node:crypto";
2
- import * as path from "node:path";
3
- import { fileURLToPath } from "node:url";
4
- import ts from "typescript";
5
- class LruCache {
6
- constructor(maxEntries) {
7
- this.maxEntries = maxEntries;
8
- this.entries = new Map();
9
- }
10
- get(key) {
11
- const value = this.entries.get(key);
12
- if (value === undefined) {
13
- return undefined;
14
- }
15
- this.entries.delete(key);
16
- this.entries.set(key, value);
17
- return value;
18
- }
19
- set(key, value) {
20
- if (this.entries.has(key)) {
21
- this.entries.delete(key);
22
- }
23
- this.entries.set(key, value);
24
- if (this.entries.size <= this.maxEntries) {
25
- return;
26
- }
27
- const oldestKey = this.entries.keys().next().value;
28
- if (oldestKey !== undefined) {
29
- this.entries.delete(oldestKey);
30
- }
31
- }
32
- }
33
- const DEFAULT_ALLOWED_EXTERNAL_PACKAGES = ["@wp-typia/block-types"];
34
- const ANALYSIS_PROGRAM_CACHE_MAX_ENTRIES = 20;
35
- const TYPESCRIPT_LIB_DIRECTORY = path.dirname(ts.getDefaultLibFilePath({}));
36
- const RUNTIME_DIRECTORY = path.dirname(fileURLToPath(import.meta.url));
37
- const SYNC_BLOCK_METADATA_FAILURE_CODE = Symbol("sync-block-metadata-failure-code");
38
- const analysisProgramCache = new LruCache(ANALYSIS_PROGRAM_CACHE_MAX_ENTRIES);
39
- function tagMetadataDiagnosticError(error) {
40
- error[SYNC_BLOCK_METADATA_FAILURE_CODE] = "typescript-diagnostic";
41
- return error;
42
- }
43
- export function getTaggedSyncBlockMetadataFailureCode(error) {
44
- return error[SYNC_BLOCK_METADATA_FAILURE_CODE];
45
- }
46
- function isProjectLocalSourceFile(filePath, projectRoot) {
47
- if (filePath.startsWith(TYPESCRIPT_LIB_DIRECTORY)) {
48
- return false;
49
- }
50
- if (filePath.includes(`${path.sep}node_modules${path.sep}`)) {
51
- return false;
52
- }
53
- return !path.relative(projectRoot, filePath).startsWith("..");
54
- }
55
- function collectSourceFileModuleSpecifiers(sourceFile) {
56
- const moduleSpecifiers = [];
57
- for (const statement of sourceFile.statements) {
58
- if ((ts.isImportDeclaration(statement) ||
59
- ts.isExportDeclaration(statement)) &&
60
- statement.moduleSpecifier &&
61
- ts.isStringLiteralLike(statement.moduleSpecifier)) {
62
- moduleSpecifiers.push(statement.moduleSpecifier.text);
63
- }
64
- }
65
- ts.forEachChild(sourceFile, (node) => {
66
- if (ts.isImportTypeNode(node) &&
67
- ts.isLiteralTypeNode(node.argument) &&
68
- ts.isStringLiteral(node.argument.literal)) {
69
- moduleSpecifiers.push(node.argument.literal.text);
70
- }
71
- });
72
- return moduleSpecifiers;
73
- }
74
- function collectReferencedLocalSourceFiles(program, entryFilePath, compilerOptions, projectRoot) {
75
- const visited = new Set();
76
- const queue = [entryFilePath];
77
- while (queue.length > 0) {
78
- const filePath = queue.pop();
79
- if (filePath === undefined ||
80
- visited.has(filePath) ||
81
- !isProjectLocalSourceFile(filePath, projectRoot)) {
82
- continue;
83
- }
84
- visited.add(filePath);
85
- const sourceFile = program.getSourceFile(filePath);
86
- if (sourceFile === undefined) {
87
- continue;
88
- }
89
- for (const moduleSpecifier of collectSourceFileModuleSpecifiers(sourceFile)) {
90
- const resolved = ts.resolveModuleName(moduleSpecifier, filePath, compilerOptions, ts.sys).resolvedModule;
91
- const resolvedFileName = resolved?.resolvedFileName;
92
- if (resolvedFileName &&
93
- isProjectLocalSourceFile(resolvedFileName, projectRoot)) {
94
- queue.push(resolvedFileName);
95
- }
96
- }
97
- }
98
- return visited;
99
- }
100
- function stableSerializeAnalysisValue(value) {
101
- if (value === undefined) {
102
- return '"__undefined__"';
103
- }
104
- if (value === null || typeof value !== "object") {
105
- return JSON.stringify(value);
106
- }
107
- if (Array.isArray(value)) {
108
- return `[${value.map((entry) => stableSerializeAnalysisValue(entry)).join(",")}]`;
109
- }
110
- return `{${Object.entries(value)
111
- .sort(([left], [right]) => left.localeCompare(right))
112
- .map(([key, entry]) => `${JSON.stringify(key)}:${stableSerializeAnalysisValue(entry)}`)
113
- .join(",")}}`;
114
- }
115
- function buildAnalysisProgramStructureKey(projectRoot, typesFilePath, { compilerOptions, configPath, rootNames, typiaTagsAugmentationPath, }) {
116
- return stableSerializeAnalysisValue({
117
- compilerOptions,
118
- configPath,
119
- projectRoot,
120
- rootNames: [...rootNames].sort(),
121
- typiaTagsAugmentationPath,
122
- typesFilePath,
123
- });
124
- }
125
- function createAnalysisProgramContentFingerprint(filePaths, onMissingFile = "throw") {
126
- const hash = createHash("sha1");
127
- const fingerprintPaths = [...new Set(filePaths)].sort();
128
- for (const filePath of fingerprintPaths) {
129
- const fileContents = ts.sys.readFile(filePath);
130
- if (fileContents === undefined) {
131
- if (onMissingFile === "return-null") {
132
- return null;
133
- }
134
- if (onMissingFile === "hash-missing") {
135
- hash.update(filePath);
136
- hash.update("\0");
137
- hash.update("__missing__");
138
- hash.update("\0");
139
- continue;
140
- }
141
- throw new Error(`Unable to read metadata analysis dependency: ${filePath}`);
142
- }
143
- hash.update(filePath);
144
- hash.update("\0");
145
- hash.update(fileContents);
146
- hash.update("\0");
147
- }
148
- return hash.digest("hex");
149
- }
150
- function getAnalysisProgramDependencyPaths(program, configPath) {
151
- const sourceFilePaths = program
152
- .getSourceFiles()
153
- .map((sourceFile) => sourceFile.fileName)
154
- .filter((filePath) => !filePath.startsWith(TYPESCRIPT_LIB_DIRECTORY));
155
- const dependencyPaths = new Set(sourceFilePaths);
156
- for (const filePath of sourceFilePaths) {
157
- let currentDir = path.dirname(filePath);
158
- while (true) {
159
- dependencyPaths.add(path.join(currentDir, "package.json"));
160
- const parentDir = path.dirname(currentDir);
161
- if (parentDir === currentDir) {
162
- break;
163
- }
164
- currentDir = parentDir;
165
- }
166
- }
167
- if (configPath) {
168
- dependencyPaths.add(configPath);
169
- }
170
- return [...dependencyPaths].sort();
171
- }
172
- function resolveAnalysisProgramInputs(projectRoot, typesFilePath) {
173
- const configPath = ts.findConfigFile(projectRoot, ts.sys.fileExists, "tsconfig.json");
174
- const compilerOptions = {
175
- allowJs: false,
176
- esModuleInterop: true,
177
- module: ts.ModuleKind.NodeNext,
178
- moduleResolution: ts.ModuleResolutionKind.NodeNext,
179
- resolveJsonModule: true,
180
- skipLibCheck: true,
181
- target: ts.ScriptTarget.ES2022,
182
- };
183
- let rootNames = [typesFilePath];
184
- const typiaTagsAugmentationPath = resolveTypiaTagsAugmentationPath();
185
- if (configPath !== undefined) {
186
- const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
187
- if (configFile.error) {
188
- throw formatDiagnosticError(configFile.error);
189
- }
190
- const parsed = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path.dirname(configPath), compilerOptions, configPath);
191
- if (parsed.errors.length > 0) {
192
- throw formatDiagnosticError(parsed.errors[0]);
193
- }
194
- rootNames = parsed.fileNames.includes(typesFilePath)
195
- ? parsed.fileNames
196
- : [...parsed.fileNames, typesFilePath];
197
- if (typiaTagsAugmentationPath &&
198
- !rootNames.includes(typiaTagsAugmentationPath)) {
199
- rootNames = [...rootNames, typiaTagsAugmentationPath];
200
- }
201
- Object.assign(compilerOptions, parsed.options);
202
- }
203
- else if (typiaTagsAugmentationPath) {
204
- rootNames = [...rootNames, typiaTagsAugmentationPath];
205
- }
206
- const structureKey = buildAnalysisProgramStructureKey(projectRoot, typesFilePath, {
207
- compilerOptions,
208
- configPath: configPath ?? null,
209
- rootNames,
210
- typiaTagsAugmentationPath,
211
- });
212
- return {
213
- compilerOptions,
214
- configPath: configPath ?? null,
215
- rootNames,
216
- structureKey,
217
- typiaTagsAugmentationPath,
218
- };
219
- }
220
- export function createAnalysisContext(projectRoot, typesFilePath) {
221
- const analysisInputs = resolveAnalysisProgramInputs(projectRoot, typesFilePath);
222
- const cachedAnalysis = analysisProgramCache.get(analysisInputs.structureKey);
223
- if (cachedAnalysis) {
224
- const currentDependencyFingerprint = createAnalysisProgramContentFingerprint(cachedAnalysis.dependencyPaths, "hash-missing");
225
- if (currentDependencyFingerprint !== null &&
226
- currentDependencyFingerprint === cachedAnalysis.dependencyFingerprint) {
227
- return {
228
- allowedExternalPackages: new Set(DEFAULT_ALLOWED_EXTERNAL_PACKAGES),
229
- checker: cachedAnalysis.checker,
230
- packageNameCache: new Map(),
231
- projectRoot,
232
- program: cachedAnalysis.program,
233
- recursionGuard: new Set(),
234
- };
235
- }
236
- }
237
- const program = ts.createProgram({
238
- oldProgram: cachedAnalysis?.program,
239
- options: analysisInputs.compilerOptions,
240
- rootNames: analysisInputs.rootNames,
241
- });
242
- const diagnostics = ts.getPreEmitDiagnostics(program);
243
- const localSourceFiles = collectReferencedLocalSourceFiles(program, typesFilePath, analysisInputs.compilerOptions, projectRoot);
244
- const blockingDiagnostic = diagnostics.find((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error &&
245
- diagnostic.file !== undefined &&
246
- localSourceFiles.has(diagnostic.file.fileName));
247
- if (blockingDiagnostic) {
248
- throw formatDiagnosticError(blockingDiagnostic);
249
- }
250
- const checker = program.getTypeChecker();
251
- const dependencyPaths = getAnalysisProgramDependencyPaths(program, analysisInputs.configPath);
252
- const dependencyFingerprint = createAnalysisProgramContentFingerprint(dependencyPaths, "hash-missing");
253
- if (dependencyFingerprint === null) {
254
- throw new Error("Unable to fingerprint metadata analysis dependencies.");
255
- }
256
- analysisProgramCache.set(analysisInputs.structureKey, {
257
- checker,
258
- dependencyFingerprint,
259
- dependencyPaths,
260
- program,
261
- });
262
- return {
263
- allowedExternalPackages: new Set(DEFAULT_ALLOWED_EXTERNAL_PACKAGES),
264
- checker,
265
- packageNameCache: new Map(),
266
- projectRoot,
267
- program,
268
- recursionGuard: new Set(),
269
- };
270
- }
271
- function resolveTypiaTagsAugmentationPath() {
272
- const candidates = [
273
- path.join(RUNTIME_DIRECTORY, "typia-tags.d.ts"),
274
- path.join(RUNTIME_DIRECTORY, "typia-tags.ts"),
275
- ];
276
- for (const candidate of candidates) {
277
- if (ts.sys.fileExists(candidate)) {
278
- return candidate;
279
- }
280
- }
281
- return null;
282
- }
283
- function formatDiagnosticError(diagnostic) {
284
- return tagMetadataDiagnosticError(new Error(ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n")));
285
- }
1
+ /**
2
+ * Re-exports metadata analysis helpers from `@wp-typia/block-runtime`.
3
+ * This adapter preserves the public project-tools module path while sharing
4
+ * the runtime implementation with block-runtime.
5
+ * @module
6
+ */
7
+ export * from "@wp-typia/block-runtime/metadata-analysis";
@@ -1,84 +1,7 @@
1
- export type JsonPrimitive = string | number | boolean | null;
2
- export type JsonValue = JsonPrimitive | JsonValue[] | {
3
- [key: string]: JsonValue;
4
- };
5
- export type AttributeKind = "string" | "number" | "boolean" | "array" | "object" | "union";
6
- export type WordPressAttributeKind = "string" | "number" | "boolean" | "array" | "object";
7
- export type WordPressAttributeSource = "html" | "text" | "rich-text";
8
- export interface AttributeConstraints {
9
- exclusiveMaximum: number | null;
10
- exclusiveMinimum: number | null;
11
- format: string | null;
12
- maxLength: number | null;
13
- maxItems: number | null;
14
- maximum: number | null;
15
- minLength: number | null;
16
- minItems: number | null;
17
- minimum: number | null;
18
- multipleOf: number | null;
19
- pattern: string | null;
20
- typeTag: string | null;
21
- }
22
- export interface AttributeNode {
23
- constraints: AttributeConstraints;
24
- defaultValue?: JsonValue;
25
- enumValues: Array<string | number | boolean> | null;
26
- items?: AttributeNode;
27
- kind: AttributeKind;
28
- path: string;
29
- properties?: Record<string, AttributeNode>;
30
- required: boolean;
31
- union?: AttributeUnion | null;
32
- wp: {
33
- selector: string | null;
34
- source: WordPressAttributeSource | null;
35
- };
36
- }
37
- export interface AttributeUnion {
38
- branches: Record<string, AttributeNode>;
39
- discriminator: string;
40
- }
41
- export interface BlockJsonAttribute {
42
- default?: JsonValue;
43
- enum?: Array<string | number | boolean>;
44
- selector?: string;
45
- source?: WordPressAttributeSource;
46
- type: WordPressAttributeKind;
47
- }
48
- export interface ManifestAttribute {
49
- typia: {
50
- constraints: AttributeConstraints;
51
- defaultValue: JsonValue | null;
52
- hasDefault: boolean;
53
- };
54
- ts: {
55
- items: ManifestAttribute | null;
56
- kind: AttributeKind;
57
- properties: Record<string, ManifestAttribute> | null;
58
- required: boolean;
59
- union: ManifestUnion | null;
60
- };
61
- wp: {
62
- defaultValue: JsonValue | null;
63
- enum: Array<string | number | boolean> | null;
64
- hasDefault: boolean;
65
- selector?: string | null;
66
- source?: WordPressAttributeSource | null;
67
- type: WordPressAttributeKind;
68
- };
69
- }
70
- export interface ManifestUnion {
71
- branches: Record<string, ManifestAttribute>;
72
- discriminator: string;
73
- }
74
- export interface ManifestDocument {
75
- attributes: Record<string, ManifestAttribute>;
76
- manifestVersion: 2;
77
- sourceType: string;
78
- }
79
- export declare function defaultAttributeConstraints(): AttributeConstraints;
80
- export declare function getWordPressKind(node: AttributeNode): WordPressAttributeKind;
81
- export declare function baseNode(kind: AttributeKind, pathLabel: string): AttributeNode;
82
- export declare function withRequired(node: AttributeNode, required: boolean): AttributeNode;
83
- export declare function cloneUnion(union: AttributeUnion): AttributeUnion;
84
- export declare function cloneProperties(properties: Record<string, AttributeNode>): Record<string, AttributeNode>;
1
+ /**
2
+ * Re-exports the metadata model types and helpers from `@wp-typia/block-runtime`.
3
+ * This adapter keeps the public project-tools runtime path stable while the
4
+ * implementation is consolidated in block-runtime.
5
+ * @module
6
+ */
7
+ export * from "@wp-typia/block-runtime/metadata-model";
@@ -1,59 +1,7 @@
1
- export function defaultAttributeConstraints() {
2
- return {
3
- exclusiveMaximum: null,
4
- exclusiveMinimum: null,
5
- format: null,
6
- maxLength: null,
7
- maxItems: null,
8
- maximum: null,
9
- minLength: null,
10
- minItems: null,
11
- minimum: null,
12
- multipleOf: null,
13
- pattern: null,
14
- typeTag: null,
15
- };
16
- }
17
- export function getWordPressKind(node) {
18
- return node.kind === "union" ? "object" : node.kind;
19
- }
20
- export function baseNode(kind, pathLabel) {
21
- return {
22
- constraints: defaultAttributeConstraints(),
23
- enumValues: null,
24
- kind,
25
- path: pathLabel,
26
- required: true,
27
- union: null,
28
- wp: {
29
- selector: null,
30
- source: null,
31
- },
32
- };
33
- }
34
- export function withRequired(node, required) {
35
- return {
36
- ...node,
37
- items: node.items
38
- ? withRequired(node.items, node.items.required)
39
- : undefined,
40
- properties: node.properties ? cloneProperties(node.properties) : undefined,
41
- required,
42
- union: node.union ? cloneUnion(node.union) : null,
43
- };
44
- }
45
- export function cloneUnion(union) {
46
- return {
47
- branches: Object.fromEntries(Object.entries(union.branches).map(([key, branch]) => [
48
- key,
49
- withRequired(branch, branch.required),
50
- ])),
51
- discriminator: union.discriminator,
52
- };
53
- }
54
- export function cloneProperties(properties) {
55
- return Object.fromEntries(Object.entries(properties).map(([key, node]) => [
56
- key,
57
- withRequired(node, node.required),
58
- ]));
59
- }
1
+ /**
2
+ * Re-exports the metadata model types and helpers from `@wp-typia/block-runtime`.
3
+ * This adapter keeps the public project-tools runtime path stable while the
4
+ * implementation is consolidated in block-runtime.
5
+ * @module
6
+ */
7
+ export * from "@wp-typia/block-runtime/metadata-model";
@@ -1,53 +1,7 @@
1
- import ts from "typescript";
2
- import { type AnalysisContext } from "./metadata-analysis.js";
3
- import { type AttributeNode } from "./metadata-model.js";
4
1
  /**
5
- * Analyze one named source type from a TypeScript module.
6
- *
7
- * @param options Metadata analysis options including the project root, source
8
- * type name, and types file path.
9
- * @returns The resolved project root plus the parsed root attribute node for
10
- * the requested source type.
2
+ * Re-exports metadata parser utilities from `@wp-typia/block-runtime`.
3
+ * This adapter keeps the public project-tools runtime path stable while the
4
+ * implementation is consolidated in block-runtime.
5
+ * @module
11
6
  */
12
- export declare function analyzeSourceType(options: {
13
- projectRoot?: string;
14
- sourceTypeName: string;
15
- typesFile: string;
16
- }): {
17
- projectRoot: string;
18
- rootNode: AttributeNode;
19
- };
20
- /**
21
- * Analyze multiple named source types from a TypeScript module.
22
- *
23
- * @param options Metadata analysis options including the optional project root
24
- * and the relative types file path to parse.
25
- * @param sourceTypeNames Exported type or interface names to resolve from the
26
- * configured types file.
27
- * @returns A record keyed by source type name with parsed attribute-node trees
28
- * for each requested type.
29
- */
30
- export declare function analyzeSourceTypes(options: {
31
- projectRoot?: string;
32
- typesFile: string;
33
- }, sourceTypeNames: string[]): Record<string, AttributeNode>;
34
- /**
35
- * Parse an interface or type alias declaration into one attribute-node tree.
36
- *
37
- * @param declaration TypeScript declaration node to parse.
38
- * @param ctx Shared analysis context used for type resolution and recursion
39
- * detection.
40
- * @param pathLabel Human-readable path label for diagnostics.
41
- * @param required Whether the resulting node should be marked as required.
42
- * @returns The parsed attribute-node representation for the declaration.
43
- */
44
- export declare function parseNamedDeclaration(declaration: ts.InterfaceDeclaration | ts.TypeAliasDeclaration, ctx: AnalysisContext, pathLabel: string, required: boolean): AttributeNode;
45
- /**
46
- * Parse one TypeScript type node into the internal metadata model.
47
- *
48
- * @param node TypeScript AST node describing the source type shape.
49
- * @param ctx Shared analysis context used for symbol and type resolution.
50
- * @param pathLabel Human-readable path label used in parse errors and warnings.
51
- * @returns The parsed attribute-node representation of the provided type node.
52
- */
53
- export declare function parseTypeNode(node: ts.TypeNode, ctx: AnalysisContext, pathLabel: string): AttributeNode;
7
+ export * from "@wp-typia/block-runtime/metadata-parser";