progressive-zod 1.4.2 → 1.4.4
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/cli/index.js +38 -19
- package/dist/client.cjs +63 -40
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +5 -4
- package/dist/client.d.ts +5 -4
- package/dist/client.js +63 -40
- package/dist/client.js.map +1 -1
- package/dist/index.cjs +63 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +63 -40
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/client.js
CHANGED
|
@@ -60,6 +60,18 @@ var MemoryStorage = class {
|
|
|
60
60
|
};
|
|
61
61
|
|
|
62
62
|
// src/storage/resolve.ts
|
|
63
|
+
var GLOBAL_KEY = /* @__PURE__ */ Symbol.for("progressive-zod");
|
|
64
|
+
function getGlobal() {
|
|
65
|
+
const g = globalThis;
|
|
66
|
+
if (!g[GLOBAL_KEY]) {
|
|
67
|
+
g[GLOBAL_KEY] = {
|
|
68
|
+
config: {},
|
|
69
|
+
storage: null,
|
|
70
|
+
factory: async (config) => new MemoryStorage(config)
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return g[GLOBAL_KEY];
|
|
74
|
+
}
|
|
63
75
|
var progressiveConfigSchema = z.object({
|
|
64
76
|
storage: z.enum(["memory", "redis", "amplitude"]).optional(),
|
|
65
77
|
redisUrl: z.string().optional(),
|
|
@@ -85,19 +97,17 @@ var progressiveConfigSchema = z.object({
|
|
|
85
97
|
});
|
|
86
98
|
}
|
|
87
99
|
});
|
|
88
|
-
var currentConfig = {};
|
|
89
|
-
var currentStorage = null;
|
|
90
|
-
var storageFactory = async (config) => new MemoryStorage(config);
|
|
91
100
|
function _setStorageFactory(factory) {
|
|
92
|
-
|
|
101
|
+
getGlobal().factory = factory;
|
|
93
102
|
}
|
|
94
103
|
function configure(config) {
|
|
95
|
-
const
|
|
104
|
+
const state = getGlobal();
|
|
105
|
+
const merged = { ...state.config, ...config };
|
|
96
106
|
progressiveConfigSchema.parse(merged);
|
|
97
|
-
|
|
98
|
-
if (
|
|
99
|
-
|
|
100
|
-
|
|
107
|
+
state.config = merged;
|
|
108
|
+
if (state.storage) {
|
|
109
|
+
state.storage.disconnect();
|
|
110
|
+
state.storage = null;
|
|
101
111
|
}
|
|
102
112
|
}
|
|
103
113
|
function env(key) {
|
|
@@ -107,20 +117,22 @@ function env(key) {
|
|
|
107
117
|
return void 0;
|
|
108
118
|
}
|
|
109
119
|
function getConfig() {
|
|
120
|
+
const { config } = getGlobal();
|
|
110
121
|
return {
|
|
111
|
-
storage:
|
|
112
|
-
redisUrl:
|
|
113
|
-
keyPrefix:
|
|
114
|
-
maxViolations:
|
|
115
|
-
maxSamples:
|
|
116
|
-
dataDir:
|
|
122
|
+
storage: config.storage ?? env("PROGRESSIVE_ZOD_STORAGE") ?? "memory",
|
|
123
|
+
redisUrl: config.redisUrl ?? env("PROGRESSIVE_ZOD_REDIS_URL"),
|
|
124
|
+
keyPrefix: config.keyPrefix ?? env("PROGRESSIVE_ZOD_KEY_PREFIX") ?? "pzod:",
|
|
125
|
+
maxViolations: config.maxViolations ?? parseInt(env("PROGRESSIVE_ZOD_MAX_VIOLATIONS") ?? "1000", 10),
|
|
126
|
+
maxSamples: config.maxSamples ?? parseInt(env("PROGRESSIVE_ZOD_MAX_SAMPLES") ?? "1000", 10),
|
|
127
|
+
dataDir: config.dataDir ?? env("PROGRESSIVE_ZOD_DATA_DIR")
|
|
117
128
|
};
|
|
118
129
|
}
|
|
119
130
|
async function getStorage() {
|
|
120
|
-
|
|
131
|
+
const state = getGlobal();
|
|
132
|
+
if (state.storage) return state.storage;
|
|
121
133
|
const config = getConfig();
|
|
122
|
-
|
|
123
|
-
return
|
|
134
|
+
state.storage = await state.factory(config, state.config);
|
|
135
|
+
return state.storage;
|
|
124
136
|
}
|
|
125
137
|
|
|
126
138
|
// src/batch-processor.ts
|
|
@@ -144,7 +156,7 @@ var BatchProcessor = class {
|
|
|
144
156
|
* Enqueue an observation. This is synchronous and fast — no I/O happens here.
|
|
145
157
|
* If the queue is full, the oldest observation is dropped (bounded memory).
|
|
146
158
|
*/
|
|
147
|
-
enqueue(name, input, schema) {
|
|
159
|
+
enqueue(name, input, schema, opts) {
|
|
148
160
|
this.ensureTimer();
|
|
149
161
|
let serialized;
|
|
150
162
|
try {
|
|
@@ -156,7 +168,7 @@ var BatchProcessor = class {
|
|
|
156
168
|
this.queue.shift();
|
|
157
169
|
this.droppedCount++;
|
|
158
170
|
}
|
|
159
|
-
this.queue.push({ name, serialized, schema });
|
|
171
|
+
this.queue.push({ name, serialized, schema, opts });
|
|
160
172
|
if (this.queue.length >= this.maxExportBatchSize) {
|
|
161
173
|
this.flushAsync();
|
|
162
174
|
}
|
|
@@ -235,52 +247,56 @@ var BatchProcessor = class {
|
|
|
235
247
|
if (obs.schema) {
|
|
236
248
|
const result = obs.schema.safeParse(JSON.parse(obs.serialized));
|
|
237
249
|
if (result.success) {
|
|
238
|
-
await storage.incrConform(obs.name, obs.serialized);
|
|
250
|
+
await storage.incrConform(obs.name, obs.serialized, obs.opts);
|
|
239
251
|
} else {
|
|
240
252
|
const errors = result.error.issues.map((i) => {
|
|
241
253
|
const path = i.path.length > 0 ? i.path.join(".") : "(root)";
|
|
242
254
|
return `${path}: ${i.message}`;
|
|
243
255
|
}).join("; ");
|
|
244
|
-
await storage.incrViolate(obs.name, obs.serialized, errors);
|
|
256
|
+
await storage.incrViolate(obs.name, obs.serialized, errors, obs.opts);
|
|
245
257
|
await storage.addViolation(obs.name, obs.serialized);
|
|
246
258
|
}
|
|
247
259
|
} else {
|
|
248
|
-
await storage.incrViolate(obs.name, obs.serialized, "no schema defined");
|
|
260
|
+
await storage.incrViolate(obs.name, obs.serialized, "no schema defined", obs.opts);
|
|
249
261
|
await storage.addViolation(obs.name, obs.serialized);
|
|
250
262
|
}
|
|
251
263
|
}
|
|
252
264
|
};
|
|
253
265
|
|
|
254
266
|
// src/progressive.ts
|
|
255
|
-
var
|
|
267
|
+
var PROCESSOR_KEY = /* @__PURE__ */ Symbol.for("progressive-zod:processor");
|
|
256
268
|
function getProcessor() {
|
|
257
|
-
|
|
258
|
-
|
|
269
|
+
const g = globalThis;
|
|
270
|
+
if (!g[PROCESSOR_KEY]) {
|
|
271
|
+
g[PROCESSOR_KEY] = new BatchProcessor();
|
|
259
272
|
}
|
|
260
|
-
return
|
|
273
|
+
return g[PROCESSOR_KEY];
|
|
261
274
|
}
|
|
262
275
|
function configureBatch(config) {
|
|
263
|
-
|
|
264
|
-
|
|
276
|
+
const g = globalThis;
|
|
277
|
+
if (g[PROCESSOR_KEY]) {
|
|
278
|
+
g[PROCESSOR_KEY].forceFlush().catch(() => {
|
|
265
279
|
});
|
|
266
280
|
}
|
|
267
|
-
|
|
281
|
+
g[PROCESSOR_KEY] = new BatchProcessor(config);
|
|
268
282
|
}
|
|
269
283
|
async function forceFlush() {
|
|
270
|
-
|
|
271
|
-
|
|
284
|
+
const g = globalThis;
|
|
285
|
+
if (g[PROCESSOR_KEY]) {
|
|
286
|
+
await g[PROCESSOR_KEY].forceFlush();
|
|
272
287
|
}
|
|
273
288
|
}
|
|
274
289
|
async function shutdown() {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
290
|
+
const g = globalThis;
|
|
291
|
+
if (g[PROCESSOR_KEY]) {
|
|
292
|
+
await g[PROCESSOR_KEY].shutdown();
|
|
293
|
+
g[PROCESSOR_KEY] = void 0;
|
|
278
294
|
}
|
|
279
295
|
}
|
|
280
|
-
function progressive(name, schema) {
|
|
296
|
+
function progressive(name, schema, opts) {
|
|
281
297
|
return {
|
|
282
298
|
parse(input) {
|
|
283
|
-
getProcessor().enqueue(name, input, schema);
|
|
299
|
+
getProcessor().enqueue(name, input, schema, opts);
|
|
284
300
|
return input;
|
|
285
301
|
}
|
|
286
302
|
};
|
|
@@ -307,10 +323,14 @@ var AmplitudeStorage = class {
|
|
|
307
323
|
}
|
|
308
324
|
addViolation(_name, _violation) {
|
|
309
325
|
}
|
|
310
|
-
incrConform(name, _sample) {
|
|
311
|
-
|
|
326
|
+
incrConform(name, _sample, opts) {
|
|
327
|
+
const properties = { type_name: name, result: "conforms" };
|
|
328
|
+
if (opts && Object.keys(opts).length > 0) {
|
|
329
|
+
properties.options = Object.entries(opts).map(([k, v]) => `${k}=${v}`).join("; ");
|
|
330
|
+
}
|
|
331
|
+
this.client.track(this.eventName, properties);
|
|
312
332
|
}
|
|
313
|
-
incrViolate(name, sample, errors) {
|
|
333
|
+
incrViolate(name, sample, errors, opts) {
|
|
314
334
|
const properties = {
|
|
315
335
|
type_name: name,
|
|
316
336
|
result: "violation"
|
|
@@ -331,6 +351,9 @@ var AmplitudeStorage = class {
|
|
|
331
351
|
if (errors) {
|
|
332
352
|
properties.validation_errors = errors.slice(0, 1024);
|
|
333
353
|
}
|
|
354
|
+
if (opts && Object.keys(opts).length > 0) {
|
|
355
|
+
properties.options = Object.entries(opts).map(([k, v]) => `${k}=${v}`).join("; ");
|
|
356
|
+
}
|
|
334
357
|
this.client.track(this.eventName, properties);
|
|
335
358
|
}
|
|
336
359
|
// --- Read methods: no-ops (use Amplitude dashboard) ---
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/storage/resolve.ts","../src/storage/memory.ts","../src/batch-processor.ts","../src/progressive.ts","../src/storage/amplitude.ts","../src/storage/client.ts","../src/infer-schema.ts","../src/schema-to-code.ts"],"sourcesContent":["import { z } from \"zod\";\nimport type { ProgressiveConfig, StorageBackend } from \"../types.js\";\nimport { MemoryStorage } from \"./memory.js\";\n\nconst progressiveConfigSchema = z\n .object({\n storage: z.enum([\"memory\", \"redis\", \"amplitude\"]).optional(),\n redisUrl: z.string().optional(),\n keyPrefix: z.string().optional(),\n maxViolations: z.number().optional(),\n maxSamples: z.number().optional(),\n dataDir: z.string().optional(),\n amplitudeClient: z.any().optional(),\n amplitudeEventName: z.string().optional(),\n })\n .superRefine((data, ctx) => {\n if (data.amplitudeEventName && data.storage !== \"amplitude\") {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message:\n 'amplitudeEventName can only be used when storage is \"amplitude\"',\n path: [\"amplitudeEventName\"],\n });\n }\n if (data.amplitudeClient && data.storage !== \"amplitude\") {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message:\n 'amplitudeClient can only be used when storage is \"amplitude\"',\n path: [\"amplitudeClient\"],\n });\n }\n });\n\nlet currentConfig: ProgressiveConfig = {};\nlet currentStorage: StorageBackend | null = null;\n\nexport type StorageFactory = (\n resolvedConfig: ProgressiveConfig,\n userConfig: ProgressiveConfig,\n) => Promise<StorageBackend>;\n\n// Default factory: memory-only (safe for any environment)\nlet storageFactory: StorageFactory = async (config) => new MemoryStorage(config);\n\n/**\n * Register a storage factory. Called by entry-point modules\n * (storage/index.ts for server, storage/client.ts for client)\n * to control which backends are available.\n */\nexport function _setStorageFactory(factory: StorageFactory): void {\n storageFactory = factory;\n}\n\nexport function configure(config: ProgressiveConfig): void {\n const merged = { ...currentConfig, ...config };\n progressiveConfigSchema.parse(merged);\n currentConfig = merged;\n // Force re-creation on next access\n if (currentStorage) {\n currentStorage.disconnect();\n currentStorage = null;\n }\n}\n\nfunction env(key: string): string | undefined {\n if (typeof process !== \"undefined\" && process.env) {\n return process.env[key];\n }\n return undefined;\n}\n\nexport function getConfig(): ProgressiveConfig {\n return {\n storage: currentConfig.storage ?? (env(\"PROGRESSIVE_ZOD_STORAGE\") as any) ?? \"memory\",\n redisUrl: currentConfig.redisUrl ?? env(\"PROGRESSIVE_ZOD_REDIS_URL\"),\n keyPrefix: currentConfig.keyPrefix ?? env(\"PROGRESSIVE_ZOD_KEY_PREFIX\") ?? \"pzod:\",\n maxViolations: currentConfig.maxViolations ?? parseInt(env(\"PROGRESSIVE_ZOD_MAX_VIOLATIONS\") ?? \"1000\", 10),\n maxSamples: currentConfig.maxSamples ?? parseInt(env(\"PROGRESSIVE_ZOD_MAX_SAMPLES\") ?? \"1000\", 10),\n dataDir: currentConfig.dataDir ?? env(\"PROGRESSIVE_ZOD_DATA_DIR\"),\n };\n}\n\nexport async function getStorage(): Promise<StorageBackend> {\n if (currentStorage) return currentStorage;\n\n const config = getConfig();\n currentStorage = await storageFactory(config, currentConfig);\n return currentStorage;\n}\n\nexport async function disconnectStorage(): Promise<void> {\n if (currentStorage) {\n await currentStorage.disconnect();\n currentStorage = null;\n }\n}\n","import type { StorageBackend, ProgressiveConfig } from \"../types.js\";\n\ninterface TypeData {\n samples: string[];\n violations: string[];\n conform: number;\n violate: number;\n}\n\n/**\n * In-memory storage backend.\n * No Node.js built-in dependencies — safe for browser bundles.\n */\nexport class MemoryStorage implements StorageBackend {\n protected names = new Set<string>();\n protected data = new Map<string, TypeData>();\n protected maxSamples: number;\n protected maxViolations: number;\n\n constructor(config: ProgressiveConfig = {}) {\n this.maxSamples = config.maxSamples ?? 1000;\n this.maxViolations = config.maxViolations ?? 1000;\n }\n\n protected getOrCreate(name: string): TypeData {\n let entry = this.data.get(name);\n if (!entry) {\n entry = { samples: [], violations: [], conform: 0, violate: 0 };\n this.data.set(name, entry);\n }\n return entry;\n }\n\n addName(name: string): void {\n this.names.add(name);\n }\n\n addSample(name: string, sample: string): void {\n const entry = this.getOrCreate(name);\n entry.samples.unshift(sample);\n if (entry.samples.length > this.maxSamples) {\n entry.samples.length = this.maxSamples;\n }\n }\n\n addViolation(name: string, violation: string): void {\n const entry = this.getOrCreate(name);\n entry.violations.unshift(violation);\n if (entry.violations.length > this.maxViolations) {\n entry.violations.length = this.maxViolations;\n }\n }\n\n incrConform(name: string): void {\n this.getOrCreate(name).conform++;\n }\n\n incrViolate(name: string): void {\n this.getOrCreate(name).violate++;\n }\n\n getNames(): string[] {\n return [...this.names].sort();\n }\n\n getSamples(name: string): string[] {\n return this.getOrCreate(name).samples;\n }\n\n getViolations(name: string, limit: number): string[] {\n return this.getOrCreate(name).violations.slice(0, limit);\n }\n\n async getStats(name: string): Promise<{ conform: number; violate: number }> {\n const entry = this.getOrCreate(name);\n return { conform: entry.conform, violate: entry.violate };\n }\n\n disconnect(): void {\n // No-op for pure in-memory storage\n }\n}\n","import type { z } from \"zod\";\nimport type { StorageBackend } from \"./types.js\";\nimport { getStorage } from \"./storage/resolve.js\";\n\nexport interface BatchConfig {\n /** Max observations to buffer before forcing a flush. Default: 512 */\n maxQueueSize?: number;\n /** Flush interval in milliseconds. Default: 5000 */\n flushIntervalMs?: number;\n /** Max observations to export per flush. Default: 512 */\n maxExportBatchSize?: number;\n}\n\ninterface Observation {\n name: string;\n serialized: string;\n schema?: z.ZodTypeAny;\n}\n\nconst DEFAULT_MAX_QUEUE_SIZE = 2048;\nconst DEFAULT_FLUSH_INTERVAL_MS = 5000;\nconst DEFAULT_MAX_EXPORT_BATCH_SIZE = 512;\n\nexport class BatchProcessor {\n private queue: Observation[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private flushing = false;\n private droppedCount = 0;\n\n private readonly maxQueueSize: number;\n private readonly flushIntervalMs: number;\n private readonly maxExportBatchSize: number;\n\n constructor(config: BatchConfig = {}) {\n this.maxQueueSize = config.maxQueueSize ?? DEFAULT_MAX_QUEUE_SIZE;\n this.flushIntervalMs = config.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS;\n this.maxExportBatchSize = config.maxExportBatchSize ?? DEFAULT_MAX_EXPORT_BATCH_SIZE;\n }\n\n /**\n * Enqueue an observation. This is synchronous and fast — no I/O happens here.\n * If the queue is full, the oldest observation is dropped (bounded memory).\n */\n enqueue(name: string, input: unknown, schema?: z.ZodTypeAny): void {\n this.ensureTimer();\n\n let serialized: string;\n try {\n serialized = JSON.stringify(input);\n } catch {\n // Non-serializable input — skip silently\n return;\n }\n\n if (this.queue.length >= this.maxQueueSize) {\n // Drop oldest to stay within bounds\n this.queue.shift();\n this.droppedCount++;\n }\n\n this.queue.push({ name, serialized, schema });\n\n // Flush immediately if we've hit the export batch size\n if (this.queue.length >= this.maxExportBatchSize) {\n this.flushAsync();\n }\n }\n\n /**\n * Force flush all pending observations. Call during graceful shutdown.\n */\n async forceFlush(): Promise<void> {\n this.clearTimer();\n await this.flush();\n }\n\n /**\n * Shut down the processor: flush remaining data and stop the timer.\n */\n async shutdown(): Promise<void> {\n await this.forceFlush();\n }\n\n /** Number of observations currently in the queue */\n get pendingCount(): number {\n return this.queue.length;\n }\n\n /** Number of observations dropped due to queue overflow */\n get dropped(): number {\n return this.droppedCount;\n }\n\n private ensureTimer(): void {\n if (this.timer) return;\n this.timer = setInterval(() => {\n this.flushAsync();\n }, this.flushIntervalMs);\n // Don't keep the process alive just for telemetry\n if (this.timer && typeof this.timer === \"object\" && \"unref\" in this.timer) {\n this.timer.unref();\n }\n }\n\n private clearTimer(): void {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n }\n\n /** Non-blocking flush — errors are swallowed */\n private flushAsync(): void {\n this.flush().catch(() => {});\n }\n\n /** Drain the queue and send observations to storage in batch */\n private async flush(): Promise<void> {\n if (this.flushing || this.queue.length === 0) return;\n this.flushing = true;\n\n // Drain up to maxExportBatchSize\n const batch = this.queue.splice(0, this.maxExportBatchSize);\n\n try {\n const storage = await getStorage();\n await this.exportBatch(storage, batch);\n } catch {\n // Swallow errors — observability must never crash the app\n } finally {\n this.flushing = false;\n // If items accumulated during flush, schedule another\n if (this.queue.length >= this.maxExportBatchSize) {\n this.flushAsync();\n }\n }\n }\n\n private async exportBatch(\n storage: StorageBackend,\n batch: Observation[],\n ): Promise<void> {\n // Collect unique names first\n const names = new Set<string>();\n for (const obs of batch) {\n names.add(obs.name);\n }\n\n // Register all names\n await Promise.all([...names].map((n) => storage.addName(n)));\n\n // Process each observation\n // We batch the promises to avoid creating thousands of concurrent promises\n const promises: Promise<void>[] = [];\n\n for (const obs of batch) {\n promises.push(this.exportOne(storage, obs));\n }\n\n await Promise.all(promises);\n }\n\n private async exportOne(\n storage: StorageBackend,\n obs: Observation,\n ): Promise<void> {\n await storage.addSample(obs.name, obs.serialized);\n\n if (obs.schema) {\n const result = obs.schema.safeParse(JSON.parse(obs.serialized));\n if (result.success) {\n await storage.incrConform(obs.name, obs.serialized);\n } else {\n const errors = result.error.issues\n .map((i) => {\n const path = i.path.length > 0 ? i.path.join(\".\") : \"(root)\";\n return `${path}: ${i.message}`;\n })\n .join(\"; \");\n await storage.incrViolate(obs.name, obs.serialized, errors);\n await storage.addViolation(obs.name, obs.serialized);\n }\n } else {\n await storage.incrViolate(obs.name, obs.serialized, \"no schema defined\");\n await storage.addViolation(obs.name, obs.serialized);\n }\n }\n}\n","import type { z } from \"zod\";\nimport type { ProgressiveSchema } from \"./types.js\";\nimport { BatchProcessor } from \"./batch-processor.js\";\nimport type { BatchConfig } from \"./batch-processor.js\";\n\nlet processor: BatchProcessor | null = null;\n\nfunction getProcessor(): BatchProcessor {\n if (!processor) {\n processor = new BatchProcessor();\n }\n return processor;\n}\n\n/**\n * Configure the batch processor. Call before first `progressive()` use.\n * Follows the OpenTelemetry provider pattern:\n * - Observations are buffered in memory (synchronous, zero I/O on hot path)\n * - Flushed to storage in batches on a timer or when buffer is full\n * - Queue is bounded to prevent memory leaks\n * - Timer is unref'd so it won't keep the process alive\n */\nexport function configureBatch(config: BatchConfig): void {\n if (processor) {\n // Flush existing before reconfiguring\n processor.forceFlush().catch(() => {});\n }\n processor = new BatchProcessor(config);\n}\n\n/**\n * Force flush all pending observations. Call during graceful shutdown.\n *\n * @example\n * ```ts\n * process.on(\"SIGTERM\", async () => {\n * await forceFlush();\n * process.exit(0);\n * });\n * ```\n */\nexport async function forceFlush(): Promise<void> {\n if (processor) {\n await processor.forceFlush();\n }\n}\n\n/**\n * Shut down the batch processor and flush remaining data.\n */\nexport async function shutdown(): Promise<void> {\n if (processor) {\n await processor.shutdown();\n processor = null;\n }\n}\n\n/**\n * Create a progressive schema that tracks runtime data and optionally validates.\n *\n * - Never throws — always returns input unchanged\n * - Records samples for later schema inference\n * - If a schema is provided, tracks conformance vs violations\n * - Observations are batched and flushed asynchronously (OTel-style)\n * - Zero I/O on the hot path — enqueue is synchronous\n */\nexport function progressive(\n name: string,\n schema?: z.ZodTypeAny,\n): ProgressiveSchema {\n return {\n parse(input: unknown): unknown {\n // Synchronous enqueue — no I/O, no promises, no overhead\n getProcessor().enqueue(name, input, schema);\n return input;\n },\n };\n}\n","import type { ProgressiveConfig, StorageBackend } from \"../types.js\";\n\n/**\n * Minimal interface for an Amplitude client.\n * Compatible with @amplitude/analytics-node's `track()` signature.\n * Pass an instance initialized with your observability project's API key\n * (separate from your main product analytics project).\n */\nexport interface AmplitudeClient {\n track(\n eventName: string,\n eventProperties?: Record<string, unknown>,\n options?: { user_id?: string; device_id?: string },\n ): void;\n}\n\n/**\n * Amplitude storage backend for progressive-zod.\n *\n * Sends a single event per type check:\n *\n * this.eventName\n * - type_name: string — the boundary name passed to progressive()\n * - result: \"conforms\" | \"violation\"\n * - sample_type: string — JS typeof the observed value (violation only)\n * - field_count: number — number of top-level keys (violation only, objects)\n * - sample_preview: string — first 256 chars of JSON (violation only)\n * - validation_errors: string — human-readable Zod validation errors (violation only)\n *\n * Read methods (getNames, getSamples, etc.) are no-ops — use the\n * Amplitude dashboard to query your data.\n */\n/**\n * Convert a value into a flat \"key=value; ...\" string so Amplitude\n * treats it as an opaque string instead of exploding JSON keys into\n * separate event properties.\n */\nfunction flattenToString(value: unknown): string {\n if (value === null || value === undefined) return String(value);\n if (typeof value !== \"object\") return String(value);\n if (Array.isArray(value)) return value.map(String).join(\", \");\n const entries = Object.entries(value as Record<string, unknown>);\n return entries.map(([k, v]) => `${k}=${JSON.stringify(v)}`).join(\"; \");\n}\n\nexport class AmplitudeStorage implements StorageBackend {\n private readonly client: AmplitudeClient;\n private readonly eventName: string;\n\n constructor(\n client: AmplitudeClient,\n config: ProgressiveConfig,\n ) {\n this.client = client;\n this.eventName = config.amplitudeEventName ?? \"progressive-zod: results\";\n }\n\n addName(_name: string): void {\n // No-op: we only track type checks\n }\n\n addSample(_name: string, _sample: string): void {\n // No-op: we only track type checks\n }\n\n addViolation(_name: string, _violation: string): void {\n // No-op: violation data is included in the type_checked event via incrViolate\n }\n\n incrConform(name: string, _sample?: string): void {\n this.client.track(this.eventName, { type_name: name, result: \"conforms\" });\n }\n\n incrViolate(name: string, sample?: string, errors?: string): void {\n const properties: Record<string, unknown> = {\n type_name: name,\n result: \"violation\",\n };\n\n if (sample) {\n try {\n const parsed = JSON.parse(sample);\n properties.sample_type = typeof parsed;\n if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n properties.field_count = Object.keys(parsed).length;\n }\n // Flatten to key=value pairs so Amplitude doesn't explode JSON into N properties\n properties.sample_preview = flattenToString(parsed).slice(0, 256);\n } catch {\n properties.sample_type = \"unknown\";\n properties.sample_preview = sample.slice(0, 256);\n }\n }\n\n if (errors) {\n properties.validation_errors = errors.slice(0, 1024);\n }\n\n this.client.track(this.eventName, properties);\n }\n\n // --- Read methods: no-ops (use Amplitude dashboard) ---\n\n async getNames(): Promise<string[]> {\n return [];\n }\n\n async getSamples(_name: string): Promise<string[]> {\n return [];\n }\n\n async getViolations(_name: string, _limit: number): Promise<string[]> {\n return [];\n }\n\n async getStats(_name: string): Promise<{ conform: number; violate: number }> {\n return { conform: 0, violate: 0 };\n }\n\n disconnect(): void {\n // Amplitude SDK manages its own lifecycle — nothing to clean up\n }\n}\n","import { _setStorageFactory } from \"./resolve.js\";\nimport { MemoryStorage } from \"./memory.js\";\nimport { AmplitudeStorage } from \"./amplitude.js\";\n\n// Register client storage factory — no Redis (avoids bundling ioredis)\n_setStorageFactory(async (config, userConfig) => {\n if (config.storage === \"amplitude\") {\n if (!userConfig.amplitudeClient) {\n throw new Error(\n \"progressive-zod: storage is set to 'amplitude' but no amplitudeClient was provided. \" +\n \"Pass an Amplitude client instance via configure({ amplitudeClient }).\",\n );\n }\n return new AmplitudeStorage(userConfig.amplitudeClient, config);\n } else if (config.storage === \"redis\") {\n throw new Error(\n 'progressive-zod: Redis storage is not available in the client bundle. ' +\n 'Import from \"progressive-zod\" instead of \"progressive-zod/client\".',\n );\n }\n\n return new MemoryStorage(config);\n});\n\nexport { configure, getConfig, getStorage, disconnectStorage } from \"./resolve.js\";\n","import { z } from \"zod\";\n\n/**\n * Infer a Zod schema from an array of runtime samples.\n */\nexport function inferSchema(samples: unknown[]): z.ZodTypeAny {\n const objects = samples.filter(\n (s): s is Record<string, unknown> =>\n typeof s === \"object\" && s !== null && !Array.isArray(s),\n );\n\n if (objects.length === 0) {\n return inferPrimitiveUnion(samples);\n }\n\n // Group samples by their shape (set of keys)\n const groups = groupByShape(objects);\n\n if (groups.length === 1) {\n return buildObjectSchema(groups[0]);\n }\n\n // Try to find a discriminator field\n const discriminator = findDiscriminator(groups);\n if (discriminator) {\n return z.discriminatedUnion(\n discriminator,\n groups.map(\n (group) => buildObjectSchema(group) as z.ZodObject<any>,\n ) as any,\n );\n }\n\n return z.union(\n groups.map((group) => buildObjectSchema(group)) as any,\n );\n}\n\nfunction shapeKey(obj: Record<string, unknown>): string {\n return Object.keys(obj).sort().join(\",\");\n}\n\nfunction groupByShape(\n objects: Record<string, unknown>[],\n): Record<string, unknown>[][] {\n const map = new Map<string, Record<string, unknown>[]>();\n for (const obj of objects) {\n const key = shapeKey(obj);\n let group = map.get(key);\n if (!group) {\n group = [];\n map.set(key, group);\n }\n group.push(obj);\n }\n return [...map.values()];\n}\n\nfunction findDiscriminator(\n groups: Record<string, unknown>[][],\n): string | null {\n if (groups.length < 2) return null;\n\n // Get keys present in all groups\n const keySets = groups.map(\n (g) => new Set(Object.keys(g[0])),\n );\n const commonKeys = [...keySets[0]].filter((k) =>\n keySets.every((s) => s.has(k)),\n );\n\n for (const key of commonKeys) {\n // Check if this key has a single string literal value per group\n // and the values are distinct across groups\n const values = new Set<string>();\n let valid = true;\n\n for (const group of groups) {\n const groupValues = new Set(\n group.map((obj) => obj[key]).filter((v) => typeof v === \"string\"),\n );\n if (groupValues.size !== 1) {\n valid = false;\n break;\n }\n const val = [...groupValues][0] as string;\n if (values.has(val)) {\n valid = false;\n break;\n }\n values.add(val);\n }\n\n if (valid && values.size === groups.length) {\n return key;\n }\n }\n\n return null;\n}\n\nfunction buildObjectSchema(\n samples: Record<string, unknown>[],\n): z.ZodObject<any> {\n const keys = Object.keys(samples[0]);\n const shape: Record<string, z.ZodTypeAny> = {};\n\n for (const key of keys) {\n const values = samples.map((s) => s[key]);\n // If all values are the same string, use z.literal() (needed for discriminated unions)\n const unique = new Set(values);\n if (unique.size === 1 && typeof values[0] === \"string\") {\n shape[key] = z.literal(values[0] as string);\n } else {\n shape[key] = inferFieldType(values);\n }\n }\n\n return z.object(shape).strict();\n}\n\nfunction inferFieldType(values: unknown[]): z.ZodTypeAny {\n const types = new Set(values.map(classifyValue));\n\n if (types.size === 1) {\n const type = [...types][0];\n if (type === \"string\") return z.string();\n if (type === \"number\") return z.number();\n if (type === \"boolean\") return z.boolean();\n if (type === \"null\") return z.null();\n if (type === \"object\") {\n return inferSchema(values);\n }\n if (type === \"array\") {\n const allItems = values.flatMap((v) =>\n Array.isArray(v) ? v : [],\n );\n if (allItems.length === 0) return z.array(z.unknown());\n return z.array(inferFieldType(allItems));\n }\n }\n\n // Check if it's string literal values (for discriminator fields)\n if (types.size === 1 && types.has(\"string\")) {\n const unique = new Set(values);\n if (unique.size === 1) {\n return z.literal(values[0] as string);\n }\n }\n\n // Mixed types — build a union\n const members: z.ZodTypeAny[] = [];\n if (types.has(\"string\")) members.push(z.string());\n if (types.has(\"number\")) members.push(z.number());\n if (types.has(\"boolean\")) members.push(z.boolean());\n if (types.has(\"null\")) members.push(z.null());\n if (types.has(\"object\")) {\n const objs = values.filter(\n (v) => typeof v === \"object\" && v !== null && !Array.isArray(v),\n );\n members.push(inferSchema(objs));\n }\n if (types.has(\"array\")) {\n const arrs = values.filter(Array.isArray);\n const allItems = arrs.flat();\n members.push(\n z.array(allItems.length > 0 ? inferFieldType(allItems) : z.unknown()),\n );\n }\n\n if (members.length === 1) return members[0];\n if (members.length === 2) return z.union([members[0], members[1]] as any);\n return z.union(members as any);\n}\n\nfunction classifyValue(v: unknown): string {\n if (v === null) return \"null\";\n if (Array.isArray(v)) return \"array\";\n return typeof v;\n}\n\nfunction inferPrimitiveUnion(samples: unknown[]): z.ZodTypeAny {\n const types = new Set(samples.map(classifyValue));\n const members: z.ZodTypeAny[] = [];\n if (types.has(\"string\")) members.push(z.string());\n if (types.has(\"number\")) members.push(z.number());\n if (types.has(\"boolean\")) members.push(z.boolean());\n if (types.has(\"null\")) members.push(z.null());\n if (members.length === 0) return z.unknown();\n if (members.length === 1) return members[0];\n return z.union(members as any);\n}\n","import { z } from \"zod\";\n\n/**\n * Convert a Zod schema into readable TypeScript code that recreates it.\n */\nexport function schemaToCode(schema: z.ZodTypeAny, indent = 0): string {\n const pad = \" \".repeat(indent);\n\n if (schema instanceof z.ZodString) return \"z.string()\";\n if (schema instanceof z.ZodNumber) return \"z.number()\";\n if (schema instanceof z.ZodBoolean) return \"z.boolean()\";\n if (schema instanceof z.ZodNull) return \"z.null()\";\n if (schema instanceof z.ZodUnknown) return \"z.unknown()\";\n\n if (schema instanceof z.ZodLiteral) {\n const val = schema.value;\n return typeof val === \"string\" ? `z.literal(\"${val}\")` : `z.literal(${val})`;\n }\n\n if (schema instanceof z.ZodArray) {\n const inner = schemaToCode(schema.element, indent);\n return `z.array(${inner})`;\n }\n\n if (schema instanceof z.ZodObject) {\n const shape = schema.shape as Record<string, z.ZodTypeAny>;\n const keys = Object.keys(shape);\n if (keys.length === 0) return \"z.object({})\";\n\n const inner = pad + \" \";\n const fields = keys.map(\n (k) => `${inner}${safeProp(k)}: ${schemaToCode(shape[k], indent + 1)},`,\n );\n\n const strict =\n schema._def && (schema._def as any).unknownKeys === \"strict\"\n ? \".strict()\"\n : \"\";\n\n return `z.object({\\n${fields.join(\"\\n\")}\\n${pad}})${strict}`;\n }\n\n if (schema instanceof z.ZodUnion) {\n const opts = (schema as any).options as z.ZodTypeAny[];\n const members = opts.map((o) => schemaToCode(o, indent));\n if (members.every((m) => !m.includes(\"\\n\"))) {\n return `z.union([${members.join(\", \")}])`;\n }\n const inner = pad + \" \";\n return `z.union([\\n${members.map((m) => `${inner}${m},`).join(\"\\n\")}\\n${pad}])`;\n }\n\n if (schema instanceof z.ZodDiscriminatedUnion) {\n const disc = (schema as any)._def.discriminator as string;\n const opts = (schema as any)._def.options as z.ZodTypeAny[];\n const members = opts.map((o) => schemaToCode(o, indent + 1));\n const inner = pad + \" \";\n return `z.discriminatedUnion(\"${disc}\", [\\n${members.map((m) => `${inner}${m},`).join(\"\\n\")}\\n${pad}])`;\n }\n\n return \"z.unknown()\";\n}\n\nfunction safeProp(key: string): string {\n return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key) ? key : `\"${key}\"`;\n}\n"],"mappings":"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","names":["z","z"]}
|
|
1
|
+
{"version":3,"sources":["../src/storage/resolve.ts","../src/storage/memory.ts","../src/batch-processor.ts","../src/progressive.ts","../src/storage/amplitude.ts","../src/storage/client.ts","../src/infer-schema.ts","../src/schema-to-code.ts"],"sourcesContent":["import { z } from \"zod\";\nimport type { ProgressiveConfig, StorageBackend } from \"../types.js\";\nimport { MemoryStorage } from \"./memory.js\";\n\n/**\n * Global singleton state for progressive-zod.\n *\n * Bundlers (Vite, webpack, etc.) can create duplicate module instances when\n * a package is symlinked, installed at multiple versions, or resolved through\n * different paths in a monorepo. When that happens, module-level `let` vars\n * diverge: `configure()` writes to one copy, `getStorage()` reads from another.\n *\n * Storing shared state on `globalThis` under a unique symbol key guarantees\n * all copies of the module share the same config, storage, and factory —\n * the same pattern used by OpenTelemetry's API package.\n */\nconst GLOBAL_KEY = Symbol.for(\"progressive-zod\");\n\nexport type StorageFactory = (\n resolvedConfig: ProgressiveConfig,\n userConfig: ProgressiveConfig,\n) => Promise<StorageBackend>;\n\ninterface GlobalState {\n config: ProgressiveConfig;\n storage: StorageBackend | null;\n factory: StorageFactory;\n}\n\nfunction getGlobal(): GlobalState {\n const g = globalThis as Record<symbol, GlobalState | undefined>;\n if (!g[GLOBAL_KEY]) {\n g[GLOBAL_KEY] = {\n config: {},\n storage: null,\n factory: async (config) => new MemoryStorage(config),\n };\n }\n return g[GLOBAL_KEY];\n}\n\nconst progressiveConfigSchema = z\n .object({\n storage: z.enum([\"memory\", \"redis\", \"amplitude\"]).optional(),\n redisUrl: z.string().optional(),\n keyPrefix: z.string().optional(),\n maxViolations: z.number().optional(),\n maxSamples: z.number().optional(),\n dataDir: z.string().optional(),\n amplitudeClient: z.any().optional(),\n amplitudeEventName: z.string().optional(),\n })\n .superRefine((data, ctx) => {\n if (data.amplitudeEventName && data.storage !== \"amplitude\") {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message:\n 'amplitudeEventName can only be used when storage is \"amplitude\"',\n path: [\"amplitudeEventName\"],\n });\n }\n if (data.amplitudeClient && data.storage !== \"amplitude\") {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message:\n 'amplitudeClient can only be used when storage is \"amplitude\"',\n path: [\"amplitudeClient\"],\n });\n }\n });\n\n/**\n * Register a storage factory. Called by entry-point modules\n * (storage/index.ts for server, storage/client.ts for client)\n * to control which backends are available.\n */\nexport function _setStorageFactory(factory: StorageFactory): void {\n getGlobal().factory = factory;\n}\n\nexport function configure(config: ProgressiveConfig): void {\n const state = getGlobal();\n const merged = { ...state.config, ...config };\n progressiveConfigSchema.parse(merged);\n state.config = merged;\n // Force re-creation on next access\n if (state.storage) {\n state.storage.disconnect();\n state.storage = null;\n }\n}\n\nfunction env(key: string): string | undefined {\n if (typeof process !== \"undefined\" && process.env) {\n return process.env[key];\n }\n return undefined;\n}\n\nexport function getConfig(): ProgressiveConfig {\n const { config } = getGlobal();\n return {\n storage: config.storage ?? (env(\"PROGRESSIVE_ZOD_STORAGE\") as any) ?? \"memory\",\n redisUrl: config.redisUrl ?? env(\"PROGRESSIVE_ZOD_REDIS_URL\"),\n keyPrefix: config.keyPrefix ?? env(\"PROGRESSIVE_ZOD_KEY_PREFIX\") ?? \"pzod:\",\n maxViolations: config.maxViolations ?? parseInt(env(\"PROGRESSIVE_ZOD_MAX_VIOLATIONS\") ?? \"1000\", 10),\n maxSamples: config.maxSamples ?? parseInt(env(\"PROGRESSIVE_ZOD_MAX_SAMPLES\") ?? \"1000\", 10),\n dataDir: config.dataDir ?? env(\"PROGRESSIVE_ZOD_DATA_DIR\"),\n };\n}\n\nexport async function getStorage(): Promise<StorageBackend> {\n const state = getGlobal();\n if (state.storage) return state.storage;\n\n const config = getConfig();\n state.storage = await state.factory(config, state.config);\n return state.storage;\n}\n\nexport async function disconnectStorage(): Promise<void> {\n const state = getGlobal();\n if (state.storage) {\n await state.storage.disconnect();\n state.storage = null;\n }\n}\n","import type { StorageBackend, ProgressiveConfig } from \"../types.js\";\n\ninterface TypeData {\n samples: string[];\n violations: string[];\n conform: number;\n violate: number;\n}\n\n/**\n * In-memory storage backend.\n * No Node.js built-in dependencies — safe for browser bundles.\n */\nexport class MemoryStorage implements StorageBackend {\n protected names = new Set<string>();\n protected data = new Map<string, TypeData>();\n protected maxSamples: number;\n protected maxViolations: number;\n\n constructor(config: ProgressiveConfig = {}) {\n this.maxSamples = config.maxSamples ?? 1000;\n this.maxViolations = config.maxViolations ?? 1000;\n }\n\n protected getOrCreate(name: string): TypeData {\n let entry = this.data.get(name);\n if (!entry) {\n entry = { samples: [], violations: [], conform: 0, violate: 0 };\n this.data.set(name, entry);\n }\n return entry;\n }\n\n addName(name: string): void {\n this.names.add(name);\n }\n\n addSample(name: string, sample: string): void {\n const entry = this.getOrCreate(name);\n entry.samples.unshift(sample);\n if (entry.samples.length > this.maxSamples) {\n entry.samples.length = this.maxSamples;\n }\n }\n\n addViolation(name: string, violation: string): void {\n const entry = this.getOrCreate(name);\n entry.violations.unshift(violation);\n if (entry.violations.length > this.maxViolations) {\n entry.violations.length = this.maxViolations;\n }\n }\n\n incrConform(name: string): void {\n this.getOrCreate(name).conform++;\n }\n\n incrViolate(name: string): void {\n this.getOrCreate(name).violate++;\n }\n\n getNames(): string[] {\n return [...this.names].sort();\n }\n\n getSamples(name: string): string[] {\n return this.getOrCreate(name).samples;\n }\n\n getViolations(name: string, limit: number): string[] {\n return this.getOrCreate(name).violations.slice(0, limit);\n }\n\n async getStats(name: string): Promise<{ conform: number; violate: number }> {\n const entry = this.getOrCreate(name);\n return { conform: entry.conform, violate: entry.violate };\n }\n\n disconnect(): void {\n // No-op for pure in-memory storage\n }\n}\n","import type { z } from \"zod\";\nimport type { StorageBackend, ProgressiveOpts } from \"./types.js\";\nimport { getStorage } from \"./storage/resolve.js\";\n\nexport interface BatchConfig {\n /** Max observations to buffer before forcing a flush. Default: 512 */\n maxQueueSize?: number;\n /** Flush interval in milliseconds. Default: 5000 */\n flushIntervalMs?: number;\n /** Max observations to export per flush. Default: 512 */\n maxExportBatchSize?: number;\n}\n\ninterface Observation {\n name: string;\n serialized: string;\n schema?: z.ZodTypeAny;\n opts?: ProgressiveOpts;\n}\n\nconst DEFAULT_MAX_QUEUE_SIZE = 2048;\nconst DEFAULT_FLUSH_INTERVAL_MS = 5000;\nconst DEFAULT_MAX_EXPORT_BATCH_SIZE = 512;\n\nexport class BatchProcessor {\n private queue: Observation[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private flushing = false;\n private droppedCount = 0;\n\n private readonly maxQueueSize: number;\n private readonly flushIntervalMs: number;\n private readonly maxExportBatchSize: number;\n\n constructor(config: BatchConfig = {}) {\n this.maxQueueSize = config.maxQueueSize ?? DEFAULT_MAX_QUEUE_SIZE;\n this.flushIntervalMs = config.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS;\n this.maxExportBatchSize = config.maxExportBatchSize ?? DEFAULT_MAX_EXPORT_BATCH_SIZE;\n }\n\n /**\n * Enqueue an observation. This is synchronous and fast — no I/O happens here.\n * If the queue is full, the oldest observation is dropped (bounded memory).\n */\n enqueue(name: string, input: unknown, schema?: z.ZodTypeAny, opts?: ProgressiveOpts): void {\n this.ensureTimer();\n\n let serialized: string;\n try {\n serialized = JSON.stringify(input);\n } catch {\n // Non-serializable input — skip silently\n return;\n }\n\n if (this.queue.length >= this.maxQueueSize) {\n // Drop oldest to stay within bounds\n this.queue.shift();\n this.droppedCount++;\n }\n\n this.queue.push({ name, serialized, schema, opts });\n\n // Flush immediately if we've hit the export batch size\n if (this.queue.length >= this.maxExportBatchSize) {\n this.flushAsync();\n }\n }\n\n /**\n * Force flush all pending observations. Call during graceful shutdown.\n */\n async forceFlush(): Promise<void> {\n this.clearTimer();\n await this.flush();\n }\n\n /**\n * Shut down the processor: flush remaining data and stop the timer.\n */\n async shutdown(): Promise<void> {\n await this.forceFlush();\n }\n\n /** Number of observations currently in the queue */\n get pendingCount(): number {\n return this.queue.length;\n }\n\n /** Number of observations dropped due to queue overflow */\n get dropped(): number {\n return this.droppedCount;\n }\n\n private ensureTimer(): void {\n if (this.timer) return;\n this.timer = setInterval(() => {\n this.flushAsync();\n }, this.flushIntervalMs);\n // Don't keep the process alive just for telemetry\n if (this.timer && typeof this.timer === \"object\" && \"unref\" in this.timer) {\n this.timer.unref();\n }\n }\n\n private clearTimer(): void {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n }\n\n /** Non-blocking flush — errors are swallowed */\n private flushAsync(): void {\n this.flush().catch(() => {});\n }\n\n /** Drain the queue and send observations to storage in batch */\n private async flush(): Promise<void> {\n if (this.flushing || this.queue.length === 0) return;\n this.flushing = true;\n\n // Drain up to maxExportBatchSize\n const batch = this.queue.splice(0, this.maxExportBatchSize);\n\n try {\n const storage = await getStorage();\n await this.exportBatch(storage, batch);\n } catch {\n // Swallow errors — observability must never crash the app\n } finally {\n this.flushing = false;\n // If items accumulated during flush, schedule another\n if (this.queue.length >= this.maxExportBatchSize) {\n this.flushAsync();\n }\n }\n }\n\n private async exportBatch(\n storage: StorageBackend,\n batch: Observation[],\n ): Promise<void> {\n // Collect unique names first\n const names = new Set<string>();\n for (const obs of batch) {\n names.add(obs.name);\n }\n\n // Register all names\n await Promise.all([...names].map((n) => storage.addName(n)));\n\n // Process each observation\n // We batch the promises to avoid creating thousands of concurrent promises\n const promises: Promise<void>[] = [];\n\n for (const obs of batch) {\n promises.push(this.exportOne(storage, obs));\n }\n\n await Promise.all(promises);\n }\n\n private async exportOne(\n storage: StorageBackend,\n obs: Observation,\n ): Promise<void> {\n await storage.addSample(obs.name, obs.serialized);\n\n if (obs.schema) {\n const result = obs.schema.safeParse(JSON.parse(obs.serialized));\n if (result.success) {\n await storage.incrConform(obs.name, obs.serialized, obs.opts);\n } else {\n const errors = result.error.issues\n .map((i) => {\n const path = i.path.length > 0 ? i.path.join(\".\") : \"(root)\";\n return `${path}: ${i.message}`;\n })\n .join(\"; \");\n await storage.incrViolate(obs.name, obs.serialized, errors, obs.opts);\n await storage.addViolation(obs.name, obs.serialized);\n }\n } else {\n await storage.incrViolate(obs.name, obs.serialized, \"no schema defined\", obs.opts);\n await storage.addViolation(obs.name, obs.serialized);\n }\n }\n}\n","import type { z } from \"zod\";\nimport type { ProgressiveSchema, ProgressiveOpts } from \"./types.js\";\nimport { BatchProcessor } from \"./batch-processor.js\";\nimport type { BatchConfig } from \"./batch-processor.js\";\n\nconst PROCESSOR_KEY = Symbol.for(\"progressive-zod:processor\");\n\nfunction getProcessor(): BatchProcessor {\n const g = globalThis as Record<symbol, BatchProcessor | undefined>;\n if (!g[PROCESSOR_KEY]) {\n g[PROCESSOR_KEY] = new BatchProcessor();\n }\n return g[PROCESSOR_KEY];\n}\n\n/**\n * Configure the batch processor. Call before first `progressive()` use.\n * Follows the OpenTelemetry provider pattern:\n * - Observations are buffered in memory (synchronous, zero I/O on hot path)\n * - Flushed to storage in batches on a timer or when buffer is full\n * - Queue is bounded to prevent memory leaks\n * - Timer is unref'd so it won't keep the process alive\n */\nexport function configureBatch(config: BatchConfig): void {\n const g = globalThis as Record<symbol, BatchProcessor | undefined>;\n if (g[PROCESSOR_KEY]) {\n // Flush existing before reconfiguring\n g[PROCESSOR_KEY].forceFlush().catch(() => {});\n }\n g[PROCESSOR_KEY] = new BatchProcessor(config);\n}\n\n/**\n * Force flush all pending observations. Call during graceful shutdown.\n *\n * @example\n * ```ts\n * process.on(\"SIGTERM\", async () => {\n * await forceFlush();\n * process.exit(0);\n * });\n * ```\n */\nexport async function forceFlush(): Promise<void> {\n const g = globalThis as Record<symbol, BatchProcessor | undefined>;\n if (g[PROCESSOR_KEY]) {\n await g[PROCESSOR_KEY].forceFlush();\n }\n}\n\n/**\n * Shut down the batch processor and flush remaining data.\n */\nexport async function shutdown(): Promise<void> {\n const g = globalThis as Record<symbol, BatchProcessor | undefined>;\n if (g[PROCESSOR_KEY]) {\n await g[PROCESSOR_KEY].shutdown();\n g[PROCESSOR_KEY] = undefined;\n }\n}\n\n/**\n * Create a progressive schema that tracks runtime data and optionally validates.\n *\n * - Never throws — always returns input unchanged\n * - Records samples for later schema inference\n * - If a schema is provided, tracks conformance vs violations\n * - Observations are batched and flushed asynchronously (OTel-style)\n * - Zero I/O on the hot path — enqueue is synchronous\n */\nexport function progressive(\n name: string,\n schema?: z.ZodTypeAny,\n opts?: ProgressiveOpts,\n): ProgressiveSchema {\n return {\n parse(input: unknown): unknown {\n // Synchronous enqueue — no I/O, no promises, no overhead\n getProcessor().enqueue(name, input, schema, opts);\n return input;\n },\n };\n}\n","import type { ProgressiveConfig, ProgressiveOpts, StorageBackend } from \"../types.js\";\n\n/**\n * Minimal interface for an Amplitude client.\n * Compatible with @amplitude/analytics-node's `track()` signature.\n * Pass an instance initialized with your observability project's API key\n * (separate from your main product analytics project).\n */\nexport interface AmplitudeClient {\n track(\n eventName: string,\n eventProperties?: Record<string, unknown>,\n options?: { user_id?: string; device_id?: string },\n ): void;\n}\n\n/**\n * Amplitude storage backend for progressive-zod.\n *\n * Sends a single event per type check:\n *\n * this.eventName\n * - type_name: string — the boundary name passed to progressive()\n * - result: \"conforms\" | \"violation\"\n * - sample_type: string — JS typeof the observed value (violation only)\n * - field_count: number — number of top-level keys (violation only, objects)\n * - sample_preview: string — first 256 chars of JSON (violation only)\n * - validation_errors: string — human-readable Zod validation errors (violation only)\n *\n * Read methods (getNames, getSamples, etc.) are no-ops — use the\n * Amplitude dashboard to query your data.\n */\n/**\n * Convert a value into a flat \"key=value; ...\" string so Amplitude\n * treats it as an opaque string instead of exploding JSON keys into\n * separate event properties.\n */\nfunction flattenToString(value: unknown): string {\n if (value === null || value === undefined) return String(value);\n if (typeof value !== \"object\") return String(value);\n if (Array.isArray(value)) return value.map(String).join(\", \");\n const entries = Object.entries(value as Record<string, unknown>);\n return entries.map(([k, v]) => `${k}=${JSON.stringify(v)}`).join(\"; \");\n}\n\nexport class AmplitudeStorage implements StorageBackend {\n private readonly client: AmplitudeClient;\n private readonly eventName: string;\n\n constructor(\n client: AmplitudeClient,\n config: ProgressiveConfig,\n ) {\n this.client = client;\n this.eventName = config.amplitudeEventName ?? \"progressive-zod: results\";\n }\n\n addName(_name: string): void {\n // No-op: we only track type checks\n }\n\n addSample(_name: string, _sample: string): void {\n // No-op: we only track type checks\n }\n\n addViolation(_name: string, _violation: string): void {\n // No-op: violation data is included in the type_checked event via incrViolate\n }\n\n incrConform(name: string, _sample?: string, opts?: ProgressiveOpts): void {\n const properties: Record<string, unknown> = { type_name: name, result: \"conforms\" };\n if (opts && Object.keys(opts).length > 0) {\n properties.options = Object.entries(opts).map(([k, v]) => `${k}=${v}`).join(\"; \");\n }\n this.client.track(this.eventName, properties);\n }\n\n incrViolate(name: string, sample?: string, errors?: string, opts?: ProgressiveOpts): void {\n const properties: Record<string, unknown> = {\n type_name: name,\n result: \"violation\",\n };\n\n if (sample) {\n try {\n const parsed = JSON.parse(sample);\n properties.sample_type = typeof parsed;\n if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n properties.field_count = Object.keys(parsed).length;\n }\n // Flatten to key=value pairs so Amplitude doesn't explode JSON into N properties\n properties.sample_preview = flattenToString(parsed).slice(0, 256);\n } catch {\n properties.sample_type = \"unknown\";\n properties.sample_preview = sample.slice(0, 256);\n }\n }\n\n if (errors) {\n properties.validation_errors = errors.slice(0, 1024);\n }\n\n if (opts && Object.keys(opts).length > 0) {\n properties.options = Object.entries(opts).map(([k, v]) => `${k}=${v}`).join(\"; \");\n }\n\n this.client.track(this.eventName, properties);\n }\n\n // --- Read methods: no-ops (use Amplitude dashboard) ---\n\n async getNames(): Promise<string[]> {\n return [];\n }\n\n async getSamples(_name: string): Promise<string[]> {\n return [];\n }\n\n async getViolations(_name: string, _limit: number): Promise<string[]> {\n return [];\n }\n\n async getStats(_name: string): Promise<{ conform: number; violate: number }> {\n return { conform: 0, violate: 0 };\n }\n\n disconnect(): void {\n // Amplitude SDK manages its own lifecycle — nothing to clean up\n }\n}\n","import { _setStorageFactory } from \"./resolve.js\";\nimport { MemoryStorage } from \"./memory.js\";\nimport { AmplitudeStorage } from \"./amplitude.js\";\n\n// Register client storage factory — no Redis (avoids bundling ioredis)\n_setStorageFactory(async (config, userConfig) => {\n if (config.storage === \"amplitude\") {\n if (!userConfig.amplitudeClient) {\n throw new Error(\n \"progressive-zod: storage is set to 'amplitude' but no amplitudeClient was provided. \" +\n \"Pass an Amplitude client instance via configure({ amplitudeClient }).\",\n );\n }\n return new AmplitudeStorage(userConfig.amplitudeClient, config);\n } else if (config.storage === \"redis\") {\n throw new Error(\n 'progressive-zod: Redis storage is not available in the client bundle. ' +\n 'Import from \"progressive-zod\" instead of \"progressive-zod/client\".',\n );\n }\n\n return new MemoryStorage(config);\n});\n\nexport { configure, getConfig, getStorage, disconnectStorage } from \"./resolve.js\";\n","import { z } from \"zod\";\n\n/**\n * Infer a Zod schema from an array of runtime samples.\n */\nexport function inferSchema(samples: unknown[]): z.ZodTypeAny {\n const objects = samples.filter(\n (s): s is Record<string, unknown> =>\n typeof s === \"object\" && s !== null && !Array.isArray(s),\n );\n\n if (objects.length === 0) {\n return inferPrimitiveUnion(samples);\n }\n\n // Group samples by their shape (set of keys)\n const groups = groupByShape(objects);\n\n if (groups.length === 1) {\n return buildObjectSchema(groups[0]);\n }\n\n // Try to find a discriminator field\n const discriminator = findDiscriminator(groups);\n if (discriminator) {\n return z.discriminatedUnion(\n discriminator,\n groups.map(\n (group) => buildObjectSchema(group) as z.ZodObject<any>,\n ) as any,\n );\n }\n\n return z.union(\n groups.map((group) => buildObjectSchema(group)) as any,\n );\n}\n\nfunction shapeKey(obj: Record<string, unknown>): string {\n return Object.keys(obj).sort().join(\",\");\n}\n\nfunction groupByShape(\n objects: Record<string, unknown>[],\n): Record<string, unknown>[][] {\n const map = new Map<string, Record<string, unknown>[]>();\n for (const obj of objects) {\n const key = shapeKey(obj);\n let group = map.get(key);\n if (!group) {\n group = [];\n map.set(key, group);\n }\n group.push(obj);\n }\n return [...map.values()];\n}\n\nfunction findDiscriminator(\n groups: Record<string, unknown>[][],\n): string | null {\n if (groups.length < 2) return null;\n\n // Get keys present in all groups\n const keySets = groups.map(\n (g) => new Set(Object.keys(g[0])),\n );\n const commonKeys = [...keySets[0]].filter((k) =>\n keySets.every((s) => s.has(k)),\n );\n\n for (const key of commonKeys) {\n // Check if this key has a single string literal value per group\n // and the values are distinct across groups\n const values = new Set<string>();\n let valid = true;\n\n for (const group of groups) {\n const groupValues = new Set(\n group.map((obj) => obj[key]).filter((v) => typeof v === \"string\"),\n );\n if (groupValues.size !== 1) {\n valid = false;\n break;\n }\n const val = [...groupValues][0] as string;\n if (values.has(val)) {\n valid = false;\n break;\n }\n values.add(val);\n }\n\n if (valid && values.size === groups.length) {\n return key;\n }\n }\n\n return null;\n}\n\nfunction buildObjectSchema(\n samples: Record<string, unknown>[],\n): z.ZodObject<any> {\n const keys = Object.keys(samples[0]);\n const shape: Record<string, z.ZodTypeAny> = {};\n\n for (const key of keys) {\n const values = samples.map((s) => s[key]);\n // If all values are the same string, use z.literal() (needed for discriminated unions)\n const unique = new Set(values);\n if (unique.size === 1 && typeof values[0] === \"string\") {\n shape[key] = z.literal(values[0] as string);\n } else {\n shape[key] = inferFieldType(values);\n }\n }\n\n return z.object(shape).strict();\n}\n\nfunction inferFieldType(values: unknown[]): z.ZodTypeAny {\n const types = new Set(values.map(classifyValue));\n\n if (types.size === 1) {\n const type = [...types][0];\n if (type === \"string\") return z.string();\n if (type === \"number\") return z.number();\n if (type === \"boolean\") return z.boolean();\n if (type === \"null\") return z.null();\n if (type === \"object\") {\n return inferSchema(values);\n }\n if (type === \"array\") {\n const allItems = values.flatMap((v) =>\n Array.isArray(v) ? v : [],\n );\n if (allItems.length === 0) return z.array(z.unknown());\n return z.array(inferFieldType(allItems));\n }\n }\n\n // Check if it's string literal values (for discriminator fields)\n if (types.size === 1 && types.has(\"string\")) {\n const unique = new Set(values);\n if (unique.size === 1) {\n return z.literal(values[0] as string);\n }\n }\n\n // Mixed types — build a union\n const members: z.ZodTypeAny[] = [];\n if (types.has(\"string\")) members.push(z.string());\n if (types.has(\"number\")) members.push(z.number());\n if (types.has(\"boolean\")) members.push(z.boolean());\n if (types.has(\"null\")) members.push(z.null());\n if (types.has(\"object\")) {\n const objs = values.filter(\n (v) => typeof v === \"object\" && v !== null && !Array.isArray(v),\n );\n members.push(inferSchema(objs));\n }\n if (types.has(\"array\")) {\n const arrs = values.filter(Array.isArray);\n const allItems = arrs.flat();\n members.push(\n z.array(allItems.length > 0 ? inferFieldType(allItems) : z.unknown()),\n );\n }\n\n if (members.length === 1) return members[0];\n if (members.length === 2) return z.union([members[0], members[1]] as any);\n return z.union(members as any);\n}\n\nfunction classifyValue(v: unknown): string {\n if (v === null) return \"null\";\n if (Array.isArray(v)) return \"array\";\n return typeof v;\n}\n\nfunction inferPrimitiveUnion(samples: unknown[]): z.ZodTypeAny {\n const types = new Set(samples.map(classifyValue));\n const members: z.ZodTypeAny[] = [];\n if (types.has(\"string\")) members.push(z.string());\n if (types.has(\"number\")) members.push(z.number());\n if (types.has(\"boolean\")) members.push(z.boolean());\n if (types.has(\"null\")) members.push(z.null());\n if (members.length === 0) return z.unknown();\n if (members.length === 1) return members[0];\n return z.union(members as any);\n}\n","import { z } from \"zod\";\n\n/**\n * Convert a Zod schema into readable TypeScript code that recreates it.\n */\nexport function schemaToCode(schema: z.ZodTypeAny, indent = 0): string {\n const pad = \" \".repeat(indent);\n\n if (schema instanceof z.ZodString) return \"z.string()\";\n if (schema instanceof z.ZodNumber) return \"z.number()\";\n if (schema instanceof z.ZodBoolean) return \"z.boolean()\";\n if (schema instanceof z.ZodNull) return \"z.null()\";\n if (schema instanceof z.ZodUnknown) return \"z.unknown()\";\n\n if (schema instanceof z.ZodLiteral) {\n const val = schema.value;\n return typeof val === \"string\" ? `z.literal(\"${val}\")` : `z.literal(${val})`;\n }\n\n if (schema instanceof z.ZodArray) {\n const inner = schemaToCode(schema.element, indent);\n return `z.array(${inner})`;\n }\n\n if (schema instanceof z.ZodObject) {\n const shape = schema.shape as Record<string, z.ZodTypeAny>;\n const keys = Object.keys(shape);\n if (keys.length === 0) return \"z.object({})\";\n\n const inner = pad + \" \";\n const fields = keys.map(\n (k) => `${inner}${safeProp(k)}: ${schemaToCode(shape[k], indent + 1)},`,\n );\n\n const strict =\n schema._def && (schema._def as any).unknownKeys === \"strict\"\n ? \".strict()\"\n : \"\";\n\n return `z.object({\\n${fields.join(\"\\n\")}\\n${pad}})${strict}`;\n }\n\n if (schema instanceof z.ZodUnion) {\n const opts = (schema as any).options as z.ZodTypeAny[];\n const members = opts.map((o) => schemaToCode(o, indent));\n if (members.every((m) => !m.includes(\"\\n\"))) {\n return `z.union([${members.join(\", \")}])`;\n }\n const inner = pad + \" \";\n return `z.union([\\n${members.map((m) => `${inner}${m},`).join(\"\\n\")}\\n${pad}])`;\n }\n\n if (schema instanceof z.ZodDiscriminatedUnion) {\n const disc = (schema as any)._def.discriminator as string;\n const opts = (schema as any)._def.options as z.ZodTypeAny[];\n const members = opts.map((o) => schemaToCode(o, indent + 1));\n const inner = pad + \" \";\n return `z.discriminatedUnion(\"${disc}\", [\\n${members.map((m) => `${inner}${m},`).join(\"\\n\")}\\n${pad}])`;\n }\n\n return \"z.unknown()\";\n}\n\nfunction safeProp(key: string): string {\n return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key) ? key : `\"${key}\"`;\n}\n"],"mappings":"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","names":["z","z"]}
|
package/dist/index.cjs
CHANGED
|
@@ -59,10 +59,14 @@ var init_amplitude = __esm({
|
|
|
59
59
|
}
|
|
60
60
|
addViolation(_name, _violation) {
|
|
61
61
|
}
|
|
62
|
-
incrConform(name, _sample) {
|
|
63
|
-
|
|
62
|
+
incrConform(name, _sample, opts) {
|
|
63
|
+
const properties = { type_name: name, result: "conforms" };
|
|
64
|
+
if (opts && Object.keys(opts).length > 0) {
|
|
65
|
+
properties.options = Object.entries(opts).map(([k, v]) => `${k}=${v}`).join("; ");
|
|
66
|
+
}
|
|
67
|
+
this.client.track(this.eventName, properties);
|
|
64
68
|
}
|
|
65
|
-
incrViolate(name, sample, errors) {
|
|
69
|
+
incrViolate(name, sample, errors, opts) {
|
|
66
70
|
const properties = {
|
|
67
71
|
type_name: name,
|
|
68
72
|
result: "violation"
|
|
@@ -83,6 +87,9 @@ var init_amplitude = __esm({
|
|
|
83
87
|
if (errors) {
|
|
84
88
|
properties.validation_errors = errors.slice(0, 1024);
|
|
85
89
|
}
|
|
90
|
+
if (opts && Object.keys(opts).length > 0) {
|
|
91
|
+
properties.options = Object.entries(opts).map(([k, v]) => `${k}=${v}`).join("; ");
|
|
92
|
+
}
|
|
86
93
|
this.client.track(this.eventName, properties);
|
|
87
94
|
}
|
|
88
95
|
// --- Read methods: no-ops (use Amplitude dashboard) ---
|
|
@@ -279,6 +286,18 @@ var MemoryStorage = class {
|
|
|
279
286
|
};
|
|
280
287
|
|
|
281
288
|
// src/storage/resolve.ts
|
|
289
|
+
var GLOBAL_KEY = /* @__PURE__ */ Symbol.for("progressive-zod");
|
|
290
|
+
function getGlobal() {
|
|
291
|
+
const g = globalThis;
|
|
292
|
+
if (!g[GLOBAL_KEY]) {
|
|
293
|
+
g[GLOBAL_KEY] = {
|
|
294
|
+
config: {},
|
|
295
|
+
storage: null,
|
|
296
|
+
factory: async (config) => new MemoryStorage(config)
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
return g[GLOBAL_KEY];
|
|
300
|
+
}
|
|
282
301
|
var progressiveConfigSchema = import_zod.z.object({
|
|
283
302
|
storage: import_zod.z.enum(["memory", "redis", "amplitude"]).optional(),
|
|
284
303
|
redisUrl: import_zod.z.string().optional(),
|
|
@@ -304,19 +323,17 @@ var progressiveConfigSchema = import_zod.z.object({
|
|
|
304
323
|
});
|
|
305
324
|
}
|
|
306
325
|
});
|
|
307
|
-
var currentConfig = {};
|
|
308
|
-
var currentStorage = null;
|
|
309
|
-
var storageFactory = async (config) => new MemoryStorage(config);
|
|
310
326
|
function _setStorageFactory(factory) {
|
|
311
|
-
|
|
327
|
+
getGlobal().factory = factory;
|
|
312
328
|
}
|
|
313
329
|
function configure(config) {
|
|
314
|
-
const
|
|
330
|
+
const state = getGlobal();
|
|
331
|
+
const merged = { ...state.config, ...config };
|
|
315
332
|
progressiveConfigSchema.parse(merged);
|
|
316
|
-
|
|
317
|
-
if (
|
|
318
|
-
|
|
319
|
-
|
|
333
|
+
state.config = merged;
|
|
334
|
+
if (state.storage) {
|
|
335
|
+
state.storage.disconnect();
|
|
336
|
+
state.storage = null;
|
|
320
337
|
}
|
|
321
338
|
}
|
|
322
339
|
function env(key) {
|
|
@@ -326,20 +343,22 @@ function env(key) {
|
|
|
326
343
|
return void 0;
|
|
327
344
|
}
|
|
328
345
|
function getConfig() {
|
|
346
|
+
const { config } = getGlobal();
|
|
329
347
|
return {
|
|
330
|
-
storage:
|
|
331
|
-
redisUrl:
|
|
332
|
-
keyPrefix:
|
|
333
|
-
maxViolations:
|
|
334
|
-
maxSamples:
|
|
335
|
-
dataDir:
|
|
348
|
+
storage: config.storage ?? env("PROGRESSIVE_ZOD_STORAGE") ?? "memory",
|
|
349
|
+
redisUrl: config.redisUrl ?? env("PROGRESSIVE_ZOD_REDIS_URL"),
|
|
350
|
+
keyPrefix: config.keyPrefix ?? env("PROGRESSIVE_ZOD_KEY_PREFIX") ?? "pzod:",
|
|
351
|
+
maxViolations: config.maxViolations ?? parseInt(env("PROGRESSIVE_ZOD_MAX_VIOLATIONS") ?? "1000", 10),
|
|
352
|
+
maxSamples: config.maxSamples ?? parseInt(env("PROGRESSIVE_ZOD_MAX_SAMPLES") ?? "1000", 10),
|
|
353
|
+
dataDir: config.dataDir ?? env("PROGRESSIVE_ZOD_DATA_DIR")
|
|
336
354
|
};
|
|
337
355
|
}
|
|
338
356
|
async function getStorage() {
|
|
339
|
-
|
|
357
|
+
const state = getGlobal();
|
|
358
|
+
if (state.storage) return state.storage;
|
|
340
359
|
const config = getConfig();
|
|
341
|
-
|
|
342
|
-
return
|
|
360
|
+
state.storage = await state.factory(config, state.config);
|
|
361
|
+
return state.storage;
|
|
343
362
|
}
|
|
344
363
|
|
|
345
364
|
// src/batch-processor.ts
|
|
@@ -363,7 +382,7 @@ var BatchProcessor = class {
|
|
|
363
382
|
* Enqueue an observation. This is synchronous and fast — no I/O happens here.
|
|
364
383
|
* If the queue is full, the oldest observation is dropped (bounded memory).
|
|
365
384
|
*/
|
|
366
|
-
enqueue(name, input, schema) {
|
|
385
|
+
enqueue(name, input, schema, opts) {
|
|
367
386
|
this.ensureTimer();
|
|
368
387
|
let serialized;
|
|
369
388
|
try {
|
|
@@ -375,7 +394,7 @@ var BatchProcessor = class {
|
|
|
375
394
|
this.queue.shift();
|
|
376
395
|
this.droppedCount++;
|
|
377
396
|
}
|
|
378
|
-
this.queue.push({ name, serialized, schema });
|
|
397
|
+
this.queue.push({ name, serialized, schema, opts });
|
|
379
398
|
if (this.queue.length >= this.maxExportBatchSize) {
|
|
380
399
|
this.flushAsync();
|
|
381
400
|
}
|
|
@@ -454,52 +473,56 @@ var BatchProcessor = class {
|
|
|
454
473
|
if (obs.schema) {
|
|
455
474
|
const result = obs.schema.safeParse(JSON.parse(obs.serialized));
|
|
456
475
|
if (result.success) {
|
|
457
|
-
await storage.incrConform(obs.name, obs.serialized);
|
|
476
|
+
await storage.incrConform(obs.name, obs.serialized, obs.opts);
|
|
458
477
|
} else {
|
|
459
478
|
const errors = result.error.issues.map((i) => {
|
|
460
479
|
const path2 = i.path.length > 0 ? i.path.join(".") : "(root)";
|
|
461
480
|
return `${path2}: ${i.message}`;
|
|
462
481
|
}).join("; ");
|
|
463
|
-
await storage.incrViolate(obs.name, obs.serialized, errors);
|
|
482
|
+
await storage.incrViolate(obs.name, obs.serialized, errors, obs.opts);
|
|
464
483
|
await storage.addViolation(obs.name, obs.serialized);
|
|
465
484
|
}
|
|
466
485
|
} else {
|
|
467
|
-
await storage.incrViolate(obs.name, obs.serialized, "no schema defined");
|
|
486
|
+
await storage.incrViolate(obs.name, obs.serialized, "no schema defined", obs.opts);
|
|
468
487
|
await storage.addViolation(obs.name, obs.serialized);
|
|
469
488
|
}
|
|
470
489
|
}
|
|
471
490
|
};
|
|
472
491
|
|
|
473
492
|
// src/progressive.ts
|
|
474
|
-
var
|
|
493
|
+
var PROCESSOR_KEY = /* @__PURE__ */ Symbol.for("progressive-zod:processor");
|
|
475
494
|
function getProcessor() {
|
|
476
|
-
|
|
477
|
-
|
|
495
|
+
const g = globalThis;
|
|
496
|
+
if (!g[PROCESSOR_KEY]) {
|
|
497
|
+
g[PROCESSOR_KEY] = new BatchProcessor();
|
|
478
498
|
}
|
|
479
|
-
return
|
|
499
|
+
return g[PROCESSOR_KEY];
|
|
480
500
|
}
|
|
481
501
|
function configureBatch(config) {
|
|
482
|
-
|
|
483
|
-
|
|
502
|
+
const g = globalThis;
|
|
503
|
+
if (g[PROCESSOR_KEY]) {
|
|
504
|
+
g[PROCESSOR_KEY].forceFlush().catch(() => {
|
|
484
505
|
});
|
|
485
506
|
}
|
|
486
|
-
|
|
507
|
+
g[PROCESSOR_KEY] = new BatchProcessor(config);
|
|
487
508
|
}
|
|
488
509
|
async function forceFlush() {
|
|
489
|
-
|
|
490
|
-
|
|
510
|
+
const g = globalThis;
|
|
511
|
+
if (g[PROCESSOR_KEY]) {
|
|
512
|
+
await g[PROCESSOR_KEY].forceFlush();
|
|
491
513
|
}
|
|
492
514
|
}
|
|
493
515
|
async function shutdown() {
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
516
|
+
const g = globalThis;
|
|
517
|
+
if (g[PROCESSOR_KEY]) {
|
|
518
|
+
await g[PROCESSOR_KEY].shutdown();
|
|
519
|
+
g[PROCESSOR_KEY] = void 0;
|
|
497
520
|
}
|
|
498
521
|
}
|
|
499
|
-
function progressive(name, schema) {
|
|
522
|
+
function progressive(name, schema, opts) {
|
|
500
523
|
return {
|
|
501
524
|
parse(input) {
|
|
502
|
-
getProcessor().enqueue(name, input, schema);
|
|
525
|
+
getProcessor().enqueue(name, input, schema, opts);
|
|
503
526
|
return input;
|
|
504
527
|
}
|
|
505
528
|
};
|