cogsbox-shape 0.5.158 → 0.5.160
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.d.ts +13 -8
- package/dist/schema.js +48 -28
- package/package.json +1 -1
package/dist/schema.d.ts
CHANGED
|
@@ -40,7 +40,9 @@ type ZodTypeFromPrimitive<T> = T extends string ? z.ZodString : T extends number
|
|
|
40
40
|
type CollapsedUnion<A extends z.ZodTypeAny, B extends z.ZodTypeAny> = A extends B ? (B extends A ? A : z.ZodUnion<[A, B]>) : z.ZodUnion<[A, B]>;
|
|
41
41
|
export interface IBuilderMethods<T extends DbConfig, TSql extends z.ZodTypeAny, TNew extends z.ZodTypeAny, TInitialValue, TClient extends z.ZodTypeAny, TValidation extends z.ZodTypeAny> {
|
|
42
42
|
initialState<const TValue>(options: {
|
|
43
|
-
value: TValue | ((
|
|
43
|
+
value: TValue | ((tools: {
|
|
44
|
+
uuid: () => string;
|
|
45
|
+
}) => TValue);
|
|
44
46
|
schema?: never;
|
|
45
47
|
clientPk?: boolean;
|
|
46
48
|
}): Prettify<Builder<"new", T, TSql, ZodTypeFromPrimitive<TValue extends () => infer R ? R : TValue>, TValue extends () => infer R ? R : TValue, CollapsedUnion<TSql, ZodTypeFromPrimitive<TValue extends () => infer R ? R : TValue>>, CollapsedUnion<TSql, ZodTypeFromPrimitive<TValue extends () => infer R ? R : TValue>>>>;
|
|
@@ -50,7 +52,9 @@ export interface IBuilderMethods<T extends DbConfig, TSql extends z.ZodTypeAny,
|
|
|
50
52
|
clientPk?: boolean;
|
|
51
53
|
}): Prettify<Builder<"new", T, TSql, TSchema, z.infer<TSchema>, CollapsedUnion<TSql, TSchema>, CollapsedUnion<TSql, TSchema>>>;
|
|
52
54
|
initialState<const TValue, const TSchema extends z.ZodTypeAny>(options: {
|
|
53
|
-
value: TValue | ((
|
|
55
|
+
value: TValue | ((tools: {
|
|
56
|
+
uuid: () => string;
|
|
57
|
+
}) => TValue);
|
|
54
58
|
schema: TSchema | ((base: ZodTypeFromPrimitive<TValue extends () => infer R ? R : TValue>) => TSchema);
|
|
55
59
|
clientPk?: boolean;
|
|
56
60
|
}): Prettify<Builder<"new", T, TSql, TSchema, z.infer<TSchema>, // <-- THIS IS THE FIX: Use schema's type, not literal value
|
|
@@ -131,7 +135,9 @@ export type Reference<TGetter extends () => any> = {
|
|
|
131
135
|
getter: TGetter;
|
|
132
136
|
};
|
|
133
137
|
interface ShapeAPI {
|
|
134
|
-
initialState: <const TValue>(value: TValue | ((
|
|
138
|
+
initialState: <const TValue>(value: TValue | ((tools: {
|
|
139
|
+
uuid: () => string;
|
|
140
|
+
}) => TValue)) => Builder<"new", null, z.ZodUndefined, // No SQL schema
|
|
135
141
|
ZodTypeFromPrimitive<TValue extends () => infer R ? R : TValue>, TValue extends () => infer R ? R : TValue, ZodTypeFromPrimitive<TValue extends () => infer R ? R : TValue>, ZodTypeFromPrimitive<TValue extends () => infer R ? R : TValue>>;
|
|
136
142
|
sql: <T extends SQLType>(sqlConfig: T) => Builder<"sql", T, SQLToZodType<T, false>, SQLToZodType<T, false>, z.infer<SQLToZodType<T, false>>, SQLToZodType<T, false>, SQLToZodType<T, false>>;
|
|
137
143
|
reference: <TGetter extends () => any>(getter: TGetter) => Reference<TGetter>;
|
|
@@ -207,6 +213,7 @@ export declare function createSchema<T extends {
|
|
|
207
213
|
}, R extends Record<string, any> = {}, TActualSchema extends Omit<T & R, typeof SchemaWrapperBrand> = Omit<T & R, typeof SchemaWrapperBrand>>(schema: T, relations?: R): {
|
|
208
214
|
pk: string[] | null;
|
|
209
215
|
clientPk: string[] | null;
|
|
216
|
+
isClientRecord: ((record: any) => boolean) | undefined;
|
|
210
217
|
sqlSchema: z.ZodObject<Prettify<DeriveSchemaByKey<TActualSchema, "zodSqlSchema">>>;
|
|
211
218
|
clientSchema: z.ZodObject<Prettify<DeriveSchemaByKey<TActualSchema, "zodClientSchema">>>;
|
|
212
219
|
validationSchema: z.ZodObject<Prettify<DeriveSchemaByKey<TActualSchema, "zodValidationSchema">>>;
|
|
@@ -454,13 +461,11 @@ type DeriveDefaults<T, Depth extends any[] = []> = Prettify<Depth["length"] exte
|
|
|
454
461
|
};
|
|
455
462
|
} ? D extends () => infer R ? R : D : never : T[K] extends {
|
|
456
463
|
config: {
|
|
457
|
-
|
|
464
|
+
zodNewSchema: infer TNew;
|
|
465
|
+
zodSqlSchema: infer TSql;
|
|
458
466
|
zodClientSchema: infer TClient extends z.ZodTypeAny;
|
|
459
|
-
};
|
|
460
|
-
} ? z.infer<TClient> : T[K] extends {
|
|
461
|
-
config: {
|
|
462
467
|
initialValue: infer D;
|
|
463
468
|
};
|
|
464
|
-
} ? D extends () => infer R ? R : D : never;
|
|
469
|
+
} ? TNew extends TSql ? z.infer<TClient> : D extends () => infer R ? R : D : never;
|
|
465
470
|
}>;
|
|
466
471
|
export {};
|
package/dist/schema.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { v4 as uuid } from "uuid";
|
|
2
3
|
export const isFunction = (fn) => typeof fn === "function";
|
|
3
4
|
// Function to create a properly typed current timestamp config
|
|
4
5
|
export function currentTimeStamp() {
|
|
@@ -9,7 +10,7 @@ export function currentTimeStamp() {
|
|
|
9
10
|
}
|
|
10
11
|
export const s = {
|
|
11
12
|
initialState: (value) => {
|
|
12
|
-
const actualValue = isFunction(value) ? value() : value;
|
|
13
|
+
const actualValue = isFunction(value) ? value({ uuid }) : value;
|
|
13
14
|
// Infer the Zod type from the primitive value
|
|
14
15
|
let inferredZodType;
|
|
15
16
|
if (typeof actualValue === "string") {
|
|
@@ -129,7 +130,7 @@ function createBuilder(config) {
|
|
|
129
130
|
let finalSchema;
|
|
130
131
|
// 1. Determine the actual value
|
|
131
132
|
if (value !== undefined) {
|
|
132
|
-
actualValue = isFunction(value) ? value() : value;
|
|
133
|
+
actualValue = isFunction(value) ? value({ uuid }) : value;
|
|
133
134
|
}
|
|
134
135
|
else if (schemaOrModifier &&
|
|
135
136
|
typeof schemaOrModifier === "object" &&
|
|
@@ -459,6 +460,7 @@ export function createSchema(schema, relations) {
|
|
|
459
460
|
const fullSchema = { ...schema, ...(relations || {}) };
|
|
460
461
|
let pkKeys = [];
|
|
461
462
|
let clientPkKeys = [];
|
|
463
|
+
// FIRST PASS: Collect all fields and PKs
|
|
462
464
|
for (const key in fullSchema) {
|
|
463
465
|
const value = fullSchema[key];
|
|
464
466
|
if (key === "_tableName" ||
|
|
@@ -469,7 +471,6 @@ export function createSchema(schema, relations) {
|
|
|
469
471
|
typeof value === "function")
|
|
470
472
|
continue;
|
|
471
473
|
const definition = fullSchema[key];
|
|
472
|
-
// Handle new-style references
|
|
473
474
|
if (isReference(definition)) {
|
|
474
475
|
const targetField = definition.getter();
|
|
475
476
|
if (targetField && targetField.config) {
|
|
@@ -487,27 +488,18 @@ export function createSchema(schema, relations) {
|
|
|
487
488
|
fieldTransforms[key] = config.transforms;
|
|
488
489
|
}
|
|
489
490
|
}
|
|
490
|
-
continue;
|
|
491
|
+
continue;
|
|
491
492
|
}
|
|
492
|
-
// THEN, handle all other fields that have a config (builders, relations, etc.)
|
|
493
493
|
if (definition && definition.config) {
|
|
494
494
|
const config = definition.config;
|
|
495
|
-
|
|
496
|
-
pkKeys.push(key);
|
|
497
|
-
}
|
|
498
|
-
if (config.sql?.isClientPk) {
|
|
499
|
-
clientPkKeys.push(key);
|
|
500
|
-
}
|
|
501
|
-
// The rest of the logic for builders
|
|
495
|
+
// ... pk collection logic ...
|
|
502
496
|
const sqlConfig = config.sql;
|
|
503
497
|
if (sqlConfig &&
|
|
504
498
|
typeof sqlConfig === "object" &&
|
|
505
499
|
["hasMany", "hasOne", "belongsTo", "manyToMany"].includes(sqlConfig.type)) {
|
|
506
|
-
// This is for relations, which also aren't PKs, so we just continue.
|
|
507
500
|
continue;
|
|
508
501
|
}
|
|
509
502
|
else {
|
|
510
|
-
// This is for regular s.sql() fields
|
|
511
503
|
sqlFields[key] = config.zodSqlSchema;
|
|
512
504
|
clientFields[key] = config.zodClientSchema;
|
|
513
505
|
serverFields[key] = config.zodValidationSchema;
|
|
@@ -516,28 +508,55 @@ export function createSchema(schema, relations) {
|
|
|
516
508
|
}
|
|
517
509
|
const initialValueOrFn = config.initialValue;
|
|
518
510
|
defaultGenerators[key] = initialValueOrFn;
|
|
519
|
-
|
|
511
|
+
// Get the raw default value
|
|
512
|
+
let rawDefault = isFunction(initialValueOrFn)
|
|
520
513
|
? initialValueOrFn()
|
|
521
514
|
: initialValueOrFn;
|
|
515
|
+
// Apply toClient transform if it exists
|
|
516
|
+
if (config.transforms?.toClient && rawDefault !== undefined) {
|
|
517
|
+
defaultValues[key] = config.transforms.toClient(rawDefault);
|
|
518
|
+
}
|
|
519
|
+
else {
|
|
520
|
+
defaultValues[key] = rawDefault;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
// AFTER THE LOOP: Build isClientRecord checker
|
|
526
|
+
let isClientRecord;
|
|
527
|
+
const explicitChecker = fullSchema.__isClientChecker;
|
|
528
|
+
if (explicitChecker) {
|
|
529
|
+
isClientRecord = explicitChecker;
|
|
530
|
+
}
|
|
531
|
+
else if (clientPkKeys.length > 0) {
|
|
532
|
+
const autoChecks = [];
|
|
533
|
+
for (const key of clientPkKeys) {
|
|
534
|
+
const field = fullSchema[key];
|
|
535
|
+
const sqlType = field?.config?.sql?.type;
|
|
536
|
+
const initialValue = field?.config?.initialValue;
|
|
537
|
+
const dbIsNumeric = sqlType === "int";
|
|
538
|
+
const clientIsString = typeof initialValue === "string";
|
|
539
|
+
if (dbIsNumeric && clientIsString) {
|
|
540
|
+
autoChecks.push({ key, check: (val) => typeof val === "string" });
|
|
522
541
|
}
|
|
523
542
|
}
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
if (key in defaultValues && defaultValues[key] !== undefined) {
|
|
527
|
-
defaultValues[key] = fieldTransforms[key].toClient(defaultValues[key]);
|
|
543
|
+
if (autoChecks.length > 0) {
|
|
544
|
+
isClientRecord = (record) => autoChecks.some(({ key, check }) => check(record[key]));
|
|
528
545
|
}
|
|
529
546
|
}
|
|
530
547
|
const generateDefaults = () => {
|
|
531
548
|
const freshDefaults = {};
|
|
532
549
|
for (const key in defaultGenerators) {
|
|
533
550
|
const generatorOrValue = defaultGenerators[key];
|
|
534
|
-
|
|
535
|
-
? generatorOrValue()
|
|
536
|
-
: generatorOrValue;
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
551
|
+
let rawValue = isFunction(generatorOrValue)
|
|
552
|
+
? generatorOrValue()
|
|
553
|
+
: generatorOrValue;
|
|
554
|
+
// Apply toClient transform if it exists
|
|
555
|
+
if (fieldTransforms[key]?.toClient && rawValue !== undefined) {
|
|
556
|
+
freshDefaults[key] = fieldTransforms[key].toClient(rawValue);
|
|
557
|
+
}
|
|
558
|
+
else {
|
|
559
|
+
freshDefaults[key] = rawValue;
|
|
541
560
|
}
|
|
542
561
|
}
|
|
543
562
|
return freshDefaults;
|
|
@@ -561,8 +580,9 @@ export function createSchema(schema, relations) {
|
|
|
561
580
|
return dbObject;
|
|
562
581
|
};
|
|
563
582
|
return {
|
|
564
|
-
pk: pkKeys
|
|
565
|
-
clientPk: clientPkKeys ? clientPkKeys : null,
|
|
583
|
+
pk: pkKeys.length ? pkKeys : null,
|
|
584
|
+
clientPk: clientPkKeys.length ? clientPkKeys : null,
|
|
585
|
+
isClientRecord, // NOW IT'S IN SCOPE
|
|
566
586
|
sqlSchema: z.object(sqlFields),
|
|
567
587
|
clientSchema: z.object(clientFields),
|
|
568
588
|
validationSchema: z.object(serverFields),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cogsbox-shape",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.160",
|
|
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",
|