@wp-typia/block-runtime 0.4.0 → 0.4.3
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/blocks.d.ts +18 -1
- package/dist/blocks.js +95 -2
- package/dist/metadata-core.js +4 -2
- package/dist/object-utils.js +2 -5
- package/dist/schema-core.d.ts +1 -0
- package/dist/schema-core.js +188 -8
- package/dist/validation.d.ts +3 -11
- package/dist/validation.js +3 -26
- package/package.json +34 -3
package/dist/blocks.d.ts
CHANGED
|
@@ -34,6 +34,19 @@ export interface TypiaWebpackConfigOptions {
|
|
|
34
34
|
path: {
|
|
35
35
|
join(...paths: string[]): string;
|
|
36
36
|
};
|
|
37
|
+
projectRoot?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface TypiaWebpackPluginLoaderOptions {
|
|
40
|
+
importTypiaWebpackPlugin: () => Promise<{
|
|
41
|
+
default: () => unknown;
|
|
42
|
+
}>;
|
|
43
|
+
projectRoot?: string;
|
|
44
|
+
}
|
|
45
|
+
interface TypiaWebpackVersionMatrix {
|
|
46
|
+
"@typia/unplugin": string | null;
|
|
47
|
+
"@wordpress/scripts": string | null;
|
|
48
|
+
typia: string | null;
|
|
49
|
+
webpack: string | null;
|
|
37
50
|
}
|
|
38
51
|
type OverrideProperties<TBase, TOverride> = Omit<TBase, keyof TOverride> & TOverride;
|
|
39
52
|
type ScaffoldSupportDefaultControls<TFeature extends string> = Readonly<Partial<Record<TFeature, boolean>> & Record<string, boolean | undefined>>;
|
|
@@ -169,8 +182,12 @@ export interface BuildScaffoldBlockRegistrationResult<TSettings extends object>
|
|
|
169
182
|
name: string;
|
|
170
183
|
settings: TSettings;
|
|
171
184
|
}
|
|
185
|
+
export declare function assertTypiaWebpackCompatibility({ projectRoot, }?: {
|
|
186
|
+
projectRoot?: string;
|
|
187
|
+
}): Promise<TypiaWebpackVersionMatrix>;
|
|
188
|
+
export declare function loadCompatibleTypiaWebpackPlugin({ importTypiaWebpackPlugin, projectRoot, }: TypiaWebpackPluginLoaderOptions): Promise<() => unknown>;
|
|
172
189
|
export declare function buildScaffoldBlockRegistration<TSettings extends object>(metadata: ScaffoldBlockMetadata, overrides: Partial<TSettings> & Record<string, unknown>): BuildScaffoldBlockRegistrationResult<TSettings>;
|
|
173
|
-
export declare function createTypiaWebpackConfig({ defaultConfig, fs, getArtifactEntries, getEditorEntries, getOptionalModuleEntries, importTypiaWebpackPlugin, isScriptModuleAsset, moduleEntriesMode, nonModuleEntriesMode, path, }: TypiaWebpackConfigOptions): Promise<{
|
|
190
|
+
export declare function createTypiaWebpackConfig({ defaultConfig, fs, getArtifactEntries, getEditorEntries, getOptionalModuleEntries, importTypiaWebpackPlugin, isScriptModuleAsset, moduleEntriesMode, nonModuleEntriesMode, path, projectRoot, }: TypiaWebpackConfigOptions): Promise<{
|
|
174
191
|
entry: () => Promise<Record<string, unknown>>;
|
|
175
192
|
plugins: unknown[];
|
|
176
193
|
} | {
|
package/dist/blocks.js
CHANGED
|
@@ -15,6 +15,96 @@ function isModuleConfig(config) {
|
|
|
15
15
|
config !== null &&
|
|
16
16
|
config.output?.module === true);
|
|
17
17
|
}
|
|
18
|
+
function parseMajorVersion(version) {
|
|
19
|
+
if (!version) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
const match = /^(\d+)/u.exec(version);
|
|
23
|
+
return match ? Number.parseInt(match[1], 10) : null;
|
|
24
|
+
}
|
|
25
|
+
function readPackageVersion(readFileSync, packageJsonPath) {
|
|
26
|
+
try {
|
|
27
|
+
return JSON.parse(readFileSync(packageJsonPath, "utf8")).version;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async function loadNodeRuntimeHelpers() {
|
|
34
|
+
const importNodeModule = Function("specifier", "return import(specifier);");
|
|
35
|
+
const [fsModule, moduleBuiltin, pathBuiltin] = (await Promise.all([
|
|
36
|
+
importNodeModule("node:fs"),
|
|
37
|
+
importNodeModule("node:module"),
|
|
38
|
+
importNodeModule("node:path"),
|
|
39
|
+
]));
|
|
40
|
+
return {
|
|
41
|
+
createRequire: moduleBuiltin.createRequire,
|
|
42
|
+
pathModule: pathBuiltin,
|
|
43
|
+
readFileSync: fsModule.readFileSync,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function resolveInstalledPackageVersion(readFileSync, requireFromProject, packageName) {
|
|
47
|
+
try {
|
|
48
|
+
return readPackageVersion(readFileSync, requireFromProject.resolve(`${packageName}/package.json`));
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function resolveWebpackVersion(readFileSync, requireFromProject, createRequire) {
|
|
55
|
+
try {
|
|
56
|
+
const wordpressScriptsPackageJsonPath = requireFromProject.resolve("@wordpress/scripts/package.json");
|
|
57
|
+
const requireFromWordPressScripts = createRequire(wordpressScriptsPackageJsonPath);
|
|
58
|
+
const bundledWebpackVersion = resolveInstalledPackageVersion(readFileSync, requireFromWordPressScripts, "webpack");
|
|
59
|
+
if (bundledWebpackVersion) {
|
|
60
|
+
return bundledWebpackVersion;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// fall through to the project-level webpack resolution below
|
|
65
|
+
}
|
|
66
|
+
return resolveInstalledPackageVersion(readFileSync, requireFromProject, "webpack");
|
|
67
|
+
}
|
|
68
|
+
async function getTypiaWebpackVersionMatrix(projectRoot = process.cwd()) {
|
|
69
|
+
const { createRequire, pathModule, readFileSync } = await loadNodeRuntimeHelpers();
|
|
70
|
+
const packageJsonPath = pathModule.resolve(projectRoot, "package.json");
|
|
71
|
+
const requireFromProject = createRequire(packageJsonPath);
|
|
72
|
+
return {
|
|
73
|
+
"@typia/unplugin": resolveInstalledPackageVersion(readFileSync, requireFromProject, "@typia/unplugin"),
|
|
74
|
+
"@wordpress/scripts": resolveInstalledPackageVersion(readFileSync, requireFromProject, "@wordpress/scripts"),
|
|
75
|
+
typia: resolveInstalledPackageVersion(readFileSync, requireFromProject, "typia"),
|
|
76
|
+
webpack: resolveWebpackVersion(readFileSync, requireFromProject, createRequire),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function formatInstalledMatrix(versionMatrix) {
|
|
80
|
+
return [
|
|
81
|
+
`typia=${versionMatrix.typia ?? "missing"}`,
|
|
82
|
+
`@typia/unplugin=${versionMatrix["@typia/unplugin"] ?? "missing"}`,
|
|
83
|
+
`@wordpress/scripts=${versionMatrix["@wordpress/scripts"] ?? "missing"}`,
|
|
84
|
+
`webpack=${versionMatrix.webpack ?? "missing"}`,
|
|
85
|
+
].join(", ");
|
|
86
|
+
}
|
|
87
|
+
export async function assertTypiaWebpackCompatibility({ projectRoot = process.cwd(), } = {}) {
|
|
88
|
+
const versionMatrix = await getTypiaWebpackVersionMatrix(projectRoot);
|
|
89
|
+
const isSupported = parseMajorVersion(versionMatrix.typia) === 12 &&
|
|
90
|
+
parseMajorVersion(versionMatrix["@typia/unplugin"]) === 12 &&
|
|
91
|
+
parseMajorVersion(versionMatrix["@wordpress/scripts"]) === 30 &&
|
|
92
|
+
parseMajorVersion(versionMatrix.webpack) === 5;
|
|
93
|
+
if (isSupported) {
|
|
94
|
+
return versionMatrix;
|
|
95
|
+
}
|
|
96
|
+
throw new Error([
|
|
97
|
+
"Unsupported Typia/Webpack toolchain for generated wp-typia projects.",
|
|
98
|
+
`Installed versions: ${formatInstalledMatrix(versionMatrix)}.`,
|
|
99
|
+
"Supported matrix: typia 12.x, @typia/unplugin 12.x, @wordpress/scripts 30.x with webpack 5.x.",
|
|
100
|
+
"Generated project defaults were tested against this matrix.",
|
|
101
|
+
].join(" "));
|
|
102
|
+
}
|
|
103
|
+
export async function loadCompatibleTypiaWebpackPlugin({ importTypiaWebpackPlugin, projectRoot = process.cwd(), }) {
|
|
104
|
+
await assertTypiaWebpackCompatibility({ projectRoot });
|
|
105
|
+
const { default: UnpluginTypia } = await importTypiaWebpackPlugin();
|
|
106
|
+
return UnpluginTypia;
|
|
107
|
+
}
|
|
18
108
|
function mergeEntries(existingEntries, nextEntries, mode) {
|
|
19
109
|
if (!nextEntries) {
|
|
20
110
|
return existingEntries;
|
|
@@ -40,8 +130,11 @@ export function buildScaffoldBlockRegistration(metadata, overrides) {
|
|
|
40
130
|
},
|
|
41
131
|
};
|
|
42
132
|
}
|
|
43
|
-
export async function createTypiaWebpackConfig({ defaultConfig, fs, getArtifactEntries, getEditorEntries, getOptionalModuleEntries, importTypiaWebpackPlugin, isScriptModuleAsset = (assetName) => /(^|\/)(interactivity|view)\.asset\.php$/.test(assetName), moduleEntriesMode = "merge", nonModuleEntriesMode = "merge", path, }) {
|
|
44
|
-
const
|
|
133
|
+
export async function createTypiaWebpackConfig({ defaultConfig, fs, getArtifactEntries, getEditorEntries, getOptionalModuleEntries, importTypiaWebpackPlugin, isScriptModuleAsset = (assetName) => /(^|\/)(interactivity|view)\.asset\.php$/.test(assetName), moduleEntriesMode = "merge", nonModuleEntriesMode = "merge", path, projectRoot = process.cwd(), }) {
|
|
134
|
+
const UnpluginTypia = await loadCompatibleTypiaWebpackPlugin({
|
|
135
|
+
importTypiaWebpackPlugin,
|
|
136
|
+
projectRoot,
|
|
137
|
+
});
|
|
45
138
|
const resolvedDefaultConfig = typeof defaultConfig === "function"
|
|
46
139
|
? await defaultConfig()
|
|
47
140
|
: defaultConfig;
|
package/dist/metadata-core.js
CHANGED
|
@@ -4,7 +4,7 @@ import { getTaggedSyncBlockMetadataFailureCode } from './metadata-analysis.js';
|
|
|
4
4
|
import { renderPhpValidator } from './metadata-php-render.js';
|
|
5
5
|
import { analyzeSourceType, analyzeSourceTypes } from './metadata-parser.js';
|
|
6
6
|
import { createBlockJsonAttribute, createExampleValue, createManifestDocument, validateWordPressExtractionAttributes, } from './metadata-projection.js';
|
|
7
|
-
import { buildEndpointOpenApiDocument, manifestToJsonSchema, manifestToOpenApi, normalizeEndpointAuthDefinition, } from './schema-core.js';
|
|
7
|
+
import { buildEndpointOpenApiDocument, manifestToJsonSchema, manifestToOpenApi, normalizeEndpointAuthDefinition, projectJsonSchemaDocument, } from './schema-core.js';
|
|
8
8
|
/**
|
|
9
9
|
* Preserve literal TypeScript inference for backend-neutral endpoint manifests.
|
|
10
10
|
*
|
|
@@ -251,7 +251,9 @@ export async function syncTypeSchemas(options, executionOptions = {}) {
|
|
|
251
251
|
: undefined;
|
|
252
252
|
reconcileGeneratedArtifacts([
|
|
253
253
|
{
|
|
254
|
-
content: JSON.stringify(manifestToJsonSchema(manifest),
|
|
254
|
+
content: JSON.stringify(projectJsonSchemaDocument(manifestToJsonSchema(manifest), {
|
|
255
|
+
profile: 'rest',
|
|
256
|
+
}), null, '\t'),
|
|
255
257
|
path: jsonSchemaPath,
|
|
256
258
|
},
|
|
257
259
|
...(openApiPath
|
package/dist/object-utils.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
+
import { isPlainObject as isSharedPlainObject } from "@wp-typia/api-client/runtime-primitives";
|
|
1
2
|
export function isPlainObject(value) {
|
|
2
|
-
|
|
3
|
-
return false;
|
|
4
|
-
}
|
|
5
|
-
const prototype = Object.getPrototypeOf(value);
|
|
6
|
-
return prototype === Object.prototype || prototype === null;
|
|
3
|
+
return isSharedPlainObject(value);
|
|
7
4
|
}
|
package/dist/schema-core.d.ts
CHANGED
|
@@ -59,6 +59,7 @@ export interface OpenApiResponse extends JsonSchemaObject {
|
|
|
59
59
|
"application/json": OpenApiMediaType;
|
|
60
60
|
};
|
|
61
61
|
description: string;
|
|
62
|
+
headers?: Record<string, JsonSchemaObject>;
|
|
62
63
|
}
|
|
63
64
|
/**
|
|
64
65
|
* Header-based security scheme used by authenticated WordPress REST routes.
|
package/dist/schema-core.js
CHANGED
|
@@ -149,15 +149,35 @@ function applyProjectedTypeTag(schema, typeTag, path) {
|
|
|
149
149
|
throw new Error(`Unsupported wp-typia schema type tag "${typeTag}" at "${path}".`);
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
|
+
function canProjectTypeTag(typeTag) {
|
|
153
|
+
switch (typeTag) {
|
|
154
|
+
case "uint32":
|
|
155
|
+
case "int32":
|
|
156
|
+
case "float":
|
|
157
|
+
case "double":
|
|
158
|
+
return true;
|
|
159
|
+
default:
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
152
163
|
function projectSchemaArrayItemsForAiStructuredOutput(items, path) {
|
|
153
164
|
return items.map((item, index) => projectSchemaObjectForAiStructuredOutput(item, `${path}/${index}`));
|
|
154
165
|
}
|
|
166
|
+
function projectSchemaArrayItemsForRest(items, path) {
|
|
167
|
+
return items.map((item, index) => projectSchemaObjectForRest(item, `${path}/${index}`));
|
|
168
|
+
}
|
|
155
169
|
function projectSchemaPropertyMapForAiStructuredOutput(properties, path) {
|
|
156
170
|
return Object.fromEntries(Object.entries(properties).map(([key, value]) => [
|
|
157
171
|
key,
|
|
158
172
|
projectSchemaObjectForAiStructuredOutput(value, `${path}/${key}`),
|
|
159
173
|
]));
|
|
160
174
|
}
|
|
175
|
+
function projectSchemaPropertyMapForRest(properties, path) {
|
|
176
|
+
return Object.fromEntries(Object.entries(properties).map(([key, value]) => [
|
|
177
|
+
key,
|
|
178
|
+
projectSchemaObjectForRest(value, `${path}/${key}`),
|
|
179
|
+
]));
|
|
180
|
+
}
|
|
161
181
|
function projectSchemaObjectForAiStructuredOutput(node, path) {
|
|
162
182
|
const projectedNode = cloneJsonSchemaNode(node);
|
|
163
183
|
const rawTypeTag = projectedNode[WP_TYPIA_OPENAPI_EXTENSION_KEYS.TYPE_TAG];
|
|
@@ -188,6 +208,126 @@ function projectSchemaObjectForAiStructuredOutput(node, path) {
|
|
|
188
208
|
}
|
|
189
209
|
return projectedNode;
|
|
190
210
|
}
|
|
211
|
+
function projectSchemaObjectForRest(node, path) {
|
|
212
|
+
const projectedNode = cloneJsonSchemaNode(node);
|
|
213
|
+
const rawTypeTag = projectedNode[WP_TYPIA_OPENAPI_EXTENSION_KEYS.TYPE_TAG];
|
|
214
|
+
if (typeof rawTypeTag === "string" && canProjectTypeTag(rawTypeTag)) {
|
|
215
|
+
applyProjectedTypeTag(projectedNode, rawTypeTag, path);
|
|
216
|
+
}
|
|
217
|
+
for (const key of Object.keys(projectedNode)) {
|
|
218
|
+
const child = projectedNode[key];
|
|
219
|
+
if (Array.isArray(child)) {
|
|
220
|
+
projectedNode[key] = child.every(isJsonSchemaObject)
|
|
221
|
+
? projectSchemaArrayItemsForRest(child, `${path}/${key}`)
|
|
222
|
+
: child;
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
if (!isJsonSchemaObject(child)) {
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
if (key === "properties") {
|
|
229
|
+
projectedNode[key] = projectSchemaPropertyMapForRest(child, `${path}/${key}`);
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
projectedNode[key] = projectSchemaObjectForRest(child, `${path}/${key}`);
|
|
233
|
+
}
|
|
234
|
+
applyProjectedBootstrapContract(projectedNode);
|
|
235
|
+
return projectedNode;
|
|
236
|
+
}
|
|
237
|
+
function applyProjectedBootstrapContract(schema) {
|
|
238
|
+
if (schema.type !== "object" || !isJsonSchemaObject(schema.properties)) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
const properties = schema.properties;
|
|
242
|
+
if (properties.canWrite?.type !== "boolean") {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
const allOf = Array.isArray(schema.allOf)
|
|
246
|
+
? [...schema.allOf]
|
|
247
|
+
: [];
|
|
248
|
+
const canWriteIsTrue = {
|
|
249
|
+
properties: {
|
|
250
|
+
canWrite: {
|
|
251
|
+
const: true,
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
required: ["canWrite"],
|
|
255
|
+
};
|
|
256
|
+
const buildRequiredPropertyObject = (requiredKeys) => Object.fromEntries(requiredKeys.map((requiredKey) => [requiredKey, properties[requiredKey] ?? {}]));
|
|
257
|
+
const hasRestNonce = properties.restNonce?.type === "string";
|
|
258
|
+
const hasPublicWriteCredential = properties.publicWriteToken?.type === "string" &&
|
|
259
|
+
isJsonSchemaObject(properties.publicWriteExpiresAt);
|
|
260
|
+
if (hasRestNonce && hasPublicWriteCredential) {
|
|
261
|
+
allOf.push({
|
|
262
|
+
if: canWriteIsTrue,
|
|
263
|
+
then: {
|
|
264
|
+
anyOf: [
|
|
265
|
+
{
|
|
266
|
+
properties: buildRequiredPropertyObject(["restNonce"]),
|
|
267
|
+
required: ["restNonce"],
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
properties: buildRequiredPropertyObject([
|
|
271
|
+
"publicWriteExpiresAt",
|
|
272
|
+
"publicWriteToken",
|
|
273
|
+
]),
|
|
274
|
+
required: ["publicWriteExpiresAt", "publicWriteToken"],
|
|
275
|
+
},
|
|
276
|
+
],
|
|
277
|
+
},
|
|
278
|
+
else: {
|
|
279
|
+
not: {
|
|
280
|
+
anyOf: [
|
|
281
|
+
{
|
|
282
|
+
properties: buildRequiredPropertyObject(["restNonce"]),
|
|
283
|
+
required: ["restNonce"],
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
properties: buildRequiredPropertyObject(["publicWriteToken"]),
|
|
287
|
+
required: ["publicWriteToken"],
|
|
288
|
+
},
|
|
289
|
+
],
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
if (hasRestNonce && !hasPublicWriteCredential) {
|
|
295
|
+
allOf.push({
|
|
296
|
+
if: canWriteIsTrue,
|
|
297
|
+
then: {
|
|
298
|
+
properties: buildRequiredPropertyObject(["restNonce"]),
|
|
299
|
+
required: ["restNonce"],
|
|
300
|
+
},
|
|
301
|
+
else: {
|
|
302
|
+
not: {
|
|
303
|
+
properties: buildRequiredPropertyObject(["restNonce"]),
|
|
304
|
+
required: ["restNonce"],
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
if (hasPublicWriteCredential && !hasRestNonce) {
|
|
310
|
+
allOf.push({
|
|
311
|
+
if: canWriteIsTrue,
|
|
312
|
+
then: {
|
|
313
|
+
properties: buildRequiredPropertyObject([
|
|
314
|
+
"publicWriteExpiresAt",
|
|
315
|
+
"publicWriteToken",
|
|
316
|
+
]),
|
|
317
|
+
required: ["publicWriteExpiresAt", "publicWriteToken"],
|
|
318
|
+
},
|
|
319
|
+
else: {
|
|
320
|
+
not: {
|
|
321
|
+
properties: buildRequiredPropertyObject(["publicWriteToken"]),
|
|
322
|
+
required: ["publicWriteToken"],
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
if (allOf.length > 0) {
|
|
328
|
+
schema.allOf = allOf;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
191
331
|
function manifestUnionToJsonSchema(union) {
|
|
192
332
|
const oneOf = Object.entries(union.branches).map(([branchKey, branch]) => {
|
|
193
333
|
if (branch.ts.kind !== "object") {
|
|
@@ -305,7 +445,7 @@ export function manifestToJsonSchema(doc) {
|
|
|
305
445
|
*/
|
|
306
446
|
export function projectJsonSchemaDocument(schema, options) {
|
|
307
447
|
if (options.profile === "rest") {
|
|
308
|
-
return
|
|
448
|
+
return projectSchemaObjectForRest(schema, "#");
|
|
309
449
|
}
|
|
310
450
|
if (options.profile === "ai-structured-output") {
|
|
311
451
|
return projectSchemaObjectForAiStructuredOutput(schema, "#");
|
|
@@ -321,10 +461,14 @@ export function projectJsonSchemaDocument(schema, options) {
|
|
|
321
461
|
*/
|
|
322
462
|
export function manifestToOpenApi(doc, info = {}) {
|
|
323
463
|
const schemaName = doc.sourceType ?? "TypiaDocument";
|
|
464
|
+
const projectedSchema = projectJsonSchemaDocument(manifestToJsonSchema(doc), {
|
|
465
|
+
profile: "rest",
|
|
466
|
+
});
|
|
467
|
+
delete projectedSchema.$schema;
|
|
324
468
|
return {
|
|
325
469
|
components: {
|
|
326
470
|
schemas: {
|
|
327
|
-
[schemaName]:
|
|
471
|
+
[schemaName]: projectedSchema,
|
|
328
472
|
},
|
|
329
473
|
},
|
|
330
474
|
info: {
|
|
@@ -486,7 +630,36 @@ function buildQueryParameters(contract) {
|
|
|
486
630
|
schema: manifestAttributeToJsonSchema(attribute),
|
|
487
631
|
}));
|
|
488
632
|
}
|
|
489
|
-
function
|
|
633
|
+
function createBootstrapResponseHeaders(normalizedAuth) {
|
|
634
|
+
const headers = {
|
|
635
|
+
"Cache-Control": {
|
|
636
|
+
description: "Must be non-cacheable for fresh bootstrap write/session state.",
|
|
637
|
+
schema: {
|
|
638
|
+
type: "string",
|
|
639
|
+
example: "private, no-store, no-cache, must-revalidate",
|
|
640
|
+
},
|
|
641
|
+
},
|
|
642
|
+
Pragma: {
|
|
643
|
+
description: "Legacy non-cacheable bootstrap response directive.",
|
|
644
|
+
schema: {
|
|
645
|
+
type: "string",
|
|
646
|
+
example: "no-cache",
|
|
647
|
+
},
|
|
648
|
+
},
|
|
649
|
+
};
|
|
650
|
+
if (normalizedAuth.wordpressAuth?.mechanism ===
|
|
651
|
+
WP_TYPIA_OPENAPI_LITERALS.WORDPRESS_REST_NONCE_MECHANISM) {
|
|
652
|
+
headers.Vary = {
|
|
653
|
+
description: "Viewer-aware bootstrap responses should vary on cookie-backed auth state.",
|
|
654
|
+
schema: {
|
|
655
|
+
type: "string",
|
|
656
|
+
example: "Cookie",
|
|
657
|
+
},
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
return headers;
|
|
661
|
+
}
|
|
662
|
+
function createSuccessResponse(schemaName, headers) {
|
|
490
663
|
return {
|
|
491
664
|
content: {
|
|
492
665
|
[WP_TYPIA_OPENAPI_LITERALS.JSON_CONTENT_TYPE]: {
|
|
@@ -494,14 +667,18 @@ function createSuccessResponse(schemaName) {
|
|
|
494
667
|
},
|
|
495
668
|
},
|
|
496
669
|
description: WP_TYPIA_OPENAPI_LITERALS.SUCCESS_RESPONSE_DESCRIPTION,
|
|
670
|
+
...(headers ? { headers } : {}),
|
|
497
671
|
};
|
|
498
672
|
}
|
|
499
673
|
function buildEndpointOpenApiOperation(endpoint, contracts) {
|
|
500
674
|
const normalizedAuth = normalizeEndpointAuthDefinition(endpoint);
|
|
675
|
+
const isBootstrapEndpoint = endpoint.path.endsWith("/bootstrap");
|
|
501
676
|
const operation = {
|
|
502
677
|
operationId: endpoint.operationId,
|
|
503
678
|
responses: {
|
|
504
|
-
"200": createSuccessResponse(getContractSchemaName(endpoint.responseContract, contracts[endpoint.responseContract], endpoint, "response")
|
|
679
|
+
"200": createSuccessResponse(getContractSchemaName(endpoint.responseContract, contracts[endpoint.responseContract], endpoint, "response"), isBootstrapEndpoint
|
|
680
|
+
? createBootstrapResponseHeaders(normalizedAuth)
|
|
681
|
+
: undefined),
|
|
505
682
|
},
|
|
506
683
|
tags: [...endpoint.tags],
|
|
507
684
|
[WP_TYPIA_OPENAPI_EXTENSION_KEYS.AUTH_INTENT]: normalizedAuth.auth,
|
|
@@ -554,10 +731,13 @@ function buildEndpointOpenApiOperation(endpoint, contracts) {
|
|
|
554
731
|
*/
|
|
555
732
|
export function buildEndpointOpenApiDocument(options) {
|
|
556
733
|
const contractEntries = Object.entries(options.contracts);
|
|
557
|
-
const schemas = Object.fromEntries(contractEntries.map(([contractKey, contract]) =>
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
734
|
+
const schemas = Object.fromEntries(contractEntries.map(([contractKey, contract]) => {
|
|
735
|
+
const projectedSchema = projectJsonSchemaDocument(manifestToJsonSchema(contract.document), {
|
|
736
|
+
profile: "rest",
|
|
737
|
+
});
|
|
738
|
+
delete projectedSchema.$schema;
|
|
739
|
+
return [getContractSchemaName(contractKey, contract), projectedSchema];
|
|
740
|
+
}));
|
|
561
741
|
const paths = {};
|
|
562
742
|
const topLevelTags = [...new Set(options.endpoints.flatMap((endpoint) => endpoint.tags))]
|
|
563
743
|
.filter((tag) => typeof tag === "string" && tag.length > 0)
|
package/dist/validation.d.ts
CHANGED
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
import type { ManifestDefaultsDocument } from "./defaults.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
path: string;
|
|
6
|
-
value: unknown;
|
|
7
|
-
}
|
|
8
|
-
export interface ValidationResult<T> {
|
|
9
|
-
data?: T;
|
|
10
|
-
errors: TypiaValidationError[];
|
|
11
|
-
isValid: boolean;
|
|
12
|
-
}
|
|
2
|
+
import { type ValidationError as SharedValidationError, type ValidationResult as SharedValidationResult } from "@wp-typia/api-client/runtime-primitives";
|
|
3
|
+
export type TypiaValidationError = SharedValidationError;
|
|
4
|
+
export type ValidationResult<T> = SharedValidationResult<T>;
|
|
13
5
|
export interface ValidationState<T> extends ValidationResult<T> {
|
|
14
6
|
errorMessages: string[];
|
|
15
7
|
}
|
package/dist/validation.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { applyTemplateDefaultsFromManifest } from "./defaults.js";
|
|
2
|
-
import { isPlainObject as isRecord } from "
|
|
2
|
+
import { isPlainObject as isRecord, normalizeValidationError as normalizeSharedValidationError, toValidationResult as toSharedValidationResult, } from "@wp-typia/api-client/runtime-primitives";
|
|
3
3
|
const UNSAFE_PATH_SEGMENTS = new Set(["__proto__", "constructor", "prototype"]);
|
|
4
4
|
function getValueType(value) {
|
|
5
5
|
if (value === null) {
|
|
@@ -18,33 +18,10 @@ function redactValidationErrors(errors) {
|
|
|
18
18
|
}));
|
|
19
19
|
}
|
|
20
20
|
export function normalizeValidationError(error) {
|
|
21
|
-
|
|
22
|
-
? error
|
|
23
|
-
: {};
|
|
24
|
-
return {
|
|
25
|
-
description: typeof raw.description === "string" ? raw.description : undefined,
|
|
26
|
-
expected: typeof raw.expected === "string" ? raw.expected : "unknown",
|
|
27
|
-
path: typeof raw.path === "string" && raw.path.length > 0 ? raw.path : "(root)",
|
|
28
|
-
value: Object.prototype.hasOwnProperty.call(raw, "value") ? raw.value : undefined,
|
|
29
|
-
};
|
|
21
|
+
return normalizeSharedValidationError(error);
|
|
30
22
|
}
|
|
31
23
|
export function toValidationResult(result) {
|
|
32
|
-
|
|
33
|
-
? result
|
|
34
|
-
: undefined;
|
|
35
|
-
if (raw?.success === true) {
|
|
36
|
-
return {
|
|
37
|
-
data: raw.data,
|
|
38
|
-
errors: [],
|
|
39
|
-
isValid: true,
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
const rawErrors = Array.isArray(raw?.errors) ? raw.errors : [];
|
|
43
|
-
return {
|
|
44
|
-
data: undefined,
|
|
45
|
-
errors: rawErrors.map(normalizeValidationError),
|
|
46
|
-
isValid: false,
|
|
47
|
-
};
|
|
24
|
+
return toSharedValidationResult(result);
|
|
48
25
|
}
|
|
49
26
|
export function formatValidationError(error) {
|
|
50
27
|
return `${error.path}: ${error.expected} expected, got ${getValueType(error.value)}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wp-typia/block-runtime",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"description": "Generated-project runtime and metadata sync helpers for wp-typia",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -21,6 +21,31 @@
|
|
|
21
21
|
"import": "./dist/metadata-core.js",
|
|
22
22
|
"default": "./dist/metadata-core.js"
|
|
23
23
|
},
|
|
24
|
+
"./metadata-analysis": {
|
|
25
|
+
"types": "./dist/metadata-analysis.d.ts",
|
|
26
|
+
"import": "./dist/metadata-analysis.js",
|
|
27
|
+
"default": "./dist/metadata-analysis.js"
|
|
28
|
+
},
|
|
29
|
+
"./metadata-model": {
|
|
30
|
+
"types": "./dist/metadata-model.d.ts",
|
|
31
|
+
"import": "./dist/metadata-model.js",
|
|
32
|
+
"default": "./dist/metadata-model.js"
|
|
33
|
+
},
|
|
34
|
+
"./metadata-parser": {
|
|
35
|
+
"types": "./dist/metadata-parser.d.ts",
|
|
36
|
+
"import": "./dist/metadata-parser.js",
|
|
37
|
+
"default": "./dist/metadata-parser.js"
|
|
38
|
+
},
|
|
39
|
+
"./metadata-php-render": {
|
|
40
|
+
"types": "./dist/metadata-php-render.d.ts",
|
|
41
|
+
"import": "./dist/metadata-php-render.js",
|
|
42
|
+
"default": "./dist/metadata-php-render.js"
|
|
43
|
+
},
|
|
44
|
+
"./metadata-projection": {
|
|
45
|
+
"types": "./dist/metadata-projection.d.ts",
|
|
46
|
+
"import": "./dist/metadata-projection.js",
|
|
47
|
+
"default": "./dist/metadata-projection.js"
|
|
48
|
+
},
|
|
24
49
|
"./defaults": {
|
|
25
50
|
"types": "./dist/defaults.d.ts",
|
|
26
51
|
"import": "./dist/defaults.js",
|
|
@@ -46,6 +71,11 @@
|
|
|
46
71
|
"import": "./dist/validation.js",
|
|
47
72
|
"default": "./dist/validation.js"
|
|
48
73
|
},
|
|
74
|
+
"./json-utils": {
|
|
75
|
+
"types": "./dist/json-utils.d.ts",
|
|
76
|
+
"import": "./dist/json-utils.js",
|
|
77
|
+
"default": "./dist/json-utils.js"
|
|
78
|
+
},
|
|
49
79
|
"./package.json": "./package.json"
|
|
50
80
|
},
|
|
51
81
|
"files": [
|
|
@@ -54,7 +84,7 @@
|
|
|
54
84
|
"package.json"
|
|
55
85
|
],
|
|
56
86
|
"scripts": {
|
|
57
|
-
"build": "rm -rf dist && tsc -p tsconfig.build.json",
|
|
87
|
+
"build": "bun run --filter @wp-typia/api-client build && rm -rf dist && tsc -p tsconfig.build.json",
|
|
58
88
|
"clean": "rm -rf dist",
|
|
59
89
|
"test:prepare": "bun run build",
|
|
60
90
|
"test": "bun run test:prepare && bun test tests",
|
|
@@ -78,7 +108,7 @@
|
|
|
78
108
|
"engines": {
|
|
79
109
|
"node": ">=20.0.0",
|
|
80
110
|
"npm": ">=10.0.0",
|
|
81
|
-
"bun": ">=1.3.
|
|
111
|
+
"bun": ">=1.3.11"
|
|
82
112
|
},
|
|
83
113
|
"peerDependencies": {
|
|
84
114
|
"react": "^18.0.0 || ^19.0.0"
|
|
@@ -89,6 +119,7 @@
|
|
|
89
119
|
}
|
|
90
120
|
},
|
|
91
121
|
"dependencies": {
|
|
122
|
+
"@wp-typia/api-client": "^0.4.2",
|
|
92
123
|
"typescript": "^5.9.2"
|
|
93
124
|
},
|
|
94
125
|
"devDependencies": {
|