@anby/platform-sdk 0.1.0 → 0.7.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 (69) hide show
  1. package/dist/cjs/apps/publish.d.ts +23 -0
  2. package/dist/cjs/apps/publish.d.ts.map +1 -1
  3. package/dist/cjs/apps/publish.js +65 -5
  4. package/dist/cjs/apps/publish.js.map +1 -1
  5. package/dist/cjs/auth/index.d.ts +33 -3
  6. package/dist/cjs/auth/index.d.ts.map +1 -1
  7. package/dist/cjs/auth/index.js +105 -24
  8. package/dist/cjs/auth/index.js.map +1 -1
  9. package/dist/cjs/bootstrap/cache.d.ts +4 -0
  10. package/dist/cjs/bootstrap/cache.d.ts.map +1 -0
  11. package/dist/cjs/bootstrap/cache.js +52 -0
  12. package/dist/cjs/bootstrap/cache.js.map +1 -0
  13. package/dist/cjs/bootstrap/index.d.ts +79 -0
  14. package/dist/cjs/bootstrap/index.d.ts.map +1 -0
  15. package/dist/cjs/bootstrap/index.js +280 -0
  16. package/dist/cjs/bootstrap/index.js.map +1 -0
  17. package/dist/cjs/bootstrap/types.d.ts +53 -0
  18. package/dist/cjs/bootstrap/types.d.ts.map +1 -0
  19. package/dist/cjs/bootstrap/types.js +14 -0
  20. package/dist/cjs/bootstrap/types.js.map +1 -0
  21. package/dist/cjs/events/http-transport.d.ts +38 -0
  22. package/dist/cjs/events/http-transport.d.ts.map +1 -0
  23. package/dist/cjs/events/http-transport.js +63 -0
  24. package/dist/cjs/events/http-transport.js.map +1 -0
  25. package/dist/cjs/events/index.d.ts +49 -0
  26. package/dist/cjs/events/index.d.ts.map +1 -1
  27. package/dist/cjs/events/index.js +14 -1
  28. package/dist/cjs/events/index.js.map +1 -1
  29. package/dist/cjs/index.d.ts +6 -3
  30. package/dist/cjs/index.d.ts.map +1 -1
  31. package/dist/cjs/index.js +30 -11
  32. package/dist/cjs/index.js.map +1 -1
  33. package/dist/cjs/package.json +1 -0
  34. package/dist/cjs/vite/index.d.ts +20 -0
  35. package/dist/cjs/vite/index.d.ts.map +1 -0
  36. package/dist/cjs/vite/index.js +154 -0
  37. package/dist/cjs/vite/index.js.map +1 -0
  38. package/dist/esm/apps/publish.js +31 -5
  39. package/dist/esm/apps/publish.js.map +1 -1
  40. package/dist/esm/auth/index.js +102 -23
  41. package/dist/esm/auth/index.js.map +1 -1
  42. package/dist/esm/bootstrap/cache.js +48 -0
  43. package/dist/esm/bootstrap/cache.js.map +1 -0
  44. package/dist/esm/bootstrap/index.js +272 -0
  45. package/dist/esm/bootstrap/index.js.map +1 -0
  46. package/dist/esm/bootstrap/types.js +11 -0
  47. package/dist/esm/bootstrap/types.js.map +1 -0
  48. package/dist/esm/events/http-transport.js +59 -0
  49. package/dist/esm/events/http-transport.js.map +1 -0
  50. package/dist/esm/events/index.js +14 -1
  51. package/dist/esm/events/index.js.map +1 -1
  52. package/dist/esm/index.js +8 -2
  53. package/dist/esm/index.js.map +1 -1
  54. package/dist/esm/package.json +1 -0
  55. package/dist/esm/vite/index.js +151 -0
  56. package/dist/esm/vite/index.js.map +1 -0
  57. package/package.json +20 -7
  58. package/src/apps/publish.ts +45 -6
  59. package/src/auth/index.test.ts +249 -0
  60. package/src/auth/index.ts +126 -32
  61. package/src/bootstrap/cache.ts +60 -0
  62. package/src/bootstrap/index.test.ts +277 -0
  63. package/src/bootstrap/index.ts +350 -0
  64. package/src/bootstrap/types.ts +56 -0
  65. package/src/events/http-transport.test.ts +135 -0
  66. package/src/events/http-transport.ts +77 -0
  67. package/src/events/index.ts +73 -2
  68. package/src/index.ts +29 -1
  69. package/src/vite/index.ts +195 -0
@@ -0,0 +1,280 @@
1
+ "use strict";
2
+ /**
3
+ * Third-party app bootstrap (PLAN-app-bootstrap.md PR2).
4
+ *
5
+ * `bootstrapFromToken({ appToken })` is the SINGLE platform-init call a
6
+ * third-party app needs at boot. Given a connection-string token, it:
7
+ *
8
+ * 1. Parses the token (sync, no network) → appId, platformUrl, privateKey
9
+ * 2. Fetches GET ${platformUrl}/registry/discovery (cached on success)
10
+ * 3. Fetches GET ${endpoints.authPublicKeyUrl} (the user JWT verification key)
11
+ * 4. Configures the SDK's auth, platform, and entity-identity layers
12
+ * 5. Schedules a background refresh at 80% of cacheTtlSeconds
13
+ *
14
+ * After this returns, the app can use `requireAuth()`, `verifyUserJwt()`,
15
+ * `publishEvent()`, the entity client, etc. exactly as if it had been
16
+ * configured via the legacy env-based path.
17
+ *
18
+ * Cache: discovery is cached to disk so cold starts survive a brief
19
+ * registry outage. The token itself is NOT cached — it lives in the env
20
+ * var. Cached entries are per-app and contain only public information
21
+ * (URLs and the auth public key PEM, no secrets).
22
+ */
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.ANBY_TOKEN_PREFIX = void 0;
25
+ exports._resetBootstrapForTests = _resetBootstrapForTests;
26
+ exports.getDiscoveredEndpoints = getDiscoveredEndpoints;
27
+ exports.getDiscoveredRegistryBaseUrl = getDiscoveredRegistryBaseUrl;
28
+ exports.parseAppToken = parseAppToken;
29
+ exports.bootstrapFromToken = bootstrapFromToken;
30
+ const index_js_1 = require("../auth/index.js");
31
+ const index_js_2 = require("../config/index.js");
32
+ const identity_js_1 = require("../entities/identity.js");
33
+ const index_js_3 = require("../events/index.js");
34
+ const http_transport_js_1 = require("../events/http-transport.js");
35
+ const cache_js_1 = require("./cache.js");
36
+ const types_js_1 = require("./types.js");
37
+ Object.defineProperty(exports, "ANBY_TOKEN_PREFIX", { enumerable: true, get: function () { return types_js_1.ANBY_TOKEN_PREFIX; } });
38
+ let _state = null;
39
+ /** For tests: clears the module-level bootstrap state so a fresh
40
+ * bootstrapFromToken call re-runs from scratch. Not exported from the
41
+ * root barrel. */
42
+ function _resetBootstrapForTests() {
43
+ _state = null;
44
+ }
45
+ /**
46
+ * Returns the discovery response cached by the most recent successful
47
+ * bootstrapFromToken call. Throws if bootstrap has not yet started.
48
+ *
49
+ * Resolves the in-progress promise if bootstrap is still in flight, so
50
+ * callers can `await getDiscoveredEndpoints()` from anywhere safely.
51
+ */
52
+ async function getDiscoveredEndpoints() {
53
+ if (!_state) {
54
+ throw new Error('bootstrap not started — call bootstrapFromToken() before reading discovery state');
55
+ }
56
+ await _state.promise;
57
+ if (!_state.discovery) {
58
+ throw new Error('bootstrap completed but no discovery cached');
59
+ }
60
+ return _state.discovery.endpoints;
61
+ }
62
+ /**
63
+ * Returns the registry HOST root (e.g. "http://localhost:3003"), without
64
+ * the /registry path suffix. Use this for callers that already append
65
+ * /registry/... themselves (autoPublishOnBoot, RegistryPublicKeyVerifier).
66
+ *
67
+ * Falls back to discovery.endpoints.registryUrl with /registry stripped
68
+ * if the registryBaseUrl field is missing (older registries that haven't
69
+ * deployed PR3 yet).
70
+ */
71
+ async function getDiscoveredRegistryBaseUrl() {
72
+ const endpoints = await getDiscoveredEndpoints();
73
+ if (endpoints.registryBaseUrl)
74
+ return endpoints.registryBaseUrl;
75
+ // Backward compat: strip /registry suffix from registryUrl.
76
+ return endpoints.registryUrl.replace(/\/registry\/?$/, '');
77
+ }
78
+ /**
79
+ * Parse an `anby_v1_<base64json>` token. Throws on malformed input.
80
+ *
81
+ * Sync, no network. Validates structure but does NOT verify the
82
+ * Ed25519 private key against any server — that happens later when the
83
+ * SDK tries to mint a scoped-token.
84
+ */
85
+ function parseAppToken(token) {
86
+ if (!token || typeof token !== 'string') {
87
+ throw new Error('ANBY_APP_TOKEN is empty');
88
+ }
89
+ if (!token.startsWith(types_js_1.ANBY_TOKEN_PREFIX)) {
90
+ throw new Error(`ANBY_APP_TOKEN must start with "${types_js_1.ANBY_TOKEN_PREFIX}". Did you paste the right value?`);
91
+ }
92
+ const b64 = token.slice(types_js_1.ANBY_TOKEN_PREFIX.length);
93
+ let json;
94
+ try {
95
+ json = Buffer.from(b64, 'base64url').toString('utf-8');
96
+ }
97
+ catch (err) {
98
+ throw new Error(`ANBY_APP_TOKEN payload is not valid base64url: ${err.message}`);
99
+ }
100
+ let parsed;
101
+ try {
102
+ parsed = JSON.parse(json);
103
+ }
104
+ catch (err) {
105
+ throw new Error(`ANBY_APP_TOKEN payload is not valid JSON: ${err.message}`);
106
+ }
107
+ const obj = parsed;
108
+ if (obj?.v !== 1 ||
109
+ typeof obj.appId !== 'string' ||
110
+ typeof obj.platformUrl !== 'string' ||
111
+ typeof obj.privateKey !== 'string') {
112
+ throw new Error('ANBY_APP_TOKEN payload missing required fields (v, appId, platformUrl, privateKey)');
113
+ }
114
+ if (!obj.privateKey.includes('PRIVATE KEY')) {
115
+ throw new Error('ANBY_APP_TOKEN.privateKey is not a PEM');
116
+ }
117
+ return {
118
+ v: 1,
119
+ appId: obj.appId,
120
+ platformUrl: obj.platformUrl.replace(/\/$/, ''),
121
+ privateKey: obj.privateKey,
122
+ };
123
+ }
124
+ async function fetchDiscovery(platformUrl, fetchImpl) {
125
+ const url = `${platformUrl}/registry/discovery`;
126
+ const res = await fetchImpl(url, { headers: { accept: 'application/json' } });
127
+ if (!res.ok) {
128
+ throw new Error(`discovery fetch failed: ${res.status} ${res.statusText}`);
129
+ }
130
+ const body = (await res.json());
131
+ if (body?.v !== 1 || !body?.endpoints?.authPublicKeyUrl) {
132
+ throw new Error('discovery response is missing required fields');
133
+ }
134
+ return body;
135
+ }
136
+ async function fetchAuthPublicKey(url, fetchImpl) {
137
+ const res = await fetchImpl(url, { headers: { accept: 'text/plain' } });
138
+ if (!res.ok) {
139
+ throw new Error(`auth-public-key fetch failed: ${res.status} ${res.statusText}`);
140
+ }
141
+ const pem = await res.text();
142
+ // CRITICAL leak check FIRST: a buggy auth-service that accidentally
143
+ // serves a private key on this endpoint must be rejected loudly,
144
+ // before any other validation that might mask the security finding.
145
+ if (pem.includes('PRIVATE KEY')) {
146
+ throw new Error('auth-public-key endpoint returned PRIVATE KEY material — refusing to use it');
147
+ }
148
+ if (!pem.includes('BEGIN PUBLIC KEY')) {
149
+ throw new Error('auth-public-key response is not a PEM public key');
150
+ }
151
+ return pem;
152
+ }
153
+ /**
154
+ * The single bootstrap entrypoint a third-party app calls at boot.
155
+ *
156
+ * Idempotent: if called multiple times in the same process (e.g. once
157
+ * from entry.server.tsx and again from a refresh timer), the second call
158
+ * returns the same in-flight promise instead of starting a parallel
159
+ * bootstrap.
160
+ *
161
+ * @example
162
+ * ```ts
163
+ * import { bootstrapFromToken, requireAuth } from '@anby/platform-sdk';
164
+ *
165
+ * await bootstrapFromToken({ appToken: process.env.ANBY_APP_TOKEN! });
166
+ *
167
+ * app.get('/api/widgets', requireAuth(), handler);
168
+ * ```
169
+ */
170
+ function bootstrapFromToken(opts) {
171
+ // PLAN-app-bootstrap-phase2 PR3: dedupe concurrent calls. Multiple
172
+ // entry points (entry.server, autoPublishOnBoot, refresh timer) can
173
+ // all await the same shared promise without spawning parallel work.
174
+ if (_state)
175
+ return _state.promise;
176
+ _state = {
177
+ promise: doBootstrap(opts).catch((err) => {
178
+ // Failed bootstrap clears state so the next call retries.
179
+ _state = null;
180
+ throw err;
181
+ }),
182
+ };
183
+ return _state.promise;
184
+ }
185
+ async function doBootstrap(opts) {
186
+ const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
187
+ if (!fetchImpl) {
188
+ throw new Error('No fetch implementation available. Pass opts.fetchImpl or run on Node 18+.');
189
+ }
190
+ const cacheDir = opts.cacheDir ?? `${process.cwd()}/.anby-cache`;
191
+ // 1. Parse the token (sync, no network)
192
+ const token = parseAppToken(opts.appToken);
193
+ if (_state)
194
+ _state.appToken = token;
195
+ // 2. Try fetching fresh discovery + auth public key. Fall back to disk
196
+ // cache if the network is unreachable on cold start.
197
+ let discovery;
198
+ let authPublicKeyPem;
199
+ let usedCache = false;
200
+ try {
201
+ discovery = await fetchDiscovery(token.platformUrl, fetchImpl);
202
+ authPublicKeyPem = await fetchAuthPublicKey(discovery.endpoints.authPublicKeyUrl, fetchImpl);
203
+ }
204
+ catch (fetchErr) {
205
+ const cached = await (0, cache_js_1.readCache)(cacheDir, token.appId);
206
+ if (!cached) {
207
+ throw new Error(`bootstrap failed and no cache available: ${fetchErr.message}`);
208
+ }
209
+ discovery = cached.discovery;
210
+ authPublicKeyPem = cached.authPublicKeyPem;
211
+ usedCache = true;
212
+ }
213
+ // Cache discovery into the shared module state so other modules can
214
+ // read it via getDiscoveredEndpoints() / getDiscoveredRegistryBaseUrl().
215
+ if (_state)
216
+ _state.discovery = discovery;
217
+ // 3. Configure SDK subsystems
218
+ (0, index_js_1.configureAuth)({ jwtPublicKey: authPublicKeyPem });
219
+ (0, index_js_2.configurePlatform)({
220
+ appId: token.appId,
221
+ registryUrl: discovery.endpoints.registryUrl,
222
+ });
223
+ (0, identity_js_1.configureAppIdentity)({
224
+ appId: token.appId,
225
+ privateKeyPem: token.privateKey,
226
+ });
227
+ // PLAN-app-bootstrap-phase2 PR3: auto-wire HttpEventTransport so dev
228
+ // calls to publishEvent() work without any manual configuration. The
229
+ // events endpoint URL comes from discovery — fall back to deriving it
230
+ // from registryBaseUrl if older discovery responses lack the explicit
231
+ // eventsUrl field.
232
+ const eventsUrl = discovery.endpoints.eventsUrl ??
233
+ `${discovery.endpoints.registryBaseUrl ?? discovery.endpoints.registryUrl.replace(/\/registry\/?$/, '')}/registry/events`;
234
+ (0, index_js_3.configureEventTransport)(new http_transport_js_1.HttpEventTransport({
235
+ endpoint: eventsUrl,
236
+ identity: { appId: token.appId, privateKeyPem: token.privateKey },
237
+ }));
238
+ // 4. Persist to cache (only on successful network fetch — don't
239
+ // overwrite a fresh cache with a stale-cache value)
240
+ if (!usedCache) {
241
+ const fetchedAt = new Date();
242
+ const staleAt = new Date(fetchedAt.getTime() + discovery.cacheTtlSeconds * 1000);
243
+ const entry = {
244
+ fetchedAt: fetchedAt.toISOString(),
245
+ staleAt: staleAt.toISOString(),
246
+ discovery,
247
+ authPublicKeyPem,
248
+ };
249
+ try {
250
+ await (0, cache_js_1.writeCache)(cacheDir, token.appId, entry);
251
+ }
252
+ catch (err) {
253
+ // Cache write failure is non-fatal. The SDK still works in memory;
254
+ // the next cold start just can't use the disk fallback.
255
+ console.warn(`[anby] failed to write bootstrap cache: ${err.message}`);
256
+ }
257
+ }
258
+ // 5. Schedule background refresh at 80% of TTL.
259
+ const refreshInMs = Math.max(60_000, discovery.cacheTtlSeconds * 1000 * 0.8);
260
+ scheduleRefresh(opts, refreshInMs);
261
+ }
262
+ /**
263
+ * Background refresh loop. Re-runs bootstrapFromToken at the scheduled
264
+ * interval. On failure, logs and keeps using the existing in-memory
265
+ * config — there's no degraded mode because the data we cache (URLs +
266
+ * public key) is not security-critical and can be stale.
267
+ */
268
+ function scheduleRefresh(opts, delayMs) {
269
+ const handle = setTimeout(() => {
270
+ bootstrapFromToken(opts).catch((err) => {
271
+ console.warn(`[anby] bootstrap refresh failed: ${err.message} (will retry on next interval)`);
272
+ // Re-schedule with the same delay even on failure.
273
+ scheduleRefresh(opts, delayMs);
274
+ });
275
+ }, delayMs);
276
+ // Don't keep the event loop alive just for refresh.
277
+ if (typeof handle.unref === 'function')
278
+ handle.unref();
279
+ }
280
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/bootstrap/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Types for the third-party app bootstrap flow
3
+ * (PLAN-app-bootstrap.md PR2).
4
+ *
5
+ * `AnbyAppToken` is the parsed payload of the `ANBY_APP_TOKEN` env var.
6
+ * The wire format is `anby_v1_<base64url(json(AnbyAppToken))>`.
7
+ *
8
+ * `DiscoveryResponse` is what `GET /registry/discovery` returns.
9
+ */
10
+ export declare const ANBY_TOKEN_PREFIX = "anby_v1_";
11
+ export interface AnbyAppToken {
12
+ v: 1;
13
+ appId: string;
14
+ /** Externally-reachable platform base URL, e.g. "https://anby.io". */
15
+ platformUrl: string;
16
+ /** PEM-encoded Ed25519 private key for service-to-service signing. */
17
+ privateKey: string;
18
+ }
19
+ export interface DiscoveryResponse {
20
+ v: 1;
21
+ platform: {
22
+ name: string;
23
+ version: string;
24
+ };
25
+ endpoints: {
26
+ authPublicKeyUrl: string;
27
+ scopedTokenUrl: string;
28
+ entityTokenPublicKeyUrl: string;
29
+ /** PR1 of phase2: events ingestion endpoint. Optional for back-compat
30
+ * with older registries that don't expose it yet. */
31
+ eventsUrl?: string;
32
+ gatewayUrl: string;
33
+ /** Registry HTTP API root with /registry suffix already appended.
34
+ * Existing callers expect this exact shape. */
35
+ registryUrl: string;
36
+ /** PR3 of phase2: registry HOST root WITHOUT /registry suffix.
37
+ * Optional for back-compat with older registries. */
38
+ registryBaseUrl?: string;
39
+ tenantServiceUrl: string;
40
+ eventRouterUrl: string;
41
+ };
42
+ cacheTtlSeconds: number;
43
+ }
44
+ export interface CachedBootstrap {
45
+ /** When the discovery response was fetched (ISO 8601). */
46
+ fetchedAt: string;
47
+ /** When this cache entry should be considered stale (ISO 8601). */
48
+ staleAt: string;
49
+ discovery: DiscoveryResponse;
50
+ /** PEM string of the auth-service public key (RS256). */
51
+ authPublicKeyPem: string;
52
+ }
53
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/bootstrap/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,iBAAiB,aAAa,CAAC;AAE5C,MAAM,WAAW,YAAY;IAC3B,CAAC,EAAE,CAAC,CAAC;IACL,KAAK,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,CAAC,EAAE,CAAC,CAAC;IACL,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,SAAS,EAAE;QACT,gBAAgB,EAAE,MAAM,CAAC;QACzB,cAAc,EAAE,MAAM,CAAC;QACvB,uBAAuB,EAAE,MAAM,CAAC;QAChC;8DACsD;QACtD,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB;wDACgD;QAChD,WAAW,EAAE,MAAM,CAAC;QACpB;8DACsD;QACtD,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,gBAAgB,EAAE,MAAM,CAAC;QACzB,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,0DAA0D;IAC1D,SAAS,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,yDAAyD;IACzD,gBAAgB,EAAE,MAAM,CAAC;CAC1B"}
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ /**
3
+ * Types for the third-party app bootstrap flow
4
+ * (PLAN-app-bootstrap.md PR2).
5
+ *
6
+ * `AnbyAppToken` is the parsed payload of the `ANBY_APP_TOKEN` env var.
7
+ * The wire format is `anby_v1_<base64url(json(AnbyAppToken))>`.
8
+ *
9
+ * `DiscoveryResponse` is what `GET /registry/discovery` returns.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.ANBY_TOKEN_PREFIX = void 0;
13
+ exports.ANBY_TOKEN_PREFIX = 'anby_v1_';
14
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/bootstrap/types.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAEU,QAAA,iBAAiB,GAAG,UAAU,CAAC"}
@@ -0,0 +1,38 @@
1
+ import type { AnbyEvent } from '@anby/contracts';
2
+ import { type AppIdentity } from '../entities/identity.js';
3
+ import type { EventTransport } from './index.js';
4
+ /**
5
+ * HttpEventTransport (PLAN-app-bootstrap-phase2 PR2).
6
+ *
7
+ * Replaces PostgresEventTransport for third-party apps. POSTs an AnbyEvent
8
+ * envelope (or array, batched) to the platform's POST /registry/events
9
+ * endpoint, signed with the app's per-request Ed25519 signature using the
10
+ * canonical scheme:
11
+ *
12
+ * ANBY-APP-V1\n{appId}\n{tenantId}\n{iso}\n{bodySha256}
13
+ *
14
+ * Headers attached:
15
+ * x-anby-app, x-anby-timestamp, x-anby-body-sha256, x-anby-signature
16
+ *
17
+ * Same scheme as POST /registry/scoped-token, so no scoped-token round-trip
18
+ * is needed.
19
+ *
20
+ * Configured automatically by `bootstrapFromToken` once the discovery
21
+ * response and the app's per-app private key are available. App code never
22
+ * instantiates this directly.
23
+ */
24
+ export declare class HttpEventTransport implements EventTransport {
25
+ private readonly endpoint;
26
+ private readonly identity;
27
+ private readonly fetchImpl;
28
+ constructor(opts: {
29
+ /** Full URL of POST /registry/events on the registry. */
30
+ endpoint: string;
31
+ /** Per-app identity from ANBY_APP_TOKEN. */
32
+ identity: AppIdentity;
33
+ /** Override for tests. */
34
+ fetchImpl?: typeof fetch;
35
+ });
36
+ publish(event: AnbyEvent): Promise<void>;
37
+ }
38
+ //# sourceMappingURL=http-transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-transport.d.ts","sourceRoot":"","sources":["../../../src/events/http-transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,kBAAmB,YAAW,cAAc;IACvD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAc;IACvC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;gBAE7B,IAAI,EAAE;QAChB,yDAAyD;QACzD,QAAQ,EAAE,MAAM,CAAC;QACjB,4CAA4C;QAC5C,QAAQ,EAAE,WAAW,CAAC;QACtB,0BAA0B;QAC1B,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;KAC1B;IAWK,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;CA6B/C"}
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HttpEventTransport = void 0;
4
+ const identity_js_1 = require("../entities/identity.js");
5
+ /**
6
+ * HttpEventTransport (PLAN-app-bootstrap-phase2 PR2).
7
+ *
8
+ * Replaces PostgresEventTransport for third-party apps. POSTs an AnbyEvent
9
+ * envelope (or array, batched) to the platform's POST /registry/events
10
+ * endpoint, signed with the app's per-request Ed25519 signature using the
11
+ * canonical scheme:
12
+ *
13
+ * ANBY-APP-V1\n{appId}\n{tenantId}\n{iso}\n{bodySha256}
14
+ *
15
+ * Headers attached:
16
+ * x-anby-app, x-anby-timestamp, x-anby-body-sha256, x-anby-signature
17
+ *
18
+ * Same scheme as POST /registry/scoped-token, so no scoped-token round-trip
19
+ * is needed.
20
+ *
21
+ * Configured automatically by `bootstrapFromToken` once the discovery
22
+ * response and the app's per-app private key are available. App code never
23
+ * instantiates this directly.
24
+ */
25
+ class HttpEventTransport {
26
+ endpoint;
27
+ identity;
28
+ fetchImpl;
29
+ constructor(opts) {
30
+ this.endpoint = opts.endpoint;
31
+ this.identity = opts.identity;
32
+ this.fetchImpl = opts.fetchImpl ?? globalThis.fetch;
33
+ if (!this.fetchImpl) {
34
+ throw new Error('HttpEventTransport: no fetch implementation. Run on Node 18+ or pass fetchImpl.');
35
+ }
36
+ }
37
+ async publish(event) {
38
+ // Body is the canonical JSON of the event envelope. The signed
39
+ // body-hash is computed over these EXACT bytes — the receiver hashes
40
+ // its raw request body and compares.
41
+ const body = JSON.stringify(event);
42
+ const headers = (0, identity_js_1.signAppRequest)({
43
+ identity: this.identity,
44
+ tenantId: event.tenantId,
45
+ body,
46
+ });
47
+ const res = await this.fetchImpl(this.endpoint, {
48
+ method: 'POST',
49
+ headers: {
50
+ 'content-type': 'application/json',
51
+ accept: 'application/json',
52
+ ...headers,
53
+ },
54
+ body,
55
+ });
56
+ if (!res.ok) {
57
+ const text = await res.text().catch(() => '');
58
+ throw new Error(`HttpEventTransport: POST ${this.endpoint} failed with ${res.status}: ${text}`);
59
+ }
60
+ }
61
+ }
62
+ exports.HttpEventTransport = HttpEventTransport;
63
+ //# sourceMappingURL=http-transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-transport.js","sourceRoot":"","sources":["../../../src/events/http-transport.ts"],"names":[],"mappings":";;;AACA,yDAA2E;AAG3E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAa,kBAAkB;IACZ,QAAQ,CAAS;IACjB,QAAQ,CAAc;IACtB,SAAS,CAAe;IAEzC,YAAY,IAOX;QACC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,UAAU,CAAC,KAAK,CAAC;QACpD,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CACb,iFAAiF,CAClF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,KAAgB;QAC5B,+DAA+D;QAC/D,qEAAqE;QACrE,qCAAqC;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAEnC,MAAM,OAAO,GAAG,IAAA,4BAAc,EAAC;YAC7B,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,IAAI;SACL,CAAC,CAAC;QAEH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE;YAC9C,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,MAAM,EAAE,kBAAkB;gBAC1B,GAAG,OAAO;aACX;YACD,IAAI;SACL,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,MAAM,IAAI,KAAK,CACb,4BAA4B,IAAI,CAAC,QAAQ,gBAAgB,GAAG,CAAC,MAAM,KAAK,IAAI,EAAE,CAC/E,CAAC;QACJ,CAAC;IACH,CAAC;CACF;AApDD,gDAoDC"}
@@ -1,4 +1,27 @@
1
1
  import type { AnbyEvent } from '@anby/contracts';
2
+ /**
3
+ * PLAN-app-bootstrap-phase2 PR5: type-safe event registry.
4
+ *
5
+ * Codegen extends these interfaces via TypeScript declaration merging
6
+ * in `.anby/types.d.ts` (auto-generated by `@anby/platform-sdk/vite`
7
+ * from each app's `anby-app.manifest.json`). When empty (no codegen
8
+ * has run), `publishEvent` falls through to the loose `AnbyEvent`
9
+ * overload, so existing untyped callers keep working.
10
+ *
11
+ * Generated file looks like:
12
+ * ```ts
13
+ * declare module '@anby/platform-sdk' {
14
+ * interface AppProvidedEvents {
15
+ * 'org.node.created': Record<string, unknown>;
16
+ * 'org.node.updated': Record<string, unknown>;
17
+ * }
18
+ * }
19
+ * ```
20
+ */
21
+ export interface AppProvidedEvents {
22
+ }
23
+ export interface AppRequiredEvents {
24
+ }
2
25
  export interface EventTransport {
3
26
  publish(event: AnbyEvent): Promise<void>;
4
27
  }
@@ -20,6 +43,32 @@ export declare function createEvent<T>(params: {
20
43
  data: T;
21
44
  correlationId?: string;
22
45
  }): AnbyEvent<T>;
46
+ /**
47
+ * Publish an event through the configured transport.
48
+ *
49
+ * Two overloads:
50
+ * 1. Strongly-typed shorthand — pass `{ type, tenantId, actor, data }`
51
+ * where `type` is constrained to declared `AppProvidedEvents` keys
52
+ * and `data` is narrowed to that key's payload type. Codegen sets up
53
+ * this constraint by extending AppProvidedEvents in `.anby/types.d.ts`.
54
+ * This overload only matches when codegen has run AND the type is a
55
+ * known event name. Catches typos at compile time.
56
+ *
57
+ * 2. Loose escape hatch — pass a full AnbyEvent built via createEvent().
58
+ * Always works, even without codegen. Use for events not declared in
59
+ * the manifest, or for cross-app forwarding.
60
+ */
61
+ export declare function publishEvent<K extends keyof AppProvidedEvents>(event: {
62
+ type: K;
63
+ tenantId: string;
64
+ source?: string;
65
+ actor: {
66
+ userId: string;
67
+ email: string;
68
+ };
69
+ data: AppProvidedEvents[K];
70
+ correlationId?: string;
71
+ }): Promise<void>;
23
72
  export declare function publishEvent(event: AnbyEvent): Promise<void>;
24
73
  /**
25
74
  * PostgresEventTransport writes events to the app_events DB table.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/events/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C;AAED,cAAM,iBAAkB,YAAW,cAAc;IAC/C,OAAO,CAAC,MAAM,CAAmB;IAE3B,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9C,SAAS,IAAI,SAAS,EAAE;IAIxB,KAAK,IAAI,IAAI;CAGd;AAID,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,cAAc,GAAG,IAAI,CAEvE;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACzC,IAAI,EAAE,CAAC,CAAC;IACR,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GAAG,SAAS,CAAC,CAAC,CAAC,CAYf;AAED,wBAAsB,YAAY,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAElE;AAED;;;;;GAKG;AACH,qBAAa,sBAAuB,YAAW,cAAc;IAG/C,OAAO,CAAC,gBAAgB;IAFpC,OAAO,CAAC,IAAI,CAAM;gBAEE,gBAAgB,EAAE,MAAM;YAE9B,OAAO;IAWf,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IASxC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAM7B;AAED,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/events/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,iBAAiB;CAAG;AACrC,MAAM,WAAW,iBAAiB;CAAG;AAErC,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C;AAED,cAAM,iBAAkB,YAAW,cAAc;IAC/C,OAAO,CAAC,MAAM,CAAmB;IAE3B,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9C,SAAS,IAAI,SAAS,EAAE;IAIxB,KAAK,IAAI,IAAI;CAGd;AAID,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,cAAc,GAAG,IAAI,CAEvE;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACzC,IAAI,EAAE,CAAC,CAAC;IACR,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GAAG,SAAS,CAAC,CAAC,CAAC,CAYf;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,YAAY,CAChC,CAAC,SAAS,MAAM,iBAAiB,EACjC,KAAK,EAAE;IACP,IAAI,EAAE,CAAC,CAAC;IACR,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACzC,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAClB,wBAAsB,YAAY,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AA4BpE;;;;;GAKG;AACH,qBAAa,sBAAuB,YAAW,cAAc;IAG/C,OAAO,CAAC,gBAAgB;IAFpC,OAAO,CAAC,IAAI,CAAM;gBAEE,gBAAgB,EAAE,MAAM;YAE9B,OAAO;IAWf,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IASxC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAM7B;AAED,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
@@ -72,7 +72,20 @@ function createEvent(params) {
72
72
  };
73
73
  }
74
74
  async function publishEvent(event) {
75
- await _transport.publish(event);
75
+ // If the caller passed a partial shape (no id/timestamp/version), build
76
+ // a full envelope on their behalf. Otherwise pass through unchanged.
77
+ const isFullEnvelope = 'id' in event && 'timestamp' in event && 'version' in event;
78
+ const envelope = isFullEnvelope
79
+ ? event
80
+ : createEvent({
81
+ type: event.type,
82
+ source: event.source ?? '',
83
+ tenantId: event.tenantId,
84
+ actor: event.actor,
85
+ data: event.data,
86
+ correlationId: event.correlationId,
87
+ });
88
+ await _transport.publish(envelope);
76
89
  }
77
90
  /**
78
91
  * PostgresEventTransport writes events to the app_events DB table.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/events/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,0DAEC;AAED,kCAmBC;AAED,oCAEC;AAnDD,oDAA4B;AAM5B,MAAM,iBAAiB;IACb,MAAM,GAAgB,EAAE,CAAC;IAEjC,KAAK,CAAC,OAAO,CAAC,KAAgB;QAC5B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;IAED,SAAS;QACP,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;IACnB,CAAC;CACF;AAwEQ,8CAAiB;AAtE1B,IAAI,UAAU,GAAmB,IAAI,iBAAiB,EAAE,CAAC;AAEzD,SAAgB,uBAAuB,CAAC,SAAyB;IAC/D,UAAU,GAAG,SAAS,CAAC;AACzB,CAAC;AAED,SAAgB,WAAW,CAAI,MAO9B;IACC,OAAO;QACL,EAAE,EAAE,gBAAM,CAAC,UAAU,EAAE;QACvB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,OAAO,EAAE,GAAG;QACZ,aAAa,EAAE,MAAM,CAAC,aAAa,IAAI,gBAAM,CAAC,UAAU,EAAE;QAC1D,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,IAAI,EAAE,MAAM,CAAC,IAAI;KAClB,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,YAAY,CAAC,KAAgB;IACjD,MAAM,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAClC,CAAC;AAED;;;;;GAKG;AACH,MAAa,sBAAsB;IAGb;IAFZ,IAAI,CAAM;IAElB,YAAoB,gBAAwB;QAAxB,qBAAgB,GAAhB,gBAAgB,CAAQ;IAAG,CAAC;IAExC,KAAK,CAAC,OAAO;QACnB,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,6DAA6D;YAC7D,gEAAgE;YAChE,qDAAqD;YACrD,MAAM,EAAE,IAAI,EAAE,GAAG,wDAAa,IAAI,GAAC,CAAC;YACpC,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,CAAC,EAAE,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,KAAgB;QAC5B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QAClC,MAAM,IAAI,CAAC,KAAK,CACd;iDAC2C,EAC3C,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAC5E,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACnB,CAAC;IACH,CAAC;CACF;AA/BD,wDA+BC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/events/index.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,10 @@
1
- export { configureAuth, verifyJwt, verifyHmac, signHmac, authenticateRequest, requireAuth, type AuthUser, type AuthConfig, } from './auth/index.js';
2
- export { configureEventTransport, createEvent, publishEvent, InMemoryTransport, PostgresEventTransport, type EventTransport, } from './events/index.js';
1
+ export { configureAuth, verifyUserJwt, verifyInternalJwt, verifyHmac, signHmac, authenticateRequest, requireAuth, JWT_ISSUER, JWT_AUDIENCE, TYP_USER, TYP_INTERNAL, TYP_OAUTH_STATE, type AuthUser, type AuthConfig, } from './auth/index.js';
2
+ export { bootstrapFromToken, parseAppToken, ANBY_TOKEN_PREFIX, type AnbyAppToken, type DiscoveryResponse, type BootstrapOptions, } from './bootstrap/index.js';
3
+ export { configureEventTransport, createEvent, publishEvent, InMemoryTransport, PostgresEventTransport, type EventTransport, type AppProvidedEvents, type AppRequiredEvents, } from './events/index.js';
4
+ export { HttpEventTransport } from './events/http-transport.js';
5
+ export { getDiscoveredEndpoints, getDiscoveredRegistryBaseUrl, } from './bootstrap/index.js';
3
6
  export { configurePlatform, getPlatformConfig, type PlatformConfig, } from './config/index.js';
4
- export { publishAppFromManifest, autoPublishOnBoot, type PublishAppOptions, type PublishAppResult, } from './apps/publish.js';
7
+ export { publishAppFromManifest, autoPublishOnBoot, getInlinedManifest, type PublishAppOptions, type PublishAppResult, } from './apps/publish.js';
5
8
  export { getPreviewModeFromRequest, isPreviewMode, type PreviewMode, } from './preview.js';
6
9
  export * from './entities/index.js';
7
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,SAAS,EACT,UAAU,EACV,QAAQ,EACR,mBAAmB,EACnB,WAAW,EACX,KAAK,QAAQ,EACb,KAAK,UAAU,GAChB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,uBAAuB,EACvB,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,sBAAsB,EACtB,KAAK,cAAc,GACpB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,cAAc,GACpB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,yBAAyB,EACzB,aAAa,EACb,KAAK,WAAW,GACjB,MAAM,cAAc,CAAC;AAKtB,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,QAAQ,EACR,mBAAmB,EACnB,WAAW,EACX,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,YAAY,EACZ,eAAe,EACf,KAAK,QAAQ,EACb,KAAK,UAAU,GAChB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,uBAAuB,EACvB,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,sBAAsB,EACtB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,GACvB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAKhE,OAAO,EACL,sBAAsB,EACtB,4BAA4B,GAC7B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,cAAc,GACpB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,kBAAkB,EAClB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,yBAAyB,EACzB,aAAa,EACb,KAAK,WAAW,GACjB,MAAM,cAAc,CAAC;AAKtB,cAAc,qBAAqB,CAAC"}