@gialicus/smart-object 1.0.0 → 2.0.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 (58) hide show
  1. package/CHANGELOG.md +38 -1
  2. package/README.md +127 -19
  3. package/dist/errors.d.ts +20 -0
  4. package/dist/errors.d.ts.map +1 -0
  5. package/dist/errors.js +40 -0
  6. package/dist/index.d.ts +4 -2
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +2 -1
  9. package/dist/smart-object/apply-operations.d.ts +5 -0
  10. package/dist/smart-object/apply-operations.d.ts.map +1 -0
  11. package/dist/smart-object/apply-operations.js +21 -0
  12. package/dist/smart-object/build-class.d.ts +3 -0
  13. package/dist/smart-object/build-class.d.ts.map +1 -0
  14. package/dist/smart-object/build-class.js +31 -0
  15. package/dist/smart-object/codecs.d.ts +15 -0
  16. package/dist/smart-object/codecs.d.ts.map +1 -0
  17. package/dist/smart-object/codecs.js +163 -0
  18. package/dist/smart-object/define-prototype.d.ts +4 -0
  19. package/dist/smart-object/define-prototype.d.ts.map +1 -0
  20. package/dist/smart-object/define-prototype.js +76 -0
  21. package/dist/{smart-object.d.ts → smart-object/factory.d.ts} +4 -2
  22. package/dist/smart-object/factory.d.ts.map +1 -0
  23. package/dist/smart-object/factory.js +27 -0
  24. package/dist/smart-object/index.d.ts +2 -0
  25. package/dist/smart-object/index.d.ts.map +1 -0
  26. package/dist/smart-object/index.js +1 -0
  27. package/dist/smart-object/instance-state.d.ts +9 -0
  28. package/dist/smart-object/instance-state.d.ts.map +1 -0
  29. package/dist/smart-object/instance-state.js +23 -0
  30. package/dist/smart-object/json-patch.d.ts +4 -0
  31. package/dist/smart-object/json-patch.d.ts.map +1 -0
  32. package/dist/smart-object/json-patch.js +27 -0
  33. package/dist/smart-object/read-field.d.ts +2 -0
  34. package/dist/smart-object/read-field.d.ts.map +1 -0
  35. package/dist/smart-object/read-field.js +13 -0
  36. package/dist/smart-object/setters/object-field.d.ts +5 -0
  37. package/dist/smart-object/setters/object-field.d.ts.map +1 -0
  38. package/dist/smart-object/setters/object-field.js +56 -0
  39. package/dist/smart-object/setters/record-field.d.ts +7 -0
  40. package/dist/smart-object/setters/record-field.d.ts.map +1 -0
  41. package/dist/smart-object/setters/record-field.js +133 -0
  42. package/dist/smart-object/setters/union-field.d.ts +4 -0
  43. package/dist/smart-object/setters/union-field.d.ts.map +1 -0
  44. package/dist/smart-object/setters/union-field.js +25 -0
  45. package/dist/smart-object/setters/variant-switch.d.ts +5 -0
  46. package/dist/smart-object/setters/variant-switch.d.ts.map +1 -0
  47. package/dist/smart-object/setters/variant-switch.js +37 -0
  48. package/dist/smart-object/union-variant.d.ts +5 -0
  49. package/dist/smart-object/union-variant.d.ts.map +1 -0
  50. package/dist/smart-object/union-variant.js +38 -0
  51. package/dist/types.d.ts +36 -3
  52. package/dist/types.d.ts.map +1 -1
  53. package/dist/zod-introspect.d.ts +50 -0
  54. package/dist/zod-introspect.d.ts.map +1 -0
  55. package/dist/zod-introspect.js +252 -0
  56. package/package.json +1 -1
  57. package/dist/smart-object.d.ts.map +0 -1
  58. package/dist/smart-object.js +0 -157
package/dist/types.d.ts CHANGED
@@ -2,9 +2,9 @@ import type { Operation } from "fast-json-patch";
2
2
  import type { z } from "zod";
3
3
  export type { Operation };
4
4
  /**
5
- * Schemas accepted by SmartObject: plain objects or unions of objects at root.
5
+ * Schemas accepted by SmartObject: plain objects, unions of objects, intersections, or lazy wrappers at root.
6
6
  */
7
- export type SmartObjectSchema = z.ZodObject | z.ZodDiscriminatedUnion | z.ZodUnion;
7
+ export type SmartObjectSchema = z.ZodObject | z.ZodDiscriminatedUnion | z.ZodUnion | z.ZodIntersection | z.ZodLazy;
8
8
  /**
9
9
  * Compile-time map of `set*` methods for each schema key.
10
10
  *
@@ -26,6 +26,30 @@ export type AllKeys<T> = T extends unknown ? keyof T : never;
26
26
  export type SetMethodsUnion<T> = {
27
27
  [K in AllKeys<T> as `set${Capitalize<string & K>}`]: (value: T extends unknown ? (K extends keyof T ? T[K] : never) : never) => void;
28
28
  };
29
+ type UnionToIntersection<U> = (U extends unknown ? (value: U) => void : never) extends (value: infer I) => void ? I : never;
30
+ type OmitDiscriminator<T, D extends PropertyKey> = Omit<T, D & keyof T>;
31
+ type PerVariantSwitchMethod<T, D extends PropertyKey> = T extends Record<D, infer Tag extends string> ? Tag extends string ? {
32
+ [K in `switchTo${Capitalize<Tag>}`]: (value: OmitDiscriminator<T, D>) => void;
33
+ } : never : never;
34
+ /**
35
+ * Variant switching for union root schemas.
36
+ */
37
+ export type VariantSwitchMethods<T> = {
38
+ switchVariant(value: T): void;
39
+ };
40
+ export type DiscriminatedVariantSwitchMethods<T, D extends PropertyKey> = VariantSwitchMethods<T> & UnionToIntersection<PerVariantSwitchMethod<T, D>>;
41
+ type EntryValue<T> = T extends Record<string, infer V> ? V : T extends Map<string, infer V> ? V : never;
42
+ type IsEntryField<T> = NonNullable<T> extends Record<string, unknown> ? true : NonNullable<T> extends Map<string, infer _V> ? true : false;
43
+ /**
44
+ * Dynamic entry accessors for `z.record` and string-key `z.map` fields.
45
+ */
46
+ export type RecordFieldMethods<T> = {
47
+ [K in keyof T as IsEntryField<T[K]> extends true ? `get${Capitalize<string & K>}Entry` : never]: (key: string) => EntryValue<NonNullable<T[K]>> | undefined;
48
+ } & {
49
+ [K in keyof T as IsEntryField<T[K]> extends true ? `set${Capitalize<string & K>}Entry` : never]: (key: string, value: EntryValue<NonNullable<T[K]>>) => void;
50
+ } & {
51
+ [K in keyof T as IsEntryField<T[K]> extends true ? `delete${Capitalize<string & K>}Entry` : never]: (key: string) => void;
52
+ };
29
53
  /**
30
54
  * Read/write surface and audit trail are separate concerns in the public API.
31
55
  *
@@ -38,18 +62,27 @@ export type OperationsAccessor = {
38
62
  /** Drops accumulated patches after persist/sync without rolling back state */
39
63
  clearOperations(): void;
40
64
  };
65
+ /**
66
+ * Snapshot serialization — returns a deep clone safe for JSON.stringify.
67
+ */
68
+ export type SnapshotAccessor<T extends SmartObjectSchema> = {
69
+ toJSON(): z.infer<T>;
70
+ };
41
71
  /**
42
72
  * Flattened data shape for union roots — exposes all variant keys on one surface.
43
73
  */
44
74
  export type UnionDataShape<U> = {
45
75
  [K in AllKeys<U>]: U extends unknown ? (K extends keyof U ? U[K] : never) : never;
46
76
  };
77
+ type ObjectLikeSchema<T extends SmartObjectSchema> = T extends z.ZodObject | z.ZodIntersection | z.ZodLazy ? z.infer<T> : never;
78
+ type UnionRootExtras<T extends SmartObjectSchema> = T extends z.ZodDiscriminatedUnion<infer _Options, infer Discriminator extends string> ? DiscriminatedVariantSwitchMethods<z.infer<T>, Discriminator> : T extends z.ZodUnion ? VariantSwitchMethods<z.infer<T>> : Record<string, never>;
79
+ type ObjectRootExtras<T extends SmartObjectSchema> = T extends z.ZodObject ? RecordFieldMethods<z.infer<T>> : T extends z.ZodIntersection | z.ZodLazy ? RecordFieldMethods<ObjectLikeSchema<T>> : Record<string, never>;
47
80
  /**
48
81
  * Full instance contract: validated data shape, typed mutators, and patch log.
49
82
  *
50
83
  * Intersection types merge these concerns into one consumable surface for callers.
51
84
  */
52
- export type SmartObjectInstance<T extends SmartObjectSchema> = (T extends z.ZodObject ? z.infer<T> : UnionDataShape<z.infer<T>>) & (T extends z.ZodObject ? SetMethods<z.infer<T>> : SetMethodsUnion<z.infer<T>>) & OperationsAccessor;
85
+ export type SmartObjectInstance<T extends SmartObjectSchema> = (T extends z.ZodObject ? z.infer<T> : T extends z.ZodIntersection | z.ZodLazy ? z.infer<T> : UnionDataShape<z.infer<T>>) & (T extends z.ZodObject | z.ZodIntersection | z.ZodLazy ? SetMethods<z.infer<T>> : SetMethodsUnion<z.infer<T>>) & ObjectRootExtras<T> & UnionRootExtras<T> & OperationsAccessor & SnapshotAccessor<T>;
53
86
  /**
54
87
  * Constructor type for a SmartObject class, including replay as a first-class capability.
55
88
  *
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B,YAAY,EAAE,SAAS,EAAE,CAAC;AAE1B;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,qBAAqB,GAAG,CAAC,CAAC,QAAQ,CAAC;AAEnF;;;;;GAKG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI;KACzB,CAAC,IAAI,MAAM,CAAC,IAAI,MAAM,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI;CACxE,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,OAAO,GAAG,MAAM,CAAC,GAAG,KAAK,CAAC;AAE7D;;;;GAIG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI;KAC9B,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,IAAI,MAAM,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,GAAG,CACnD,KAAK,EAAE,CAAC,SAAS,OAAO,GAAG,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,KAAK,KAClE,IAAI;CACV,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,qEAAqE;IACrE,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IAC1C,8EAA8E;IAC9E,eAAe,IAAI,IAAI,CAAC;CACzB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI;KAC7B,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,OAAO,GAAG,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,KAAK;CAClF,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,CAAC,CAAC,SAAS,iBAAiB,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,GACjF,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GACV,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAC7B,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAC9E,kBAAkB,CAAC;AAErB;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,CAAC,CAAC,SAAS,iBAAiB,IAAI;IAChE,KAAK,OAAO,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC;IACnD,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC;CAClG,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import type { z } from "zod";
2
+ import type { SmartObjectSchema } from "./types.js";
3
+ export type ZodObjectLike = z.ZodObject;
4
+ export type ZodUnionRootLike = z.ZodUnion;
5
+ export type ZodDiscriminatedUnionLike = z.ZodDiscriminatedUnion;
6
+ export type ZodIntersectionLike = z.ZodIntersection;
7
+ export type ZodLazyLike = z.ZodLazy;
8
+ export type DiscriminatedVariantInfo = {
9
+ tag: string | number | boolean;
10
+ schema: ZodObjectLike;
11
+ methodName: string;
12
+ };
13
+ export type RecordFieldInfo = {
14
+ fieldName: string;
15
+ fieldSchema: z.ZodType;
16
+ valueSchema: z.ZodType;
17
+ storage: "record" | "map";
18
+ };
19
+ export declare function isZodObject(schema: unknown): schema is ZodObjectLike;
20
+ export declare function isZodUnionRoot(schema: SmartObjectSchema): schema is ZodUnionRootLike;
21
+ export declare function isZodDiscriminatedUnion(schema: ZodUnionRootLike): schema is ZodDiscriminatedUnionLike;
22
+ export declare function isZodUnionOfObjects(schema: ZodUnionRootLike): boolean;
23
+ export declare function getObjectShapeKeys(schema: ZodObjectLike): string[];
24
+ export declare function getUnionObjectKeys(schema: ZodUnionRootLike): string[];
25
+ export declare function getDiscriminator(schema: ZodDiscriminatedUnionLike): string;
26
+ export declare function toSetterMethodName(key: string): string;
27
+ export declare function toVariantSwitchMethodName(tag: string | number | boolean): string;
28
+ export declare function toRecordEntryMethodPrefix(fieldName: string): string;
29
+ export declare function getLiteralValue(schema: unknown): string | number | boolean | undefined;
30
+ export declare function getDiscriminatedVariants(schema: ZodDiscriminatedUnionLike): DiscriminatedVariantInfo[];
31
+ export declare function isZodRecord(schema: unknown): schema is z.ZodRecord;
32
+ export declare function isZodDate(schema: unknown): boolean;
33
+ export declare function isZodMap(schema: unknown): schema is z.ZodMap;
34
+ export declare function isZodSet(schema: unknown): schema is z.ZodSet;
35
+ export declare function isZodBigInt(schema: unknown): boolean;
36
+ export declare function isStringKeyMap(schema: unknown): schema is z.ZodMap;
37
+ export declare function unwrapFieldSchema(schema: z.ZodType): z.ZodType;
38
+ /** @deprecated Use unwrapFieldSchema */
39
+ export declare function unwrapOptionalNullable(schema: z.ZodType): z.ZodType;
40
+ export declare function isZodIntersection(schema: SmartObjectSchema): schema is ZodIntersectionLike;
41
+ export declare function isZodLazy(schema: SmartObjectSchema): schema is ZodLazyLike;
42
+ export declare function resolveLazySchema(schema: SmartObjectSchema): SmartObjectSchema;
43
+ export declare function getRecordFields(schema: ZodObjectLike): RecordFieldInfo[];
44
+ export declare function getRecordFieldsFromSchema(schema: SmartObjectSchema): RecordFieldInfo[];
45
+ export declare function getMergedObjectShape(schema: SmartObjectSchema): Record<string, z.ZodType>;
46
+ export declare function getSchemaShapeKeys(schema: SmartObjectSchema): string[];
47
+ export declare function getFieldSchema(schema: SmartObjectSchema, key: string): z.ZodType | undefined;
48
+ export declare function getObjectSchemaForFields(schema: SmartObjectSchema): ZodObjectLike | undefined;
49
+ export declare function isObjectLikeRoot(schema: SmartObjectSchema): boolean;
50
+ //# sourceMappingURL=zod-introspect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zod-introspect.d.ts","sourceRoot":"","sources":["../src/zod-introspect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,252 @@
1
+ export function isZodObject(schema) {
2
+ return (typeof schema === "object" &&
3
+ schema !== null &&
4
+ "_zod" in schema &&
5
+ schema._zod.def.type === "object");
6
+ }
7
+ export function isZodUnionRoot(schema) {
8
+ return schema._zod.def.type === "union";
9
+ }
10
+ export function isZodDiscriminatedUnion(schema) {
11
+ return "discriminator" in schema._zod.def;
12
+ }
13
+ export function isZodUnionOfObjects(schema) {
14
+ return schema.options.length > 0 && schema.options.every(isZodObject);
15
+ }
16
+ export function getObjectShapeKeys(schema) {
17
+ return Object.keys(schema.shape);
18
+ }
19
+ export function getUnionObjectKeys(schema) {
20
+ const keys = new Set();
21
+ for (const option of schema.options) {
22
+ if (!isZodObject(option)) {
23
+ continue;
24
+ }
25
+ for (const key of Object.keys(option.shape)) {
26
+ keys.add(key);
27
+ }
28
+ }
29
+ return [...keys];
30
+ }
31
+ export function getDiscriminator(schema) {
32
+ return schema._zod.def.discriminator;
33
+ }
34
+ export function toSetterMethodName(key) {
35
+ return `set${key.charAt(0).toUpperCase()}${key.slice(1)}`;
36
+ }
37
+ export function toVariantSwitchMethodName(tag) {
38
+ const label = typeof tag === "string" ? tag : String(tag);
39
+ return `switchTo${label.charAt(0).toUpperCase()}${label.slice(1)}`;
40
+ }
41
+ export function toRecordEntryMethodPrefix(fieldName) {
42
+ return fieldName.charAt(0).toUpperCase() + fieldName.slice(1);
43
+ }
44
+ export function getLiteralValue(schema) {
45
+ if (typeof schema !== "object" || schema === null || !("_zod" in schema)) {
46
+ return undefined;
47
+ }
48
+ const def = schema._zod.def;
49
+ if (def.type === "literal" && Array.isArray(def.values) && def.values.length === 1) {
50
+ const value = def.values[0];
51
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
52
+ return value;
53
+ }
54
+ }
55
+ return undefined;
56
+ }
57
+ export function getDiscriminatedVariants(schema) {
58
+ const discriminator = getDiscriminator(schema);
59
+ const variants = [];
60
+ for (const option of schema.options) {
61
+ if (!isZodObject(option)) {
62
+ continue;
63
+ }
64
+ const tagSchema = option.shape[discriminator];
65
+ const tag = getLiteralValue(tagSchema);
66
+ if (tag === undefined) {
67
+ continue;
68
+ }
69
+ variants.push({
70
+ tag,
71
+ schema: option,
72
+ methodName: toVariantSwitchMethodName(tag),
73
+ });
74
+ }
75
+ return variants;
76
+ }
77
+ export function isZodRecord(schema) {
78
+ return (typeof schema === "object" &&
79
+ schema !== null &&
80
+ "_zod" in schema &&
81
+ schema._zod.def.type === "record");
82
+ }
83
+ export function isZodDate(schema) {
84
+ if (typeof schema !== "object" || schema === null || !("_zod" in schema)) {
85
+ return false;
86
+ }
87
+ const def = schema._zod.def;
88
+ return def.type === "date";
89
+ }
90
+ export function isZodMap(schema) {
91
+ return (typeof schema === "object" &&
92
+ schema !== null &&
93
+ "_zod" in schema &&
94
+ schema._zod.def.type === "map");
95
+ }
96
+ export function isZodSet(schema) {
97
+ return (typeof schema === "object" &&
98
+ schema !== null &&
99
+ "_zod" in schema &&
100
+ schema._zod.def.type === "set");
101
+ }
102
+ export function isZodBigInt(schema) {
103
+ if (typeof schema !== "object" || schema === null || !("_zod" in schema)) {
104
+ return false;
105
+ }
106
+ return schema._zod.def.type === "bigint";
107
+ }
108
+ export function isStringKeyMap(schema) {
109
+ if (!isZodMap(schema)) {
110
+ return false;
111
+ }
112
+ const keyType = unwrapFieldSchema(schema._zod.def.keyType);
113
+ return keyType._zod.def.type === "string";
114
+ }
115
+ export function unwrapFieldSchema(schema) {
116
+ const def = schema._zod.def;
117
+ if (def.type === "optional" || def.type === "nullable" || def.type === "default") {
118
+ return unwrapFieldSchema(def.innerType);
119
+ }
120
+ if (def.type === "lazy") {
121
+ return unwrapFieldSchema(def.getter?.());
122
+ }
123
+ if (def.type === "pipe") {
124
+ const outType = def.out?._zod.def.type;
125
+ if (outType === "transform") {
126
+ return unwrapFieldSchema(def.in);
127
+ }
128
+ return unwrapFieldSchema(def.out);
129
+ }
130
+ return schema;
131
+ }
132
+ /** @deprecated Use unwrapFieldSchema */
133
+ export function unwrapOptionalNullable(schema) {
134
+ return unwrapFieldSchema(schema);
135
+ }
136
+ export function isZodIntersection(schema) {
137
+ return schema._zod.def.type === "intersection";
138
+ }
139
+ export function isZodLazy(schema) {
140
+ return schema._zod.def.type === "lazy";
141
+ }
142
+ export function resolveLazySchema(schema) {
143
+ if (isZodLazy(schema)) {
144
+ return resolveLazySchema(schema._zod.def.getter());
145
+ }
146
+ return schema;
147
+ }
148
+ function collectEntryField(fieldName, fieldSchema, unwrapped) {
149
+ if (isZodRecord(unwrapped)) {
150
+ return {
151
+ fieldName,
152
+ fieldSchema,
153
+ valueSchema: unwrapped._zod.def.valueType,
154
+ storage: "record",
155
+ };
156
+ }
157
+ if (isStringKeyMap(unwrapped)) {
158
+ return {
159
+ fieldName,
160
+ fieldSchema,
161
+ valueSchema: unwrapped._zod.def.valueType,
162
+ storage: "map",
163
+ };
164
+ }
165
+ return undefined;
166
+ }
167
+ export function getRecordFields(schema) {
168
+ const fields = [];
169
+ for (const [fieldName, fieldSchema] of Object.entries(schema.shape)) {
170
+ const unwrapped = unwrapFieldSchema(fieldSchema);
171
+ const entryField = collectEntryField(fieldName, fieldSchema, unwrapped);
172
+ if (entryField) {
173
+ fields.push(entryField);
174
+ }
175
+ }
176
+ return fields;
177
+ }
178
+ export function getRecordFieldsFromSchema(schema) {
179
+ const resolved = resolveLazySchema(schema);
180
+ if (isZodObject(resolved)) {
181
+ return getRecordFields(resolved);
182
+ }
183
+ if (isZodIntersection(resolved)) {
184
+ const left = resolved._zod.def.left;
185
+ const right = resolved._zod.def.right;
186
+ return [...getRecordFieldsFromSchema(left), ...getRecordFieldsFromSchema(right)];
187
+ }
188
+ return [];
189
+ }
190
+ export function getMergedObjectShape(schema) {
191
+ const resolved = resolveLazySchema(schema);
192
+ if (isZodObject(resolved)) {
193
+ return resolved.shape;
194
+ }
195
+ if (isZodIntersection(resolved)) {
196
+ const left = resolved._zod.def.left;
197
+ const right = resolved._zod.def.right;
198
+ return {
199
+ ...getMergedObjectShape(left),
200
+ ...getMergedObjectShape(right),
201
+ };
202
+ }
203
+ return {};
204
+ }
205
+ export function getSchemaShapeKeys(schema) {
206
+ const resolved = resolveLazySchema(schema);
207
+ if (isZodObject(resolved)) {
208
+ return getObjectShapeKeys(resolved);
209
+ }
210
+ if (isZodUnionRoot(resolved)) {
211
+ return getUnionObjectKeys(resolved);
212
+ }
213
+ if (isZodIntersection(resolved)) {
214
+ const left = resolved._zod.def.left;
215
+ const right = resolved._zod.def.right;
216
+ return [...new Set([...getSchemaShapeKeys(left), ...getSchemaShapeKeys(right)])];
217
+ }
218
+ return [];
219
+ }
220
+ export function getFieldSchema(schema, key) {
221
+ const resolved = resolveLazySchema(schema);
222
+ if (isZodObject(resolved)) {
223
+ return resolved.shape[key];
224
+ }
225
+ if (isZodIntersection(resolved)) {
226
+ const left = resolved._zod.def.left;
227
+ const right = resolved._zod.def.right;
228
+ return getFieldSchema(left, key) ?? getFieldSchema(right, key);
229
+ }
230
+ return undefined;
231
+ }
232
+ export function getObjectSchemaForFields(schema) {
233
+ const resolved = resolveLazySchema(schema);
234
+ if (isZodObject(resolved)) {
235
+ return resolved;
236
+ }
237
+ if (isZodIntersection(resolved)) {
238
+ const left = resolved._zod.def.left;
239
+ const right = resolved._zod.def.right;
240
+ const leftObject = getObjectSchemaForFields(left);
241
+ const rightObject = getObjectSchemaForFields(right);
242
+ if (leftObject && rightObject) {
243
+ return leftObject;
244
+ }
245
+ return leftObject ?? rightObject;
246
+ }
247
+ return undefined;
248
+ }
249
+ export function isObjectLikeRoot(schema) {
250
+ const resolved = resolveLazySchema(schema);
251
+ return isZodObject(resolved) || isZodIntersection(resolved);
252
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gialicus/smart-object",
3
- "version": "1.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "Oggetti TypeScript generati da schemi Zod con getter, set* tipizzati e operazioni JSON Patch",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1 +0,0 @@
1
- {"version":3,"file":"smart-object.d.ts","sourceRoot":"","sources":["../src/smart-object.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,sBAAsB,EAA0C,MAAM,YAAY,CAAC;AAsMjG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;AAC5F,wBAAgB,WAAW,CAAC,CAAC,SAAS,CAAC,CAAC,qBAAqB,EAC3D,SAAS,EAAE,CAAC,GACX,sBAAsB,CAAC,CAAC,CAAC,CAAC;AAC7B,wBAAgB,WAAW,CAAC,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,CAAC,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC"}
@@ -1,157 +0,0 @@
1
- import jsonPatch from "fast-json-patch";
2
- const { applyPatch, compare, deepClone } = jsonPatch;
3
- function isZodObject(schema) {
4
- return (typeof schema === "object" &&
5
- schema !== null &&
6
- "_zod" in schema &&
7
- schema._zod.def.type === "object");
8
- }
9
- function isZodUnionRoot(schema) {
10
- return schema._zod.def.type === "union";
11
- }
12
- function isZodDiscriminatedUnion(schema) {
13
- return "discriminator" in schema._zod.def;
14
- }
15
- function isZodUnionOfObjects(schema) {
16
- return schema.options.length > 0 && schema.options.every(isZodObject);
17
- }
18
- function getObjectShapeKeys(schema) {
19
- return Object.keys(schema.shape);
20
- }
21
- function getUnionObjectKeys(schema) {
22
- const keys = new Set();
23
- for (const option of schema.options) {
24
- if (!isZodObject(option)) {
25
- continue;
26
- }
27
- for (const key of Object.keys(option.shape)) {
28
- keys.add(key);
29
- }
30
- }
31
- return [...keys];
32
- }
33
- function buildSmartObjectClass(zodSchema) {
34
- const keys = isZodObject(zodSchema)
35
- ? getObjectShapeKeys(zodSchema)
36
- : getUnionObjectKeys(zodSchema);
37
- class SmartObjectClass {
38
- #data;
39
- #operations = [];
40
- static fromOperations(initial, operations) {
41
- const instance = new SmartObjectClass(initial);
42
- instance.#applyOperations(operations);
43
- return instance;
44
- }
45
- #applyOperations(operations) {
46
- if (operations.length === 0) {
47
- return;
48
- }
49
- applyPatch(this.#data, operations, false, true);
50
- this.#operations.push(...operations);
51
- }
52
- get operations() {
53
- return this.#operations;
54
- }
55
- clearOperations() {
56
- this.#operations.length = 0;
57
- }
58
- constructor(initial) {
59
- for (const key of keys) {
60
- const setMethodName = `set${key.charAt(0).toUpperCase()}${key.slice(1)}`;
61
- Object.defineProperty(this, key, {
62
- get: () => this.#data[key],
63
- enumerable: true,
64
- configurable: true,
65
- });
66
- Object.defineProperty(this, setMethodName, {
67
- value: isZodObject(zodSchema)
68
- ? this.#createObjectFieldSetter(zodSchema, key)
69
- : this.#createUnionFieldSetter(zodSchema, key),
70
- enumerable: false,
71
- configurable: true,
72
- writable: true,
73
- });
74
- }
75
- this.#data = zodSchema.parse(initial ?? {});
76
- }
77
- #createObjectFieldSetter(schema, key) {
78
- const fieldSchema = schema.shape[key];
79
- return (value) => {
80
- const parsed = fieldSchema.parse(value);
81
- const beforeData = deepClone(this.#data);
82
- const afterData = { ...deepClone(this.#data), [key]: parsed };
83
- const patch = compare(beforeData, afterData);
84
- if (patch.length === 0) {
85
- return;
86
- }
87
- applyPatch(this.#data, patch, false, true);
88
- this.#operations.push(...patch);
89
- };
90
- }
91
- #getActiveVariantViaDiscriminator(schema, data) {
92
- const discriminator = schema._zod.def.discriminator;
93
- const tag = data[discriminator];
94
- for (const option of schema.options) {
95
- if (!isZodObject(option)) {
96
- continue;
97
- }
98
- const tagSchema = option.shape[discriminator];
99
- if (tagSchema?.safeParse(tag).success) {
100
- return option;
101
- }
102
- }
103
- return undefined;
104
- }
105
- #getMatchingVariantObjects(schema) {
106
- if (isZodDiscriminatedUnion(schema)) {
107
- const activeVariant = this.#getActiveVariantViaDiscriminator(schema, this.#data);
108
- return activeVariant ? [activeVariant] : [];
109
- }
110
- return schema.options
111
- .filter(isZodObject)
112
- .filter((option) => option.safeParse(this.#data).success);
113
- }
114
- #assertKeyAllowedOnMatchingVariants(matchingVariants, key) {
115
- if (matchingVariants.length === 0) {
116
- throw new Error("Cannot set field on invalid union state");
117
- }
118
- if (matchingVariants.length === 1) {
119
- if (!(key in matchingVariants[0].shape)) {
120
- throw new Error(`Cannot set "${key}" on the active union variant`);
121
- }
122
- return;
123
- }
124
- if (!matchingVariants.some((variant) => key in variant.shape)) {
125
- throw new Error(`Cannot set "${key}" on the active union variant`);
126
- }
127
- }
128
- #createUnionFieldSetter(schema, key) {
129
- return (value) => {
130
- const matchingVariants = this.#getMatchingVariantObjects(schema);
131
- this.#assertKeyAllowedOnMatchingVariants(matchingVariants, key);
132
- const beforeData = deepClone(this.#data);
133
- const candidate = { ...deepClone(this.#data), [key]: value };
134
- const parsed = schema.parse(candidate);
135
- const patch = compare(beforeData, parsed);
136
- if (patch.length === 0) {
137
- return;
138
- }
139
- this.#data = parsed;
140
- this.#operations.push(...patch);
141
- };
142
- }
143
- }
144
- return SmartObjectClass;
145
- }
146
- export function SmartObject(zodSchema) {
147
- if (isZodObject(zodSchema)) {
148
- return buildSmartObjectClass(zodSchema);
149
- }
150
- if (isZodUnionRoot(zodSchema)) {
151
- if (!isZodUnionOfObjects(zodSchema)) {
152
- throw new TypeError("SmartObject union root requires all options to be z.object(...)");
153
- }
154
- return buildSmartObjectClass(zodSchema);
155
- }
156
- throw new TypeError("SmartObject requires a z.object(...), z.union([...]), or z.discriminatedUnion(...) schema");
157
- }