@gialicus/smart-object 1.0.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/CHANGELOG.md ADDED
@@ -0,0 +1,18 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.0.0] - 2026-06-27
9
+
10
+ ### Added
11
+
12
+ - `SmartObject(schema)` factory: typed getters and `set*` methods generated from a Zod object schema
13
+ - RFC 6902 operation log (`operations`) for every validated change
14
+ - `clearOperations()` to reset the audit trail without rolling back state
15
+ - `fromOperations(initial, operations)` static method for deterministic replay
16
+ - Exported types: `Operation`, `SetMethods`, `OperationsAccessor`, `SmartObjectConstructor`, `SmartObjectInstance`
17
+
18
+ [1.0.0]: https://github.com/gialicus/smart-object/releases/tag/v1.0.0
package/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2026, Gia Licoletta
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,127 @@
1
+ # @gialicus/smart-object
2
+
3
+ Typed TypeScript objects backed by Zod schemas, with an RFC 6902 operation log for every validated change. Use them when you need mutable, type-safe state plus a portable delta trail for audit, sync, or replay — without bolting on a separate change-tracking layer.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @gialicus/smart-object zod
9
+ ```
10
+
11
+ Dependencies: [Zod](https://zod.dev) (peer dependency — schema validation) and [fast-json-patch](https://github.com/Starcounter-Jack/JSON-Patch) (RFC 6902 patch application, bundled).
12
+
13
+ ## Usage
14
+
15
+ ```typescript
16
+ import z from "zod";
17
+ import { SmartObject } from "@gialicus/smart-object";
18
+
19
+ const Person = SmartObject(z.object({
20
+ name: z.string(),
21
+ age: z.number(),
22
+ }));
23
+
24
+ const person = new Person({ name: "Mario", age: 30 });
25
+
26
+ // Reads expose validated state without side effects
27
+ console.log(person.name); // "Mario"
28
+
29
+ // Writes validate first, then append patches to person.operations
30
+ person.setName("Luigi");
31
+ person.setAge(31);
32
+
33
+ console.log(person.operations);
34
+ // [
35
+ // { op: "replace", path: "/name", value: "Luigi" },
36
+ // { op: "replace", path: "/age", value: 31 },
37
+ // ]
38
+
39
+ person.setName("Luigi"); // Unchanged value — no operation added (keeps sync payloads minimal)
40
+
41
+ person.clearOperations(); // Drops the audit trail after persist/sync; state is unchanged
42
+
43
+ // Initial construction is the replay baseline — it never emits operations
44
+ console.log(new Person({ name: "Mario", age: 30 }).operations); // []
45
+
46
+ // Reconstruct from baseline + accumulated deltas
47
+ const initial = { name: "Mario", age: 30 };
48
+ const person2 = Person.fromOperations(initial, [...person.operations]);
49
+ ```
50
+
51
+ ## API
52
+
53
+ ### `SmartObject(schema)`
54
+
55
+ Factory that accepts a `z.object(...)` and returns an instantiable class.
56
+
57
+ | Parameter | Type | Description |
58
+ |-----------|------|-------------|
59
+ | `schema` | `z.ZodObject` | Zod schema defining the object shape |
60
+
61
+ **Members generated for each schema field `foo`:**
62
+
63
+ | Member | Type | Description |
64
+ |--------|------|-------------|
65
+ | `foo` | getter | Exposes the current validated field value |
66
+ | `setFoo(value)` | `(value: T) => void` | Validates, updates state, and records patches only when the value actually changes |
67
+
68
+ **Instance members:**
69
+
70
+ | Member | Type | Description |
71
+ |--------|------|-------------|
72
+ | `operations` | `readonly Operation[]` | Chronological RFC 6902 patch log |
73
+ | `clearOperations()` | `() => void` | Clears the patch log without rolling back state |
74
+
75
+ `set*` method names follow camelCase with the field name capitalized (`name` → `setName`, `address` → `setAddress`).
76
+
77
+ **Static members:**
78
+
79
+ | Member | Type | Description |
80
+ |--------|------|-------------|
81
+ | `fromOperations(initial, operations)` | `(initial, Operation[]) => Instance` | Builds an instance from a baseline, replays operations, and copies them into the accumulator |
82
+
83
+ ### `Operation`
84
+
85
+ RFC 6902 operation emitted by [fast-json-patch](https://github.com/Starcounter-Jack/JSON-Patch) when a field actually changes. Examples:
86
+
87
+ ```typescript
88
+ { op: "replace", path: "/name", value: "Luigi" }
89
+ { op: "add", path: "/age", value: 30 }
90
+ ```
91
+
92
+ ### Exported types
93
+
94
+ - `Operation` — JSON Patch operation (re-export from `fast-json-patch`)
95
+ - `SetMethods<T>` — mapped type of inferred `set*` methods for shape `T`
96
+ - `OperationsAccessor` — `operations` and `clearOperations()`
97
+ - `SmartObjectConstructor<T>` — constructor type including `fromOperations`
98
+
99
+ ## Design rationale
100
+
101
+ 1. **Construction** — `new Person(initial)` validates and seeds internal state without emitting operations, because that snapshot is the baseline every later patch is measured against.
102
+ 2. **Validation** — Each write is validated against the schema so the operation log only records structurally valid changes.
103
+ 3. **No-op writes** — Identical values are skipped to keep the patch log minimal and suitable for network sync.
104
+ 4. **Patch-based updates** — Changes are expressed as RFC 6902 operations so deltas are standard, composable, and replayable.
105
+ 5. **Operation accumulation** — Patches from `compare` are appended in order, preserving causality for audit and replay.
106
+ 6. **Replay** — `fromOperations(initial, operations)` requires the same baseline used when the operations were produced, enabling deterministic reconstruction on another client or after persistence.
107
+
108
+ - `SmartObjectInstance<T>` — full instance type (getters + set* + operations)
109
+
110
+ ## Full example
111
+
112
+ See [`examples/person.ts`](examples/person.ts) for a demo with primitives, nested objects, and arrays.
113
+
114
+ ## Project structure
115
+
116
+ ```
117
+ smart-object/
118
+ ├── src/
119
+ │ ├── index.ts # Public API barrel export
120
+ │ ├── smart-object.ts # SmartObject factory
121
+ │ └── types.ts # Operation and inferred types
122
+ ├── examples/
123
+ │ └── person.ts # Usage demo
124
+ ├── tests/
125
+ │ └── smart-object.test.ts
126
+ └── dist/ # Build output (generated)
127
+ ```
@@ -0,0 +1,3 @@
1
+ export { SmartObject } from "./smart-object.js";
2
+ export type { AllKeys, Operation, OperationsAccessor, SetMethods, SetMethodsUnion, SmartObjectConstructor, SmartObjectInstance, SmartObjectSchema, UnionDataShape, } from "./types.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EACV,OAAO,EACP,SAAS,EACT,kBAAkB,EAClB,UAAU,EACV,eAAe,EACf,sBAAsB,EACtB,mBAAmB,EACnB,iBAAiB,EACjB,cAAc,GACf,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export { SmartObject } from "./smart-object.js";
@@ -0,0 +1,36 @@
1
+ import type { z } from "zod";
2
+ import type { SmartObjectConstructor } from "./types.js";
3
+ /**
4
+ * Builds a typed SmartObject class from a Zod schema.
5
+ *
6
+ * The goal is to offer mutable, schema-validated objects that also produce an
7
+ * RFC 6902 operation log — useful for audit trails, client/server sync, and
8
+ * event replay without a separate change-tracking layer.
9
+ *
10
+ * Zod is the single source of truth: the same schema drives runtime validation,
11
+ * TypeScript inference, and the dynamically generated read/write API.
12
+ *
13
+ * Initial construction does not emit operations because that state is the baseline
14
+ * every subsequent patch is measured against.
15
+ *
16
+ * @typeParam T - Zod object or union-of-objects schema that defines the instance shape
17
+ * @param zodSchema - A `z.object({ ... })`, `z.union([...])`, or `z.discriminatedUnion(...)` schema
18
+ * @returns An instantiable class with types inferred from the schema
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * const Person = SmartObject(z.object({
23
+ * name: z.string(),
24
+ * age: z.number(),
25
+ * }));
26
+ *
27
+ * const person = new Person({ name: "Mario", age: 30 });
28
+ * person.setName("Luigi");
29
+ * // Only actual changes become operations — suitable for sync payloads
30
+ * console.log(person.operations); // [{ op: "replace", path: "/name", value: "Luigi" }]
31
+ * ```
32
+ */
33
+ export declare function SmartObject<T extends z.ZodObject>(zodSchema: T): SmartObjectConstructor<T>;
34
+ export declare function SmartObject<T extends z.ZodDiscriminatedUnion>(zodSchema: T): SmartObjectConstructor<T>;
35
+ export declare function SmartObject<T extends z.ZodUnion>(zodSchema: T): SmartObjectConstructor<T>;
36
+ //# sourceMappingURL=smart-object.d.ts.map
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,157 @@
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
+ }
@@ -0,0 +1,63 @@
1
+ import type { Operation } from "fast-json-patch";
2
+ import type { z } from "zod";
3
+ export type { Operation };
4
+ /**
5
+ * Schemas accepted by SmartObject: plain objects or unions of objects at root.
6
+ */
7
+ export type SmartObjectSchema = z.ZodObject | z.ZodDiscriminatedUnion | z.ZodUnion;
8
+ /**
9
+ * Compile-time map of `set*` methods for each schema key.
10
+ *
11
+ * Setters are generated at runtime, so mapped types preserve type safety
12
+ * even though the class body is built dynamically from the Zod shape.
13
+ */
14
+ export type SetMethods<T> = {
15
+ [K in keyof T as `set${Capitalize<string & K>}`]: (value: T[K]) => void;
16
+ };
17
+ /**
18
+ * All keys across union members — `keyof` on a union only yields common keys.
19
+ */
20
+ export type AllKeys<T> = T extends unknown ? keyof T : never;
21
+ /**
22
+ * `set*` methods for union root schemas.
23
+ *
24
+ * Each setter accepts the union of value types for that key across variants.
25
+ */
26
+ export type SetMethodsUnion<T> = {
27
+ [K in AllKeys<T> as `set${Capitalize<string & K>}`]: (value: T extends unknown ? (K extends keyof T ? T[K] : never) : never) => void;
28
+ };
29
+ /**
30
+ * Read/write surface and audit trail are separate concerns in the public API.
31
+ *
32
+ * Grouping operations here keeps mutation methods focused on state while
33
+ * consumers can still inspect or reset the patch history explicitly.
34
+ */
35
+ export type OperationsAccessor = {
36
+ /** Chronological RFC 6902 log — order matters for replay and sync */
37
+ readonly operations: readonly Operation[];
38
+ /** Drops accumulated patches after persist/sync without rolling back state */
39
+ clearOperations(): void;
40
+ };
41
+ /**
42
+ * Flattened data shape for union roots — exposes all variant keys on one surface.
43
+ */
44
+ export type UnionDataShape<U> = {
45
+ [K in AllKeys<U>]: U extends unknown ? (K extends keyof U ? U[K] : never) : never;
46
+ };
47
+ /**
48
+ * Full instance contract: validated data shape, typed mutators, and patch log.
49
+ *
50
+ * Intersection types merge these concerns into one consumable surface for callers.
51
+ */
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;
53
+ /**
54
+ * Constructor type for a SmartObject class, including replay as a first-class capability.
55
+ *
56
+ * `fromOperations` lives on the constructor type because replay is a core use case,
57
+ * not an optional utility added after the fact.
58
+ */
59
+ export type SmartObjectConstructor<T extends SmartObjectSchema> = {
60
+ new (initial?: z.input<T>): SmartObjectInstance<T>;
61
+ fromOperations(initial: z.input<T> | undefined, operations: Operation[]): SmartObjectInstance<T>;
62
+ };
63
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +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"}
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json ADDED
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "@gialicus/smart-object",
3
+ "version": "1.0.0",
4
+ "description": "Oggetti TypeScript generati da schemi Zod con getter, set* tipizzati e operazioni JSON Patch",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "CHANGELOG.md"
17
+ ],
18
+ "scripts": {
19
+ "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
20
+ "build": "npm run clean && tsc -p tsconfig.build.json",
21
+ "typecheck": "tsc --noEmit",
22
+ "check": "biome check .",
23
+ "check:fix": "biome check --write .",
24
+ "format": "biome format --write .",
25
+ "dev": "npm run build && tsx examples/person.ts",
26
+ "test": "vitest run",
27
+ "test:watch": "vitest",
28
+ "prepublishOnly": "npm run build && npm test",
29
+ "prepare": "node -e \"process.exit(require('fs').existsSync('.git')?0:1)\" && husky || true"
30
+ },
31
+ "peerDependencies": {
32
+ "zod": "^4.0.0"
33
+ },
34
+ "dependencies": {
35
+ "fast-json-patch": "^3.1.1"
36
+ },
37
+ "devDependencies": {
38
+ "@biomejs/biome": "^2.5.1",
39
+ "@commitlint/cli": "^21.1.0",
40
+ "@commitlint/config-conventional": "^21.1.0",
41
+ "husky": "^9.1.7",
42
+ "tsx": "^4.20.3",
43
+ "typescript": "^5.9.3",
44
+ "vitest": "^3.2.4",
45
+ "zod": "^4.4.3"
46
+ },
47
+ "keywords": [
48
+ "zod",
49
+ "json-patch",
50
+ "typescript",
51
+ "audit",
52
+ "sync",
53
+ "rfc6902",
54
+ "smart-object",
55
+ "change-tracking"
56
+ ],
57
+ "author": "Gia Licoletta",
58
+ "license": "ISC",
59
+ "repository": {
60
+ "type": "git",
61
+ "url": "git+https://github.com/gialicus/smart-object.git"
62
+ },
63
+ "homepage": "https://github.com/gialicus/smart-object#readme",
64
+ "bugs": {
65
+ "url": "https://github.com/gialicus/smart-object/issues"
66
+ },
67
+ "publishConfig": {
68
+ "access": "public"
69
+ },
70
+ "sideEffects": false,
71
+ "engines": {
72
+ "node": ">=18"
73
+ }
74
+ }