@atscript/typescript 0.0.29 → 0.0.30

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/utils.cjs ADDED
@@ -0,0 +1,552 @@
1
+ "use strict";
2
+
3
+ //#region packages/typescript/src/validator.ts
4
+ function _define_property(obj, key, value) {
5
+ if (key in obj) Object.defineProperty(obj, key, {
6
+ value,
7
+ enumerable: true,
8
+ configurable: true,
9
+ writable: true
10
+ });
11
+ else obj[key] = value;
12
+ return obj;
13
+ }
14
+ const regexCache = new Map();
15
+ var Validator = class {
16
+ isLimitExceeded() {
17
+ if (this.stackErrors.length > 0) return this.stackErrors[this.stackErrors.length - 1].length >= this.opts.errorLimit;
18
+ return this.errors.length >= this.opts.errorLimit;
19
+ }
20
+ push(name) {
21
+ this.stackPath.push(name);
22
+ this.stackErrors.push([]);
23
+ }
24
+ pop(saveErrors) {
25
+ this.stackPath.pop();
26
+ const popped = this.stackErrors.pop();
27
+ if (saveErrors && popped?.length) popped.forEach((error) => {
28
+ this.error(error.message, error.path, error.details);
29
+ });
30
+ return popped;
31
+ }
32
+ clear() {
33
+ this.stackErrors[this.stackErrors.length - 1] = [];
34
+ }
35
+ error(message, path, details) {
36
+ const errors = this.stackErrors[this.stackErrors.length - 1] || this.errors;
37
+ const error = {
38
+ path: path || this.path,
39
+ message
40
+ };
41
+ if (details?.length) error.details = details;
42
+ errors.push(error);
43
+ }
44
+ throw() {
45
+ throw new ValidatorError(this.errors);
46
+ }
47
+ validate(value, safe) {
48
+ this.push("");
49
+ this.errors = [];
50
+ this.stackErrors = [];
51
+ const passed = this.validateSafe(this.def, value);
52
+ this.pop(!passed);
53
+ if (!passed) {
54
+ if (safe) return false;
55
+ this.throw();
56
+ }
57
+ return true;
58
+ }
59
+ validateSafe(def, value) {
60
+ if (this.isLimitExceeded()) return false;
61
+ if (!isAnnotatedType(def)) throw new Error("Can not validate not-annotated type");
62
+ if (typeof this.opts.replace === "function") def = this.opts.replace(def, this.path);
63
+ if (def.optional && value === undefined) return true;
64
+ for (const plugin of this.opts.plugins) {
65
+ const result = plugin(this, def, value);
66
+ if (result === false || result === true) return result;
67
+ }
68
+ return this.validateAnnotatedType(def, value);
69
+ }
70
+ get path() {
71
+ return this.stackPath.slice(1).join(".");
72
+ }
73
+ validateAnnotatedType(def, value) {
74
+ switch (def.type.kind) {
75
+ case "object": return this.validateObject(def, value);
76
+ case "union": return this.validateUnion(def, value);
77
+ case "intersection": return this.validateIntersection(def, value);
78
+ case "tuple": return this.validateTuple(def, value);
79
+ case "array": return this.validateArray(def, value);
80
+ case "": return this.validatePrimitive(def, value);
81
+ default: throw new Error(`Unknown type "${def.type.kind}"`);
82
+ }
83
+ }
84
+ validateUnion(def, value) {
85
+ let i = 0;
86
+ const popped = [];
87
+ for (const item of def.type.items) {
88
+ this.push(`[${item.type.kind || item.type.designType}(${i})]`);
89
+ if (this.validateSafe(item, value)) {
90
+ this.pop(false);
91
+ return true;
92
+ }
93
+ const errors = this.pop(false);
94
+ if (errors) popped.push(...errors);
95
+ i++;
96
+ }
97
+ this.clear();
98
+ const expected = def.type.items.map((item, i$1) => `[${item.type.kind || item.type.designType}(${i$1})]`).join(", ");
99
+ this.error(`Value does not match any of the allowed types: ${expected}`, undefined, popped);
100
+ return false;
101
+ }
102
+ validateIntersection(def, value) {
103
+ for (const item of def.type.items) if (!this.validateSafe(item, value)) return false;
104
+ return true;
105
+ }
106
+ validateTuple(def, value) {
107
+ if (!Array.isArray(value) || value.length !== def.type.items.length) {
108
+ this.error(`Expected array of length ${def.type.items.length}`);
109
+ return false;
110
+ }
111
+ let i = 0;
112
+ for (const item of def.type.items) {
113
+ this.push(`[${i}]`);
114
+ if (!this.validateSafe(item, value[i])) {
115
+ this.pop(true);
116
+ return false;
117
+ }
118
+ this.pop(false);
119
+ i++;
120
+ }
121
+ return true;
122
+ }
123
+ validateArray(def, value) {
124
+ if (!Array.isArray(value)) {
125
+ this.error("Expected array");
126
+ return false;
127
+ }
128
+ const minLength = def.metadata.get("expect.minLength");
129
+ if (typeof minLength === "number" && value.length < minLength) {
130
+ this.error(`Expected minimum length of ${minLength} items, got ${value.length} items`);
131
+ return false;
132
+ }
133
+ const maxLength = def.metadata.get("expect.maxLength");
134
+ if (typeof maxLength === "number" && value.length > maxLength) {
135
+ this.error(`Expected maximum length of ${maxLength} items, got ${value.length} items`);
136
+ return false;
137
+ }
138
+ let i = 0;
139
+ let passed = true;
140
+ for (const item of value) {
141
+ this.push(`[${i}]`);
142
+ if (!this.validateSafe(def.type.of, item)) {
143
+ passed = false;
144
+ this.pop(true);
145
+ if (this.isLimitExceeded()) return false;
146
+ } else this.pop(false);
147
+ i++;
148
+ }
149
+ return passed;
150
+ }
151
+ validateObject(def, value) {
152
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
153
+ this.error("Expected object");
154
+ return false;
155
+ }
156
+ let passed = true;
157
+ const valueKeys = new Set(Object.keys(value));
158
+ const typeKeys = new Set();
159
+ const skipList = new Set();
160
+ if (this.opts.skipList) {
161
+ const path = this.stackPath.length > 1 ? `${this.path}.` : "";
162
+ this.opts.skipList.forEach((item) => {
163
+ if (item.startsWith(path)) {
164
+ const key = item.slice(path.length);
165
+ skipList.add(key);
166
+ valueKeys.delete(key);
167
+ }
168
+ });
169
+ }
170
+ let partialFunctionMatched = false;
171
+ if (typeof this.opts.partial === "function") partialFunctionMatched = this.opts.partial(def, this.path);
172
+ for (const [key, item] of def.type.props.entries()) {
173
+ if (skipList.has(key)) continue;
174
+ typeKeys.add(key);
175
+ if (value[key] === undefined) {
176
+ if (partialFunctionMatched || this.opts.partial === "deep" || this.opts.partial === true && this.stackPath.length <= 1) continue;
177
+ }
178
+ this.push(key);
179
+ if (this.validateSafe(item, value[key])) this.pop(false);
180
+ else {
181
+ passed = false;
182
+ this.pop(true);
183
+ if (this.isLimitExceeded()) return false;
184
+ }
185
+ }
186
+ for (const key of valueKeys)
187
+ /** matched patterns for unknown keys */ if (!typeKeys.has(key)) {
188
+ const matched = [];
189
+ for (const { pattern, def: propDef } of def.type.propsPatterns) if (pattern.test(key)) matched.push({
190
+ pattern,
191
+ def: propDef
192
+ });
193
+ if (matched.length) {
194
+ let keyPassed = false;
195
+ for (const { def: def$1 } of matched) if (this.validateSafe(def$1, value[key])) {
196
+ this.pop(false);
197
+ keyPassed = true;
198
+ break;
199
+ }
200
+ if (!keyPassed) {
201
+ this.push(key);
202
+ this.validateSafe(matched[0].def, value[key]);
203
+ this.pop(true);
204
+ passed = false;
205
+ if (this.isLimitExceeded()) return false;
206
+ }
207
+ } else if (this.opts.unknwonProps !== "ignore") {
208
+ if (this.opts.unknwonProps === "error") {
209
+ this.push(key);
210
+ this.error(`Unexpected property`);
211
+ this.pop(true);
212
+ if (this.isLimitExceeded()) return false;
213
+ passed = false;
214
+ } else if (this.opts.unknwonProps === "strip") delete value[key];
215
+ }
216
+ }
217
+ return passed;
218
+ }
219
+ validatePrimitive(def, value) {
220
+ if (typeof def.type.value !== "undefined") {
221
+ if (value !== def.type.value) {
222
+ this.error(`Expected ${def.type.value}, got ${value}`);
223
+ return false;
224
+ }
225
+ return true;
226
+ }
227
+ const typeOfValue = Array.isArray(value) ? "array" : typeof value;
228
+ switch (def.type.designType) {
229
+ case "never":
230
+ this.error(`This type is impossible, must be an internal problem`);
231
+ return false;
232
+ case "any": return true;
233
+ case "string":
234
+ if (typeOfValue !== def.type.designType) {
235
+ this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
236
+ return false;
237
+ }
238
+ return this.validateString(def, value);
239
+ case "number":
240
+ if (typeOfValue !== def.type.designType) {
241
+ this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
242
+ return false;
243
+ }
244
+ return this.validateNumber(def, value);
245
+ case "boolean":
246
+ if (typeOfValue !== def.type.designType) {
247
+ this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
248
+ return false;
249
+ }
250
+ return true;
251
+ case "undefined":
252
+ if (value !== undefined) {
253
+ this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
254
+ return false;
255
+ }
256
+ return true;
257
+ case "null":
258
+ if (value !== null) {
259
+ this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
260
+ return false;
261
+ }
262
+ return true;
263
+ default: throw new Error(`Unknown type "${def.type.designType}"`);
264
+ }
265
+ }
266
+ validateString(def, value) {
267
+ const minLength = def.metadata.get("expect.minLength");
268
+ if (typeof minLength === "number" && value.length < minLength) {
269
+ this.error(`Expected minimum length of ${minLength} characters, got ${value.length} characters`);
270
+ return false;
271
+ }
272
+ const maxLength = def.metadata.get("expect.maxLength");
273
+ if (typeof maxLength === "number" && value.length > maxLength) {
274
+ this.error(`Expected maximum length of ${maxLength} characters, got ${value.length} characters`);
275
+ return false;
276
+ }
277
+ const patterns = def.metadata.get("expect.pattern");
278
+ for (const { pattern, flags, message } of patterns || []) {
279
+ if (!pattern) continue;
280
+ const cacheKey = `${pattern}//${flags || ""}`;
281
+ let regex = regexCache.get(cacheKey);
282
+ if (!regex) {
283
+ regex = new RegExp(pattern, flags);
284
+ regexCache.set(cacheKey, regex);
285
+ }
286
+ if (!regex.test(value)) {
287
+ this.error(message || `Value is expected to match pattern "${pattern}"`);
288
+ return false;
289
+ }
290
+ }
291
+ return true;
292
+ }
293
+ validateNumber(def, value) {
294
+ const int = def.metadata.get("expect.int");
295
+ if (typeof int === "boolean" && int && value % 1 !== 0) {
296
+ this.error(`Expected integer, got ${value}`);
297
+ return false;
298
+ }
299
+ const min = def.metadata.get("expect.min");
300
+ if (typeof min === "number" && value < min) {
301
+ this.error(`Expected minimum ${min}, got ${value}`);
302
+ return false;
303
+ }
304
+ const max = def.metadata.get("expect.max");
305
+ if (typeof max === "number" && value > max) {
306
+ this.error(`Expected maximum ${max}, got ${value}`);
307
+ return false;
308
+ }
309
+ return true;
310
+ }
311
+ constructor(def, opts) {
312
+ _define_property(this, "def", void 0);
313
+ _define_property(this, "opts", void 0);
314
+ _define_property(this, "errors", void 0);
315
+ _define_property(this, "stackErrors", void 0);
316
+ _define_property(this, "stackPath", void 0);
317
+ this.def = def;
318
+ this.errors = [];
319
+ this.stackErrors = [];
320
+ this.stackPath = [];
321
+ this.opts = {
322
+ partial: false,
323
+ unknwonProps: "error",
324
+ errorLimit: 10,
325
+ ...opts,
326
+ plugins: opts?.plugins || []
327
+ };
328
+ }
329
+ };
330
+ var ValidatorError = class extends Error {
331
+ constructor(errors) {
332
+ super(`${errors[0].path ? errors[0].path + ": " : ""}${errors[0].message}`), _define_property(this, "errors", void 0), _define_property(this, "name", void 0), this.errors = errors, this.name = "Validation Error";
333
+ }
334
+ };
335
+
336
+ //#endregion
337
+ //#region packages/typescript/src/annotated-type.ts
338
+ function isAnnotatedType(type) {
339
+ return type && type.__is_atscript_annotated_type;
340
+ }
341
+ function defineAnnotatedType(_kind, base) {
342
+ const kind = _kind || "";
343
+ const type = base?.type || {};
344
+ type.kind = kind;
345
+ if ([
346
+ "union",
347
+ "intersection",
348
+ "tuple"
349
+ ].includes(kind)) type.items = [];
350
+ if (kind === "object") {
351
+ type.props = new Map();
352
+ type.propsPatterns = [];
353
+ }
354
+ type.tags = new Set();
355
+ const metadata = base?.metadata || new Map();
356
+ if (base) Object.assign(base, {
357
+ __is_atscript_annotated_type: true,
358
+ metadata,
359
+ type,
360
+ validator(opts) {
361
+ return new Validator(this, opts);
362
+ }
363
+ });
364
+ else base = {
365
+ __is_atscript_annotated_type: true,
366
+ metadata,
367
+ type,
368
+ validator(opts) {
369
+ return new Validator(this, opts);
370
+ }
371
+ };
372
+ const handle = {
373
+ $type: base,
374
+ $def: type,
375
+ $metadata: metadata,
376
+ _existingObject: undefined,
377
+ tags(...tags) {
378
+ for (const tag of tags) this.$def.tags.add(tag);
379
+ return this;
380
+ },
381
+ designType(value) {
382
+ this.$def.designType = value;
383
+ return this;
384
+ },
385
+ value(value) {
386
+ this.$def.value = value;
387
+ return this;
388
+ },
389
+ of(value) {
390
+ this.$def.of = value;
391
+ return this;
392
+ },
393
+ item(value) {
394
+ this.$def.items.push(value);
395
+ return this;
396
+ },
397
+ prop(name, value) {
398
+ this.$def.props.set(name, value);
399
+ return this;
400
+ },
401
+ propPattern(pattern, def) {
402
+ this.$def.propsPatterns.push({
403
+ pattern,
404
+ def
405
+ });
406
+ return this;
407
+ },
408
+ optional(value = true) {
409
+ this.$type.optional = value;
410
+ return this;
411
+ },
412
+ copyMetadata(fromMetadata, ignore) {
413
+ for (const [key, value] of fromMetadata.entries()) if (!ignore || !ignore.has(key)) this.$metadata.set(key, value);
414
+ return this;
415
+ },
416
+ refTo(type$1, chain) {
417
+ let newBase = type$1;
418
+ const typeName = type$1.name || "Unknown";
419
+ if (isAnnotatedType(newBase)) {
420
+ let keys = "";
421
+ for (const c of chain || []) {
422
+ keys += `["${c}"]`;
423
+ if (newBase.type.kind === "object" && newBase.type.props.has(c)) newBase = newBase.type.props.get(c);
424
+ else throw new Error(`Can't find prop ${typeName}${keys}`);
425
+ }
426
+ if (!newBase && keys) throw new Error(`Can't find prop ${typeName}${keys}`);
427
+ else if (!newBase) throw new Error(`"${typeName}" is not annotated type`);
428
+ this.$type = {
429
+ __is_atscript_annotated_type: true,
430
+ type: newBase.type,
431
+ metadata,
432
+ validator(opts) {
433
+ return new Validator(this, opts);
434
+ }
435
+ };
436
+ } else throw new Error(`${type$1} is not annotated type`);
437
+ return this;
438
+ },
439
+ annotate(key, value, asArray) {
440
+ if (asArray) if (this.$metadata.has(key)) {
441
+ const a = this.$metadata.get(key);
442
+ if (Array.isArray(a)) a.push(value);
443
+ else this.$metadata.set(key, [a, value]);
444
+ } else this.$metadata.set(key, [value]);
445
+ else this.$metadata.set(key, value);
446
+ return this;
447
+ }
448
+ };
449
+ return handle;
450
+ }
451
+ function isAnnotatedTypeOfPrimitive(t) {
452
+ if (["array", "object"].includes(t.type.kind)) return false;
453
+ if (!t.type.kind) return true;
454
+ if ([
455
+ "union",
456
+ "tuple",
457
+ "intersection"
458
+ ].includes(t.type.kind)) {
459
+ for (const item of t.type.items) if (!isAnnotatedTypeOfPrimitive(item)) return false;
460
+ return true;
461
+ }
462
+ return false;
463
+ }
464
+
465
+ //#endregion
466
+ //#region packages/typescript/src/json-schema.ts
467
+ function buildJsonSchema(type) {
468
+ const build = (def) => {
469
+ const t = def.type;
470
+ const meta = def.metadata;
471
+ switch (t.kind) {
472
+ case "object": {
473
+ const obj = t;
474
+ const properties = {};
475
+ const required = [];
476
+ for (const [key, val] of obj.props.entries()) {
477
+ properties[key] = build(val);
478
+ if (!val.optional) required.push(key);
479
+ }
480
+ const schema = {
481
+ type: "object",
482
+ properties
483
+ };
484
+ if (required.length) schema.required = required;
485
+ return schema;
486
+ }
487
+ case "array": {
488
+ const arr = t;
489
+ const schema = {
490
+ type: "array",
491
+ items: build(arr.of)
492
+ };
493
+ const minLength = meta.get("expect.minLength");
494
+ if (typeof minLength === "number") schema.minItems = minLength;
495
+ const maxLength = meta.get("expect.maxLength");
496
+ if (typeof maxLength === "number") schema.maxItems = maxLength;
497
+ return schema;
498
+ }
499
+ case "union": {
500
+ const grp = t;
501
+ return { anyOf: grp.items.map(build) };
502
+ }
503
+ case "intersection": {
504
+ const grp = t;
505
+ return { allOf: grp.items.map(build) };
506
+ }
507
+ case "tuple": {
508
+ const grp = t;
509
+ return {
510
+ type: "array",
511
+ items: grp.items.map(build),
512
+ additionalItems: false
513
+ };
514
+ }
515
+ case "": {
516
+ const fin = t;
517
+ const schema = {};
518
+ if (fin.value !== undefined) schema.const = fin.value;
519
+ if (fin.designType && fin.designType !== "any") {
520
+ schema.type = fin.designType === "undefined" ? "null" : fin.designType;
521
+ if (schema.type === "number" && meta.get("expect.int")) schema.type = "integer";
522
+ }
523
+ if (schema.type === "string") {
524
+ const minLength = meta.get("expect.minLength");
525
+ if (typeof minLength === "number") schema.minLength = minLength;
526
+ const maxLength = meta.get("expect.maxLength");
527
+ if (typeof maxLength === "number") schema.maxLength = maxLength;
528
+ const patterns = meta.get("expect.pattern");
529
+ if (patterns?.length) if (patterns.length === 1) schema.pattern = patterns[0].pattern;
530
+ else schema.allOf = (schema.allOf || []).concat(patterns.map((p) => ({ pattern: p.pattern })));
531
+ }
532
+ if (schema.type === "number" || schema.type === "integer") {
533
+ const min = meta.get("expect.min");
534
+ if (typeof min === "number") schema.minimum = min;
535
+ const max = meta.get("expect.max");
536
+ if (typeof max === "number") schema.maximum = max;
537
+ }
538
+ return schema;
539
+ }
540
+ default: return {};
541
+ }
542
+ };
543
+ return build(type);
544
+ }
545
+
546
+ //#endregion
547
+ exports.Validator = Validator
548
+ exports.ValidatorError = ValidatorError
549
+ exports.buildJsonSchema = buildJsonSchema
550
+ exports.defineAnnotatedType = defineAnnotatedType
551
+ exports.isAnnotatedType = isAnnotatedType
552
+ exports.isAnnotatedTypeOfPrimitive = isAnnotatedTypeOfPrimitive
@@ -0,0 +1,132 @@
1
+ interface TError {
2
+ path: string;
3
+ message: string;
4
+ details?: TError[];
5
+ }
6
+ type TValidatorPlugin = (ctx: TValidatorPluginContext, def: TAtscriptAnnotatedType, value: any) => boolean | undefined;
7
+ interface TValidatorOptions {
8
+ partial: boolean | 'deep' | ((type: TAtscriptAnnotatedType<TAtscriptTypeObject>, path: string) => boolean);
9
+ replace?: (type: TAtscriptAnnotatedType, path: string) => TAtscriptAnnotatedType;
10
+ plugins: TValidatorPlugin[];
11
+ unknwonProps: 'strip' | 'ignore' | 'error';
12
+ errorLimit: number;
13
+ skipList?: Set<string>;
14
+ }
15
+ interface TValidatorPluginContext {
16
+ opts: Validator<any>['opts'];
17
+ validateAnnotatedType: Validator<any>['validateAnnotatedType'];
18
+ error: Validator<any>['error'];
19
+ path: Validator<any>['path'];
20
+ }
21
+ declare class Validator<T extends TAtscriptAnnotatedTypeConstructor> {
22
+ protected readonly def: T | TAtscriptAnnotatedType<any>;
23
+ protected opts: TValidatorOptions;
24
+ constructor(def: T | TAtscriptAnnotatedType<any>, opts?: Partial<TValidatorOptions>);
25
+ errors: TError[];
26
+ protected stackErrors: TError[][];
27
+ protected stackPath: string[];
28
+ protected isLimitExceeded(): boolean;
29
+ protected push(name: string): void;
30
+ protected pop(saveErrors: boolean): TError[] | undefined;
31
+ protected clear(): void;
32
+ protected error(message: string, path?: string, details?: TError[]): void;
33
+ protected throw(): void;
34
+ validate<TT = T>(value: any, safe?: boolean): value is TT;
35
+ protected validateSafe(def: TAtscriptAnnotatedType, value: any): boolean;
36
+ protected get path(): string;
37
+ protected validateAnnotatedType(def: TAtscriptAnnotatedType, value: any): boolean;
38
+ protected validateUnion(def: TAtscriptAnnotatedType<TAtscriptTypeComplex>, value: any): boolean;
39
+ protected validateIntersection(def: TAtscriptAnnotatedType<TAtscriptTypeComplex>, value: any): boolean;
40
+ protected validateTuple(def: TAtscriptAnnotatedType<TAtscriptTypeComplex>, value: any): boolean;
41
+ protected validateArray(def: TAtscriptAnnotatedType<TAtscriptTypeArray>, value: any): boolean;
42
+ protected validateObject(def: TAtscriptAnnotatedType<TAtscriptTypeObject>, value: any): boolean;
43
+ protected validatePrimitive(def: TAtscriptAnnotatedType<TAtscriptTypeFinal>, value: any): boolean;
44
+ protected validateString(def: TAtscriptAnnotatedType<TAtscriptTypeFinal>, value: string): boolean;
45
+ protected validateNumber(def: TAtscriptAnnotatedType<TAtscriptTypeFinal>, value: number): boolean;
46
+ }
47
+ declare class ValidatorError extends Error {
48
+ readonly errors: TError[];
49
+ name: string;
50
+ constructor(errors: TError[]);
51
+ }
52
+
53
+ interface TAtscriptTypeComplex {
54
+ kind: 'union' | 'intersection' | 'tuple';
55
+ items: TAtscriptAnnotatedType[];
56
+ tags: Set<AtscriptPrimitiveTags>;
57
+ }
58
+ interface TAtscriptTypeArray {
59
+ kind: 'array';
60
+ of: TAtscriptAnnotatedType;
61
+ tags: Set<AtscriptPrimitiveTags>;
62
+ }
63
+ interface TAtscriptTypeObject<K extends string = string> {
64
+ kind: 'object';
65
+ props: Map<K, TAtscriptAnnotatedType>;
66
+ propsPatterns: {
67
+ pattern: RegExp;
68
+ def: TAtscriptAnnotatedType;
69
+ }[];
70
+ tags: Set<AtscriptPrimitiveTags>;
71
+ }
72
+ interface TAtscriptTypeFinal {
73
+ kind: '';
74
+ /**
75
+ * design type
76
+ */
77
+ designType: 'string' | 'number' | 'boolean' | 'undefined' | 'null' | 'object' | 'any' | 'never';
78
+ /**
79
+ * value for literals
80
+ */
81
+ value?: string | number | boolean;
82
+ tags: Set<AtscriptPrimitiveTags>;
83
+ }
84
+ type TAtscriptTypeDef = TAtscriptTypeComplex | TAtscriptTypeFinal | TAtscriptTypeArray | TAtscriptTypeObject<string>;
85
+ interface TAtscriptAnnotatedType<T = TAtscriptTypeDef> {
86
+ __is_atscript_annotated_type: true;
87
+ type: T;
88
+ validator: <TT extends TAtscriptAnnotatedTypeConstructor>(opts?: Partial<TValidatorOptions>) => Validator<TT>;
89
+ metadata: TMetadataMap<AtscriptMetadata>;
90
+ optional?: boolean;
91
+ }
92
+ type TAtscriptAnnotatedTypeConstructor = TAtscriptAnnotatedType & (new (...args: any[]) => any);
93
+ /**
94
+ * Type Guard to check if a type is atscript-annotated
95
+ */
96
+ declare function isAnnotatedType(type: any): type is TAtscriptAnnotatedType;
97
+ type TKind = '' | 'array' | 'object' | 'union' | 'intersection' | 'tuple';
98
+ declare function defineAnnotatedType(_kind?: TKind, base?: any): TAnnotatedTypeHandle;
99
+ /**
100
+ * Atscript Metadata Map with typed setters/getters
101
+ */
102
+ interface TMetadataMap<O extends object> extends Map<keyof O, O[keyof O]> {
103
+ get<K extends keyof O>(key: K): O[K] | undefined;
104
+ set<K extends keyof O>(key: K, value: O[K]): this;
105
+ }
106
+ interface TAnnotatedTypeHandle {
107
+ $type: TAtscriptAnnotatedType;
108
+ $def: {
109
+ kind: TKind;
110
+ } & Omit<TAtscriptTypeComplex, 'kind'> & Omit<TAtscriptTypeFinal, 'kind'> & Omit<TAtscriptTypeArray, 'kind'> & Omit<TAtscriptTypeObject<string>, 'kind'>;
111
+ $metadata: TMetadataMap<AtscriptMetadata>;
112
+ _existingObject: TAtscriptAnnotatedType | undefined;
113
+ tags(...tags: string[]): TAnnotatedTypeHandle;
114
+ designType(value: TAtscriptTypeFinal['designType']): TAnnotatedTypeHandle;
115
+ value(value: string | number | boolean): TAnnotatedTypeHandle;
116
+ of(value: TAtscriptAnnotatedType): TAnnotatedTypeHandle;
117
+ item(value: TAtscriptAnnotatedType): TAnnotatedTypeHandle;
118
+ prop(name: string, value: TAtscriptAnnotatedType): TAnnotatedTypeHandle;
119
+ propPattern(pattern: RegExp, value: TAtscriptAnnotatedType): TAnnotatedTypeHandle;
120
+ optional(value?: boolean): TAnnotatedTypeHandle;
121
+ copyMetadata(fromMetadata: TMetadataMap<AtscriptMetadata>): TAnnotatedTypeHandle;
122
+ refTo(type: TAtscriptAnnotatedType & {
123
+ name?: string;
124
+ }, chain?: string[]): TAnnotatedTypeHandle;
125
+ annotate(key: keyof AtscriptMetadata, value: any, asArray?: boolean): TAnnotatedTypeHandle;
126
+ }
127
+ declare function isAnnotatedTypeOfPrimitive(t: TAtscriptAnnotatedType): boolean;
128
+
129
+ type TJsonSchema = Record<string, any>;
130
+ declare function buildJsonSchema(type: TAtscriptAnnotatedType): TJsonSchema;
131
+
132
+ export { type TAnnotatedTypeHandle, type TAtscriptAnnotatedType, type TAtscriptAnnotatedTypeConstructor, type TAtscriptTypeArray, type TAtscriptTypeComplex, type TAtscriptTypeDef, type TAtscriptTypeFinal, type TAtscriptTypeObject, type TMetadataMap, type TValidatorOptions, type TValidatorPlugin, type TValidatorPluginContext, Validator, ValidatorError, buildJsonSchema, defineAnnotatedType, isAnnotatedType, isAnnotatedTypeOfPrimitive };