@substrat-run/contracts 0.91.1 → 0.92.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.
@@ -0,0 +1,104 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Where the request came from, as far as the edge could tell.
4
+ *
5
+ * `region` is the human name (`Stockholm County`), not a code — codes differ per
6
+ * country and a person reads the name. `timezone` is an IANA name, which is what a
7
+ * UI hands to `Intl.DateTimeFormat` to show the visitor's local time.
8
+ */
9
+ export declare const clientGeo: z.ZodObject<{
10
+ country: z.ZodNullable<z.ZodString>;
11
+ region: z.ZodNullable<z.ZodString>;
12
+ city: z.ZodNullable<z.ZodString>;
13
+ timezone: z.ZodNullable<z.ZodString>;
14
+ continent: z.ZodNullable<z.ZodString>;
15
+ }, z.core.$strip>;
16
+ export type ClientGeo = z.infer<typeof clientGeo>;
17
+ export declare const EMPTY_GEO: ClientGeo;
18
+ /**
19
+ * What kind of thing sent the request. Coarse on purpose: the question a person
20
+ * asks is "were they on a phone?", and a finer answer than this would be a guess
21
+ * dressed as a fact — user agents lie, and iPadOS reports itself as a Mac.
22
+ */
23
+ export declare const clientDeviceKind: z.ZodEnum<{
24
+ bot: "bot";
25
+ desktop: "desktop";
26
+ mobile: "mobile";
27
+ tablet: "tablet";
28
+ unknown: "unknown";
29
+ }>;
30
+ export type ClientDeviceKind = z.infer<typeof clientDeviceKind>;
31
+ /** The browser and operating system, parsed out of the `User-Agent` into names a person reads. */
32
+ export declare const clientDevice: z.ZodObject<{
33
+ browser: z.ZodNullable<z.ZodString>;
34
+ browserVersion: z.ZodNullable<z.ZodString>;
35
+ os: z.ZodNullable<z.ZodString>;
36
+ osVersion: z.ZodNullable<z.ZodString>;
37
+ kind: z.ZodEnum<{
38
+ bot: "bot";
39
+ desktop: "desktop";
40
+ mobile: "mobile";
41
+ tablet: "tablet";
42
+ unknown: "unknown";
43
+ }>;
44
+ }, z.core.$strip>;
45
+ export type ClientDevice = z.infer<typeof clientDevice>;
46
+ export declare const clientContext: z.ZodObject<{
47
+ userAgent: z.ZodNullable<z.ZodString>;
48
+ language: z.ZodNullable<z.ZodString>;
49
+ device: z.ZodObject<{
50
+ browser: z.ZodNullable<z.ZodString>;
51
+ browserVersion: z.ZodNullable<z.ZodString>;
52
+ os: z.ZodNullable<z.ZodString>;
53
+ osVersion: z.ZodNullable<z.ZodString>;
54
+ kind: z.ZodEnum<{
55
+ bot: "bot";
56
+ desktop: "desktop";
57
+ mobile: "mobile";
58
+ tablet: "tablet";
59
+ unknown: "unknown";
60
+ }>;
61
+ }, z.core.$strip>;
62
+ geo: z.ZodObject<{
63
+ country: z.ZodNullable<z.ZodString>;
64
+ region: z.ZodNullable<z.ZodString>;
65
+ city: z.ZodNullable<z.ZodString>;
66
+ timezone: z.ZodNullable<z.ZodString>;
67
+ continent: z.ZodNullable<z.ZodString>;
68
+ }, z.core.$strip>;
69
+ }, z.core.$strip>;
70
+ export type ClientContext = z.infer<typeof clientContext>;
71
+ /**
72
+ * Turn a `User-Agent` into names a person reads.
73
+ *
74
+ * Hand-rolled and small on purpose. A full UA database is a dependency that
75
+ * changes weekly and answers questions nobody here asks (which Nokia model?); this
76
+ * answers the four a support agent does — which browser, which OS, phone or not,
77
+ * human or not — and stores the raw string beside them so a wrong answer can be
78
+ * re-read later. Absent or unrecognised input is `unknown`, never a throw: a request
79
+ * with a strange UA is still a request.
80
+ */
81
+ export declare function parseUserAgent(userAgent: string | null | undefined): ClientDevice;
82
+ /** The subset of the web-standard `Headers` this needs — so a test hands in a plain object. */
83
+ export interface HeadersLike {
84
+ get(name: string): string | null;
85
+ }
86
+ /**
87
+ * The first language tag of `Accept-Language`, or null. The header is a weighted
88
+ * list (`sv-SE,sv;q=0.9,en;q=0.8`) and browsers put the preferred one first, so the
89
+ * head is the answer; weights are not re-sorted, because no browser sends them out
90
+ * of order and a hand-written header that does is not worth a parser.
91
+ */
92
+ export declare function preferredLanguage(acceptLanguage: string | null | undefined): string | null;
93
+ /**
94
+ * Build a `ClientContext` from a request's headers and whatever geo the host knows.
95
+ *
96
+ * This is the runtime-neutral half: the headers are the same on every host, and the
97
+ * geo is what differs — so a host with none (the node dev server) passes nothing and
98
+ * gets `EMPTY_GEO`, and one with some (`cloudflareClientContext`) passes what it
99
+ * normalised. A partial geo is filled out to the full shape so a row always has
100
+ * every column — and a field that is present but `undefined` counts as absent, since
101
+ * `Partial` admits it and a spread would carry it through to a schema that does not.
102
+ */
103
+ export declare function clientContextOf(headers: HeadersLike, geo?: Partial<ClientGeo>): ClientContext;
104
+ //# sourceMappingURL=client-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-context.d.ts","sourceRoot":"","sources":["../src/client-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAgCxB;;;;;;GAMG;AACH,eAAO,MAAM,SAAS;;;;;;iBAOpB,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC;AAElD,eAAO,MAAM,SAAS,EAAE,SAMtB,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,gBAAgB;;;;;;EAA4D,CAAC;AAC1F,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEhE,kGAAkG;AAClG,eAAO,MAAM,YAAY;;;;;;;;;;;;iBASvB,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAExD,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;iBAOxB,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAiG1D;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,YAAY,CAsBjF;AAMD,+FAA+F;AAC/F,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;CAClC;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAG1F;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,aAAa,CAc7F"}
@@ -0,0 +1,243 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Who is on the other end of a request — the CLIENT, not the principal.
4
+ *
5
+ * A principal says who is authorised; this says what they are holding and roughly
6
+ * where they are holding it: the browser and OS a support agent needs to reproduce
7
+ * a bug, the country and timezone that tell them it is 3 am for the person typing,
8
+ * the language the reply should probably be in. None of it is authority, and none of
9
+ * it is trusted for anything but display and triage.
10
+ *
11
+ * It is a NORMALISED shape, and that is the point of it. Every runtime hands these
12
+ * facts over differently — Cloudflare puts geo on `request.cf`, another edge puts it
13
+ * in headers, a node dev server has no geo at all — and a vertical that read the raw
14
+ * source would be a vertical that only runs on one host. So a host builds one of
15
+ * these (`@substrat-run/adapter-cloudflare` exports `cloudflareClientContext`), passes
16
+ * it in as operation input, and module code sees only this. The one part that is the
17
+ * same everywhere — the `User-Agent` and `Accept-Language` headers — is parsed here,
18
+ * so every host reads "Safari 17 on iOS" the same way.
19
+ *
20
+ * What is deliberately absent: the IP address. It is the most identifying field a
21
+ * request carries and the least useful to a person reading a conversation; the
22
+ * country and city it resolves to carry the useful part without the fingerprint.
23
+ * Every COLLECTED value is nullable, because every one is something a request may not
24
+ * say; the shape around them is not. `device` and `geo` are always present, and
25
+ * `device.kind` is always a kind — `'unknown'` when the parser could not tell — so a
26
+ * reader destructures without guarding and a row always has every column.
27
+ */
28
+ /** ISO 3166-1 alpha-2, upper case. */
29
+ const countryCode = z.string().regex(/^[A-Z]{2}$/);
30
+ /**
31
+ * Where the request came from, as far as the edge could tell.
32
+ *
33
+ * `region` is the human name (`Stockholm County`), not a code — codes differ per
34
+ * country and a person reads the name. `timezone` is an IANA name, which is what a
35
+ * UI hands to `Intl.DateTimeFormat` to show the visitor's local time.
36
+ */
37
+ export const clientGeo = z.object({
38
+ country: countryCode.nullable(),
39
+ region: z.string().nullable(),
40
+ city: z.string().nullable(),
41
+ timezone: z.string().nullable(),
42
+ /** Two-letter continent code as Cloudflare reports it (`EU`, `NA`, …). */
43
+ continent: z.string().regex(/^[A-Z]{2}$/).nullable(),
44
+ });
45
+ export const EMPTY_GEO = Object.freeze({
46
+ country: null,
47
+ region: null,
48
+ city: null,
49
+ timezone: null,
50
+ continent: null,
51
+ });
52
+ /**
53
+ * What kind of thing sent the request. Coarse on purpose: the question a person
54
+ * asks is "were they on a phone?", and a finer answer than this would be a guess
55
+ * dressed as a fact — user agents lie, and iPadOS reports itself as a Mac.
56
+ */
57
+ export const clientDeviceKind = z.enum(['desktop', 'mobile', 'tablet', 'bot', 'unknown']);
58
+ /** The browser and operating system, parsed out of the `User-Agent` into names a person reads. */
59
+ export const clientDevice = z.object({
60
+ /** `Chrome`, `Safari`, `Firefox`, `Edge`, `Samsung Internet`, `Opera`, `Internet Explorer`, or a bot's name. */
61
+ browser: z.string().nullable(),
62
+ /** As reported, e.g. `126.0.6478.127`; show the major. */
63
+ browserVersion: z.string().nullable(),
64
+ /** `iOS`, `Android`, `macOS`, `Windows`, `Linux`, `ChromeOS`. */
65
+ os: z.string().nullable(),
66
+ osVersion: z.string().nullable(),
67
+ kind: clientDeviceKind,
68
+ });
69
+ export const clientContext = z.object({
70
+ /** The raw header, kept so a better parser can re-read it later. */
71
+ userAgent: z.string().nullable(),
72
+ /** The first tag of `Accept-Language` (BCP 47, e.g. `sv-SE`) — what the person asked to be spoken to in. */
73
+ language: z.string().nullable(),
74
+ device: clientDevice,
75
+ geo: clientGeo,
76
+ });
77
+ // ---------------------------------------------------------------------------
78
+ // User-Agent parsing
79
+ // ---------------------------------------------------------------------------
80
+ const UNKNOWN_DEVICE = Object.freeze({
81
+ browser: null,
82
+ browserVersion: null,
83
+ os: null,
84
+ osVersion: null,
85
+ kind: 'unknown',
86
+ });
87
+ /**
88
+ * The bots worth naming. Anything else matching the generic tail is still a bot,
89
+ * just an unnamed one.
90
+ */
91
+ const BOT_NAMES = [
92
+ [/Googlebot/i, 'Googlebot'],
93
+ [/bingbot/i, 'Bingbot'],
94
+ [/DuckDuckBot/i, 'DuckDuckBot'],
95
+ [/Slackbot/i, 'Slackbot'],
96
+ [/Twitterbot/i, 'Twitterbot'],
97
+ [/facebookexternalhit/i, 'Facebook'],
98
+ [/LinkedInBot/i, 'LinkedInBot'],
99
+ [/Applebot/i, 'Applebot'],
100
+ [/GPTBot/i, 'GPTBot'],
101
+ [/ClaudeBot/i, 'ClaudeBot'],
102
+ [/HeadlessChrome/i, 'Headless Chrome'],
103
+ [/Lighthouse/i, 'Lighthouse'],
104
+ [/curl\//i, 'curl'],
105
+ [/Wget\//i, 'wget'],
106
+ [/python-requests|python-urllib|aiohttp/i, 'Python'],
107
+ [/Go-http-client/i, 'Go'],
108
+ [/node-fetch|undici/i, 'Node'],
109
+ ];
110
+ const BOT_GENERIC = /bot|crawl|spider|slurp|scrape|fetch|monitor|preview|headless/i;
111
+ /**
112
+ * Browsers in the order they must be tried. Every Chromium fork carries `Chrome/`
113
+ * and every WebKit browser carries `Safari/`, so the specific names go first and
114
+ * the two generic ones last.
115
+ */
116
+ const BROWSERS = [
117
+ [/\bEdg(?:e|A|iOS)?\/([\d.]+)/, 'Edge'],
118
+ [/\bOPR\/([\d.]+)/, 'Opera'],
119
+ [/\bOpera[/ ]([\d.]+)/, 'Opera'],
120
+ [/\bSamsungBrowser\/([\d.]+)/, 'Samsung Internet'],
121
+ [/\bFirefox\/([\d.]+)/, 'Firefox'],
122
+ [/\bFxiOS\/([\d.]+)/, 'Firefox'],
123
+ [/\bCriOS\/([\d.]+)/, 'Chrome'],
124
+ [/\bChrome\/([\d.]+)/, 'Chrome'],
125
+ // Safari's own version is in `Version/`; the `Safari/` token is the WebKit build.
126
+ [/\bVersion\/([\d.]+).*\bSafari\//, 'Safari'],
127
+ [/\bMSIE ([\d.]+)/, 'Internet Explorer'],
128
+ [/\bTrident\/.*\brv:([\d.]+)/, 'Internet Explorer'],
129
+ ];
130
+ /** `Windows NT 10.0` is Windows 10 (or 11 — the UA cannot tell them apart). */
131
+ const WINDOWS_NT = {
132
+ '10.0': '10',
133
+ '6.3': '8.1',
134
+ '6.2': '8',
135
+ '6.1': '7',
136
+ '6.0': 'Vista',
137
+ '5.1': 'XP',
138
+ };
139
+ function os(ua) {
140
+ let m;
141
+ if ((m = /\b(?:iPhone|iPad|iPod)\b.*?\bOS (\d+(?:_\d+)*)/.exec(ua)))
142
+ return { os: 'iOS', osVersion: m[1].replace(/_/g, '.') };
143
+ if (/\b(?:iPhone|iPad|iPod)\b/.test(ua))
144
+ return { os: 'iOS', osVersion: null };
145
+ if ((m = /\bAndroid (\d+(?:\.\d+)*)/.exec(ua)))
146
+ return { os: 'Android', osVersion: m[1] };
147
+ if (/\bAndroid\b/.test(ua))
148
+ return { os: 'Android', osVersion: null };
149
+ if ((m = /\bWindows NT (\d+\.\d+)/.exec(ua)))
150
+ return { os: 'Windows', osVersion: WINDOWS_NT[m[1]] ?? m[1] };
151
+ if (/\bWindows\b/.test(ua))
152
+ return { os: 'Windows', osVersion: null };
153
+ if ((m = /\bMac OS X (\d+(?:[_.]\d+)*)/.exec(ua)))
154
+ return { os: 'macOS', osVersion: m[1].replace(/_/g, '.') };
155
+ if (/\bMacintosh\b/.test(ua))
156
+ return { os: 'macOS', osVersion: null };
157
+ if (/\bCrOS\b/.test(ua))
158
+ return { os: 'ChromeOS', osVersion: null };
159
+ if (/\bLinux\b|\bX11\b/.test(ua))
160
+ return { os: 'Linux', osVersion: null };
161
+ return { os: null, osVersion: null };
162
+ }
163
+ function kindOf(ua, osName) {
164
+ if (/\biPad\b|\bTablet\b/i.test(ua))
165
+ return 'tablet';
166
+ // Android reports `Mobile` on phones and omits it on tablets.
167
+ if (osName === 'Android')
168
+ return /\bMobile\b/.test(ua) ? 'mobile' : 'tablet';
169
+ if (/\biPhone\b|\biPod\b|\bMobi/i.test(ua))
170
+ return 'mobile';
171
+ if (osName === 'Windows' || osName === 'macOS' || osName === 'Linux' || osName === 'ChromeOS')
172
+ return 'desktop';
173
+ return 'unknown';
174
+ }
175
+ /**
176
+ * Turn a `User-Agent` into names a person reads.
177
+ *
178
+ * Hand-rolled and small on purpose. A full UA database is a dependency that
179
+ * changes weekly and answers questions nobody here asks (which Nokia model?); this
180
+ * answers the four a support agent does — which browser, which OS, phone or not,
181
+ * human or not — and stores the raw string beside them so a wrong answer can be
182
+ * re-read later. Absent or unrecognised input is `unknown`, never a throw: a request
183
+ * with a strange UA is still a request.
184
+ */
185
+ export function parseUserAgent(userAgent) {
186
+ const ua = userAgent?.trim() ?? '';
187
+ if (!ua)
188
+ return UNKNOWN_DEVICE;
189
+ for (const [re, name] of BOT_NAMES)
190
+ if (re.test(ua))
191
+ return { ...UNKNOWN_DEVICE, browser: name, kind: 'bot' };
192
+ const platform = os(ua);
193
+ let browser = null;
194
+ let browserVersion = null;
195
+ for (const [re, name] of BROWSERS) {
196
+ const m = re.exec(ua);
197
+ if (m) {
198
+ browser = name;
199
+ browserVersion = m[1] ?? null;
200
+ break;
201
+ }
202
+ }
203
+ // An unnamed crawler that still says "bot" somewhere: a browser never does, so the
204
+ // browser and OS it may spoof are kept (they are what it claims) and the kind is not.
205
+ const kind = BOT_GENERIC.test(ua) ? 'bot' : kindOf(ua, platform.os);
206
+ return { browser, browserVersion, os: platform.os, osVersion: platform.osVersion, kind };
207
+ }
208
+ /**
209
+ * The first language tag of `Accept-Language`, or null. The header is a weighted
210
+ * list (`sv-SE,sv;q=0.9,en;q=0.8`) and browsers put the preferred one first, so the
211
+ * head is the answer; weights are not re-sorted, because no browser sends them out
212
+ * of order and a hand-written header that does is not worth a parser.
213
+ */
214
+ export function preferredLanguage(acceptLanguage) {
215
+ const first = acceptLanguage?.split(',')[0]?.split(';')[0]?.trim() ?? '';
216
+ return /^[A-Za-z]{1,8}(?:-[A-Za-z0-9]{1,8})*$/.test(first) ? first : null;
217
+ }
218
+ /**
219
+ * Build a `ClientContext` from a request's headers and whatever geo the host knows.
220
+ *
221
+ * This is the runtime-neutral half: the headers are the same on every host, and the
222
+ * geo is what differs — so a host with none (the node dev server) passes nothing and
223
+ * gets `EMPTY_GEO`, and one with some (`cloudflareClientContext`) passes what it
224
+ * normalised. A partial geo is filled out to the full shape so a row always has
225
+ * every column — and a field that is present but `undefined` counts as absent, since
226
+ * `Partial` admits it and a spread would carry it through to a schema that does not.
227
+ */
228
+ export function clientContextOf(headers, geo) {
229
+ const userAgent = headers.get('user-agent')?.trim() || null;
230
+ return {
231
+ userAgent,
232
+ language: preferredLanguage(headers.get('accept-language')),
233
+ device: parseUserAgent(userAgent),
234
+ geo: {
235
+ country: geo?.country ?? null,
236
+ region: geo?.region ?? null,
237
+ city: geo?.city ?? null,
238
+ timezone: geo?.timezone ?? null,
239
+ continent: geo?.continent ?? null,
240
+ },
241
+ };
242
+ }
243
+ //# sourceMappingURL=client-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-context.js","sourceRoot":"","sources":["../src/client-context.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -42,4 +42,5 @@ export * from './attachments.js';
42
42
  export * from './model.js';
43
43
  export * from './operations.js';
44
44
  export * from './lifecycle.js';
45
+ export * from './client-context.js';
45
46
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC"}
package/dist/index.js CHANGED
@@ -42,4 +42,5 @@ export * from './attachments.js';
42
42
  export * from './model.js';
43
43
  export * from './operations.js';
44
44
  export * from './lifecycle.js';
45
+ export * from './client-context.js';
45
46
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@substrat-run/contracts",
3
- "version": "0.91.1",
3
+ "version": "0.92.0",
4
4
  "description": "Substrat kernel contract schemas — Zod is the source of truth (master plan D-22); OAS/JSON Schema are emitted artifacts",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {