@nubase/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # @nubase/core
2
+
3
+ Core schema and types for the nubase ecosystem.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @nubase/core
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import { BaseSchema, nu } from '@nubase/core';
15
+
16
+ // Example usage of base schema
17
+ const mySchema = new BaseSchema({
18
+ fields: {
19
+ name: { type: 'string', required: true },
20
+ age: { type: 'number', required: false }
21
+ }
22
+ });
23
+
24
+ // Example usage of nu types
25
+ const result = nu.string().parse('hello world');
26
+ ```
27
+
28
+ ## Features
29
+
30
+ - Type-safe schema definitions
31
+ - Zod-based validation
32
+ - TypeScript-first design
33
+ - Extensible base schema system
34
+
35
+ ## API Reference
36
+
37
+ ### BaseSchema
38
+
39
+ Base class for creating type-safe schemas with metadata.
40
+
41
+ ### nu
42
+
43
+ Utility functions and types for schema validation.
44
+
45
+ ## Contributing
46
+
47
+ Please see the main repository for contributing guidelines.
48
+
49
+ ## License
50
+
51
+ MIT
@@ -0,0 +1,93 @@
1
+ interface SchemaMetadata<Output = any> {
2
+ label?: string;
3
+ description?: string;
4
+ defaultValue?: Output;
5
+ }
6
+ declare abstract class BaseSchema<Output = any> {
7
+ /**
8
+ * Phantom property used for TypeScript type inference.
9
+ * Does not exist at runtime.
10
+ * @internal
11
+ */
12
+ readonly _outputType: Output;
13
+ _meta: SchemaMetadata<Output>;
14
+ /**
15
+ * Replace the schema metadata with a new object.
16
+ * @param meta The new metadata object.
17
+ * @returns The schema instance for chaining.
18
+ */
19
+ meta(meta: SchemaMetadata<Output>): this;
20
+ /**
21
+ * Parses and validates the input data against the schema.
22
+ * Should throw an error if validation fails.
23
+ * @param data The data to parse.
24
+ * @returns The parsed data (potentially transformed).
25
+ */
26
+ abstract parse(data: any): Output;
27
+ }
28
+
29
+ declare class BooleanSchema extends BaseSchema<boolean> {
30
+ parse(data: any): boolean;
31
+ }
32
+ declare class StringSchema extends BaseSchema<string> {
33
+ parse(data: any): string;
34
+ }
35
+ declare class NumberSchema extends BaseSchema<number> {
36
+ parse(data: any): number;
37
+ }
38
+ /**
39
+ * Type representing the shape of an object schema (key to schema mapping).
40
+ */
41
+ type ObjectShape = {
42
+ [key: string]: BaseSchema<any>;
43
+ };
44
+ /**
45
+ * Infers the TypeScript output type from an ObjectShape.
46
+ * Use mapped types to get the output type of each property schema.
47
+ */
48
+ type ObjectOutput<TShape extends ObjectShape> = {
49
+ [K in keyof TShape]: TShape[K]['_outputType'];
50
+ };
51
+ declare class ObjectSchema<TShape extends ObjectShape> extends BaseSchema<ObjectOutput<TShape>> {
52
+ _shape: TShape;
53
+ constructor(shape: TShape);
54
+ parse(data: any): ObjectOutput<TShape>;
55
+ }
56
+ /**
57
+ * Infers the TypeScript output type from an element schema for an array.
58
+ */
59
+ type ArrayOutput<TElementSchema extends BaseSchema<any>> = Array<TElementSchema['_outputType']>;
60
+ declare class ArraySchema<TElementSchema extends BaseSchema<any>> extends BaseSchema<ArrayOutput<TElementSchema>> {
61
+ _element: TElementSchema;
62
+ constructor(elementSchema: TElementSchema);
63
+ parse(data: any): ArrayOutput<TElementSchema>;
64
+ }
65
+ type NuSchema = BooleanSchema | StringSchema | NumberSchema | ObjectSchema<any> | ArraySchema<any>;
66
+
67
+ /**
68
+ * The main nubase schema instance.
69
+ * Provides factory methods to create different schema types.
70
+ */
71
+ declare const nu: {
72
+ boolean: () => BooleanSchema;
73
+ /**
74
+ * Creates a string schema.
75
+ */
76
+ string: () => StringSchema;
77
+ /**
78
+ * Creates a number schema.
79
+ */
80
+ number: () => NumberSchema;
81
+ /**
82
+ * Creates an object schema with a defined shape.
83
+ * @param shape An object mapping keys to schemas.
84
+ */
85
+ object: <TShape extends ObjectShape>(shape: TShape) => ObjectSchema<TShape>;
86
+ /**
87
+ * Creates an array schema with a defined element schema.
88
+ * @param elementSchema The schema for elements within the array.
89
+ */
90
+ array: <TElementSchema extends BaseSchema<any>>(elementSchema: TElementSchema) => ArraySchema<TElementSchema>;
91
+ };
92
+
93
+ export { type ArrayOutput, ArraySchema, BaseSchema, BooleanSchema, type NuSchema, NumberSchema, type ObjectOutput, ObjectSchema, type ObjectShape, type SchemaMetadata, StringSchema, nu };
@@ -0,0 +1,93 @@
1
+ interface SchemaMetadata<Output = any> {
2
+ label?: string;
3
+ description?: string;
4
+ defaultValue?: Output;
5
+ }
6
+ declare abstract class BaseSchema<Output = any> {
7
+ /**
8
+ * Phantom property used for TypeScript type inference.
9
+ * Does not exist at runtime.
10
+ * @internal
11
+ */
12
+ readonly _outputType: Output;
13
+ _meta: SchemaMetadata<Output>;
14
+ /**
15
+ * Replace the schema metadata with a new object.
16
+ * @param meta The new metadata object.
17
+ * @returns The schema instance for chaining.
18
+ */
19
+ meta(meta: SchemaMetadata<Output>): this;
20
+ /**
21
+ * Parses and validates the input data against the schema.
22
+ * Should throw an error if validation fails.
23
+ * @param data The data to parse.
24
+ * @returns The parsed data (potentially transformed).
25
+ */
26
+ abstract parse(data: any): Output;
27
+ }
28
+
29
+ declare class BooleanSchema extends BaseSchema<boolean> {
30
+ parse(data: any): boolean;
31
+ }
32
+ declare class StringSchema extends BaseSchema<string> {
33
+ parse(data: any): string;
34
+ }
35
+ declare class NumberSchema extends BaseSchema<number> {
36
+ parse(data: any): number;
37
+ }
38
+ /**
39
+ * Type representing the shape of an object schema (key to schema mapping).
40
+ */
41
+ type ObjectShape = {
42
+ [key: string]: BaseSchema<any>;
43
+ };
44
+ /**
45
+ * Infers the TypeScript output type from an ObjectShape.
46
+ * Use mapped types to get the output type of each property schema.
47
+ */
48
+ type ObjectOutput<TShape extends ObjectShape> = {
49
+ [K in keyof TShape]: TShape[K]['_outputType'];
50
+ };
51
+ declare class ObjectSchema<TShape extends ObjectShape> extends BaseSchema<ObjectOutput<TShape>> {
52
+ _shape: TShape;
53
+ constructor(shape: TShape);
54
+ parse(data: any): ObjectOutput<TShape>;
55
+ }
56
+ /**
57
+ * Infers the TypeScript output type from an element schema for an array.
58
+ */
59
+ type ArrayOutput<TElementSchema extends BaseSchema<any>> = Array<TElementSchema['_outputType']>;
60
+ declare class ArraySchema<TElementSchema extends BaseSchema<any>> extends BaseSchema<ArrayOutput<TElementSchema>> {
61
+ _element: TElementSchema;
62
+ constructor(elementSchema: TElementSchema);
63
+ parse(data: any): ArrayOutput<TElementSchema>;
64
+ }
65
+ type NuSchema = BooleanSchema | StringSchema | NumberSchema | ObjectSchema<any> | ArraySchema<any>;
66
+
67
+ /**
68
+ * The main nubase schema instance.
69
+ * Provides factory methods to create different schema types.
70
+ */
71
+ declare const nu: {
72
+ boolean: () => BooleanSchema;
73
+ /**
74
+ * Creates a string schema.
75
+ */
76
+ string: () => StringSchema;
77
+ /**
78
+ * Creates a number schema.
79
+ */
80
+ number: () => NumberSchema;
81
+ /**
82
+ * Creates an object schema with a defined shape.
83
+ * @param shape An object mapping keys to schemas.
84
+ */
85
+ object: <TShape extends ObjectShape>(shape: TShape) => ObjectSchema<TShape>;
86
+ /**
87
+ * Creates an array schema with a defined element schema.
88
+ * @param elementSchema The schema for elements within the array.
89
+ */
90
+ array: <TElementSchema extends BaseSchema<any>>(elementSchema: TElementSchema) => ArraySchema<TElementSchema>;
91
+ };
92
+
93
+ export { type ArrayOutput, ArraySchema, BaseSchema, BooleanSchema, type NuSchema, NumberSchema, type ObjectOutput, ObjectSchema, type ObjectShape, type SchemaMetadata, StringSchema, nu };
package/dist/index.js ADDED
@@ -0,0 +1,178 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // schema/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ ArraySchema: () => ArraySchema,
24
+ BaseSchema: () => BaseSchema,
25
+ BooleanSchema: () => BooleanSchema,
26
+ NumberSchema: () => NumberSchema,
27
+ ObjectSchema: () => ObjectSchema,
28
+ StringSchema: () => StringSchema,
29
+ nu: () => nu
30
+ });
31
+ module.exports = __toCommonJS(index_exports);
32
+
33
+ // schema/base-schema.ts
34
+ var BaseSchema = class {
35
+ /**
36
+ * Phantom property used for TypeScript type inference.
37
+ * Does not exist at runtime.
38
+ * @internal
39
+ */
40
+ _outputType;
41
+ _meta = {};
42
+ /**
43
+ * Replace the schema metadata with a new object.
44
+ * @param meta The new metadata object.
45
+ * @returns The schema instance for chaining.
46
+ */
47
+ meta(meta) {
48
+ this._meta = meta;
49
+ return this;
50
+ }
51
+ // We could also add a safeParse method like Zod if needed
52
+ // safeParse(data: any): { success: true; data: Output } | { success: false; error: SchemaError };
53
+ };
54
+
55
+ // schema/types.ts
56
+ var BooleanSchema = class extends BaseSchema {
57
+ parse(data) {
58
+ if (typeof data !== "boolean") {
59
+ throw new Error(`Expected boolean, received ${typeof data}`);
60
+ }
61
+ return data;
62
+ }
63
+ };
64
+ var StringSchema = class extends BaseSchema {
65
+ parse(data) {
66
+ if (typeof data !== "string") {
67
+ throw new Error(`Expected string, received ${typeof data}`);
68
+ }
69
+ return data;
70
+ }
71
+ // Add string-specific validation methods here (e.g., minLength, pattern)
72
+ };
73
+ var NumberSchema = class extends BaseSchema {
74
+ parse(data) {
75
+ if (typeof data !== "number" || !Number.isFinite(data)) {
76
+ throw new Error(`Expected number, received ${typeof data}`);
77
+ }
78
+ return data;
79
+ }
80
+ // Add number-specific validation methods here (e.g., min, max)
81
+ };
82
+ var ObjectSchema = class extends BaseSchema {
83
+ _shape;
84
+ constructor(shape) {
85
+ super();
86
+ this._shape = shape;
87
+ }
88
+ parse(data) {
89
+ if (typeof data !== "object" || data === null) {
90
+ throw new Error(`Expected object, received ${typeof data}`);
91
+ }
92
+ const result = {};
93
+ const errors = [];
94
+ for (const key in this._shape) {
95
+ if (Object.prototype.hasOwnProperty.call(this._shape, key)) {
96
+ const schema = this._shape[key];
97
+ const value = data[key];
98
+ try {
99
+ if (schema) {
100
+ result[key] = schema.parse(value);
101
+ }
102
+ } catch (e) {
103
+ errors.push(`Property "${key}": ${e.message}`);
104
+ }
105
+ }
106
+ }
107
+ for (const key in data) {
108
+ if (Object.prototype.hasOwnProperty.call(data, key) && !Object.prototype.hasOwnProperty.call(this._shape, key)) {
109
+ }
110
+ }
111
+ if (errors.length > 0) {
112
+ throw new Error(`Object validation failed:
113
+ ${errors.join("\n")}`);
114
+ }
115
+ return result;
116
+ }
117
+ };
118
+ var ArraySchema = class extends BaseSchema {
119
+ _element;
120
+ constructor(elementSchema) {
121
+ super();
122
+ this._element = elementSchema;
123
+ }
124
+ parse(data) {
125
+ if (!Array.isArray(data)) {
126
+ throw new Error(`Expected array, received ${typeof data}`);
127
+ }
128
+ const result = [];
129
+ const errors = [];
130
+ for (let i = 0; i < data.length; i++) {
131
+ try {
132
+ result[i] = this._element.parse(data[i]);
133
+ } catch (e) {
134
+ errors.push(`Element at index ${i}: ${e.message}`);
135
+ }
136
+ }
137
+ if (errors.length > 0) {
138
+ throw new Error(`Array validation failed:
139
+ ${errors.join("\n")}`);
140
+ }
141
+ return result;
142
+ }
143
+ };
144
+
145
+ // schema/nu.ts
146
+ var nu = {
147
+ boolean: () => new BooleanSchema(),
148
+ /**
149
+ * Creates a string schema.
150
+ */
151
+ string: () => new StringSchema(),
152
+ /**
153
+ * Creates a number schema.
154
+ */
155
+ number: () => new NumberSchema(),
156
+ /**
157
+ * Creates an object schema with a defined shape.
158
+ * @param shape An object mapping keys to schemas.
159
+ */
160
+ object: (shape) => new ObjectSchema(shape),
161
+ /**
162
+ * Creates an array schema with a defined element schema.
163
+ * @param elementSchema The schema for elements within the array.
164
+ */
165
+ array: (elementSchema) => new ArraySchema(elementSchema)
166
+ // Add more factory methods here (boolean, union, literal, etc.)
167
+ };
168
+ // Annotate the CommonJS export names for ESM import in node:
169
+ 0 && (module.exports = {
170
+ ArraySchema,
171
+ BaseSchema,
172
+ BooleanSchema,
173
+ NumberSchema,
174
+ ObjectSchema,
175
+ StringSchema,
176
+ nu
177
+ });
178
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../schema/index.ts","../schema/base-schema.ts","../schema/types.ts","../schema/nu.ts"],"sourcesContent":["export * from './types';\nexport { BaseSchema, type SchemaMetadata } from './base-schema';\nexport * from './nu';\n","// src/schema/BaseSchema.ts\n\nimport { z } from 'zod'; // We'll need Zod later for toZod conversion\n\n// Define metadata types\nexport interface SchemaMetadata<Output = any> {\n label?: string;\n description?: string;\n defaultValue?: Output;\n}\n\n// Base schema class\nexport abstract class BaseSchema<Output = any> {\n /**\n * Phantom property used for TypeScript type inference.\n * Does not exist at runtime.\n * @internal\n */\n readonly _outputType!: Output;\n\n _meta: SchemaMetadata<Output> = {};\n\n /**\n * Replace the schema metadata with a new object.\n * @param meta The new metadata object.\n * @returns The schema instance for chaining.\n */\n meta(meta: SchemaMetadata<Output>): this {\n this._meta = meta;\n return this;\n }\n\n /**\n * Parses and validates the input data against the schema.\n * Should throw an error if validation fails.\n * @param data The data to parse.\n * @returns The parsed data (potentially transformed).\n */\n abstract parse(data: any): Output;\n\n // We could also add a safeParse method like Zod if needed\n // safeParse(data: any): { success: true; data: Output } | { success: false; error: SchemaError };\n}\n\n// Define a union type of all concrete schema types for easier handling\nexport type NuSchema = BaseSchema<any>; // This will be refined later","// src/schema/types.ts\n\nimport { BaseSchema } from './base-schema';\n\n// --- Primitive Schemas ---\n\nexport class BooleanSchema extends BaseSchema<boolean> {\n parse(data: any): boolean {\n if (typeof data !== 'boolean') {\n throw new Error(`Expected boolean, received ${typeof data}`);\n }\n return data;\n }\n}\n\nexport class StringSchema extends BaseSchema<string> {\n parse(data: any): string {\n if (typeof data !== 'string') {\n throw new Error(`Expected string, received ${typeof data}`);\n }\n return data;\n }\n // Add string-specific validation methods here (e.g., minLength, pattern)\n}\n\nexport class NumberSchema extends BaseSchema<number> {\n parse(data: any): number {\n if (typeof data !== 'number' || !Number.isFinite(data)) {\n throw new Error(`Expected number, received ${typeof data}`);\n }\n return data;\n }\n // Add number-specific validation methods here (e.g., min, max)\n}\n\n// Add more primitives like BooleanSchema, NullableSchema, OptionalSchema etc.\n\n// --- Complex Schemas ---\n\n/**\n * Type representing the shape of an object schema (key to schema mapping).\n */\nexport type ObjectShape = {\n [key: string]: BaseSchema<any>;\n};\n\n/**\n * Infers the TypeScript output type from an ObjectShape.\n * Use mapped types to get the output type of each property schema.\n */\nexport type ObjectOutput<TShape extends ObjectShape> = {\n [K in keyof TShape]: TShape[K]['_outputType'];\n};\n\nexport class ObjectSchema<TShape extends ObjectShape> extends BaseSchema<ObjectOutput<TShape>> {\n _shape: TShape;\n\n constructor(shape: TShape) {\n super();\n this._shape = shape;\n }\n\n parse(data: any): ObjectOutput<TShape> {\n if (typeof data !== 'object' || data === null) {\n throw new Error(`Expected object, received ${typeof data}`);\n }\n\n const result: any = {};\n const errors: string[] = [];\n\n // Validate defined properties\n for (const key in this._shape) {\n if (Object.prototype.hasOwnProperty.call(this._shape, key)) {\n const schema = this._shape[key];\n const value = (data as any)[key]; // Get value from input data\n try {\n if (schema) {\n result[key] = schema.parse(value); // Recursively parse property\n }\n } catch (e: any) {\n errors.push(`Property \"${key}\": ${e.message}`);\n }\n }\n }\n\n // Basic handling for extra keys (can be made configurable)\n for (const key in data) {\n if (Object.prototype.hasOwnProperty.call(data, key) && !Object.prototype.hasOwnProperty.call(this._shape, key)) {\n // For now, ignore extra keys. Could throw an error or strip them.\n // errors.push(`Unknown property \"${key}\"`);\n // console.warn(`Warning: Unknown property \"${key}\" in object data.`);\n }\n }\n\n\n if (errors.length > 0) {\n throw new Error(`Object validation failed:\\n${errors.join('\\n')}`);\n }\n\n return result as ObjectOutput<TShape>;\n }\n}\n\n/**\n * Infers the TypeScript output type from an element schema for an array.\n */\nexport type ArrayOutput<TElementSchema extends BaseSchema<any>> = Array<TElementSchema['_outputType']>;\n\n\nexport class ArraySchema<TElementSchema extends BaseSchema<any>> extends BaseSchema<ArrayOutput<TElementSchema>> {\n _element: TElementSchema;\n\n constructor(elementSchema: TElementSchema) {\n super();\n this._element = elementSchema;\n }\n\n parse(data: any): ArrayOutput<TElementSchema> {\n if (!Array.isArray(data)) {\n throw new Error(`Expected array, received ${typeof data}`);\n }\n\n const result: any[] = [];\n const errors: string[] = [];\n\n for (let i = 0; i < data.length; i++) {\n try {\n result[i] = this._element.parse(data[i]); // Recursively parse each element\n } catch (e: any) {\n errors.push(`Element at index ${i}: ${e.message}`);\n }\n }\n\n if (errors.length > 0) {\n throw new Error(`Array validation failed:\\n${errors.join('\\n')}`);\n }\n\n return result as ArrayOutput<TElementSchema>;\n }\n}\n\n// Refine NuSchema union after defining concrete types\nexport type NuSchema =\n | BooleanSchema\n | StringSchema\n | NumberSchema\n // Add others like BooleanSchema\n | ObjectSchema<any>\n | ArraySchema<any>;","// src/nu.ts\n\nimport { BaseSchema } from \"./base-schema\";\nimport { StringSchema, NumberSchema, ObjectShape, ObjectSchema, ArraySchema, BooleanSchema } from \"./types\";\n\n\n/**\n * The main nubase schema instance.\n * Provides factory methods to create different schema types.\n */\nexport const nu = {\n boolean : () => new BooleanSchema(),\n /**\n * Creates a string schema.\n */\n string: () => new StringSchema(),\n\n /**\n * Creates a number schema.\n */\n number: () => new NumberSchema(),\n\n /**\n * Creates an object schema with a defined shape.\n * @param shape An object mapping keys to schemas.\n */\n object: <TShape extends ObjectShape>(shape: TShape) => new ObjectSchema(shape),\n\n /**\n * Creates an array schema with a defined element schema.\n * @param elementSchema The schema for elements within the array.\n */\n array: <TElementSchema extends BaseSchema<any>>(elementSchema: TElementSchema) => new ArraySchema(elementSchema),\n\n // Add more factory methods here (boolean, union, literal, etc.)\n};"],"mappings":"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","names":[]}
package/dist/index.mjs ADDED
@@ -0,0 +1,145 @@
1
+ // schema/base-schema.ts
2
+ var BaseSchema = class {
3
+ /**
4
+ * Phantom property used for TypeScript type inference.
5
+ * Does not exist at runtime.
6
+ * @internal
7
+ */
8
+ _outputType;
9
+ _meta = {};
10
+ /**
11
+ * Replace the schema metadata with a new object.
12
+ * @param meta The new metadata object.
13
+ * @returns The schema instance for chaining.
14
+ */
15
+ meta(meta) {
16
+ this._meta = meta;
17
+ return this;
18
+ }
19
+ // We could also add a safeParse method like Zod if needed
20
+ // safeParse(data: any): { success: true; data: Output } | { success: false; error: SchemaError };
21
+ };
22
+
23
+ // schema/types.ts
24
+ var BooleanSchema = class extends BaseSchema {
25
+ parse(data) {
26
+ if (typeof data !== "boolean") {
27
+ throw new Error(`Expected boolean, received ${typeof data}`);
28
+ }
29
+ return data;
30
+ }
31
+ };
32
+ var StringSchema = class extends BaseSchema {
33
+ parse(data) {
34
+ if (typeof data !== "string") {
35
+ throw new Error(`Expected string, received ${typeof data}`);
36
+ }
37
+ return data;
38
+ }
39
+ // Add string-specific validation methods here (e.g., minLength, pattern)
40
+ };
41
+ var NumberSchema = class extends BaseSchema {
42
+ parse(data) {
43
+ if (typeof data !== "number" || !Number.isFinite(data)) {
44
+ throw new Error(`Expected number, received ${typeof data}`);
45
+ }
46
+ return data;
47
+ }
48
+ // Add number-specific validation methods here (e.g., min, max)
49
+ };
50
+ var ObjectSchema = class extends BaseSchema {
51
+ _shape;
52
+ constructor(shape) {
53
+ super();
54
+ this._shape = shape;
55
+ }
56
+ parse(data) {
57
+ if (typeof data !== "object" || data === null) {
58
+ throw new Error(`Expected object, received ${typeof data}`);
59
+ }
60
+ const result = {};
61
+ const errors = [];
62
+ for (const key in this._shape) {
63
+ if (Object.prototype.hasOwnProperty.call(this._shape, key)) {
64
+ const schema = this._shape[key];
65
+ const value = data[key];
66
+ try {
67
+ if (schema) {
68
+ result[key] = schema.parse(value);
69
+ }
70
+ } catch (e) {
71
+ errors.push(`Property "${key}": ${e.message}`);
72
+ }
73
+ }
74
+ }
75
+ for (const key in data) {
76
+ if (Object.prototype.hasOwnProperty.call(data, key) && !Object.prototype.hasOwnProperty.call(this._shape, key)) {
77
+ }
78
+ }
79
+ if (errors.length > 0) {
80
+ throw new Error(`Object validation failed:
81
+ ${errors.join("\n")}`);
82
+ }
83
+ return result;
84
+ }
85
+ };
86
+ var ArraySchema = class extends BaseSchema {
87
+ _element;
88
+ constructor(elementSchema) {
89
+ super();
90
+ this._element = elementSchema;
91
+ }
92
+ parse(data) {
93
+ if (!Array.isArray(data)) {
94
+ throw new Error(`Expected array, received ${typeof data}`);
95
+ }
96
+ const result = [];
97
+ const errors = [];
98
+ for (let i = 0; i < data.length; i++) {
99
+ try {
100
+ result[i] = this._element.parse(data[i]);
101
+ } catch (e) {
102
+ errors.push(`Element at index ${i}: ${e.message}`);
103
+ }
104
+ }
105
+ if (errors.length > 0) {
106
+ throw new Error(`Array validation failed:
107
+ ${errors.join("\n")}`);
108
+ }
109
+ return result;
110
+ }
111
+ };
112
+
113
+ // schema/nu.ts
114
+ var nu = {
115
+ boolean: () => new BooleanSchema(),
116
+ /**
117
+ * Creates a string schema.
118
+ */
119
+ string: () => new StringSchema(),
120
+ /**
121
+ * Creates a number schema.
122
+ */
123
+ number: () => new NumberSchema(),
124
+ /**
125
+ * Creates an object schema with a defined shape.
126
+ * @param shape An object mapping keys to schemas.
127
+ */
128
+ object: (shape) => new ObjectSchema(shape),
129
+ /**
130
+ * Creates an array schema with a defined element schema.
131
+ * @param elementSchema The schema for elements within the array.
132
+ */
133
+ array: (elementSchema) => new ArraySchema(elementSchema)
134
+ // Add more factory methods here (boolean, union, literal, etc.)
135
+ };
136
+ export {
137
+ ArraySchema,
138
+ BaseSchema,
139
+ BooleanSchema,
140
+ NumberSchema,
141
+ ObjectSchema,
142
+ StringSchema,
143
+ nu
144
+ };
145
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../schema/base-schema.ts","../schema/types.ts","../schema/nu.ts"],"sourcesContent":["// src/schema/BaseSchema.ts\n\nimport { z } from 'zod'; // We'll need Zod later for toZod conversion\n\n// Define metadata types\nexport interface SchemaMetadata<Output = any> {\n label?: string;\n description?: string;\n defaultValue?: Output;\n}\n\n// Base schema class\nexport abstract class BaseSchema<Output = any> {\n /**\n * Phantom property used for TypeScript type inference.\n * Does not exist at runtime.\n * @internal\n */\n readonly _outputType!: Output;\n\n _meta: SchemaMetadata<Output> = {};\n\n /**\n * Replace the schema metadata with a new object.\n * @param meta The new metadata object.\n * @returns The schema instance for chaining.\n */\n meta(meta: SchemaMetadata<Output>): this {\n this._meta = meta;\n return this;\n }\n\n /**\n * Parses and validates the input data against the schema.\n * Should throw an error if validation fails.\n * @param data The data to parse.\n * @returns The parsed data (potentially transformed).\n */\n abstract parse(data: any): Output;\n\n // We could also add a safeParse method like Zod if needed\n // safeParse(data: any): { success: true; data: Output } | { success: false; error: SchemaError };\n}\n\n// Define a union type of all concrete schema types for easier handling\nexport type NuSchema = BaseSchema<any>; // This will be refined later","// src/schema/types.ts\n\nimport { BaseSchema } from './base-schema';\n\n// --- Primitive Schemas ---\n\nexport class BooleanSchema extends BaseSchema<boolean> {\n parse(data: any): boolean {\n if (typeof data !== 'boolean') {\n throw new Error(`Expected boolean, received ${typeof data}`);\n }\n return data;\n }\n}\n\nexport class StringSchema extends BaseSchema<string> {\n parse(data: any): string {\n if (typeof data !== 'string') {\n throw new Error(`Expected string, received ${typeof data}`);\n }\n return data;\n }\n // Add string-specific validation methods here (e.g., minLength, pattern)\n}\n\nexport class NumberSchema extends BaseSchema<number> {\n parse(data: any): number {\n if (typeof data !== 'number' || !Number.isFinite(data)) {\n throw new Error(`Expected number, received ${typeof data}`);\n }\n return data;\n }\n // Add number-specific validation methods here (e.g., min, max)\n}\n\n// Add more primitives like BooleanSchema, NullableSchema, OptionalSchema etc.\n\n// --- Complex Schemas ---\n\n/**\n * Type representing the shape of an object schema (key to schema mapping).\n */\nexport type ObjectShape = {\n [key: string]: BaseSchema<any>;\n};\n\n/**\n * Infers the TypeScript output type from an ObjectShape.\n * Use mapped types to get the output type of each property schema.\n */\nexport type ObjectOutput<TShape extends ObjectShape> = {\n [K in keyof TShape]: TShape[K]['_outputType'];\n};\n\nexport class ObjectSchema<TShape extends ObjectShape> extends BaseSchema<ObjectOutput<TShape>> {\n _shape: TShape;\n\n constructor(shape: TShape) {\n super();\n this._shape = shape;\n }\n\n parse(data: any): ObjectOutput<TShape> {\n if (typeof data !== 'object' || data === null) {\n throw new Error(`Expected object, received ${typeof data}`);\n }\n\n const result: any = {};\n const errors: string[] = [];\n\n // Validate defined properties\n for (const key in this._shape) {\n if (Object.prototype.hasOwnProperty.call(this._shape, key)) {\n const schema = this._shape[key];\n const value = (data as any)[key]; // Get value from input data\n try {\n if (schema) {\n result[key] = schema.parse(value); // Recursively parse property\n }\n } catch (e: any) {\n errors.push(`Property \"${key}\": ${e.message}`);\n }\n }\n }\n\n // Basic handling for extra keys (can be made configurable)\n for (const key in data) {\n if (Object.prototype.hasOwnProperty.call(data, key) && !Object.prototype.hasOwnProperty.call(this._shape, key)) {\n // For now, ignore extra keys. Could throw an error or strip them.\n // errors.push(`Unknown property \"${key}\"`);\n // console.warn(`Warning: Unknown property \"${key}\" in object data.`);\n }\n }\n\n\n if (errors.length > 0) {\n throw new Error(`Object validation failed:\\n${errors.join('\\n')}`);\n }\n\n return result as ObjectOutput<TShape>;\n }\n}\n\n/**\n * Infers the TypeScript output type from an element schema for an array.\n */\nexport type ArrayOutput<TElementSchema extends BaseSchema<any>> = Array<TElementSchema['_outputType']>;\n\n\nexport class ArraySchema<TElementSchema extends BaseSchema<any>> extends BaseSchema<ArrayOutput<TElementSchema>> {\n _element: TElementSchema;\n\n constructor(elementSchema: TElementSchema) {\n super();\n this._element = elementSchema;\n }\n\n parse(data: any): ArrayOutput<TElementSchema> {\n if (!Array.isArray(data)) {\n throw new Error(`Expected array, received ${typeof data}`);\n }\n\n const result: any[] = [];\n const errors: string[] = [];\n\n for (let i = 0; i < data.length; i++) {\n try {\n result[i] = this._element.parse(data[i]); // Recursively parse each element\n } catch (e: any) {\n errors.push(`Element at index ${i}: ${e.message}`);\n }\n }\n\n if (errors.length > 0) {\n throw new Error(`Array validation failed:\\n${errors.join('\\n')}`);\n }\n\n return result as ArrayOutput<TElementSchema>;\n }\n}\n\n// Refine NuSchema union after defining concrete types\nexport type NuSchema =\n | BooleanSchema\n | StringSchema\n | NumberSchema\n // Add others like BooleanSchema\n | ObjectSchema<any>\n | ArraySchema<any>;","// src/nu.ts\n\nimport { BaseSchema } from \"./base-schema\";\nimport { StringSchema, NumberSchema, ObjectShape, ObjectSchema, ArraySchema, BooleanSchema } from \"./types\";\n\n\n/**\n * The main nubase schema instance.\n * Provides factory methods to create different schema types.\n */\nexport const nu = {\n boolean : () => new BooleanSchema(),\n /**\n * Creates a string schema.\n */\n string: () => new StringSchema(),\n\n /**\n * Creates a number schema.\n */\n number: () => new NumberSchema(),\n\n /**\n * Creates an object schema with a defined shape.\n * @param shape An object mapping keys to schemas.\n */\n object: <TShape extends ObjectShape>(shape: TShape) => new ObjectSchema(shape),\n\n /**\n * Creates an array schema with a defined element schema.\n * @param elementSchema The schema for elements within the array.\n */\n array: <TElementSchema extends BaseSchema<any>>(elementSchema: TElementSchema) => new ArraySchema(elementSchema),\n\n // Add more factory methods here (boolean, union, literal, etc.)\n};"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@nubase/core",
3
+ "version": "0.1.0",
4
+ "description": "Core schema and types for nubase",
5
+ "keywords": ["schema", "types", "validation", "zod"],
6
+ "sideEffects": [
7
+ "**/*.css"
8
+ ],
9
+ "files": [
10
+ "dist",
11
+ "schema"
12
+ ],
13
+ "main": "./dist/index.js",
14
+ "module": "./dist/index.mjs",
15
+ "types": "./dist/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/index.d.ts",
19
+ "import": "./dist/index.mjs",
20
+ "require": "./dist/index.js"
21
+ },
22
+ "./schema": {
23
+ "types": "./dist/index.d.ts",
24
+ "import": "./dist/index.mjs",
25
+ "require": "./dist/index.js"
26
+ }
27
+ },
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
31
+ "license": "MIT",
32
+ "scripts": {
33
+ "build": "tsup",
34
+ "test": "vitest",
35
+ "typecheck": "tsc --noEmit",
36
+ "prepublishOnly": "npm run build"
37
+ },
38
+ "devDependencies": {
39
+ "tsup": "^8.0.0",
40
+ "typescript": "^5.8.3",
41
+ "vite": "^6.3.5",
42
+ "vitest": "^3.1.4"
43
+ },
44
+ "dependencies": {
45
+ "zod": "^3.25.20"
46
+ }
47
+ }
@@ -0,0 +1,46 @@
1
+ // src/schema/BaseSchema.ts
2
+
3
+ import { z } from 'zod'; // We'll need Zod later for toZod conversion
4
+
5
+ // Define metadata types
6
+ export interface SchemaMetadata<Output = any> {
7
+ label?: string;
8
+ description?: string;
9
+ defaultValue?: Output;
10
+ }
11
+
12
+ // Base schema class
13
+ export abstract class BaseSchema<Output = any> {
14
+ /**
15
+ * Phantom property used for TypeScript type inference.
16
+ * Does not exist at runtime.
17
+ * @internal
18
+ */
19
+ readonly _outputType!: Output;
20
+
21
+ _meta: SchemaMetadata<Output> = {};
22
+
23
+ /**
24
+ * Replace the schema metadata with a new object.
25
+ * @param meta The new metadata object.
26
+ * @returns The schema instance for chaining.
27
+ */
28
+ meta(meta: SchemaMetadata<Output>): this {
29
+ this._meta = meta;
30
+ return this;
31
+ }
32
+
33
+ /**
34
+ * Parses and validates the input data against the schema.
35
+ * Should throw an error if validation fails.
36
+ * @param data The data to parse.
37
+ * @returns The parsed data (potentially transformed).
38
+ */
39
+ abstract parse(data: any): Output;
40
+
41
+ // We could also add a safeParse method like Zod if needed
42
+ // safeParse(data: any): { success: true; data: Output } | { success: false; error: SchemaError };
43
+ }
44
+
45
+ // Define a union type of all concrete schema types for easier handling
46
+ export type NuSchema = BaseSchema<any>; // This will be refined later
@@ -0,0 +1,19 @@
1
+ import { BaseSchema } from "./base-schema"
2
+
3
+ export interface ResourceDescriptor {
4
+ search: ResourceOperationDescriptor
5
+ view: ResourceOperationDescriptor
6
+ edit: ResourceOperationDescriptor
7
+ create: ResourceOperationDescriptor
8
+ delete: ResourceOperationDescriptor
9
+ }
10
+
11
+ export type ResourceOperationDescriptor = {
12
+ // /r/contacts
13
+ resourceName: string,
14
+ endpoint: string
15
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE',
16
+ querySchema?: BaseSchema,
17
+ bodySchema?: BaseSchema,
18
+ responseSchema?: BaseSchema
19
+ }
@@ -0,0 +1,3 @@
1
+ export * from './types';
2
+ export { BaseSchema, type SchemaMetadata } from './base-schema';
3
+ export * from './nu';
@@ -0,0 +1,325 @@
1
+ // src/tests/nu.test.ts
2
+
3
+ import { describe, it, expect, expectTypeOf } from 'vitest';
4
+ import { nu } from './nu';
5
+ import { toZod } from './toZod';
6
+ import { z } from 'zod';
7
+
8
+ describe('nubase Schema Library (nu)', () => {
9
+
10
+ // --- Basic Schema Creation and Metadata ---
11
+ it('should create a string schema with metadata', () => {
12
+ const stringSchema = nu.string().meta({
13
+ label: 'Username',
14
+ description: 'The user\'s login name',
15
+ })
16
+ expect(stringSchema).toBeDefined();
17
+ expect(stringSchema._meta.label).toBe('Username');
18
+ expect(stringSchema._meta.description).toBe('The user\'s login name');
19
+ });
20
+
21
+ it('should create a number schema with metadata', () => {
22
+ const numberSchema = nu.number().meta({
23
+ label: 'Age',
24
+ });
25
+ expect(numberSchema).toBeDefined();
26
+ expect(numberSchema._meta.label).toBe('Age');
27
+ });
28
+
29
+ it('should create an object schema with nested schemas and metadata', () => {
30
+ const objectSchema = nu.object({
31
+ id: nu.number(),
32
+ name: nu.string().meta({
33
+ label: 'Full Name',
34
+ }),
35
+ address: nu.object({
36
+ street: nu.string(),
37
+ city: nu.string(),
38
+ zip: nu.string(),
39
+ }).meta({
40
+ label: 'Address',
41
+ description: 'User\'s mailing address',
42
+ }),
43
+ }).meta({
44
+ description: 'User Profile',
45
+ });
46
+
47
+ expect(objectSchema).toBeDefined();
48
+ expect(objectSchema._shape.id).toBeDefined();
49
+ expect(objectSchema._shape.name).toBeDefined();
50
+ expect(objectSchema._shape.name._meta.label).toBe('Full Name');
51
+ expect(objectSchema._meta.description).toBe('User Profile');
52
+ });
53
+
54
+ it('should create an array schema with an element schema', () => {
55
+ const arraySchema = nu.array(nu.string().meta({ label: 'Item' })).meta({ label: 'List of Items' });
56
+ expect(arraySchema).toBeDefined();
57
+ expect(arraySchema._element).toBeDefined();
58
+ expect(arraySchema._element._meta.label).toBe('Item');
59
+ expect(arraySchema._meta.label).toBe('List of Items');
60
+ });
61
+
62
+ // --- Parse/Validation Tests ---
63
+ it('should parse valid string data', () => {
64
+ const stringSchema = nu.string();
65
+ expect(stringSchema.parse('hello')).toBe('hello');
66
+ });
67
+
68
+ it('should throw error for invalid string data', () => {
69
+ const stringSchema = nu.string();
70
+ expect(() => stringSchema.parse(123)).toThrow('Expected string, received number');
71
+ });
72
+
73
+ it('should parse valid number data', () => {
74
+ const numberSchema = nu.number();
75
+ expect(numberSchema.parse(123)).toBe(123);
76
+ expect(numberSchema.parse(123.45)).toBe(123.45);
77
+ });
78
+
79
+ it('should throw error for invalid number data', () => {
80
+ const numberSchema = nu.number();
81
+ expect(() => numberSchema.parse('abc')).toThrow('Expected number, received string');
82
+ expect(() => numberSchema.parse(NaN)).toThrow('Expected number, received number'); // NaN is typeof number but not finite
83
+ expect(() => numberSchema.parse(Infinity)).toThrow('Expected number, received number');
84
+ });
85
+
86
+ it('should parse valid object data', () => {
87
+ const userSchema = nu.object({
88
+ id: nu.number(),
89
+ name: nu.string(),
90
+ isActive: nu.boolean().meta({ label: 'Active', defaultValue: true }), // Only supported keys
91
+ });
92
+ // Note: Literal/boolean schemas aren't implemented, using parse here as a placeholder for demo.
93
+ // A real implementation would have nu.boolean() and potentially nu.literal()
94
+
95
+ const validData = { id: 1, name: 'Alice', isActive: true };
96
+ expect(userSchema.parse(validData)).toEqual(validData);
97
+ });
98
+
99
+
100
+ it('should throw error for invalid object data (wrong type)', () => {
101
+ const userSchema = nu.object({ id: nu.number(), name: nu.string() });
102
+ expect(() => userSchema.parse(123)).toThrow('Expected object, received number');
103
+ expect(() => userSchema.parse(null)).toThrow('Expected object, received object'); // typeof null is 'object'
104
+ });
105
+
106
+ it('should throw error for invalid object data (invalid property)', () => {
107
+ const userSchema = nu.object({ id: nu.number(), name: nu.string() });
108
+ const invalidData = { id: 'one', name: 'Alice' };
109
+ expect(() => userSchema.parse(invalidData)).toThrow(/Object validation failed:\nProperty "id": Expected number, received string/);
110
+ });
111
+
112
+ // Note: Current ObjectSchema parse ignores extra keys. Add a test if you change that.
113
+ it('should ignore extra keys in object data by default', () => {
114
+ const userSchema = nu.object({ id: nu.number(), name: nu.string() });
115
+ const dataWithExtra = { id: 1, name: 'Alice', age: 30 };
116
+ const parsedData = userSchema.parse(dataWithExtra);
117
+ expect(parsedData).toEqual({ id: 1, name: 'Alice' }); // Extra 'age' is ignored
118
+ });
119
+
120
+
121
+ it('should parse valid array data', () => {
122
+ const stringArraySchema = nu.array(nu.string());
123
+ const validData = ['a', 'b', 'c'];
124
+ expect(stringArraySchema.parse(validData)).toEqual(validData);
125
+ });
126
+
127
+ it('should throw error for invalid array data (wrong type)', () => {
128
+ const stringArraySchema = nu.array(nu.string());
129
+ expect(() => stringArraySchema.parse('not an array')).toThrow('Expected array, received string');
130
+ });
131
+
132
+ it('should throw error for invalid array data (invalid element)', () => {
133
+ const stringArraySchema = nu.array(nu.string());
134
+ const invalidData = ['a', 123, 'c'];
135
+ expect(() => stringArraySchema.parse(invalidData)).toThrow(/Array validation failed:\nElement at index 1: Expected string, received number/);
136
+ });
137
+
138
+ // --- toZod Conversion Tests ---
139
+
140
+ it('should convert a string schema to a Zod string schema', () => {
141
+ const nuString = nu.string();
142
+ const zodString = toZod(nuString);
143
+ expect(zodString instanceof z.ZodString).toBe(true);
144
+ // Test Zod validation
145
+ expect(zodString.parse('test')).toBe('test');
146
+ expect(() => zodString.parse(123)).toThrow();
147
+ });
148
+
149
+ it('should convert a number schema to a Zod number schema', () => {
150
+ const nuNumber = nu.number();
151
+ const zodNumber = toZod(nuNumber);
152
+ expect(zodNumber instanceof z.ZodNumber).toBe(true);
153
+ // Test Zod validation
154
+ expect(zodNumber.parse(123)).toBe(123);
155
+ expect(() => zodNumber.parse('test')).toThrow();
156
+ });
157
+
158
+ it('should convert an object schema to a Zod object schema', () => {
159
+ const nuObject = nu.object({
160
+ name: nu.string(),
161
+ age: nu.number().meta({ label: 'User Age' })
162
+ });
163
+
164
+ const zodObject = toZod(nuObject);
165
+
166
+ expect(zodObject instanceof z.ZodObject).toBe(true);
167
+
168
+ // Check the structure of the converted Zod schema
169
+ expect(zodObject.shape.name instanceof z.ZodString).toBe(true);
170
+ expect(zodObject.shape.age instanceof z.ZodNumber).toBe(true);
171
+
172
+ // Test Zod validation
173
+ const validData = { name: 'Bob', age: 42 };
174
+ expect(zodObject.parse(validData)).toEqual(validData);
175
+ expect(() => zodObject.parse({ name: 'Bob', age: 'old' })).toThrow();
176
+ });
177
+
178
+ it('should convert an array schema to a Zod array schema', () => {
179
+ const nuArray = nu.array(nu.number());
180
+ const zodArray = toZod(nuArray);
181
+ expect(zodArray instanceof z.ZodArray).toBe(true);
182
+ expect(zodArray.element instanceof z.ZodNumber).toBe(true);
183
+
184
+ // Test Zod validation
185
+ const validData = [1, 2, 3];
186
+ expect(zodArray.parse(validData)).toEqual(validData);
187
+ expect(() => zodArray.parse([1, 'two', 3])).toThrow();
188
+ });
189
+
190
+ it('should handle nested structures in toZod conversion', () => {
191
+ const nestedNuSchema = nu.object({
192
+ user: nu.object({
193
+ name: nu.string(),
194
+ address: nu.object({
195
+ street: nu.string(),
196
+ zip: nu.string()
197
+ })
198
+ }),
199
+ tags: nu.array(nu.string())
200
+ });
201
+
202
+ const nestedZodSchema = toZod(nestedNuSchema);
203
+
204
+ // Check types in the converted Zod schema structure
205
+ expect(nestedZodSchema instanceof z.ZodObject).toBe(true);
206
+ expect(nestedZodSchema.shape.user instanceof z.ZodObject).toBe(true);
207
+ expect((nestedZodSchema.shape.user as z.ZodObject<any>).shape.name instanceof z.ZodString).toBe(true);
208
+ expect((nestedZodSchema.shape.user as z.ZodObject<any>).shape.address instanceof z.ZodObject).toBe(true);
209
+ expect(((nestedZodSchema.shape.user as z.ZodObject<any>).shape.address as z.ZodObject<any>).shape.street instanceof z.ZodString).toBe(true);
210
+ expect(nestedZodSchema.shape.tags instanceof z.ZodArray).toBe(true);
211
+ expect((nestedZodSchema.shape.tags as z.ZodArray<any>).element instanceof z.ZodString).toBe(true);
212
+
213
+
214
+ // Test Zod validation with nested structure
215
+ const validData = {
216
+ user: {
217
+ name: 'Charlie',
218
+ address: { street: 'Main St', zip: '12345' }
219
+ },
220
+ tags: ['a', 'b']
221
+ };
222
+ expect(nestedZodSchema.parse(validData)).toEqual(validData);
223
+
224
+ const invalidData = {
225
+ user: {
226
+ name: 'Charlie',
227
+ address: { street: 123, zip: '12345' } // invalid street type
228
+ },
229
+ tags: ['a', 'b']
230
+ };
231
+ expect(() => nestedZodSchema.parse(invalidData)).toThrow();
232
+ });
233
+
234
+
235
+ // --- TypeScript Type Inference Tests ---
236
+
237
+ it('should infer correct type for primitive schemas', () => {
238
+ const s = nu.string();
239
+ const n = nu.number();
240
+
241
+ // Check inferred output type
242
+ expectTypeOf(s).toHaveProperty('_outputType').toBeString();
243
+ expectTypeOf(n).toHaveProperty('_outputType').toBeNumber();
244
+ });
245
+
246
+ it('should infer correct type for object schema', () => {
247
+ const userSchema = nu.object({
248
+ id: nu.number().meta({ label: 'User ID' }),
249
+ name: nu.string(),
250
+ settings: nu.object({
251
+ theme: nu.string(),
252
+ darkMode: nu.boolean().meta({ label: 'Switch' }) // Only supported keys
253
+ })
254
+ });
255
+
256
+ // Check inferred output type structure
257
+ expectTypeOf(userSchema).toHaveProperty('_outputType').toMatchTypeOf<{
258
+ id: number;
259
+ name: string;
260
+ settings: {
261
+ theme: string;
262
+ darkMode: any; // Placeholder output type from .parse(true)
263
+ }
264
+ }>();
265
+
266
+ // Test that assigning parsed data is type-safe
267
+ const userData = { id: 1, name: 'Test', settings: { theme: 'dark', darkMode: false } };
268
+ const parsedUser = userSchema.parse(userData);
269
+ expectTypeOf(parsedUser).toMatchTypeOf<{ id: number; name: string; settings: { theme: string; darkMode: any; } }>();
270
+
271
+ // This would be a TS error if types mismatched:
272
+ // const badParsedUser: string = userSchema.parse(userData); // TS error expected
273
+ });
274
+
275
+ it('should infer correct type for array schema', () => {
276
+ const numberArraySchema = nu.array(nu.number()); // Removed unsupported minValue metadata
277
+ const stringArraySchema = nu.array(nu.string().meta({ label: 'Entry' }));
278
+ const arrayOfObjectsSchema = nu.array(nu.object({ id: nu.number(), value: nu.string() }));
279
+
280
+
281
+ // Check inferred output types
282
+ expectTypeOf(numberArraySchema).toHaveProperty('_outputType').toBeArray();
283
+ expectTypeOf(stringArraySchema).toHaveProperty('_outputType').toBeArray();
284
+ expectTypeOf(arrayOfObjectsSchema).toHaveProperty('_outputType').toBeArray();
285
+
286
+
287
+ // Test that assigning parsed data is type-safe
288
+ const numberArrayData = [1, 2, 3];
289
+ const parsedNumberArray = numberArraySchema.parse(numberArrayData);
290
+ expectTypeOf(parsedNumberArray).toBeArray();
291
+ // This would be a TS error:
292
+ // const badParsedNumberArray: string[] = parsedNumberArray; // TS error expected
293
+ });
294
+
295
+
296
+ it('should infer correct Zod schema type after toZod conversion', () => {
297
+ const nuString = nu.string().meta({ label: 'ID' });
298
+ const zodString = toZod(nuString);
299
+ expectTypeOf(zodString).toMatchTypeOf<z.ZodString>(); // Should be a ZodString
300
+ expectTypeOf(zodString._output).toBeString(); // Should infer string output
301
+
302
+
303
+ const nuObject = nu.object({
304
+ name: nu.string(),
305
+ age: nu.number()
306
+ });
307
+ const zodObject = toZod(nuObject);
308
+ expectTypeOf(zodObject).toMatchTypeOf<z.ZodObject<any>>(); // Should be a ZodObject
309
+ expectTypeOf(zodObject._output).toMatchTypeOf<{ name: string, age: number }>(); // Should infer the object type
310
+
311
+
312
+ const nuArray = nu.array(nu.string());
313
+ const zodArray = toZod(nuArray);
314
+ expectTypeOf(zodArray).toMatchTypeOf<z.ZodArray<z.ZodString>>(); // Should be ZodArray of ZodString
315
+
316
+ const nuNested = nu.object({
317
+ items: nu.array(nu.object({
318
+ id: nu.number()
319
+ }))
320
+ });
321
+ const zodNested = toZod(nuNested);
322
+ expectTypeOf(zodNested._output).toMatchTypeOf<{ items: Array<{ id: number }> }>(); // Should infer nested type
323
+ });
324
+
325
+ });
package/schema/nu.ts ADDED
@@ -0,0 +1,36 @@
1
+ // src/nu.ts
2
+
3
+ import { BaseSchema } from "./base-schema";
4
+ import { StringSchema, NumberSchema, ObjectShape, ObjectSchema, ArraySchema, BooleanSchema } from "./types";
5
+
6
+
7
+ /**
8
+ * The main nubase schema instance.
9
+ * Provides factory methods to create different schema types.
10
+ */
11
+ export const nu = {
12
+ boolean : () => new BooleanSchema(),
13
+ /**
14
+ * Creates a string schema.
15
+ */
16
+ string: () => new StringSchema(),
17
+
18
+ /**
19
+ * Creates a number schema.
20
+ */
21
+ number: () => new NumberSchema(),
22
+
23
+ /**
24
+ * Creates an object schema with a defined shape.
25
+ * @param shape An object mapping keys to schemas.
26
+ */
27
+ object: <TShape extends ObjectShape>(shape: TShape) => new ObjectSchema(shape),
28
+
29
+ /**
30
+ * Creates an array schema with a defined element schema.
31
+ * @param elementSchema The schema for elements within the array.
32
+ */
33
+ array: <TElementSchema extends BaseSchema<any>>(elementSchema: TElementSchema) => new ArraySchema(elementSchema),
34
+
35
+ // Add more factory methods here (boolean, union, literal, etc.)
36
+ };
@@ -0,0 +1,74 @@
1
+ // src/converters/toZod.ts
2
+
3
+ import { z } from 'zod';
4
+ import {
5
+ StringSchema,
6
+ NumberSchema,
7
+ ObjectSchema,
8
+ ArraySchema,
9
+ NuSchema, // The union type of all nu schemas
10
+ ObjectOutput // Type utility to get object output type
11
+ } from '../schema/types';
12
+
13
+
14
+ /**
15
+ * Infers the Zod schema type corresponding to a given NuSchema type.
16
+ * This is a conditional type that maps NuSchema types to their Zod equivalents
17
+ * and preserves the output type.
18
+ */
19
+ export type NuSchemaToZodSchema<S extends NuSchema> =
20
+ S extends StringSchema ? z.ZodString :
21
+ S extends NumberSchema ? z.ZodNumber :
22
+ S extends ObjectSchema<infer TShape> ? z.ZodObject<{
23
+ [K in keyof TShape]: NuSchemaToZodSchema<TShape[K]>;
24
+ }, any, z.ZodTypeAny, ObjectOutput<TShape>> : // Recursive mapping for object shape
25
+ S extends ArraySchema<infer TElementSchema> ? z.ZodArray<NuSchemaToZodSchema<TElementSchema>> : // Recursive mapping for array element
26
+ z.ZodSchema<any>; // Fallback for unknown types
27
+
28
+
29
+ /**
30
+ * Converts a nubase schema to a Zod schema.
31
+ * Preserves the TypeScript output type.
32
+ * Metadata (label, description etc.) is NOT translated to Zod schema properties
33
+ * as Zod doesn't have direct equivalents in its core schema structure.
34
+ * It only translates the validation structure and output type.
35
+ *
36
+ * @param schema The nubase schema to convert.
37
+ * @returns The equivalent Zod schema.
38
+ */
39
+ export function toZod<S extends NuSchema>(schema: S): NuSchemaToZodSchema<S> {
40
+ if (schema instanceof StringSchema) {
41
+ // Add Zod string validations based on schema._meta or specific properties if they exist
42
+ // e.g., if (schema._meta.minLength) zodSchema = zodSchema.min(schema._meta.minLength);
43
+ // For now, just the base type:
44
+ return z.string() as NuSchemaToZodSchema<S>;
45
+ }
46
+
47
+ if (schema instanceof NumberSchema) {
48
+ // Add Zod number validations similarly
49
+ return z.number() as NuSchemaToZodSchema<S>;
50
+ }
51
+
52
+ if (schema instanceof ObjectSchema) {
53
+ const zodShape: Record<string, z.ZodTypeAny> = {};
54
+ // Recursively convert each schema in the shape
55
+ for (const key in schema._shape) {
56
+ if (Object.prototype.hasOwnProperty.call(schema._shape, key)) {
57
+ zodShape[key] = toZod(schema._shape[key]); // Recursive call
58
+ }
59
+ }
60
+ // Zod object constructor needs the shape object
61
+ return z.object(zodShape) as NuSchemaToZodSchema<S>;
62
+ }
63
+
64
+ if (schema instanceof ArraySchema) {
65
+ // Recursively convert the element schema
66
+ const zodElementSchema = toZod(schema._element);
67
+ // Zod array constructor needs the element schema
68
+ return z.array(zodElementSchema) as NuSchemaToZodSchema<S>;
69
+ }
70
+
71
+ // Handle other schema types here...
72
+ // For now, throw an error for unsupported types
73
+ throw new Error(`Unsupported schema type for Zod conversion: ${schema.constructor.name}`);
74
+ }
@@ -0,0 +1,149 @@
1
+ // src/schema/types.ts
2
+
3
+ import { BaseSchema } from './base-schema';
4
+
5
+ // --- Primitive Schemas ---
6
+
7
+ export class BooleanSchema extends BaseSchema<boolean> {
8
+ parse(data: any): boolean {
9
+ if (typeof data !== 'boolean') {
10
+ throw new Error(`Expected boolean, received ${typeof data}`);
11
+ }
12
+ return data;
13
+ }
14
+ }
15
+
16
+ export class StringSchema extends BaseSchema<string> {
17
+ parse(data: any): string {
18
+ if (typeof data !== 'string') {
19
+ throw new Error(`Expected string, received ${typeof data}`);
20
+ }
21
+ return data;
22
+ }
23
+ // Add string-specific validation methods here (e.g., minLength, pattern)
24
+ }
25
+
26
+ export class NumberSchema extends BaseSchema<number> {
27
+ parse(data: any): number {
28
+ if (typeof data !== 'number' || !Number.isFinite(data)) {
29
+ throw new Error(`Expected number, received ${typeof data}`);
30
+ }
31
+ return data;
32
+ }
33
+ // Add number-specific validation methods here (e.g., min, max)
34
+ }
35
+
36
+ // Add more primitives like BooleanSchema, NullableSchema, OptionalSchema etc.
37
+
38
+ // --- Complex Schemas ---
39
+
40
+ /**
41
+ * Type representing the shape of an object schema (key to schema mapping).
42
+ */
43
+ export type ObjectShape = {
44
+ [key: string]: BaseSchema<any>;
45
+ };
46
+
47
+ /**
48
+ * Infers the TypeScript output type from an ObjectShape.
49
+ * Use mapped types to get the output type of each property schema.
50
+ */
51
+ export type ObjectOutput<TShape extends ObjectShape> = {
52
+ [K in keyof TShape]: TShape[K]['_outputType'];
53
+ };
54
+
55
+ export class ObjectSchema<TShape extends ObjectShape> extends BaseSchema<ObjectOutput<TShape>> {
56
+ _shape: TShape;
57
+
58
+ constructor(shape: TShape) {
59
+ super();
60
+ this._shape = shape;
61
+ }
62
+
63
+ parse(data: any): ObjectOutput<TShape> {
64
+ if (typeof data !== 'object' || data === null) {
65
+ throw new Error(`Expected object, received ${typeof data}`);
66
+ }
67
+
68
+ const result: any = {};
69
+ const errors: string[] = [];
70
+
71
+ // Validate defined properties
72
+ for (const key in this._shape) {
73
+ if (Object.prototype.hasOwnProperty.call(this._shape, key)) {
74
+ const schema = this._shape[key];
75
+ const value = (data as any)[key]; // Get value from input data
76
+ try {
77
+ if (schema) {
78
+ result[key] = schema.parse(value); // Recursively parse property
79
+ }
80
+ } catch (e: any) {
81
+ errors.push(`Property "${key}": ${e.message}`);
82
+ }
83
+ }
84
+ }
85
+
86
+ // Basic handling for extra keys (can be made configurable)
87
+ for (const key in data) {
88
+ if (Object.prototype.hasOwnProperty.call(data, key) && !Object.prototype.hasOwnProperty.call(this._shape, key)) {
89
+ // For now, ignore extra keys. Could throw an error or strip them.
90
+ // errors.push(`Unknown property "${key}"`);
91
+ // console.warn(`Warning: Unknown property "${key}" in object data.`);
92
+ }
93
+ }
94
+
95
+
96
+ if (errors.length > 0) {
97
+ throw new Error(`Object validation failed:\n${errors.join('\n')}`);
98
+ }
99
+
100
+ return result as ObjectOutput<TShape>;
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Infers the TypeScript output type from an element schema for an array.
106
+ */
107
+ export type ArrayOutput<TElementSchema extends BaseSchema<any>> = Array<TElementSchema['_outputType']>;
108
+
109
+
110
+ export class ArraySchema<TElementSchema extends BaseSchema<any>> extends BaseSchema<ArrayOutput<TElementSchema>> {
111
+ _element: TElementSchema;
112
+
113
+ constructor(elementSchema: TElementSchema) {
114
+ super();
115
+ this._element = elementSchema;
116
+ }
117
+
118
+ parse(data: any): ArrayOutput<TElementSchema> {
119
+ if (!Array.isArray(data)) {
120
+ throw new Error(`Expected array, received ${typeof data}`);
121
+ }
122
+
123
+ const result: any[] = [];
124
+ const errors: string[] = [];
125
+
126
+ for (let i = 0; i < data.length; i++) {
127
+ try {
128
+ result[i] = this._element.parse(data[i]); // Recursively parse each element
129
+ } catch (e: any) {
130
+ errors.push(`Element at index ${i}: ${e.message}`);
131
+ }
132
+ }
133
+
134
+ if (errors.length > 0) {
135
+ throw new Error(`Array validation failed:\n${errors.join('\n')}`);
136
+ }
137
+
138
+ return result as ArrayOutput<TElementSchema>;
139
+ }
140
+ }
141
+
142
+ // Refine NuSchema union after defining concrete types
143
+ export type NuSchema =
144
+ | BooleanSchema
145
+ | StringSchema
146
+ | NumberSchema
147
+ // Add others like BooleanSchema
148
+ | ObjectSchema<any>
149
+ | ArraySchema<any>;