@wp-typia/project-tools 0.15.1 → 0.15.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.
@@ -1,29 +1,7 @@
1
- import type { ManifestAttribute, ManifestDocument } from "./metadata-model.js";
2
1
  /**
3
- * Render a PHP validator class from one manifest document.
4
- *
5
- * @param manifest Manifest document describing the block attribute schema and
6
- * Typia metadata to enforce in PHP.
7
- * @returns Generated PHP source plus any warn-only coverage gaps discovered
8
- * while traversing the manifest.
2
+ * Re-exports PHP metadata rendering 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
9
6
  */
10
- export declare function renderPhpValidator(manifest: ManifestDocument): {
11
- source: string;
12
- warnings: string[];
13
- };
14
- /**
15
- * Collect warn-only PHP validator generation gaps for one manifest branch.
16
- *
17
- * @param attribute Manifest attribute metadata to inspect.
18
- * @param pathLabel Human-readable path used in emitted warning messages.
19
- * @param warnings Mutable accumulator that receives any discovered warnings.
20
- */
21
- export declare function collectPhpGenerationWarnings(attribute: ManifestAttribute, pathLabel: string, warnings: string[]): void;
22
- /**
23
- * Render one JavaScript value into a PHP literal string.
24
- *
25
- * @param value JSON-like value to encode for the generated validator manifest.
26
- * @param indentLevel Current indentation depth, expressed in tab levels.
27
- * @returns PHP source code representing the provided value.
28
- */
29
- export declare function renderPhpValue(value: unknown, indentLevel: number): string;
7
+ export * from "@wp-typia/block-runtime/metadata-php-render";
@@ -1,549 +1,7 @@
1
- const SUPPORTED_PHP_FORMATS = new Set([
2
- "uuid",
3
- "email",
4
- "url",
5
- "uri",
6
- "ipv4",
7
- "ipv6",
8
- "date-time",
9
- ]);
10
- const SUPPORTED_PHP_TYPE_TAGS = new Set([
11
- "uint32",
12
- "int32",
13
- "uint64",
14
- "float",
15
- "double",
16
- ]);
17
1
  /**
18
- * Render a PHP validator class from one manifest document.
19
- *
20
- * @param manifest Manifest document describing the block attribute schema and
21
- * Typia metadata to enforce in PHP.
22
- * @returns Generated PHP source plus any warn-only coverage gaps discovered
23
- * while traversing the manifest.
2
+ * Re-exports PHP metadata rendering 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
24
6
  */
25
- export function renderPhpValidator(manifest) {
26
- const warnings = [];
27
- for (const [key, attribute] of Object.entries(manifest.attributes)) {
28
- collectPhpGenerationWarnings(attribute, key, warnings);
29
- }
30
- const phpManifest = renderPhpValue(manifest, 2);
31
- return {
32
- source: `<?php
33
- declare(strict_types=1);
34
-
35
- /**
36
- * Generated from typia.manifest.json. Do not edit manually.
37
- */
38
- return new class {
39
- \tprivate array $manifest = ${phpManifest};
40
-
41
- \tpublic function apply_defaults(array $attributes): array
42
- \t{
43
- \t\treturn $this->applyDefaultsForObject($attributes, $this->manifest['attributes'] ?? []);
44
- \t}
45
-
46
- \tpublic function validate(array $attributes): array
47
- \t{
48
- \t\t$normalized = $this->apply_defaults($attributes);
49
- \t\t$errors = [];
50
-
51
- \t\tforeach (($this->manifest['attributes'] ?? []) as $name => $attribute) {
52
- \t\t\t$this->validateAttribute(
53
- \t\t\t\tarray_key_exists($name, $normalized),
54
- \t\t\t\t$normalized[$name] ?? null,
55
- \t\t\t\t$attribute,
56
- \t\t\t\t(string) $name,
57
- \t\t\t\t$errors,
58
- \t\t\t);
59
- \t\t}
60
-
61
- \t\treturn [
62
- \t\t\t'errors' => $errors,
63
- \t\t\t'valid' => count($errors) === 0,
64
- \t\t];
65
- \t}
66
-
67
- \tpublic function is_valid(array $attributes): bool
68
- \t{
69
- \t\treturn $this->validate($attributes)['valid'];
70
- \t}
71
-
72
- \tprivate function applyDefaultsForObject(array $attributes, array $schema): array
73
- \t{
74
- \t\t$result = $attributes;
75
-
76
- \t\tforeach ($schema as $name => $attribute) {
77
- \t\t\tif (!array_key_exists($name, $result)) {
78
- \t\t\t\t$derivedDefault = $this->deriveDefaultValue($attribute);
79
- \t\t\t\tif ($derivedDefault !== null) {
80
- \t\t\t\t\t$result[$name] = $derivedDefault;
81
- \t\t\t\t}
82
- \t\t\t\tcontinue;
83
- \t\t\t}
84
-
85
- \t\t\t$result[$name] = $this->applyDefaultsForNode($result[$name], $attribute);
86
- \t\t}
87
-
88
- \t\treturn $result;
89
- \t}
90
-
91
- \tprivate function applyDefaultsForNode($value, array $attribute)
92
- \t{
93
- \t\tif ($value === null) {
94
- \t\t\treturn null;
95
- \t\t}
96
-
97
- \t\t$kind = $attribute['ts']['kind'] ?? $attribute['wp']['type'] ?? null;
98
- \t\tif ($kind === 'union') {
99
- \t\t\treturn $this->applyDefaultsForUnion($value, $attribute);
100
- \t\t}
101
- \t\tif ($kind === 'object' && is_array($value) && !$this->isListArray($value)) {
102
- \t\t\treturn $this->applyDefaultsForObject($value, $attribute['ts']['properties'] ?? []);
103
- \t\t}
104
- \t\tif (
105
- \t\t\t$kind === 'array' &&
106
- \t\t\tis_array($value) &&
107
- \t\t\t$this->isListArray($value) &&
108
- \t\t\tisset($attribute['ts']['items']) &&
109
- \t\t\tis_array($attribute['ts']['items'])
110
- \t\t) {
111
- \t\t\t$result = [];
112
- \t\t\tforeach ($value as $index => $item) {
113
- \t\t\t\t$result[$index] = $this->applyDefaultsForNode($item, $attribute['ts']['items']);
114
- \t\t\t}
115
- \t\t\treturn $result;
116
- \t\t}
117
-
118
- \t\treturn $value;
119
- \t}
120
-
121
- \tprivate function deriveDefaultValue(array $attribute)
122
- \t{
123
- \t\tif ($this->hasDefault($attribute)) {
124
- \t\t\treturn $attribute['typia']['defaultValue'];
125
- \t\t}
126
-
127
- \t\t$kind = $attribute['ts']['kind'] ?? $attribute['wp']['type'] ?? null;
128
- \t\tif ($kind !== 'object') {
129
- \t\t\treturn null;
130
- \t\t}
131
-
132
- \t\t$properties = $attribute['ts']['properties'] ?? null;
133
- \t\tif (!is_array($properties)) {
134
- \t\t\treturn null;
135
- \t\t}
136
-
137
- \t\t$derived = [];
138
- \t\tforeach ($properties as $name => $child) {
139
- \t\t\tif (!is_array($child)) {
140
- \t\t\t\tcontinue;
141
- \t\t\t}
142
- \t\t\t$childDefault = $this->deriveDefaultValue($child);
143
- \t\t\tif ($childDefault !== null) {
144
- \t\t\t\t$derived[$name] = $childDefault;
145
- \t\t\t}
146
- \t\t}
147
-
148
- \t\treturn count($derived) > 0 ? $derived : null;
149
- \t}
150
-
151
- \tprivate function applyDefaultsForUnion($value, array $attribute)
152
- \t{
153
- \t\tif (!is_array($value) || $this->isListArray($value)) {
154
- \t\t\treturn $value;
155
- \t\t}
156
-
157
- \t\t$union = $attribute['ts']['union'] ?? null;
158
- \t\tif (!is_array($union)) {
159
- \t\t\treturn $value;
160
- \t\t}
161
-
162
- \t\t$discriminator = $union['discriminator'] ?? null;
163
- \t\tif (!is_string($discriminator) || !array_key_exists($discriminator, $value)) {
164
- \t\t\treturn $value;
165
- \t\t}
166
-
167
- \t\t$branchKey = $value[$discriminator];
168
- \t\tif (!is_string($branchKey) || !isset($union['branches'][$branchKey]) || !is_array($union['branches'][$branchKey])) {
169
- \t\t\treturn $value;
170
- \t\t}
171
-
172
- \t\treturn $this->applyDefaultsForNode($value, $union['branches'][$branchKey]);
173
- \t}
174
-
175
- \tprivate function validateAttribute(bool $exists, $value, array $attribute, string $path, array &$errors): void
176
- \t{
177
- \t\tif (!$exists) {
178
- \t\t\tif (($attribute['ts']['required'] ?? false) && !$this->hasDefault($attribute)) {
179
- \t\t\t\t$errors[] = sprintf('%s is required', $path);
180
- \t\t\t}
181
- \t\t\treturn;
182
- \t\t}
183
-
184
- \t\t$kind = $attribute['ts']['kind'] ?? $attribute['wp']['type'] ?? null;
185
- \t\tif (!is_string($kind) || $kind === '') {
186
- \t\t\t$errors[] = sprintf('%s has an invalid schema kind', $path);
187
- \t\t\treturn;
188
- \t\t}
189
- \t\tif ($value === null) {
190
- \t\t\t$errors[] = sprintf('%s must be %s', $path, $this->expectedKindLabel($attribute));
191
- \t\t\treturn;
192
- \t\t}
193
-
194
- \t\tif (($attribute['wp']['enum'] ?? null) !== null && !$this->valueInEnum($value, $attribute['wp']['enum'])) {
195
- \t\t\t$errors[] = sprintf('%s must be one of %s', $path, implode(', ', $attribute['wp']['enum']));
196
- \t\t}
197
-
198
- \t\tswitch ($kind) {
199
- \t\t\tcase 'string':
200
- \t\t\t\tif (!is_string($value)) {
201
- \t\t\t\t\t$errors[] = sprintf('%s must be string', $path);
202
- \t\t\t\t\treturn;
203
- \t\t\t\t}
204
- \t\t\t\t$this->validateString($value, $attribute, $path, $errors);
205
- \t\t\t\treturn;
206
- \t\t\tcase 'number':
207
- \t\t\t\t$allowsUint64String =
208
- \t\t\t\t\t($attribute['typia']['constraints']['typeTag'] ?? null) === 'uint64' &&
209
- \t\t\t\t\t$this->matchesUint64($value);
210
- \t\t\t\tif (!$this->isNumber($value) && !$allowsUint64String) {
211
- \t\t\t\t\t$errors[] = sprintf('%s must be number', $path);
212
- \t\t\t\t\treturn;
213
- \t\t\t\t}
214
- \t\t\t\t$this->validateNumber($value, $attribute, $path, $errors);
215
- \t\t\t\treturn;
216
- \t\t\tcase 'boolean':
217
- \t\t\t\tif (!is_bool($value)) {
218
- \t\t\t\t\t$errors[] = sprintf('%s must be boolean', $path);
219
- \t\t\t\t}
220
- \t\t\t\treturn;
221
- \t\t\tcase 'array':
222
- \t\t\t\tif (!is_array($value) || !$this->isListArray($value)) {
223
- \t\t\t\t\t$errors[] = sprintf('%s must be array', $path);
224
- \t\t\t\t\treturn;
225
- \t\t\t\t}
226
- \t\t\t\t$this->validateArray($value, $attribute, $path, $errors);
227
- \t\t\t\tif (isset($attribute['ts']['items']) && is_array($attribute['ts']['items'])) {
228
- \t\t\t\t\tforeach ($value as $index => $item) {
229
- \t\t\t\t\t\t$this->validateAttribute(true, $item, $attribute['ts']['items'], sprintf('%s[%s]', $path, (string) $index), $errors);
230
- \t\t\t\t\t}
231
- \t\t\t\t}
232
- \t\t\t\treturn;
233
- \t\t\tcase 'object':
234
- \t\t\t\tif (!is_array($value) || $this->isListArray($value)) {
235
- \t\t\t\t\t$errors[] = sprintf('%s must be object', $path);
236
- \t\t\t\t\treturn;
237
- \t\t\t\t}
238
- \t\t\t\tforeach (($attribute['ts']['properties'] ?? []) as $name => $child) {
239
- \t\t\t\t\t$this->validateAttribute(
240
- \t\t\t\t\t\tarray_key_exists($name, $value),
241
- \t\t\t\t\t\t$value[$name] ?? null,
242
- \t\t\t\t\t\t$child,
243
- \t\t\t\t\t\tsprintf('%s.%s', $path, (string) $name),
244
- \t\t\t\t\t\t$errors,
245
- \t\t\t\t\t);
246
- \t\t\t\t}
247
- \t\t\t\treturn;
248
- \t\t\tcase 'union':
249
- \t\t\t\t$this->validateUnion($value, $attribute, $path, $errors);
250
- \t\t\t\treturn;
251
- \t\t\tdefault:
252
- \t\t\t\t$errors[] = sprintf('%s has unsupported schema kind %s', $path, $kind);
253
- \t\t}
254
- \t}
255
-
256
- \tprivate function validateUnion($value, array $attribute, string $path, array &$errors): void
257
- \t{
258
- \t\tif (!is_array($value) || $this->isListArray($value)) {
259
- \t\t\t$errors[] = sprintf('%s must be object', $path);
260
- \t\t\treturn;
261
- \t\t}
262
-
263
- \t\t$union = $attribute['ts']['union'] ?? null;
264
- \t\tif (!is_array($union)) {
265
- \t\t\t$errors[] = sprintf('%s has invalid union schema metadata', $path);
266
- \t\t\treturn;
267
- \t\t}
268
-
269
- \t\t$discriminator = $union['discriminator'] ?? null;
270
- \t\tif (!is_string($discriminator) || $discriminator === '') {
271
- \t\t\t$errors[] = sprintf('%s has invalid union discriminator metadata', $path);
272
- \t\t\treturn;
273
- \t\t}
274
- \t\tif (!array_key_exists($discriminator, $value)) {
275
- \t\t\t$errors[] = sprintf('%s.%s is required', $path, $discriminator);
276
- \t\t\treturn;
277
- \t\t}
278
-
279
- \t\t$branchKey = $value[$discriminator];
280
- \t\tif (!is_string($branchKey)) {
281
- \t\t\t$errors[] = sprintf('%s.%s must be string', $path, $discriminator);
282
- \t\t\treturn;
283
- \t\t}
284
- \t\tif (!isset($union['branches'][$branchKey]) || !is_array($union['branches'][$branchKey])) {
285
- \t\t\t$errors[] = sprintf('%s.%s must be one of %s', $path, $discriminator, implode(', ', array_keys($union['branches'] ?? [])));
286
- \t\t\treturn;
287
- \t\t}
288
-
289
- \t\t$this->validateAttribute(true, $value, $union['branches'][$branchKey], $path, $errors);
290
- \t}
291
-
292
- \tprivate function validateString(string $value, array $attribute, string $path, array &$errors): void
293
- \t{
294
- \t\t$constraints = $attribute['typia']['constraints'] ?? [];
295
-
296
- \t\tif (isset($constraints['minLength']) && is_int($constraints['minLength']) && strlen($value) < $constraints['minLength']) {
297
- \t\t\t$errors[] = sprintf('%s must be at least %d characters', $path, $constraints['minLength']);
298
- \t\t}
299
- \t\tif (isset($constraints['maxLength']) && is_int($constraints['maxLength']) && strlen($value) > $constraints['maxLength']) {
300
- \t\t\t$errors[] = sprintf('%s must be at most %d characters', $path, $constraints['maxLength']);
301
- \t\t}
302
- \t\tif (
303
- \t\t\tisset($constraints['pattern']) &&
304
- \t\t\tis_string($constraints['pattern']) &&
305
- \t\t\t$constraints['pattern'] !== '' &&
306
- \t\t\t!$this->matchesPattern($constraints['pattern'], $value)
307
- \t\t) {
308
- \t\t\t$errors[] = sprintf('%s does not match %s', $path, $constraints['pattern']);
309
- \t\t}
310
- \t\tif (
311
- \t\t\tisset($constraints['format']) &&
312
- \t\t\tis_string($constraints['format']) &&
313
- \t\t\t!$this->matchesFormat($constraints['format'], $value)
314
- \t\t) {
315
- \t\t\t$errors[] = sprintf('%s must match format %s', $path, $constraints['format']);
316
- \t\t}
317
- \t}
318
-
319
- \tprivate function validateArray(array $value, array $attribute, string $path, array &$errors): void
320
- \t{
321
- \t\t$constraints = $attribute['typia']['constraints'] ?? [];
322
-
323
- \t\tif (isset($constraints['minItems']) && is_int($constraints['minItems']) && count($value) < $constraints['minItems']) {
324
- \t\t\t$errors[] = sprintf('%s must have at least %d items', $path, $constraints['minItems']);
325
- \t\t}
326
- \t\tif (isset($constraints['maxItems']) && is_int($constraints['maxItems']) && count($value) > $constraints['maxItems']) {
327
- \t\t\t$errors[] = sprintf('%s must have at most %d items', $path, $constraints['maxItems']);
328
- \t\t}
329
- \t}
330
-
331
- \tprivate function validateNumber($value, array $attribute, string $path, array &$errors): void
332
- \t{
333
- \t\t$constraints = $attribute['typia']['constraints'] ?? [];
334
-
335
- \t\tif (isset($constraints['minimum']) && $this->isNumber($constraints['minimum']) && $value < $constraints['minimum']) {
336
- \t\t\t$errors[] = sprintf('%s must be >= %s', $path, (string) $constraints['minimum']);
337
- \t\t}
338
- \t\tif (isset($constraints['maximum']) && $this->isNumber($constraints['maximum']) && $value > $constraints['maximum']) {
339
- \t\t\t$errors[] = sprintf('%s must be <= %s', $path, (string) $constraints['maximum']);
340
- \t\t}
341
- \t\tif (
342
- \t\t\tisset($constraints['exclusiveMinimum']) &&
343
- \t\t\t$this->isNumber($constraints['exclusiveMinimum']) &&
344
- \t\t\t$value <= $constraints['exclusiveMinimum']
345
- \t\t) {
346
- \t\t\t$errors[] = sprintf('%s must be > %s', $path, (string) $constraints['exclusiveMinimum']);
347
- \t\t}
348
- \t\tif (
349
- \t\t\tisset($constraints['exclusiveMaximum']) &&
350
- \t\t\t$this->isNumber($constraints['exclusiveMaximum']) &&
351
- \t\t\t$value >= $constraints['exclusiveMaximum']
352
- \t\t) {
353
- \t\t\t$errors[] = sprintf('%s must be < %s', $path, (string) $constraints['exclusiveMaximum']);
354
- \t\t}
355
- \t\tif (
356
- \t\t\tisset($constraints['multipleOf']) &&
357
- \t\t\t$this->isNumber($constraints['multipleOf']) &&
358
- \t\t\t!$this->matchesMultipleOf($value, $constraints['multipleOf'])
359
- \t\t) {
360
- \t\t\t$errors[] = sprintf('%s must be a multiple of %s', $path, (string) $constraints['multipleOf']);
361
- \t\t}
362
- \t\tif (
363
- \t\t\tisset($constraints['typeTag']) &&
364
- \t\t\tis_string($constraints['typeTag']) &&
365
- \t\t\t!$this->matchesTypeTag($value, $constraints['typeTag'])
366
- \t\t) {
367
- \t\t\t$errors[] = sprintf('%s must be a %s', $path, $constraints['typeTag']);
368
- \t\t}
369
- \t}
370
-
371
- \tprivate function hasDefault(array $attribute): bool
372
- \t{
373
- \t\treturn ($attribute['typia']['hasDefault'] ?? false) === true;
374
- \t}
375
-
376
- \tprivate function valueInEnum($value, array $enum): bool
377
- \t{
378
- \t\tforeach ($enum as $candidate) {
379
- \t\t\tif ($candidate === $value) {
380
- \t\t\t\treturn true;
381
- \t\t\t}
382
- \t\t}
383
- \t\treturn false;
384
- \t}
385
-
386
- \tprivate function matchesPattern(string $pattern, string $value): bool
387
- \t{
388
- \t\t$escapedPattern = str_replace('~', '\\\\~', $pattern);
389
- \t\t$result = @preg_match('~' . $escapedPattern . '~u', $value);
390
- \t\treturn $result === 1;
391
- \t}
392
-
393
- \tprivate function matchesFormat(string $format, string $value): bool
394
- \t{
395
- \t\tswitch ($format) {
396
- \t\t\tcase 'uuid':
397
- \t\t\t\treturn preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i', $value) === 1;
398
- \t\t\tcase 'email':
399
- \t\t\t\treturn filter_var($value, FILTER_VALIDATE_EMAIL) !== false;
400
- \t\t\tcase 'url':
401
- \t\t\tcase 'uri':
402
- \t\t\t\treturn filter_var($value, FILTER_VALIDATE_URL) !== false;
403
- \t\t\tcase 'ipv4':
404
- \t\t\t\treturn filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false;
405
- \t\t\tcase 'ipv6':
406
- \t\t\t\treturn filter_var($value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false;
407
- \t\t\tcase 'date-time':
408
- \t\t\t\treturn preg_match('/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})$/', $value) === 1;
409
- \t\t\tdefault:
410
- \t\t\t\treturn true;
411
- \t\t}
412
- \t}
413
-
414
- \tprivate function matchesTypeTag($value, string $typeTag): bool
415
- \t{
416
- \t\tswitch ($typeTag) {
417
- \t\t\tcase 'uint32':
418
- \t\t\t\treturn is_int($value) && $value >= 0 && $value <= 4294967295;
419
- \t\t\tcase 'int32':
420
- \t\t\t\treturn is_int($value) && $value >= -2147483648 && $value <= 2147483647;
421
- \t\t\tcase 'uint64':
422
- \t\t\t\treturn $this->matchesUint64($value);
423
- \t\t\tcase 'float':
424
- \t\t\tcase 'double':
425
- \t\t\t\treturn is_int($value) || is_float($value);
426
- \t\t\tdefault:
427
- \t\t\t\treturn true;
428
- \t\t}
429
- \t}
430
-
431
- \tprivate function matchesUint64($value): bool
432
- \t{
433
- \t\tif (is_int($value)) {
434
- \t\t\treturn $value >= 0;
435
- \t\t}
436
- \t\tif (!is_string($value) || $value === '' || !ctype_digit($value)) {
437
- \t\t\treturn false;
438
- \t\t}
439
- \t\tif (strlen($value) < 20) {
440
- \t\t\treturn true;
441
- \t\t}
442
- \t\tif (strlen($value) > 20) {
443
- \t\t\treturn false;
444
- \t\t}
445
- \t\treturn strcmp($value, '18446744073709551615') <= 0;
446
- \t}
447
-
448
- \tprivate function matchesMultipleOf($value, $multipleOf): bool
449
- \t{
450
- \t\tif ($multipleOf === 0) {
451
- \t\t\treturn true;
452
- \t\t}
453
- \t\tif (is_int($value) && is_int($multipleOf)) {
454
- \t\t\treturn $value % $multipleOf === 0;
455
- \t\t}
456
-
457
- \t\t$remainder = fmod((float) $value, (float) $multipleOf);
458
- \t\t$epsilon = 0.000000001;
459
- \t\treturn abs($remainder) < $epsilon || abs(abs((float) $multipleOf) - abs($remainder)) < $epsilon;
460
- \t}
461
-
462
- \tprivate function isNumber($value): bool
463
- \t{
464
- \t\treturn is_int($value) || is_float($value);
465
- \t}
466
-
467
- \tprivate function isListArray(array $value): bool
468
- \t{
469
- \t\t$expectedKey = 0;
470
- \t\tforeach ($value as $key => $_item) {
471
- \t\t\tif ($key !== $expectedKey) {
472
- \t\t\t\treturn false;
473
- \t\t\t}
474
- \t\t\t$expectedKey += 1;
475
- \t\t}
476
- \t\treturn true;
477
- \t}
478
-
479
- \tprivate function expectedKindLabel(array $attribute): string
480
- \t{
481
- \t\t$kind = $attribute['ts']['kind'] ?? $attribute['wp']['type'] ?? 'value';
482
- \t\treturn $kind === 'union' ? 'object' : (string) $kind;
483
- \t}
484
- };
485
- `,
486
- warnings,
487
- };
488
- }
489
- /**
490
- * Collect warn-only PHP validator generation gaps for one manifest branch.
491
- *
492
- * @param attribute Manifest attribute metadata to inspect.
493
- * @param pathLabel Human-readable path used in emitted warning messages.
494
- * @param warnings Mutable accumulator that receives any discovered warnings.
495
- */
496
- export function collectPhpGenerationWarnings(attribute, pathLabel, warnings) {
497
- const { format, typeTag } = attribute.typia.constraints;
498
- if (format !== null && !SUPPORTED_PHP_FORMATS.has(format)) {
499
- warnings.push(`${pathLabel}: unsupported PHP validator format "${format}"`);
500
- }
501
- if (typeTag !== null && !SUPPORTED_PHP_TYPE_TAGS.has(typeTag)) {
502
- warnings.push(`${pathLabel}: unsupported PHP validator type tag "${typeTag}"`);
503
- }
504
- if (attribute.ts.items) {
505
- collectPhpGenerationWarnings(attribute.ts.items, `${pathLabel}[]`, warnings);
506
- }
507
- for (const [key, property] of Object.entries(attribute.ts.properties ?? {})) {
508
- collectPhpGenerationWarnings(property, `${pathLabel}.${key}`, warnings);
509
- }
510
- for (const [branchKey, branch] of Object.entries(attribute.ts.union?.branches ?? {})) {
511
- collectPhpGenerationWarnings(branch, `${pathLabel}<${branchKey}>`, warnings);
512
- }
513
- }
514
- /**
515
- * Render one JavaScript value into a PHP literal string.
516
- *
517
- * @param value JSON-like value to encode for the generated validator manifest.
518
- * @param indentLevel Current indentation depth, expressed in tab levels.
519
- * @returns PHP source code representing the provided value.
520
- */
521
- export function renderPhpValue(value, indentLevel) {
522
- const indent = "\t".repeat(indentLevel);
523
- const nestedIndent = "\t".repeat(indentLevel + 1);
524
- if (value === null) {
525
- return "null";
526
- }
527
- if (typeof value === "string") {
528
- return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
529
- }
530
- if (typeof value === "number" || typeof value === "boolean") {
531
- return String(value);
532
- }
533
- if (Array.isArray(value)) {
534
- if (value.length === 0) {
535
- return "[]";
536
- }
537
- const items = value.map((item) => `${nestedIndent}${renderPhpValue(item, indentLevel + 1)}`);
538
- return `[\n${items.join(",\n")}\n${indent}]`;
539
- }
540
- if (typeof value === "object") {
541
- const entries = Object.entries(value);
542
- if (entries.length === 0) {
543
- return "[]";
544
- }
545
- const items = entries.map(([key, item]) => `${nestedIndent}'${key.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}' => ${renderPhpValue(item, indentLevel + 1)}`);
546
- return `[\n${items.join(",\n")}\n${indent}]`;
547
- }
548
- throw new Error(`Unable to encode PHP value for manifest node: ${String(value)}`);
549
- }
7
+ export * from "@wp-typia/block-runtime/metadata-php-render";
@@ -1,7 +1,7 @@
1
- import { type AttributeNode, type BlockJsonAttribute, type JsonValue, type ManifestAttribute, type ManifestDocument } from "./metadata-model.js";
2
- export declare function createBlockJsonAttribute(node: AttributeNode, warnings: string[]): BlockJsonAttribute;
3
- export declare function createManifestAttribute(node: AttributeNode): ManifestAttribute;
4
- export declare function createManifestDocument(sourceTypeName: string, attributes: Record<string, AttributeNode>): ManifestDocument;
5
- export declare function validateWordPressExtractionAttributes(attributes: Record<string, AttributeNode>): void;
6
- export declare function validateWordPressExtractionAttribute(node: AttributeNode, isTopLevel?: boolean): void;
7
- export declare function createExampleValue(node: AttributeNode, key: string): JsonValue;
1
+ /**
2
+ * Re-exports metadata projection 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
6
+ */
7
+ export * from "@wp-typia/block-runtime/metadata-projection";