@rudra-js/core 0.1.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.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +189 -0
  3. package/dist/component-generator.d.ts +84 -0
  4. package/dist/component-generator.d.ts.map +1 -0
  5. package/dist/component-generator.js +331 -0
  6. package/dist/component-generator.js.map +1 -0
  7. package/dist/component-spec.d.ts +426 -0
  8. package/dist/component-spec.d.ts.map +1 -0
  9. package/dist/component-spec.js +170 -0
  10. package/dist/component-spec.js.map +1 -0
  11. package/dist/fallback-component.d.ts +11 -0
  12. package/dist/fallback-component.d.ts.map +1 -0
  13. package/dist/fallback-component.js +69 -0
  14. package/dist/fallback-component.js.map +1 -0
  15. package/dist/fit-to-shopper.d.ts +4 -0
  16. package/dist/fit-to-shopper.d.ts.map +1 -0
  17. package/dist/fit-to-shopper.js +36 -0
  18. package/dist/fit-to-shopper.js.map +1 -0
  19. package/dist/index.d.ts +19 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +19 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/model-prompt.d.ts +29 -0
  24. package/dist/model-prompt.d.ts.map +1 -0
  25. package/dist/model-prompt.js +227 -0
  26. package/dist/model-prompt.js.map +1 -0
  27. package/dist/product-selection.d.ts +33 -0
  28. package/dist/product-selection.d.ts.map +1 -0
  29. package/dist/product-selection.js +102 -0
  30. package/dist/product-selection.js.map +1 -0
  31. package/dist/provider.d.ts +80 -0
  32. package/dist/provider.d.ts.map +1 -0
  33. package/dist/provider.js +23 -0
  34. package/dist/provider.js.map +1 -0
  35. package/dist/reconciliation.d.ts +49 -0
  36. package/dist/reconciliation.d.ts.map +1 -0
  37. package/dist/reconciliation.js +564 -0
  38. package/dist/reconciliation.js.map +1 -0
  39. package/dist/signal-digest.d.ts +66 -0
  40. package/dist/signal-digest.d.ts.map +1 -0
  41. package/dist/signal-digest.js +224 -0
  42. package/dist/signal-digest.js.map +1 -0
  43. package/dist/spec-cache.d.ts +88 -0
  44. package/dist/spec-cache.d.ts.map +1 -0
  45. package/dist/spec-cache.js +152 -0
  46. package/dist/spec-cache.js.map +1 -0
  47. package/dist/tracking-input.d.ts +258 -0
  48. package/dist/tracking-input.d.ts.map +1 -0
  49. package/dist/tracking-input.js +241 -0
  50. package/dist/tracking-input.js.map +1 -0
  51. package/package.json +60 -0
  52. package/src/component-generator.ts +521 -0
  53. package/src/component-spec.ts +243 -0
  54. package/src/fallback-component.ts +77 -0
  55. package/src/fit-to-shopper.ts +45 -0
  56. package/src/index.ts +102 -0
  57. package/src/model-prompt.ts +258 -0
  58. package/src/product-selection.ts +153 -0
  59. package/src/provider.ts +98 -0
  60. package/src/reconciliation.ts +675 -0
  61. package/src/signal-digest.ts +335 -0
  62. package/src/spec-cache.ts +223 -0
  63. package/src/tracking-input.ts +300 -0
@@ -0,0 +1,258 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * The tracking-input contract — the boundary between the host application and
4
+ * rudra-js.
5
+ *
6
+ * rudra-js does not collect, store, or aggregate anything. The host owns its
7
+ * tracking pipeline (an event stream, a CDP, a warehouse) and hands the
8
+ * framework one JSON object per render. This module is that contract: one
9
+ * schema, validated at the edge, so a malformed payload fails loudly here
10
+ * rather than quietly producing a bad prompt several layers later.
11
+ *
12
+ * Every fixed-shape object below is a `strictObject`, so an unrecognised field
13
+ * is an error rather than being dropped. That matters more than it looks: with
14
+ * a lenient object, a host that misspells `recentSearches` gets a shopper who
15
+ * silently looks like a first-time visitor, and nothing anywhere reports it.
16
+ * The only dynamic shape is `interaction.meta`, which is a record by design.
17
+ */
18
+ /**
19
+ * Every free-text field and every array is length-capped.
20
+ *
21
+ * These caps are not cosmetic. Host-supplied strings end up inside the prompt
22
+ * we send to a language model, and a model is billed per token — so an
23
+ * unbounded string is an unbounded bill, and an unbounded array of candidates
24
+ * is the same problem multiplied.
25
+ *
26
+ * What this buys is that no single field is unbounded. It is deliberately not
27
+ * an aggregate budget: the caps multiply out to far more than any context
28
+ * window, because rejecting a large-but-legitimate payload is the wrong
29
+ * response to one. Fitting a payload into a prompt is `digest`'s job, and it
30
+ * trims rather than throws.
31
+ */
32
+ export declare const FIELD_LIMITS: {
33
+ readonly identifier: 128;
34
+ readonly shortText: 200;
35
+ readonly searchQuery: 200;
36
+ readonly tag: 64;
37
+ readonly tagsPerProduct: 20;
38
+ readonly metaEntries: 50;
39
+ readonly signalsPerCategory: 500;
40
+ readonly candidates: 200;
41
+ readonly productsPerBundle: 5;
42
+ readonly bundles: 20;
43
+ };
44
+ /** A product the generated component is permitted to place. */
45
+ export declare const productSchema: z.ZodObject<{
46
+ sku: z.ZodString;
47
+ title: z.ZodString;
48
+ category: z.ZodString;
49
+ price: z.ZodNumber;
50
+ currency: z.ZodDefault<z.ZodString>;
51
+ imageUrl: z.ZodOptional<z.ZodString>;
52
+ rating: z.ZodOptional<z.ZodNumber>;
53
+ isInStock: z.ZodDefault<z.ZodBoolean>;
54
+ tags: z.ZodDefault<z.ZodArray<z.ZodString>>;
55
+ }, z.core.$strict>;
56
+ export type Product = z.infer<typeof productSchema>;
57
+ /** Base shape for any signal that points at a single SKU. */
58
+ export declare const skuSignalSchema: z.ZodObject<{
59
+ sku: z.ZodString;
60
+ category: z.ZodOptional<z.ZodString>;
61
+ at: z.ZodOptional<z.ZodNumber>;
62
+ weight: z.ZodOptional<z.ZodNumber>;
63
+ }, z.core.$strict>;
64
+ export type SkuSignal = z.infer<typeof skuSignalSchema>;
65
+ export declare const viewSignalSchema: z.ZodObject<{
66
+ sku: z.ZodString;
67
+ category: z.ZodOptional<z.ZodString>;
68
+ at: z.ZodOptional<z.ZodNumber>;
69
+ weight: z.ZodOptional<z.ZodNumber>;
70
+ views: z.ZodDefault<z.ZodNumber>;
71
+ dwellMs: z.ZodOptional<z.ZodNumber>;
72
+ }, z.core.$strict>;
73
+ export type ViewSignal = z.infer<typeof viewSignalSchema>;
74
+ export declare const purchaseSignalSchema: z.ZodObject<{
75
+ sku: z.ZodString;
76
+ category: z.ZodOptional<z.ZodString>;
77
+ at: z.ZodOptional<z.ZodNumber>;
78
+ weight: z.ZodOptional<z.ZodNumber>;
79
+ quantity: z.ZodDefault<z.ZodNumber>;
80
+ price: z.ZodOptional<z.ZodNumber>;
81
+ }, z.core.$strict>;
82
+ export type PurchaseSignal = z.infer<typeof purchaseSignalSchema>;
83
+ /**
84
+ * Catch-all for everything else the shopper did. `type` is an open vocabulary
85
+ * on purpose — 'scroll_depth', 'wishlist', 'filter_applied', whatever the host
86
+ * already emits — so hosts do not have to map their events onto ours.
87
+ */
88
+ export declare const interactionSchema: z.ZodObject<{
89
+ type: z.ZodString;
90
+ sku: z.ZodOptional<z.ZodString>;
91
+ category: z.ZodOptional<z.ZodString>;
92
+ at: z.ZodOptional<z.ZodNumber>;
93
+ value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
94
+ meta: z.ZodOptional<z.ZodPipe<z.ZodCustom<Record<string, string | number | boolean>, Record<string, string | number | boolean>>, z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>>;
95
+ }, z.core.$strict>;
96
+ export type Interaction = z.infer<typeof interactionSchema>;
97
+ /** Where on the site this component is being rendered. */
98
+ export declare const renderContextSchema: z.ZodObject<{
99
+ surface: z.ZodString;
100
+ slot: z.ZodDefault<z.ZodString>;
101
+ currentSku: z.ZodOptional<z.ZodString>;
102
+ currentCategory: z.ZodOptional<z.ZodString>;
103
+ searchQuery: z.ZodOptional<z.ZodString>;
104
+ locale: z.ZodDefault<z.ZodString>;
105
+ maxItems: z.ZodDefault<z.ZodNumber>;
106
+ }, z.core.$strict>;
107
+ export type RenderContext = z.infer<typeof renderContextSchema>;
108
+ export declare const trackingSignalsSchema: z.ZodObject<{
109
+ likes: z.ZodDefault<z.ZodArray<z.ZodObject<{
110
+ sku: z.ZodString;
111
+ category: z.ZodOptional<z.ZodString>;
112
+ at: z.ZodOptional<z.ZodNumber>;
113
+ weight: z.ZodOptional<z.ZodNumber>;
114
+ }, z.core.$strict>>>;
115
+ dislikes: z.ZodDefault<z.ZodArray<z.ZodObject<{
116
+ sku: z.ZodString;
117
+ category: z.ZodOptional<z.ZodString>;
118
+ at: z.ZodOptional<z.ZodNumber>;
119
+ weight: z.ZodOptional<z.ZodNumber>;
120
+ }, z.core.$strict>>>;
121
+ mostViewed: z.ZodDefault<z.ZodArray<z.ZodObject<{
122
+ sku: z.ZodString;
123
+ category: z.ZodOptional<z.ZodString>;
124
+ at: z.ZodOptional<z.ZodNumber>;
125
+ weight: z.ZodOptional<z.ZodNumber>;
126
+ views: z.ZodDefault<z.ZodNumber>;
127
+ dwellMs: z.ZodOptional<z.ZodNumber>;
128
+ }, z.core.$strict>>>;
129
+ lastPurchased: z.ZodDefault<z.ZodArray<z.ZodObject<{
130
+ sku: z.ZodString;
131
+ category: z.ZodOptional<z.ZodString>;
132
+ at: z.ZodOptional<z.ZodNumber>;
133
+ weight: z.ZodOptional<z.ZodNumber>;
134
+ quantity: z.ZodDefault<z.ZodNumber>;
135
+ price: z.ZodOptional<z.ZodNumber>;
136
+ }, z.core.$strict>>>;
137
+ cart: z.ZodDefault<z.ZodArray<z.ZodObject<{
138
+ sku: z.ZodString;
139
+ category: z.ZodOptional<z.ZodString>;
140
+ at: z.ZodOptional<z.ZodNumber>;
141
+ weight: z.ZodOptional<z.ZodNumber>;
142
+ }, z.core.$strict>>>;
143
+ recentSearches: z.ZodDefault<z.ZodArray<z.ZodString>>;
144
+ interactions: z.ZodDefault<z.ZodArray<z.ZodObject<{
145
+ type: z.ZodString;
146
+ sku: z.ZodOptional<z.ZodString>;
147
+ category: z.ZodOptional<z.ZodString>;
148
+ at: z.ZodOptional<z.ZodNumber>;
149
+ value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
150
+ meta: z.ZodOptional<z.ZodPipe<z.ZodCustom<Record<string, string | number | boolean>, Record<string, string | number | boolean>>, z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>>;
151
+ }, z.core.$strict>>>;
152
+ }, z.core.$strict>;
153
+ export type TrackingSignals = z.infer<typeof trackingSignalsSchema>;
154
+ /** A set the shop sells together. The model never picks or invents one. */
155
+ export declare const bundleSchema: z.ZodObject<{
156
+ id: z.ZodString;
157
+ skus: z.ZodArray<z.ZodString>;
158
+ price: z.ZodNumber;
159
+ currency: z.ZodDefault<z.ZodString>;
160
+ label: z.ZodOptional<z.ZodString>;
161
+ }, z.core.$strict>;
162
+ export type Bundle = z.infer<typeof bundleSchema>;
163
+ export declare const trackingInputSchema: z.ZodObject<{
164
+ schemaVersion: z.ZodDefault<z.ZodLiteral<"1">>;
165
+ user: z.ZodObject<{
166
+ id: z.ZodString;
167
+ segment: z.ZodOptional<z.ZodString>;
168
+ isReturning: z.ZodOptional<z.ZodBoolean>;
169
+ }, z.core.$strict>;
170
+ context: z.ZodObject<{
171
+ surface: z.ZodString;
172
+ slot: z.ZodDefault<z.ZodString>;
173
+ currentSku: z.ZodOptional<z.ZodString>;
174
+ currentCategory: z.ZodOptional<z.ZodString>;
175
+ searchQuery: z.ZodOptional<z.ZodString>;
176
+ locale: z.ZodDefault<z.ZodString>;
177
+ maxItems: z.ZodDefault<z.ZodNumber>;
178
+ }, z.core.$strict>;
179
+ signals: z.ZodPrefault<z.ZodObject<{
180
+ likes: z.ZodDefault<z.ZodArray<z.ZodObject<{
181
+ sku: z.ZodString;
182
+ category: z.ZodOptional<z.ZodString>;
183
+ at: z.ZodOptional<z.ZodNumber>;
184
+ weight: z.ZodOptional<z.ZodNumber>;
185
+ }, z.core.$strict>>>;
186
+ dislikes: z.ZodDefault<z.ZodArray<z.ZodObject<{
187
+ sku: z.ZodString;
188
+ category: z.ZodOptional<z.ZodString>;
189
+ at: z.ZodOptional<z.ZodNumber>;
190
+ weight: z.ZodOptional<z.ZodNumber>;
191
+ }, z.core.$strict>>>;
192
+ mostViewed: z.ZodDefault<z.ZodArray<z.ZodObject<{
193
+ sku: z.ZodString;
194
+ category: z.ZodOptional<z.ZodString>;
195
+ at: z.ZodOptional<z.ZodNumber>;
196
+ weight: z.ZodOptional<z.ZodNumber>;
197
+ views: z.ZodDefault<z.ZodNumber>;
198
+ dwellMs: z.ZodOptional<z.ZodNumber>;
199
+ }, z.core.$strict>>>;
200
+ lastPurchased: z.ZodDefault<z.ZodArray<z.ZodObject<{
201
+ sku: z.ZodString;
202
+ category: z.ZodOptional<z.ZodString>;
203
+ at: z.ZodOptional<z.ZodNumber>;
204
+ weight: z.ZodOptional<z.ZodNumber>;
205
+ quantity: z.ZodDefault<z.ZodNumber>;
206
+ price: z.ZodOptional<z.ZodNumber>;
207
+ }, z.core.$strict>>>;
208
+ cart: z.ZodDefault<z.ZodArray<z.ZodObject<{
209
+ sku: z.ZodString;
210
+ category: z.ZodOptional<z.ZodString>;
211
+ at: z.ZodOptional<z.ZodNumber>;
212
+ weight: z.ZodOptional<z.ZodNumber>;
213
+ }, z.core.$strict>>>;
214
+ recentSearches: z.ZodDefault<z.ZodArray<z.ZodString>>;
215
+ interactions: z.ZodDefault<z.ZodArray<z.ZodObject<{
216
+ type: z.ZodString;
217
+ sku: z.ZodOptional<z.ZodString>;
218
+ category: z.ZodOptional<z.ZodString>;
219
+ at: z.ZodOptional<z.ZodNumber>;
220
+ value: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>;
221
+ meta: z.ZodOptional<z.ZodPipe<z.ZodCustom<Record<string, string | number | boolean>, Record<string, string | number | boolean>>, z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>>;
222
+ }, z.core.$strict>>>;
223
+ }, z.core.$strict>>;
224
+ candidates: z.ZodArray<z.ZodObject<{
225
+ sku: z.ZodString;
226
+ title: z.ZodString;
227
+ category: z.ZodString;
228
+ price: z.ZodNumber;
229
+ currency: z.ZodDefault<z.ZodString>;
230
+ imageUrl: z.ZodOptional<z.ZodString>;
231
+ rating: z.ZodOptional<z.ZodNumber>;
232
+ isInStock: z.ZodDefault<z.ZodBoolean>;
233
+ tags: z.ZodDefault<z.ZodArray<z.ZodString>>;
234
+ }, z.core.$strict>>;
235
+ bundles: z.ZodDefault<z.ZodArray<z.ZodObject<{
236
+ id: z.ZodString;
237
+ skus: z.ZodArray<z.ZodString>;
238
+ price: z.ZodNumber;
239
+ currency: z.ZodDefault<z.ZodString>;
240
+ label: z.ZodOptional<z.ZodString>;
241
+ }, z.core.$strict>>>;
242
+ }, z.core.$strict>;
243
+ export type TrackingInput = z.infer<typeof trackingInputSchema>;
244
+ /** The shape a caller passes in, before defaults are applied. */
245
+ export type TrackingInputDraft = z.input<typeof trackingInputSchema>;
246
+ /**
247
+ * The result of a non-throwing parse. Exported so a consumer can type a
248
+ * validation failure without depending on zod directly.
249
+ */
250
+ export type TrackingInputResult = z.ZodSafeParseResult<TrackingInput>;
251
+ /**
252
+ * Validates a payload, throwing a `ZodError` if it does not satisfy the
253
+ * contract. An invalid payload is a caller bug, and it should be loud.
254
+ */
255
+ export declare function parseTrackingInput(value: unknown): TrackingInput;
256
+ /** Non-throwing variant, for callers that want to inspect the failure. */
257
+ export declare function safeParseTrackingInput(value: unknown): TrackingInputResult;
258
+ //# sourceMappingURL=tracking-input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracking-input.d.ts","sourceRoot":"","sources":["../src/tracking-input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;;;;GAeG;AAEH;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,YAAY;aACvB,UAAU,EAAE,GAAG;aACf,SAAS,EAAE,GAAG;aACd,WAAW,EAAE,GAAG;aAChB,GAAG,EAAE,EAAE;aACP,cAAc,EAAE,EAAE;aAClB,WAAW,EAAE,EAAE;aACf,kBAAkB,EAAE,GAAG;aACvB,UAAU,EAAE,GAAG;aACf,iBAAiB,EAAE,CAAC;aACpB,OAAO,EAAE,EAAE;CACH,CAAC;AAmCX,+DAA+D;AAC/D,eAAO,MAAM,aAAa;;;;;;;;;;kBAoBxB,CAAC;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEpD,6DAA6D;AAC7D,eAAO,MAAM,eAAe;;;;;kBAM1B,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,eAAO,MAAM,gBAAgB;;;;;;;kBAG3B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,eAAO,MAAM,oBAAoB;;;;;;;kBAG/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAkClE;;;;GAIG;AACH,eAAO,MAAM,iBAAiB;;;;;;;kBAO5B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,0DAA0D;AAC1D,eAAO,MAAM,mBAAmB;;;;;;;;kBAW9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAKhE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAQhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,2EAA2E;AAC3E,eAAO,MAAM,YAAY;;;;;;kBAiBvB,CAAC;AACH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAqD7B,CAAC;AAEJ,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,iEAAiE;AACjE,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAErE;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,kBAAkB,CAAC,aAAa,CAAC,CAAC;AAEtE;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,CAEhE;AAED,0EAA0E;AAC1E,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,mBAAmB,CAE1E"}
@@ -0,0 +1,241 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * The tracking-input contract — the boundary between the host application and
4
+ * rudra-js.
5
+ *
6
+ * rudra-js does not collect, store, or aggregate anything. The host owns its
7
+ * tracking pipeline (an event stream, a CDP, a warehouse) and hands the
8
+ * framework one JSON object per render. This module is that contract: one
9
+ * schema, validated at the edge, so a malformed payload fails loudly here
10
+ * rather than quietly producing a bad prompt several layers later.
11
+ *
12
+ * Every fixed-shape object below is a `strictObject`, so an unrecognised field
13
+ * is an error rather than being dropped. That matters more than it looks: with
14
+ * a lenient object, a host that misspells `recentSearches` gets a shopper who
15
+ * silently looks like a first-time visitor, and nothing anywhere reports it.
16
+ * The only dynamic shape is `interaction.meta`, which is a record by design.
17
+ */
18
+ /**
19
+ * Every free-text field and every array is length-capped.
20
+ *
21
+ * These caps are not cosmetic. Host-supplied strings end up inside the prompt
22
+ * we send to a language model, and a model is billed per token — so an
23
+ * unbounded string is an unbounded bill, and an unbounded array of candidates
24
+ * is the same problem multiplied.
25
+ *
26
+ * What this buys is that no single field is unbounded. It is deliberately not
27
+ * an aggregate budget: the caps multiply out to far more than any context
28
+ * window, because rejecting a large-but-legitimate payload is the wrong
29
+ * response to one. Fitting a payload into a prompt is `digest`'s job, and it
30
+ * trims rather than throws.
31
+ */
32
+ export const FIELD_LIMITS = {
33
+ identifier: 128,
34
+ shortText: 200,
35
+ searchQuery: 200,
36
+ tag: 64,
37
+ tagsPerProduct: 20,
38
+ metaEntries: 50,
39
+ signalsPerCategory: 500,
40
+ candidates: 200,
41
+ productsPerBundle: 5,
42
+ bundles: 20,
43
+ };
44
+ /** Assigning this as an object key mutates the prototype instead of the object. */
45
+ const RESERVED_META_KEY = '__proto__';
46
+ /** Upper bound on any timestamp: 2100-01-01. */
47
+ const MAX_EPOCH_MS = Date.UTC(2100, 0, 1);
48
+ const identifier = () => z.string().min(1).max(FIELD_LIMITS.identifier);
49
+ const optionalIdentifier = () => z.string().min(1).max(FIELD_LIMITS.identifier).optional();
50
+ /**
51
+ * Epoch milliseconds, used only for recency ordering. Bounded because a
52
+ * negative or year-3000 timestamp does not fail anywhere downstream — it just
53
+ * sorts to one end and silently reorders the shopper's history.
54
+ */
55
+ const epochMs = () => z.number().int().min(0).max(MAX_EPOCH_MS).optional();
56
+ /**
57
+ * An absolute http(s) URL, or a root-relative path such as `/images/tr-102.png`.
58
+ * Anything else — a bare word, a `javascript:` URI, a protocol-relative `//host`
59
+ * — is rejected before it can reach an `<img src>`.
60
+ */
61
+ const imageReference = () => z
62
+ .string()
63
+ .max(FIELD_LIMITS.shortText)
64
+ .refine((value) => value.startsWith('/') && !value.startsWith('//')
65
+ ? true
66
+ : z.url({ protocol: /^https?$/ }).safeParse(value).success, { message: 'expected an http(s) URL or a root-relative path' });
67
+ /** A product the generated component is permitted to place. */
68
+ export const productSchema = z.strictObject({
69
+ sku: identifier(),
70
+ title: z.string().min(1).max(FIELD_LIMITS.shortText),
71
+ category: identifier(),
72
+ price: z.number().nonnegative(),
73
+ currency: z
74
+ .string()
75
+ .regex(/^[A-Z]{3}$/, 'expected a three-letter ISO 4217 code')
76
+ .default('USD'),
77
+ // This lands in an `<img src>` the host did not write, so the scheme matters:
78
+ // a bare capped string would accept '' and 'javascript:'. Root-relative paths
79
+ // are allowed because most catalogs store images that way, and they carry no
80
+ // scheme to abuse.
81
+ imageUrl: imageReference().optional(),
82
+ rating: z.number().min(0).max(5).optional(),
83
+ isInStock: z.boolean().default(true),
84
+ tags: z
85
+ .array(z.string().min(1).max(FIELD_LIMITS.tag))
86
+ .max(FIELD_LIMITS.tagsPerProduct)
87
+ .default([]),
88
+ });
89
+ /** Base shape for any signal that points at a single SKU. */
90
+ export const skuSignalSchema = z.strictObject({
91
+ sku: identifier(),
92
+ category: optionalIdentifier(),
93
+ at: epochMs(),
94
+ /** Caller-supplied strength, 0..1. Defaults to 1 when absent. */
95
+ weight: z.number().min(0).max(1).optional(),
96
+ });
97
+ export const viewSignalSchema = skuSignalSchema.extend({
98
+ views: z.number().int().positive().default(1),
99
+ dwellMs: z.number().nonnegative().optional(),
100
+ });
101
+ export const purchaseSignalSchema = skuSignalSchema.extend({
102
+ quantity: z.number().int().positive().default(1),
103
+ price: z.number().nonnegative().optional(),
104
+ });
105
+ /**
106
+ * `meta` is the one dynamic shape in the contract, so its key is checked before
107
+ * the record is parsed rather than after. Zod builds its result by assigning
108
+ * each key, and assigning `__proto__` sets the prototype instead of adding a
109
+ * key — so the entry would vanish from the parsed output with no error, which
110
+ * is the silent drop this module exists to prevent.
111
+ *
112
+ * `__proto__` is the only key that behaves this way. `constructor` and
113
+ * `prototype` are ordinary own properties: assigning either shadows it on that
114
+ * one object and leaves the prototype alone, so both survive a parse intact and
115
+ * are accepted. `meta` is a host-defined vocabulary, and a shop with a facet,
116
+ * filter, or CMS field by either name should get a component, not a throw.
117
+ */
118
+ const metaKeysAreSafe = z.custom((value) => typeof value === 'object' && value !== null && !Object.hasOwn(value, RESERVED_META_KEY), { message: `meta may not use the reserved key ${RESERVED_META_KEY}` });
119
+ // `z.record` bounds key and value shape but not how many entries a record may
120
+ // carry, so the count is checked separately.
121
+ const metaSchema = metaKeysAreSafe.pipe(z
122
+ .record(z.string().min(1).max(FIELD_LIMITS.identifier), z.union([z.string().max(FIELD_LIMITS.shortText), z.number(), z.boolean()]))
123
+ .refine((entries) => Object.keys(entries).length <= FIELD_LIMITS.metaEntries, {
124
+ message: `meta may carry at most ${FIELD_LIMITS.metaEntries} entries`,
125
+ }));
126
+ /**
127
+ * Catch-all for everything else the shopper did. `type` is an open vocabulary
128
+ * on purpose — 'scroll_depth', 'wishlist', 'filter_applied', whatever the host
129
+ * already emits — so hosts do not have to map their events onto ours.
130
+ */
131
+ export const interactionSchema = z.strictObject({
132
+ type: identifier(),
133
+ sku: optionalIdentifier(),
134
+ category: optionalIdentifier(),
135
+ at: epochMs(),
136
+ value: z.union([z.string().max(FIELD_LIMITS.shortText), z.number(), z.boolean()]).optional(),
137
+ meta: metaSchema.optional(),
138
+ });
139
+ /** Where on the site this component is being rendered. */
140
+ export const renderContextSchema = z.strictObject({
141
+ /** 'pdp', 'home', 'cart', 'search', or any host-defined surface. */
142
+ surface: identifier(),
143
+ /** Named placement, e.g. 'below-fold-recommendations'. */
144
+ slot: z.string().min(1).max(FIELD_LIMITS.identifier).default('recommendations'),
145
+ currentSku: optionalIdentifier(),
146
+ currentCategory: optionalIdentifier(),
147
+ searchQuery: z.string().max(FIELD_LIMITS.searchQuery).optional(),
148
+ locale: z.string().min(2).max(35).default('en-US'),
149
+ /** Upper bound on products across the whole generated component. */
150
+ maxItems: z.number().int().min(1).max(12).default(4),
151
+ });
152
+ const signalArray = (schema) => z.array(schema).max(FIELD_LIMITS.signalsPerCategory).default([]);
153
+ export const trackingSignalsSchema = z.strictObject({
154
+ likes: signalArray(skuSignalSchema),
155
+ dislikes: signalArray(skuSignalSchema),
156
+ mostViewed: signalArray(viewSignalSchema),
157
+ lastPurchased: signalArray(purchaseSignalSchema),
158
+ cart: signalArray(skuSignalSchema),
159
+ recentSearches: signalArray(z.string().min(1).max(FIELD_LIMITS.searchQuery)),
160
+ interactions: signalArray(interactionSchema),
161
+ });
162
+ /** A set the shop sells together. The model never picks or invents one. */
163
+ export const bundleSchema = z.strictObject({
164
+ id: identifier(),
165
+ skus: z
166
+ .array(identifier())
167
+ .min(2)
168
+ .max(FIELD_LIMITS.productsPerBundle)
169
+ .refine((skus) => new Set(skus).size === skus.length, {
170
+ message: 'a bundle must not list the same product twice',
171
+ }),
172
+ // The shop's price for the set — not derived from the parts, so the set says
173
+ // which money it is in rather than borrowing it from a member.
174
+ price: z.number().nonnegative(),
175
+ currency: z
176
+ .string()
177
+ .regex(/^[A-Z]{3}$/, 'expected a three-letter ISO 4217 code')
178
+ .default('USD'),
179
+ label: z.string().min(1).max(FIELD_LIMITS.shortText).optional(),
180
+ });
181
+ export const trackingInputSchema = z
182
+ .strictObject({
183
+ schemaVersion: z.literal('1').default('1'),
184
+ user: z.strictObject({
185
+ id: identifier(),
186
+ segment: optionalIdentifier(),
187
+ isReturning: z.boolean().optional(),
188
+ }),
189
+ context: renderContextSchema,
190
+ // A payload with no `signals` block at all is the cold-start case, not an
191
+ // error. Every category defaults to empty, so a first-time visitor needs no
192
+ // special handling from the host.
193
+ signals: trackingSignalsSchema.prefault({}),
194
+ /**
195
+ * The only products the generated component may place. Merchandising rules
196
+ * belong here: whatever the host leaves out cannot be recommended, which is
197
+ * what makes it impossible to surface a product that does not exist or is not
198
+ * merchandised for this shopper.
199
+ *
200
+ * SKUs must be unique — a duplicate is a host bug that spends prompt budget
201
+ * twice and invites the same product in two slots.
202
+ */
203
+ candidates: z
204
+ .array(productSchema)
205
+ .min(1)
206
+ .max(FIELD_LIMITS.candidates)
207
+ .refine((products) => new Set(products.map((product) => product.sku)).size === products.length, {
208
+ message: 'candidates must have unique SKUs',
209
+ }),
210
+ // Ids must be unique — the renderer looks a bundle up by id alone, so a
211
+ // duplicate would let it draw the wrong set at the wrong price.
212
+ bundles: z
213
+ .array(bundleSchema)
214
+ .max(FIELD_LIMITS.bundles)
215
+ .refine((bundles) => new Set(bundles.map((bundle) => bundle.id)).size === bundles.length, {
216
+ message: 'bundles must have unique ids',
217
+ })
218
+ .default([]),
219
+ })
220
+ .refine((input) => {
221
+ const candidateSkus = new Set(input.candidates.map((product) => product.sku));
222
+ for (const bundle of input.bundles) {
223
+ for (const sku of bundle.skus) {
224
+ if (!candidateSkus.has(sku))
225
+ return false;
226
+ }
227
+ }
228
+ return true;
229
+ }, { message: 'every product in a bundle must also be a candidate' });
230
+ /**
231
+ * Validates a payload, throwing a `ZodError` if it does not satisfy the
232
+ * contract. An invalid payload is a caller bug, and it should be loud.
233
+ */
234
+ export function parseTrackingInput(value) {
235
+ return trackingInputSchema.parse(value);
236
+ }
237
+ /** Non-throwing variant, for callers that want to inspect the failure. */
238
+ export function safeParseTrackingInput(value) {
239
+ return trackingInputSchema.safeParse(value);
240
+ }
241
+ //# sourceMappingURL=tracking-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracking-input.js","sourceRoot":"","sources":["../src/tracking-input.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@rudra-js/core",
3
+ "version": "0.1.0",
4
+ "description": "The contracts and logic that turn one tracking payload into one renderable component specification",
5
+ "keywords": [
6
+ "llm",
7
+ "server-components",
8
+ "recommendations",
9
+ "ecommerce",
10
+ "personalization",
11
+ "ssr",
12
+ "zod"
13
+ ],
14
+ "license": "MIT",
15
+ "author": "Clive Dsouza",
16
+ "homepage": "https://github.com/clivedsouza1010/rudra-js/tree/main/packages/core#readme",
17
+ "bugs": {
18
+ "url": "https://github.com/clivedsouza1010/rudra-js/issues"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/clivedsouza1010/rudra-js.git",
23
+ "directory": "packages/core"
24
+ },
25
+ "engines": {
26
+ "node": "^20.19.0 || >=22.12.0"
27
+ },
28
+ "type": "module",
29
+ "main": "./dist/index.js",
30
+ "types": "./dist/index.d.ts",
31
+ "exports": {
32
+ ".": {
33
+ "types": "./dist/index.d.ts",
34
+ "default": "./dist/index.js"
35
+ },
36
+ "./package.json": "./package.json"
37
+ },
38
+ "files": [
39
+ "dist",
40
+ "src/**/*.ts",
41
+ "src/**/*.tsx",
42
+ "!src/**/*.test.ts",
43
+ "!src/**/*.test.tsx"
44
+ ],
45
+ "sideEffects": false,
46
+ "scripts": {
47
+ "build": "tsc -p tsconfig.json",
48
+ "prepack": "npm run build"
49
+ },
50
+ "publishConfig": {
51
+ "access": "public"
52
+ },
53
+ "peerDependencies": {
54
+ "zod": "^4.5.4"
55
+ },
56
+ "devDependencies": {
57
+ "@types/node": "^26.4.1",
58
+ "zod": "^4.5.4"
59
+ }
60
+ }