@wp-typia/block-runtime 0.2.3 → 0.4.0

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.
@@ -0,0 +1,285 @@
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
+ }
@@ -0,0 +1,286 @@
1
+ import { type EndpointOpenApiEndpointDefinition, type OpenApiInfo } from './schema-core.js';
2
+ export interface SyncBlockMetadataOptions {
3
+ blockJsonFile: string;
4
+ jsonSchemaFile?: string;
5
+ manifestFile?: string;
6
+ openApiFile?: string;
7
+ phpValidatorFile?: string;
8
+ projectRoot?: string;
9
+ sourceTypeName: string;
10
+ typesFile: string;
11
+ }
12
+ export interface SyncBlockMetadataResult {
13
+ attributeNames: string[];
14
+ blockJsonPath: string;
15
+ jsonSchemaPath?: string;
16
+ lossyProjectionWarnings: string[];
17
+ manifestPath: string;
18
+ openApiPath?: string;
19
+ phpGenerationWarnings: string[];
20
+ phpValidatorPath: string;
21
+ }
22
+ export interface ArtifactSyncExecutionOptions {
23
+ /**
24
+ * Verify that generated artifacts are already current without rewriting them.
25
+ */
26
+ check?: boolean;
27
+ }
28
+ /**
29
+ * High-level outcome for one `runSyncBlockMetadata()` execution.
30
+ *
31
+ * - `success`: metadata sync completed without warnings.
32
+ * - `warning`: metadata sync completed, but warn-only findings were recorded.
33
+ * - `error`: metadata sync failed, or warnings were promoted to errors by flags.
34
+ */
35
+ export type SyncBlockMetadataStatus = 'success' | 'warning' | 'error';
36
+ /**
37
+ * Stable failure bucket for structured `sync-types` error reporting.
38
+ */
39
+ export type SyncBlockMetadataFailureCode =
40
+ /** Generated artifact files are missing or stale relative to the current sources. */
41
+ 'stale-generated-artifact'
42
+ /** A TypeScript node kind is not supported by the metadata parser. */
43
+ | 'unsupported-type-node'
44
+ /** A supported node kind was used in an unsupported pattern or combination. */
45
+ | 'unsupported-type-pattern'
46
+ /** Recursive type analysis was detected and aborted. */
47
+ | 'recursive-type'
48
+ /** The configured types file or source type could not be resolved correctly. */
49
+ | 'invalid-source-type'
50
+ /** TypeScript diagnostics blocked analysis before metadata generation ran. */
51
+ | 'typescript-diagnostic'
52
+ /** The failure did not match a more specific structured bucket. */
53
+ | 'unknown-internal-error';
54
+ /**
55
+ * Structured failure payload returned when `runSyncBlockMetadata()` does not complete.
56
+ */
57
+ export interface SyncBlockMetadataFailure {
58
+ /** Stable failure bucket suitable for branching in scripts or CI. */
59
+ code: SyncBlockMetadataFailureCode;
60
+ /** Human-readable error message captured from the original failure. */
61
+ message: string;
62
+ /** Original thrown error name when available. */
63
+ name: string;
64
+ }
65
+ /**
66
+ * Optional execution flags that control how warnings affect the final report status.
67
+ */
68
+ export interface SyncBlockMetadataExecutionOptions extends ArtifactSyncExecutionOptions {
69
+ /** Promote lossy WordPress projection warnings to `error` status. */
70
+ failOnLossy?: boolean;
71
+ /** Promote PHP validator coverage warnings to `error` status. */
72
+ failOnPhpWarnings?: boolean;
73
+ /**
74
+ * Promote all warnings to `error` status.
75
+ *
76
+ * When `true`, this behaves like setting both `failOnLossy` and
77
+ * `failOnPhpWarnings` to `true`.
78
+ */
79
+ strict?: boolean;
80
+ }
81
+ /**
82
+ * Structured result returned by `runSyncBlockMetadata()`.
83
+ */
84
+ export interface SyncBlockMetadataReport {
85
+ /** Attribute keys discovered from the source type. Empty when analysis fails early. */
86
+ attributeNames: string[];
87
+ /** Absolute path to the generated or target `block.json`. */
88
+ blockJsonPath: string | null;
89
+ /** Absolute path to the generated JSON Schema file when schema output is enabled. */
90
+ jsonSchemaPath: string | null;
91
+ /** Warn-only notices for Typia constraints that cannot round-trip into `block.json`. */
92
+ lossyProjectionWarnings: string[];
93
+ /** Absolute path to the generated or target manifest file. */
94
+ manifestPath: string | null;
95
+ /** Absolute path to the generated aggregate OpenAPI file when enabled. */
96
+ openApiPath: string | null;
97
+ /** Warn-only notices for Typia constraints not yet enforced by PHP validation. */
98
+ phpGenerationWarnings: string[];
99
+ /** Absolute path to the generated or target PHP validator file. */
100
+ phpValidatorPath: string | null;
101
+ /** Structured failure payload when analysis or generation throws. */
102
+ failure: SyncBlockMetadataFailure | null;
103
+ /** Effective lossy-warning failure flag after `strict` has been applied. */
104
+ failOnLossy: boolean;
105
+ /** Effective PHP-warning failure flag after `strict` has been applied. */
106
+ failOnPhpWarnings: boolean;
107
+ /** Final execution status after warnings and failure handling are applied. */
108
+ status: SyncBlockMetadataStatus;
109
+ /** Whether the report was computed in strict mode. */
110
+ strict: boolean;
111
+ }
112
+ export interface SyncTypeSchemaOptions {
113
+ jsonSchemaFile: string;
114
+ openApiFile?: string;
115
+ openApiInfo?: OpenApiInfo;
116
+ projectRoot?: string;
117
+ sourceTypeName: string;
118
+ typesFile: string;
119
+ }
120
+ export interface SyncTypeSchemaResult {
121
+ jsonSchemaPath: string;
122
+ openApiPath?: string;
123
+ sourceTypeName: string;
124
+ }
125
+ /**
126
+ * Source type mapping used by endpoint manifests and aggregate REST OpenAPI generation.
127
+ */
128
+ export interface EndpointManifestContractDefinition {
129
+ /** Optional component name override for the generated schema reference. */
130
+ schemaName?: string;
131
+ /** Type name exported from the source `typesFile`. */
132
+ sourceTypeName: string;
133
+ }
134
+ /**
135
+ * Portable route metadata stored in one endpoint manifest entry.
136
+ */
137
+ export type EndpointManifestEndpointDefinition = EndpointOpenApiEndpointDefinition;
138
+ /**
139
+ * Canonical TypeScript description of one scaffolded REST surface.
140
+ */
141
+ export interface EndpointManifestDefinition<Contracts extends Readonly<Record<string, EndpointManifestContractDefinition>> = Readonly<Record<string, EndpointManifestContractDefinition>>, Endpoints extends readonly EndpointManifestEndpointDefinition[] = readonly EndpointManifestEndpointDefinition[]> {
142
+ /** Contract registry keyed by logical route contract ids. */
143
+ contracts: Contracts;
144
+ /** Route registry keyed by concrete REST path and method pairs. */
145
+ endpoints: Endpoints;
146
+ /** Optional document-level metadata for aggregate OpenAPI output. */
147
+ info?: OpenApiInfo;
148
+ }
149
+ /**
150
+ * Preserve literal TypeScript inference for backend-neutral endpoint manifests.
151
+ *
152
+ * @param manifest Canonical REST surface metadata authored in TypeScript.
153
+ * @returns The same manifest object with literal contract and endpoint metadata preserved.
154
+ */
155
+ export declare function defineEndpointManifest<const Contracts extends Readonly<Record<string, EndpointManifestContractDefinition>>, const Endpoints extends readonly EndpointManifestEndpointDefinition[]>(manifest: EndpointManifestDefinition<Contracts, Endpoints>): EndpointManifestDefinition<Contracts, Endpoints>;
156
+ /**
157
+ * Backward-compatible source type mapping used when generating aggregate REST OpenAPI documents.
158
+ */
159
+ export interface RestOpenApiContractDefinition extends EndpointManifestContractDefinition {
160
+ }
161
+ /**
162
+ * Backward-compatible route metadata consumed by `syncRestOpenApi()`.
163
+ */
164
+ export type RestOpenApiEndpointDefinition = EndpointManifestEndpointDefinition;
165
+ /**
166
+ * Shared file and project inputs for REST OpenAPI generation.
167
+ */
168
+ interface SyncRestOpenApiBaseOptions {
169
+ /** Output path for the aggregate OpenAPI document. */
170
+ openApiFile: string;
171
+ /** Optional project root used to resolve file paths. */
172
+ projectRoot?: string;
173
+ /** Source file that exports the REST contract types. */
174
+ typesFile: string;
175
+ }
176
+ /**
177
+ * Manifest-first options for writing a canonical endpoint-aware REST OpenAPI document.
178
+ */
179
+ export interface SyncRestOpenApiManifestOptions extends SyncRestOpenApiBaseOptions {
180
+ /** Canonical endpoint manifest describing the REST surface. */
181
+ manifest: EndpointManifestDefinition;
182
+ /** Not accepted when `manifest` is provided. */
183
+ contracts?: never;
184
+ /** Not accepted when `manifest` is provided. */
185
+ endpoints?: never;
186
+ /** Not accepted when `manifest` is provided. */
187
+ openApiInfo?: never;
188
+ }
189
+ /**
190
+ * Backward-compatible options for writing a canonical endpoint-aware REST OpenAPI document.
191
+ */
192
+ export interface SyncRestOpenApiContractsOptions extends SyncRestOpenApiBaseOptions {
193
+ /** Contract registry keyed by logical route contract ids. */
194
+ contracts: Readonly<Record<string, RestOpenApiContractDefinition>>;
195
+ /** Endpoint registry describing the REST paths, methods, and auth policies to document. */
196
+ endpoints: readonly RestOpenApiEndpointDefinition[];
197
+ /** Optional OpenAPI document metadata. */
198
+ openApiInfo?: OpenApiInfo;
199
+ /** Not accepted when `contracts` and `endpoints` are provided directly. */
200
+ manifest?: never;
201
+ }
202
+ /**
203
+ * Options for writing a canonical endpoint-aware REST OpenAPI document.
204
+ */
205
+ export type SyncRestOpenApiOptions = SyncRestOpenApiManifestOptions | SyncRestOpenApiContractsOptions;
206
+ /**
207
+ * Result returned after writing an aggregate REST OpenAPI document.
208
+ */
209
+ export interface SyncRestOpenApiResult {
210
+ /** Number of endpoints included in the generated OpenAPI file. */
211
+ endpointCount: number;
212
+ /** Absolute path to the generated OpenAPI file. */
213
+ openApiPath: string;
214
+ /** Component schema names included in the generated document. */
215
+ schemaNames: string[];
216
+ }
217
+ interface SyncEndpointClientBaseOptions {
218
+ /** Output path for the generated portable client module. */
219
+ clientFile: string;
220
+ /** Optional project root used to resolve file paths. */
221
+ projectRoot?: string;
222
+ /** Source file that exports the endpoint contract types. */
223
+ typesFile: string;
224
+ /** Optional explicit path to the validator module. */
225
+ validatorsFile?: string;
226
+ }
227
+ /**
228
+ * Manifest-first options for writing a portable endpoint client module.
229
+ */
230
+ export interface SyncEndpointClientOptions extends SyncEndpointClientBaseOptions {
231
+ /** Canonical endpoint manifest describing the REST surface. */
232
+ manifest: EndpointManifestDefinition;
233
+ }
234
+ /**
235
+ * Result returned after writing a generated portable endpoint client module.
236
+ */
237
+ export interface SyncEndpointClientResult {
238
+ /** Number of endpoints included in the generated client file. */
239
+ endpointCount: number;
240
+ /** Absolute path to the generated client file. */
241
+ clientPath: string;
242
+ /** Operation ids emitted as endpoint constants and convenience wrappers. */
243
+ operationIds: string[];
244
+ }
245
+ /**
246
+ * Synchronizes block metadata artifacts from a source TypeScript contract.
247
+ *
248
+ * This updates `block.json` attributes/examples and emits the related JSON
249
+ * Schema, manifest, OpenAPI, and optional PHP validator artifacts derived from
250
+ * the same source type.
251
+ *
252
+ * @param options Configuration for locating the project root, source types
253
+ * file/type name, and output artifact paths.
254
+ * @returns The generated artifact paths plus any lossy WordPress projection or
255
+ * PHP validator coverage warnings discovered during synchronization.
256
+ */
257
+ export declare function syncBlockMetadata(options: SyncBlockMetadataOptions, executionOptions?: ArtifactSyncExecutionOptions): Promise<SyncBlockMetadataResult>;
258
+ /**
259
+ * Execute `syncBlockMetadata()` and return a structured status report.
260
+ *
261
+ * This wrapper preserves the existing artifact-generation behavior while adding
262
+ * stable status, warning, and failure metadata for scripts and CI integrations.
263
+ * Hard analysis failures are normalized into `failure`, and warning promotion is
264
+ * controlled by `strict`, `failOnLossy`, and `failOnPhpWarnings`.
265
+ *
266
+ * @param options Artifact generation inputs shared with `syncBlockMetadata()`.
267
+ * @param executionOptions Optional warning-promotion flags for CI/reporting flows.
268
+ * @returns A structured execution report describing generated paths, warnings, and failures.
269
+ */
270
+ export declare function runSyncBlockMetadata(options: SyncBlockMetadataOptions, executionOptions?: SyncBlockMetadataExecutionOptions): Promise<SyncBlockMetadataReport>;
271
+ export declare function syncTypeSchemas(options: SyncTypeSchemaOptions, executionOptions?: ArtifactSyncExecutionOptions): Promise<SyncTypeSchemaResult>;
272
+ /**
273
+ * Generate and write a canonical OpenAPI document for scaffolded REST contracts.
274
+ *
275
+ * @param options Contracts, endpoint metadata, source file, and output file settings.
276
+ * @returns Information about the generated OpenAPI document and included schema components.
277
+ */
278
+ export declare function syncRestOpenApi(options: SyncRestOpenApiOptions, executionOptions?: ArtifactSyncExecutionOptions): Promise<SyncRestOpenApiResult>;
279
+ /**
280
+ * Generate and write a manifest-first portable endpoint client module.
281
+ *
282
+ * @param options Manifest, source file, validator file, and output path settings.
283
+ * @returns Information about the generated client file and emitted operation ids.
284
+ */
285
+ export declare function syncEndpointClient(options: SyncEndpointClientOptions, executionOptions?: ArtifactSyncExecutionOptions): Promise<SyncEndpointClientResult>;
286
+ export {};