cogsbox-shape 0.5.55 → 0.5.57

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/schema.js CHANGED
@@ -8,14 +8,12 @@ export function currentTimeStamp() {
8
8
  defaultValue: new Date(),
9
9
  };
10
10
  }
11
- // Internal type creation helper
11
+ // Now define the shape object with the explicit type annotation
12
12
  export const shape = {
13
- // Integer fields
14
13
  int: (config = {}) => shape.sql({
15
14
  type: "int",
16
15
  ...config,
17
16
  }),
18
- // String fields with variants
19
17
  varchar: (config = {}) => shape.sql({
20
18
  type: "varchar",
21
19
  ...config,
@@ -32,12 +30,10 @@ export const shape = {
32
30
  type: "longtext",
33
31
  ...config,
34
32
  }),
35
- // Boolean fields
36
33
  boolean: (config = {}) => shape.sql({
37
34
  type: "boolean",
38
35
  ...config,
39
36
  }),
40
- // Date fields
41
37
  date: (config = {}) => shape.sql({
42
38
  type: "date",
43
39
  ...config,
@@ -74,7 +70,6 @@ export const shape = {
74
70
  }
75
71
  return baseType;
76
72
  })();
77
- // Initialize with sql type for all schemas
78
73
  return createBuilder({
79
74
  stage: "sql",
80
75
  sqlConfig: sqlConfig,
@@ -85,10 +80,74 @@ export const shape = {
85
80
  validationZod: sqlZodType,
86
81
  });
87
82
  },
83
+ hasMany: (config) => {
84
+ const relationConfig = {
85
+ type: "hasMany",
86
+ ...config,
87
+ };
88
+ const relationZodType = z.array(z.any()).optional();
89
+ return createBuilder({
90
+ stage: "relation",
91
+ sqlConfig: relationConfig,
92
+ sqlZod: relationZodType,
93
+ newZod: relationZodType,
94
+ initialValue: Array.from({ length: config.defaultCount || 0 }, () => ({})),
95
+ clientZod: relationZodType,
96
+ validationZod: relationZodType,
97
+ });
98
+ },
99
+ hasOne: (config) => {
100
+ const relationConfig = {
101
+ type: "hasOne",
102
+ ...config,
103
+ };
104
+ const relationZodType = z.any().optional();
105
+ return createBuilder({
106
+ stage: "relation",
107
+ sqlConfig: relationConfig,
108
+ sqlZod: relationZodType,
109
+ newZod: relationZodType,
110
+ initialValue: {},
111
+ clientZod: relationZodType,
112
+ validationZod: relationZodType,
113
+ });
114
+ },
115
+ belongsTo: (config) => {
116
+ const relationConfig = {
117
+ type: "belongsTo",
118
+ ...config,
119
+ };
120
+ const relationZodType = z.any().optional();
121
+ return createBuilder({
122
+ stage: "relation",
123
+ sqlConfig: relationConfig,
124
+ sqlZod: relationZodType,
125
+ newZod: relationZodType,
126
+ initialValue: {},
127
+ clientZod: relationZodType,
128
+ validationZod: relationZodType,
129
+ });
130
+ },
131
+ manyToMany: (config) => {
132
+ const relationConfig = {
133
+ type: "manyToMany",
134
+ ...config,
135
+ };
136
+ const relationZodType = z.array(z.any()).optional();
137
+ return createBuilder({
138
+ stage: "relation",
139
+ sqlConfig: relationConfig,
140
+ sqlZod: relationZodType,
141
+ newZod: relationZodType,
142
+ initialValue: Array.from({ length: config.defaultCount || 0 }, () => ({})),
143
+ clientZod: relationZodType,
144
+ validationZod: relationZodType,
145
+ });
146
+ },
88
147
  };
148
+ // === UPDATED: createBuilder to Handle Relations ===
89
149
  function createBuilder(config) {
90
- // Initialize completed stages tracker
91
- const completedStages = config.completedStages || new Set(["sql"]);
150
+ const completedStages = config.completedStages || new Set([config.stage]);
92
151
  const builderObject = {
93
152
  config: {
94
153
  sql: config.sqlConfig,
@@ -100,7 +159,6 @@ function createBuilder(config) {
100
159
  zodValidationSchema: config.validationZod,
101
160
  },
102
161
  initialState: (schemaOrDefault, defaultValue) => {
103
- // Runtime validation
104
162
  if (completedStages.has("new")) {
105
163
  throw new Error("initialState() can only be called once in the chain");
106
164
  }
@@ -110,13 +168,12 @@ function createBuilder(config) {
110
168
  if (completedStages.has("validation")) {
111
169
  throw new Error("initialState() must be called before validation()");
112
170
  }
113
- // Handle overload - if no second param, first param is the default
114
171
  const hasTypeParam = defaultValue !== undefined;
115
172
  const newSchema = hasTypeParam
116
173
  ? isFunction(schemaOrDefault)
117
174
  ? schemaOrDefault({ sql: config.sqlZod })
118
175
  : schemaOrDefault
119
- : config.sqlZod; // Keep SQL type if just setting default
176
+ : config.sqlZod;
120
177
  const finalDefaultValue = hasTypeParam
121
178
  ? defaultValue
122
179
  : schemaOrDefault;
@@ -138,7 +195,6 @@ function createBuilder(config) {
138
195
  });
139
196
  },
140
197
  client: (assert) => {
141
- // Runtime validation
142
198
  if (completedStages.has("client")) {
143
199
  throw new Error("client() can only be called once in the chain");
144
200
  }
@@ -154,13 +210,11 @@ function createBuilder(config) {
154
210
  ...config,
155
211
  stage: "client",
156
212
  clientZod: clientSchema,
157
- // Always set validation to match client when client is set
158
213
  validationZod: clientSchema,
159
214
  completedStages: newCompletedStages,
160
215
  });
161
216
  },
162
217
  validation: (assert) => {
163
- // Runtime validation
164
218
  if (completedStages.has("validation")) {
165
219
  throw new Error("validation() can only be called once in the chain");
166
220
  }
@@ -181,7 +235,6 @@ function createBuilder(config) {
181
235
  });
182
236
  },
183
237
  transform: (transforms) => {
184
- // Runtime validation
185
238
  if (!completedStages.has("validation") &&
186
239
  !completedStages.has("client")) {
187
240
  throw new Error("transform() requires at least client() or validation() to be called first");
@@ -234,25 +287,40 @@ export function manyToMany(config) {
234
287
  });
235
288
  }
236
289
  function inferDefaultFromZod(zodType, sqlConfig) {
237
- // Check SQL type first for better defaults
238
- if (sqlConfig && !sqlConfig.nullable) {
239
- switch (sqlConfig.type) {
240
- case "varchar":
241
- case "text":
242
- case "char":
243
- case "longtext":
244
- return "";
245
- case "int":
246
- return 0;
247
- case "boolean":
248
- return false;
249
- case "date":
250
- case "datetime":
251
- return new Date();
290
+ // Handle relation configs
291
+ if (sqlConfig && typeof sqlConfig === "object" && "type" in sqlConfig) {
292
+ // Check if it's a relation config by looking for relation types
293
+ if (typeof sqlConfig.type === "string" &&
294
+ ["hasMany", "hasOne", "belongsTo", "manyToMany"].includes(sqlConfig.type)) {
295
+ const relationConfig = sqlConfig;
296
+ if (relationConfig.type === "hasMany" ||
297
+ relationConfig.type === "manyToMany") {
298
+ return Array.from({ length: relationConfig.defaultCount || 0 }, () => ({}));
299
+ }
300
+ // For hasOne and belongsTo
301
+ return {};
302
+ }
303
+ // Handle SQL configs (existing logic)
304
+ const sqlTypeConfig = sqlConfig;
305
+ if (sqlTypeConfig.type && !sqlTypeConfig.nullable) {
306
+ switch (sqlTypeConfig.type) {
307
+ case "varchar":
308
+ case "text":
309
+ case "char":
310
+ case "longtext":
311
+ return "";
312
+ case "int":
313
+ return 0;
314
+ case "boolean":
315
+ return false;
316
+ case "date":
317
+ case "datetime":
318
+ return new Date();
319
+ }
320
+ }
321
+ if (sqlTypeConfig.nullable) {
322
+ return null;
252
323
  }
253
- }
254
- if (sqlConfig?.nullable) {
255
- return null;
256
324
  }
257
325
  // Fall back to existing zod-based inference
258
326
  if (zodType instanceof z.ZodOptional) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cogsbox-shape",
3
- "version": "0.5.55",
3
+ "version": "0.5.57",
4
4
  "description": "A TypeScript library for creating type-safe database schemas with Zod validation, SQL type definitions, and automatic client/server transformations. Unifies client, server, and database types through a single schema definition, with built-in support for relationships and serialization.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",