@livon/schema 0.27.0-rc.1

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.
Files changed (169) hide show
  1. package/PROMPT.md +21 -0
  2. package/README.md +13 -0
  3. package/SCHEMA.md +13 -0
  4. package/dist/SchemaValidationError.cjs +41 -0
  5. package/dist/SchemaValidationError.d.ts +20 -0
  6. package/dist/SchemaValidationError.js +7 -0
  7. package/dist/SchemaValidationError.spec.cjs +65 -0
  8. package/dist/SchemaValidationError.spec.d.ts +1 -0
  9. package/dist/SchemaValidationError.spec.js +59 -0
  10. package/dist/after.cjs +36 -0
  11. package/dist/after.d.ts +30 -0
  12. package/dist/after.js +2 -0
  13. package/dist/after.spec.cjs +54 -0
  14. package/dist/after.spec.d.ts +1 -0
  15. package/dist/after.spec.js +48 -0
  16. package/dist/and.cjs +36 -0
  17. package/dist/and.d.ts +26 -0
  18. package/dist/and.js +2 -0
  19. package/dist/and.spec.cjs +57 -0
  20. package/dist/and.spec.d.ts +1 -0
  21. package/dist/and.spec.js +51 -0
  22. package/dist/api.cjs +317 -0
  23. package/dist/api.d.ts +107 -0
  24. package/dist/api.js +277 -0
  25. package/dist/api.spec.cjs +512 -0
  26. package/dist/api.spec.d.ts +1 -0
  27. package/dist/api.spec.js +506 -0
  28. package/dist/array.cjs +74 -0
  29. package/dist/array.d.ts +25 -0
  30. package/dist/array.js +40 -0
  31. package/dist/array.spec.cjs +167 -0
  32. package/dist/array.spec.d.ts +1 -0
  33. package/dist/array.spec.js +161 -0
  34. package/dist/before.cjs +36 -0
  35. package/dist/before.d.ts +30 -0
  36. package/dist/before.js +2 -0
  37. package/dist/before.spec.cjs +54 -0
  38. package/dist/before.spec.d.ts +1 -0
  39. package/dist/before.spec.js +48 -0
  40. package/dist/binary.cjs +53 -0
  41. package/dist/binary.d.ts +24 -0
  42. package/dist/binary.js +19 -0
  43. package/dist/binary.spec.cjs +107 -0
  44. package/dist/binary.spec.d.ts +1 -0
  45. package/dist/binary.spec.js +101 -0
  46. package/dist/boolean.cjs +53 -0
  47. package/dist/boolean.d.ts +24 -0
  48. package/dist/boolean.js +19 -0
  49. package/dist/boolean.spec.cjs +96 -0
  50. package/dist/boolean.spec.d.ts +1 -0
  51. package/dist/boolean.spec.js +90 -0
  52. package/dist/context.cjs +125 -0
  53. package/dist/context.d.ts +101 -0
  54. package/dist/context.js +76 -0
  55. package/dist/context.spec.cjs +244 -0
  56. package/dist/context.spec.d.ts +1 -0
  57. package/dist/context.spec.js +238 -0
  58. package/dist/date.cjs +53 -0
  59. package/dist/date.d.ts +24 -0
  60. package/dist/date.js +19 -0
  61. package/dist/date.spec.cjs +97 -0
  62. package/dist/date.spec.d.ts +1 -0
  63. package/dist/date.spec.js +91 -0
  64. package/dist/doc.cjs +54 -0
  65. package/dist/doc.d.ts +25 -0
  66. package/dist/doc.js +17 -0
  67. package/dist/doc.spec.cjs +99 -0
  68. package/dist/doc.spec.d.ts +1 -0
  69. package/dist/doc.spec.js +93 -0
  70. package/dist/enumeration.cjs +74 -0
  71. package/dist/enumeration.d.ts +50 -0
  72. package/dist/enumeration.js +40 -0
  73. package/dist/enumeration.spec.cjs +110 -0
  74. package/dist/enumeration.spec.d.ts +1 -0
  75. package/dist/enumeration.spec.js +104 -0
  76. package/dist/hydrate.cjs +18 -0
  77. package/dist/hydrate.d.ts +1 -0
  78. package/dist/hydrate.js +0 -0
  79. package/dist/index.cjs +145 -0
  80. package/dist/index.d.ts +34 -0
  81. package/dist/index.js +24 -0
  82. package/dist/index.spec.cjs +43 -0
  83. package/dist/index.spec.d.ts +1 -0
  84. package/dist/index.spec.js +37 -0
  85. package/dist/literal.cjs +55 -0
  86. package/dist/literal.d.ts +25 -0
  87. package/dist/literal.js +21 -0
  88. package/dist/literal.spec.cjs +93 -0
  89. package/dist/literal.spec.d.ts +1 -0
  90. package/dist/literal.spec.js +87 -0
  91. package/dist/number.cjs +89 -0
  92. package/dist/number.d.ts +84 -0
  93. package/dist/number.js +55 -0
  94. package/dist/number.spec.cjs +155 -0
  95. package/dist/number.spec.d.ts +1 -0
  96. package/dist/number.spec.js +149 -0
  97. package/dist/object.cjs +66 -0
  98. package/dist/object.d.ts +37 -0
  99. package/dist/object.js +32 -0
  100. package/dist/object.spec.cjs +171 -0
  101. package/dist/object.spec.d.ts +1 -0
  102. package/dist/object.spec.js +165 -0
  103. package/dist/operation.cjs +182 -0
  104. package/dist/operation.d.ts +197 -0
  105. package/dist/operation.js +133 -0
  106. package/dist/operation.spec.cjs +454 -0
  107. package/dist/operation.spec.d.ts +1 -0
  108. package/dist/operation.spec.js +448 -0
  109. package/dist/or.cjs +85 -0
  110. package/dist/or.d.ts +37 -0
  111. package/dist/or.js +51 -0
  112. package/dist/or.spec.cjs +204 -0
  113. package/dist/or.spec.d.ts +1 -0
  114. package/dist/or.spec.js +198 -0
  115. package/dist/schema.cjs +285 -0
  116. package/dist/schema.d.ts +132 -0
  117. package/dist/schema.js +233 -0
  118. package/dist/schema.spec.cjs +587 -0
  119. package/dist/schema.spec.d.ts +1 -0
  120. package/dist/schema.spec.js +581 -0
  121. package/dist/schemaFactory.cjs +125 -0
  122. package/dist/schemaFactory.d.ts +97 -0
  123. package/dist/schemaFactory.js +88 -0
  124. package/dist/schemaFactory.spec.cjs +197 -0
  125. package/dist/schemaFactory.spec.d.ts +1 -0
  126. package/dist/schemaFactory.spec.js +191 -0
  127. package/dist/schemaModule.cjs +280 -0
  128. package/dist/schemaModule.d.ts +97 -0
  129. package/dist/schemaModule.js +243 -0
  130. package/dist/schemaModule.spec.cjs +355 -0
  131. package/dist/schemaModule.spec.d.ts +1 -0
  132. package/dist/schemaModule.spec.js +349 -0
  133. package/dist/string.cjs +93 -0
  134. package/dist/string.d.ts +85 -0
  135. package/dist/string.js +59 -0
  136. package/dist/string.spec.cjs +158 -0
  137. package/dist/string.spec.d.ts +1 -0
  138. package/dist/string.spec.js +152 -0
  139. package/dist/testing/mocks/assertions.mock.cjs +48 -0
  140. package/dist/testing/mocks/assertions.mock.d.ts +5 -0
  141. package/dist/testing/mocks/assertions.mock.js +14 -0
  142. package/dist/testing/mocks/index.cjs +52 -0
  143. package/dist/testing/mocks/index.d.ts +4 -0
  144. package/dist/testing/mocks/index.js +3 -0
  145. package/dist/testing/mocks/schema.mock.cjs +120 -0
  146. package/dist/testing/mocks/schema.mock.d.ts +37 -0
  147. package/dist/testing/mocks/schema.mock.js +74 -0
  148. package/dist/tuple.cjs +58 -0
  149. package/dist/tuple.d.ts +33 -0
  150. package/dist/tuple.js +24 -0
  151. package/dist/tuple.spec.cjs +162 -0
  152. package/dist/tuple.spec.d.ts +1 -0
  153. package/dist/tuple.spec.js +156 -0
  154. package/dist/typeGuards.cjs +60 -0
  155. package/dist/typeGuards.d.ts +93 -0
  156. package/dist/typeGuards.js +8 -0
  157. package/dist/typeGuards.spec.cjs +101 -0
  158. package/dist/typeGuards.spec.d.ts +1 -0
  159. package/dist/typeGuards.spec.js +95 -0
  160. package/dist/types.cjs +18 -0
  161. package/dist/types.d.ts +289 -0
  162. package/dist/types.js +0 -0
  163. package/dist/union.cjs +74 -0
  164. package/dist/union.d.ts +33 -0
  165. package/dist/union.js +40 -0
  166. package/dist/union.spec.cjs +159 -0
  167. package/dist/union.spec.d.ts +1 -0
  168. package/dist/union.spec.js +153 -0
  169. package/package.json +47 -0
@@ -0,0 +1,349 @@
1
+ import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
2
+ import { fieldOperation, operation } from "./operation.js";
3
+ import { createSchemaModuleInput, schemaModule } from "./schemaModule.js";
4
+ import { createBaseSchemaMock } from "./testing/mocks/index.js";
5
+ const createRuntimeContextMock = ()=>{
6
+ const runtimeContext = {};
7
+ runtimeContext.emitEvent = vi.fn(async ()=>({
8
+ ok: true
9
+ }));
10
+ runtimeContext.emitReceive = vi.fn(async ()=>({
11
+ ok: true
12
+ }));
13
+ runtimeContext.emitSend = vi.fn(async ()=>({
14
+ ok: true
15
+ }));
16
+ runtimeContext.emitError = vi.fn(async ()=>({
17
+ ok: true
18
+ }));
19
+ runtimeContext.state = {
20
+ get: vi.fn(()=>void 0),
21
+ set: vi.fn(()=>void 0)
22
+ };
23
+ runtimeContext.room = vi.fn(()=>runtimeContext);
24
+ return runtimeContext;
25
+ };
26
+ const createEnvelope = (overrides = {})=>({
27
+ id: 'evt-1',
28
+ event: 'unknown',
29
+ status: 'receiving',
30
+ payload: new Uint8Array([
31
+ 1
32
+ ]),
33
+ ...overrides
34
+ });
35
+ const createRegistryMock = (state)=>({
36
+ onReceive: vi.fn((hook)=>{
37
+ state.onReceive = hook;
38
+ return {
39
+ unsub: ()=>void 0
40
+ };
41
+ }),
42
+ onSend: vi.fn(()=>({
43
+ unsub: ()=>void 0
44
+ })),
45
+ onError: vi.fn(()=>({
46
+ unsub: ()=>void 0
47
+ })),
48
+ emitReceive: vi.fn(async ()=>({
49
+ ok: true
50
+ })),
51
+ emitSend: vi.fn(async ()=>({
52
+ ok: true
53
+ })),
54
+ emitError: vi.fn(async ()=>({
55
+ ok: true
56
+ })),
57
+ state: {
58
+ get: vi.fn(()=>void 0),
59
+ set: vi.fn(()=>void 0)
60
+ }
61
+ });
62
+ describe('schemaModule utilities', ()=>{
63
+ let runtimeContext;
64
+ beforeAll(()=>{
65
+ runtimeContext = createRuntimeContextMock();
66
+ });
67
+ beforeEach(()=>{
68
+ runtimeContext = createRuntimeContextMock();
69
+ });
70
+ afterEach(()=>{
71
+ vi.clearAllMocks();
72
+ });
73
+ afterAll(()=>{
74
+ vi.restoreAllMocks();
75
+ });
76
+ describe('createSchemaModuleInput()', ()=>{
77
+ describe('happy', ()=>{
78
+ it('should keep schema module parts when valid module-like input is provided', ()=>{
79
+ const operations = {
80
+ ping: operation({
81
+ input: createBaseSchemaMock(),
82
+ exec: async ()=>'ok'
83
+ })
84
+ };
85
+ const fieldOperations = {};
86
+ const subscriptions = {};
87
+ const ast = ()=>({
88
+ type: 'api'
89
+ });
90
+ const result = createSchemaModuleInput({
91
+ operations,
92
+ fieldOperations,
93
+ subscriptions,
94
+ ast
95
+ });
96
+ expect(result.operations).toBe(operations);
97
+ expect(result.fieldOperations).toBe(fieldOperations);
98
+ expect(result.subscriptions).toBe(subscriptions);
99
+ expect(result.ast).toBe(ast);
100
+ });
101
+ });
102
+ describe('sad', ()=>{
103
+ it('should keep empty records when empty module-like input is provided', ()=>{
104
+ const result = createSchemaModuleInput({
105
+ operations: {},
106
+ fieldOperations: {},
107
+ subscriptions: {},
108
+ ast: ()=>({
109
+ type: 'api'
110
+ })
111
+ });
112
+ expect(result.operations).toEqual({});
113
+ expect(result.fieldOperations).toEqual({});
114
+ expect(result.subscriptions).toEqual({});
115
+ });
116
+ });
117
+ });
118
+ describe('schemaModule()', ()=>{
119
+ describe('happy', ()=>{
120
+ it('should register onReceive hook when runtime module register is called', ()=>{
121
+ const module = schemaModule(createSchemaModuleInput({
122
+ operations: {},
123
+ fieldOperations: {},
124
+ subscriptions: {},
125
+ ast: ()=>({
126
+ type: 'api'
127
+ })
128
+ }));
129
+ const state = {};
130
+ const registry = createRegistryMock(state);
131
+ module.register(registry);
132
+ expect(module.name).toBe('schema');
133
+ expect(registry.onReceive).toHaveBeenCalledTimes(1);
134
+ expect(typeof state.onReceive).toBe('function');
135
+ });
136
+ it('should emit explain payload when explain option is enabled and explain event is received', async ()=>{
137
+ const encode = vi.fn(()=>new Uint8Array([
138
+ 9
139
+ ]));
140
+ const module = schemaModule(createSchemaModuleInput({
141
+ operations: {},
142
+ fieldOperations: {},
143
+ subscriptions: {},
144
+ ast: ()=>({
145
+ type: 'api',
146
+ name: 'RootApi'
147
+ })
148
+ }), {
149
+ explain: true,
150
+ now: ()=>1700000000000,
151
+ encoder: encode
152
+ });
153
+ const state = {};
154
+ const registry = createRegistryMock(state);
155
+ module.register(registry);
156
+ const next = vi.fn(async ()=>createEnvelope());
157
+ await state.onReceive?.(createEnvelope({
158
+ event: '$explain',
159
+ metadata: {
160
+ ifNoneMatch: 'different-checksum'
161
+ }
162
+ }), runtimeContext, next);
163
+ expect(next).not.toHaveBeenCalled();
164
+ expect(runtimeContext.emitEvent).toHaveBeenCalledTimes(1);
165
+ expect(encode).toHaveBeenCalledTimes(1);
166
+ });
167
+ it('should execute operation and emit operation response when operation event matches schema operation', async ()=>{
168
+ const decodedInput = {
169
+ id: 'u-1'
170
+ };
171
+ const decodedOutput = {
172
+ result: 'ok'
173
+ };
174
+ const decode = vi.fn(()=>decodedInput);
175
+ const encode = vi.fn(()=>new Uint8Array([
176
+ 7
177
+ ]));
178
+ const inputSchema = createBaseSchemaMock({
179
+ outputValue: decodedInput
180
+ });
181
+ const outputSchema = createBaseSchemaMock({
182
+ outputValue: decodedOutput
183
+ });
184
+ const exec = vi.fn(async ()=>decodedOutput);
185
+ const module = schemaModule(createSchemaModuleInput({
186
+ operations: {
187
+ ping: operation({
188
+ input: inputSchema,
189
+ output: outputSchema,
190
+ exec
191
+ })
192
+ },
193
+ fieldOperations: {},
194
+ subscriptions: {},
195
+ ast: ()=>({
196
+ type: 'api'
197
+ })
198
+ }), {
199
+ decoder: decode,
200
+ encoder: encode
201
+ });
202
+ const state = {};
203
+ const registry = createRegistryMock(state);
204
+ module.register(registry);
205
+ const next = vi.fn(async ()=>createEnvelope());
206
+ const envelope = createEnvelope({
207
+ event: 'ping'
208
+ });
209
+ const result = await state.onReceive?.(envelope, runtimeContext, next);
210
+ expect(exec).toHaveBeenCalledTimes(1);
211
+ expect(runtimeContext.emitEvent).toHaveBeenCalledWith({
212
+ event: 'ping',
213
+ payload: new Uint8Array([
214
+ 7
215
+ ]),
216
+ metadata: void 0,
217
+ context: void 0
218
+ });
219
+ expect(result).toBe(envelope);
220
+ });
221
+ it('should execute field operation when field event syntax is received', async ()=>{
222
+ const decode = vi.fn(()=>({
223
+ dependsOn: {
224
+ id: 'u-1'
225
+ },
226
+ input: {
227
+ locale: 'en'
228
+ }
229
+ }));
230
+ const encode = vi.fn(()=>new Uint8Array([
231
+ 5
232
+ ]));
233
+ const dependsOnSchema = createBaseSchemaMock({
234
+ outputValue: {
235
+ id: 'u-1'
236
+ }
237
+ });
238
+ const inputSchema = createBaseSchemaMock({
239
+ outputValue: {
240
+ locale: 'en'
241
+ }
242
+ });
243
+ const outputSchema = createBaseSchemaMock({
244
+ outputValue: {
245
+ value: 'Alice'
246
+ }
247
+ });
248
+ const exec = vi.fn(async ()=>({
249
+ value: 'Alice'
250
+ }));
251
+ const module = schemaModule(createSchemaModuleInput({
252
+ operations: {},
253
+ fieldOperations: {
254
+ 'User.displayName': fieldOperation({
255
+ dependsOn: dependsOnSchema,
256
+ input: inputSchema,
257
+ output: outputSchema,
258
+ exec
259
+ })
260
+ },
261
+ subscriptions: {},
262
+ ast: ()=>({
263
+ type: 'api'
264
+ })
265
+ }), {
266
+ decoder: decode,
267
+ encoder: encode
268
+ });
269
+ const state = {};
270
+ const registry = createRegistryMock(state);
271
+ module.register(registry);
272
+ const next = vi.fn(async ()=>createEnvelope());
273
+ await state.onReceive?.(createEnvelope({
274
+ event: '$User.displayName'
275
+ }), runtimeContext, next);
276
+ expect(exec).toHaveBeenCalledTimes(1);
277
+ expect(runtimeContext.emitEvent).toHaveBeenCalledWith({
278
+ event: '$User.displayName',
279
+ payload: new Uint8Array([
280
+ 5
281
+ ]),
282
+ metadata: void 0,
283
+ context: void 0
284
+ });
285
+ });
286
+ });
287
+ describe('sad', ()=>{
288
+ it('should delegate to next when no matching operation or field operation exists', async ()=>{
289
+ const module = schemaModule(createSchemaModuleInput({
290
+ operations: {},
291
+ fieldOperations: {},
292
+ subscriptions: {},
293
+ ast: ()=>({
294
+ type: 'api'
295
+ })
296
+ }));
297
+ const state = {};
298
+ const registry = createRegistryMock(state);
299
+ module.register(registry);
300
+ const nextResult = createEnvelope({
301
+ event: 'fallback'
302
+ });
303
+ const next = vi.fn(async ()=>nextResult);
304
+ const result = await state.onReceive?.(createEnvelope({
305
+ event: 'missing.event'
306
+ }), runtimeContext, next);
307
+ expect(next).toHaveBeenCalledTimes(1);
308
+ expect(result).toBe(nextResult);
309
+ });
310
+ it('should emit runtime error when operation execution throws', async ()=>{
311
+ const decode = vi.fn(()=>({
312
+ id: 'u-1'
313
+ }));
314
+ const execError = new Error('operation failed');
315
+ const module = schemaModule(createSchemaModuleInput({
316
+ operations: {
317
+ ping: operation({
318
+ input: createBaseSchemaMock({
319
+ outputValue: {
320
+ id: 'u-1'
321
+ }
322
+ }),
323
+ exec: async ()=>{
324
+ throw execError;
325
+ }
326
+ })
327
+ },
328
+ fieldOperations: {},
329
+ subscriptions: {},
330
+ ast: ()=>({
331
+ type: 'api'
332
+ })
333
+ }), {
334
+ decoder: decode
335
+ });
336
+ const state = {};
337
+ const registry = createRegistryMock(state);
338
+ module.register(registry);
339
+ const next = vi.fn(async ()=>createEnvelope());
340
+ const envelope = createEnvelope({
341
+ event: 'ping'
342
+ });
343
+ const result = await state.onReceive?.(envelope, runtimeContext, next);
344
+ expect(runtimeContext.emitError).toHaveBeenCalledTimes(1);
345
+ expect(result).toBe(envelope);
346
+ });
347
+ });
348
+ });
349
+ });
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ string: ()=>string
28
+ });
29
+ const external_schemaFactory_cjs_namespaceObject = require("./schemaFactory.cjs");
30
+ const external_typeGuards_cjs_namespaceObject = require("./typeGuards.cjs");
31
+ const string = ({ name = 'string', doc } = {})=>(0, external_schemaFactory_cjs_namespaceObject.schemaFactory)({
32
+ name,
33
+ type: 'string',
34
+ doc,
35
+ ast: ()=>({
36
+ type: 'string',
37
+ name
38
+ }),
39
+ validate: (input)=>{
40
+ if (!(0, external_typeGuards_cjs_namespaceObject.isString)(input)) throw {
41
+ message: 'Data is not a string',
42
+ code: 'string.type'
43
+ };
44
+ return input;
45
+ },
46
+ chain: {
47
+ min: (data, _ctx)=>(min)=>{
48
+ if (data.length < min) throw {
49
+ message: 'String is too short',
50
+ code: 'string.min',
51
+ context: {
52
+ min
53
+ }
54
+ };
55
+ return data;
56
+ },
57
+ max: (data, _ctx)=>(max)=>{
58
+ if (data.length > max) throw {
59
+ message: 'String is too long',
60
+ code: 'string.max',
61
+ context: {
62
+ max
63
+ }
64
+ };
65
+ return data;
66
+ },
67
+ email: (data, _ctx)=>()=>{
68
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
69
+ if (!emailRegex.test(data)) throw {
70
+ message: 'Invalid email format',
71
+ code: 'string.email'
72
+ };
73
+ return data;
74
+ },
75
+ regex: (data, _ctx)=>(pattern)=>{
76
+ if (!pattern.test(data)) throw {
77
+ message: 'String does not match pattern',
78
+ code: 'string.regex',
79
+ context: {
80
+ pattern: pattern.source
81
+ }
82
+ };
83
+ return data;
84
+ }
85
+ }
86
+ });
87
+ exports.string = __webpack_exports__.string;
88
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
89
+ "string"
90
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
91
+ Object.defineProperty(exports, '__esModule', {
92
+ value: true
93
+ });
@@ -0,0 +1,85 @@
1
+ import { SchemaFactoryChainDefinition } from './schemaFactory.js';
2
+ import { SchemaContext, SchemaDoc } from './types.js';
3
+ export interface StringFactoryInput {
4
+ name?: string;
5
+ doc?: SchemaDoc;
6
+ }
7
+ /**
8
+ * Chain operation: validates minimum length.
9
+ *
10
+ * @see https://live-input-vector-output-node.github.io/livon-ts/docs/schema/string
11
+ *
12
+ * @example
13
+ * // Enforces at least 3 characters for a string value.
14
+ * string().min(3)
15
+ */
16
+ export interface StringChainMin {
17
+ (data: string, ctx: SchemaContext): (min: number) => string;
18
+ }
19
+ /**
20
+ * Chain operation: validates maximum length.
21
+ *
22
+ * @see https://live-input-vector-output-node.github.io/livon-ts/docs/schema/string
23
+ *
24
+ * @example
25
+ * // Enforces at most 120 characters for a string value.
26
+ * string().max(120)
27
+ */
28
+ export interface StringChainMax {
29
+ (data: string, ctx: SchemaContext): (max: number) => string;
30
+ }
31
+ /**
32
+ * Chain operation: validates e-mail format.
33
+ *
34
+ * @see https://live-input-vector-output-node.github.io/livon-ts/docs/schema/string
35
+ *
36
+ * @example
37
+ * // Validates that the string matches a basic e-mail pattern.
38
+ * string().email()
39
+ */
40
+ export interface StringChainEmail {
41
+ (data: string, ctx: SchemaContext): () => string;
42
+ }
43
+ /**
44
+ * Chain operation: validates a custom regular expression.
45
+ *
46
+ * @see https://live-input-vector-output-node.github.io/livon-ts/docs/schema/string
47
+ *
48
+ * @example
49
+ * // Validates the string against a custom regular expression.
50
+ * string().regex(/^[a-z]+$/i)
51
+ */
52
+ export interface StringChainRegex {
53
+ (data: string, ctx: SchemaContext): (pattern: RegExp) => string;
54
+ }
55
+ /**
56
+ * Chain map for `string()` schemas.
57
+ *
58
+ * @see https://live-input-vector-output-node.github.io/livon-ts/docs/schema/string
59
+ */
60
+ export interface StringChainDefinition extends SchemaFactoryChainDefinition<string> {
61
+ min: StringChainMin;
62
+ max: StringChainMax;
63
+ email: StringChainEmail;
64
+ regex: StringChainRegex;
65
+ }
66
+ export type StringSchema = ReturnType<typeof string>;
67
+ /**
68
+ * string is part of the public LIVON API.
69
+ *
70
+ * @remarks
71
+ * Parameter and return types are defined in the TypeScript signature.
72
+ *
73
+ * @see https://live-input-vector-output-node.github.io/livon-ts/docs/schema/string
74
+ *
75
+ * @example
76
+ * // Creates a basic string schema and validates a username.
77
+ * const Username = string();
78
+ * Username.parse('alice');
79
+ *
80
+ * @example
81
+ * // Adds chain rules to enforce a username length range.
82
+ * const Username = string().min(3).max(20);
83
+ * Username.parse('alice');
84
+ */
85
+ export declare const string: ({ name, doc }?: StringFactoryInput) => import("./schemaFactory.js").SchemaWithChain<string, StringChainDefinition>;
package/dist/string.js ADDED
@@ -0,0 +1,59 @@
1
+ import { schemaFactory } from "./schemaFactory.js";
2
+ import { isString } from "./typeGuards.js";
3
+ const string = ({ name = 'string', doc } = {})=>schemaFactory({
4
+ name,
5
+ type: 'string',
6
+ doc,
7
+ ast: ()=>({
8
+ type: 'string',
9
+ name
10
+ }),
11
+ validate: (input)=>{
12
+ if (!isString(input)) throw {
13
+ message: 'Data is not a string',
14
+ code: 'string.type'
15
+ };
16
+ return input;
17
+ },
18
+ chain: {
19
+ min: (data, _ctx)=>(min)=>{
20
+ if (data.length < min) throw {
21
+ message: 'String is too short',
22
+ code: 'string.min',
23
+ context: {
24
+ min
25
+ }
26
+ };
27
+ return data;
28
+ },
29
+ max: (data, _ctx)=>(max)=>{
30
+ if (data.length > max) throw {
31
+ message: 'String is too long',
32
+ code: 'string.max',
33
+ context: {
34
+ max
35
+ }
36
+ };
37
+ return data;
38
+ },
39
+ email: (data, _ctx)=>()=>{
40
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
41
+ if (!emailRegex.test(data)) throw {
42
+ message: 'Invalid email format',
43
+ code: 'string.email'
44
+ };
45
+ return data;
46
+ },
47
+ regex: (data, _ctx)=>(pattern)=>{
48
+ if (!pattern.test(data)) throw {
49
+ message: 'String does not match pattern',
50
+ code: 'string.regex',
51
+ context: {
52
+ pattern: pattern.source
53
+ }
54
+ };
55
+ return data;
56
+ }
57
+ }
58
+ });
59
+ export { string };