@picked/app-kit 0.0.1-dev.1794447047683 → 0.0.117-next.3

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,167 @@
1
+ /**
2
+ * @file The app server: a fetch-style handler that checks Picked's signature and routes
3
+ * lifecycle events, app events, tool calls and MCP requests, plus the responses its pages
4
+ * and APIs answer with.
5
+ */
6
+ import { type AppEvent, type AppManifest, type InstallationCreatedEvent, type InstallationDeletedEvent, type InstallationRef, type InstallationUpgradedEvent, type PublicKeySet, type SessionClaims, type ToolCall } from '@picked/app-protocol';
7
+ export * from '@picked/app-protocol';
8
+ export * from './client.js';
9
+ export * from './link.js';
10
+ /** A tool's body: given the call, returns what the manifest's `output` declares. */
11
+ export type ToolHandler = (call: ToolCall) => Promise<Record<string, unknown>>;
12
+ /** What an app server handles. */
13
+ export interface AppHandlerOptions {
14
+ /** Picked's public keys, which every request Picked sends must be signed by. */
15
+ pickedKeys: PublicKeySet;
16
+ /** The path the manifest's `endpoint` points at, such as `/picked`. Empty by default. */
17
+ basePath?: string;
18
+ /** Called when the app is installed on a project. */
19
+ onInstall?: (event: InstallationCreatedEvent) => Promise<void> | void;
20
+ /** Called when an installation moves to another version. */
21
+ onUpgrade?: (event: InstallationUpgradedEvent) => Promise<void> | void;
22
+ /** Called when the app is removed from a project. */
23
+ onUninstall?: (event: InstallationDeletedEvent) => Promise<void> | void;
24
+ /** Called with each event the manifest's `events` subscribes to. */
25
+ onEvent?: (event: AppEvent) => Promise<void> | void;
26
+ /** The tool bodies, by the names the manifest declares. */
27
+ tools?: Record<string, ToolHandler>;
28
+ /** The MCP server at the manifest's `mcp.url`, and the handler for the signed requests to it. */
29
+ mcp?: {
30
+ /** The pathname of the manifest's `mcp.url`, such as `/mcp`, matched against the full path. */
31
+ path: string;
32
+ handle: (request: Request, installation: InstallationRef) => Promise<Response>;
33
+ };
34
+ /** The app's manifest, which the handler serves at `GET /manifest.json`. */
35
+ manifest?: AppManifest;
36
+ /** Everything else the app serves, such as its frame pages. */
37
+ fallback?: (request: Request) => Promise<Response> | Response;
38
+ }
39
+ /**
40
+ * Answers JSON.
41
+ *
42
+ * @param {unknown} body - The body.
43
+ * @param {number} [status] - The status; 200 by default.
44
+ * @returns {Response} The response.
45
+ * @example json({ ok: true })
46
+ */
47
+ export declare function json(body: unknown, status?: number): Response;
48
+ /**
49
+ * Answers an HTML page the dashboard may frame and no other site may.
50
+ *
51
+ * @param {string} html - The page.
52
+ * @param {object} options - Who may frame it.
53
+ * @param {string[]} options.frameAncestors - The dashboard origins, such as `https://app.picked.app`.
54
+ * @returns {Response} The response.
55
+ * @example page(settingsPage(), { frameAncestors: ['https://app.picked.app'] })
56
+ */
57
+ export declare function page(html: string, options: {
58
+ frameAncestors: string[];
59
+ }): Response;
60
+ /**
61
+ * Builds the handler for an app's endpoint.
62
+ *
63
+ * @param {AppHandlerOptions} options - What the app handles.
64
+ * @returns {(request: Request) => Promise<Response>} A fetch-style handler.
65
+ * @example serve(createAppHandler({ pickedKeys: environment.pickedKeys, tools: { ping: async () => ({ ok: true }) } }))
66
+ */
67
+ export declare function createAppHandler(options: AppHandlerOptions): (request: Request) => Promise<Response>;
68
+ /**
69
+ * Reads the raw session token a frame sends as `Authorization: Bearer <token>`, which an
70
+ * installation client passes on as `sessionToken` to mint a token for that user's request.
71
+ *
72
+ * @param {Request} request - The frame's request to the app's own server.
73
+ * @returns {string | null} The token, or null when the request carries none.
74
+ * @example createInstallationClient({ ...options, sessionToken: sessionTokenOf(request) ?? undefined })
75
+ */
76
+ export declare function sessionTokenOf(request: Request): string | null;
77
+ /**
78
+ * Reads the session token a frame sends as `Authorization: Bearer <token>`.
79
+ *
80
+ * @param {Request} request - The frame's request to the app's own server.
81
+ * @param {PublicKeySet} pickedKeys - Picked's public keys, which sign session tokens.
82
+ * @returns {Promise<SessionClaims | null>} Who is asking, or null without a valid token.
83
+ * @example const session = await readSession(request, environment.pickedKeys)
84
+ */
85
+ export declare function readSession(request: Request, pickedKeys: PublicKeySet): Promise<SessionClaims | null>;
86
+ /** What every app server reads from its environment. */
87
+ export interface AppEnvironment {
88
+ /** `PICKED_APP_PRIVATE_KEY`: the app's Ed25519 private key, as the base64 of its PKCS#8 DER or a PKCS#8 PEM. */
89
+ privateKey: string;
90
+ /** `PICKED_API_URL`: the Picked API the app trusts, whose public keys verify Picked's requests. */
91
+ pickedUrl: string;
92
+ /** Picked's public keys, read from `pickedUrl`. */
93
+ pickedKeys: PublicKeySet;
94
+ /** `APP_PUBLIC_URL`: the origin the app is served at, which its manifest's endpoint names. */
95
+ publicUrl: string;
96
+ /**
97
+ * The dashboard origins the environment names: `PICKED_DASHBOARD_ORIGINS`, or `DASHBOARD_PORT`
98
+ * on localhost; empty when it names none.
99
+ */
100
+ frameAncestors: string[];
101
+ /**
102
+ * The dashboard origins that may frame the app's pages, the dashboard's own first, which an
103
+ * app links people to as `installationLinkUrl`'s `dashboardOrigin`: `frameAncestors`, or the
104
+ * ones Picked's app config at `pickedUrl` lists when the environment names none.
105
+ */
106
+ dashboardOrigins: () => Promise<string[]>;
107
+ /**
108
+ * `PICKED_APP_ID`: the app's ID on the Picked it trusts, which `picked app deploy` prints, or
109
+ * null when it is unset or not an app ID.
110
+ */
111
+ appId: string | null;
112
+ }
113
+ /**
114
+ * The dashboard origins Picked's app config lists. It fetches the config on first use, on every
115
+ * use until a fetch succeeds, and again on a use once `refreshAfterMs` has passed since the last
116
+ * success. A fetch that takes longer than `timeoutMs` is abandoned. It keeps the origins it last
117
+ * read when a fetch fails, and holds none before any fetch succeeds.
118
+ *
119
+ * @param {object} options - Where the config lives.
120
+ * @param {string} options.url - The config's URL.
121
+ * @param {typeof fetch} [options.fetch] - The fetch to read it with.
122
+ * @param {number} [options.refreshAfterMs] - The least time between fetches; five minutes by default.
123
+ * @param {number} [options.timeoutMs] - The longest a fetch may take; five seconds by default.
124
+ * @returns {() => Promise<string[]>} Reads the origins.
125
+ * @example remoteDashboardOrigins({ url: 'https://api.picked.app/.well-known/picked-app-config.json' })
126
+ */
127
+ export declare function remoteDashboardOrigins(options: {
128
+ url: string;
129
+ fetch?: typeof fetch;
130
+ refreshAfterMs?: number;
131
+ timeoutMs?: number;
132
+ }): () => Promise<string[]>;
133
+ /**
134
+ * Reads an app server's environment. An origin the environment leaves unset comes from
135
+ * Vercel when the app runs there: Picked's API from the related project `picked-api`, and the
136
+ * public URL from `VERCEL_PROJECT_PRODUCTION_URL` in production and `VERCEL_BRANCH_URL`
137
+ * elsewhere, so a preview targets the API deployed from its own branch. Locally, Picked's API
138
+ * defaults to `API_PORT` on localhost, the public URL to the app's port and the frame
139
+ * ancestors to the dashboard's port. The dashboard origins are the frame ancestors, or, when the
140
+ * environment names none, the ones in the app config Picked's API publishes: the dashboard's
141
+ * own origin first, then every tenant host.
142
+ *
143
+ * @param {Record<string, string | undefined>} env - The environment.
144
+ * @param {string} port - The port the app listens on locally.
145
+ * @param {object} [options] - How Picked's documents are read.
146
+ * @param {typeof fetch} [options.fetch] - The fetch Picked's keys and app config are read with.
147
+ * @param {number} [options.refreshAfterMs] - The least time between reads of Picked's app config.
148
+ * @param {number} [options.timeoutMs] - The longest a read of Picked's app config may take.
149
+ * @returns {AppEnvironment} The environment.
150
+ * @throws {Error} When `PICKED_APP_PRIVATE_KEY` or `PICKED_API_URL` is unset.
151
+ * @example readAppEnvironment(process.env, process.env.APP_PORT ?? '4101')
152
+ */
153
+ export declare function readAppEnvironment(env: Record<string, string | undefined>, port: string, options?: {
154
+ fetch?: typeof fetch;
155
+ refreshAfterMs?: number;
156
+ timeoutMs?: number;
157
+ }): AppEnvironment;
158
+ /**
159
+ * Serves a handler behind a Vercel rewrite of every path to `/api?__path=/:path*`, restoring
160
+ * the path the request was sent to.
161
+ *
162
+ * @param {(request: Request) => Promise<Response>} handler - The app's handler.
163
+ * @returns {(request: Request) => Promise<Response>} The handler for `api/index.ts`.
164
+ * @example export default { fetch: withRewrittenPath(handler) }
165
+ */
166
+ export declare function withRewrittenPath(handler: (request: Request) => Promise<Response>): (request: Request) => Promise<Response>;
167
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * @file Test doubles for app servers: a fake Picked API that answers the GraphQL operations the
3
+ * installation client sends, mints tokens for app assertions signed with the app's key (for an
4
+ * installation without offline access, only alongside a session token it signed), keeps
5
+ * installation labels and publishes Picked's public keys; and helpers that build the requests
6
+ * Picked and the dashboard send an app, signed with the fake's Picked key.
7
+ */
8
+ import { type InstallationRef, type PublicKeySet, type ToolCall } from '@picked/app-protocol';
9
+ import type { AppLabel } from './client.js';
10
+ /** A GraphQL operation the fake received. */
11
+ export interface ReceivedOperation {
12
+ operationName: string;
13
+ variables: Record<string, unknown>;
14
+ }
15
+ /** A fake Picked API for one app. */
16
+ export interface FakePicked {
17
+ /** The fake's API origin. */
18
+ apiUrl: string;
19
+ /** The fetch to hand the app as its Picked sender. */
20
+ fetch: typeof fetch;
21
+ /** Picked's public keys, as an app verifies Picked's requests with them. */
22
+ pickedKeys: PublicKeySet;
23
+ /** Each installation's labels, by installation id, then by `<namespace>.<key>`. */
24
+ labels: Map<string, Map<string, AppLabel>>;
25
+ /** Every GraphQL operation received, in order. */
26
+ received: ReceivedOperation[];
27
+ /** Mints a token for an installation, as Picked sends one with each request. */
28
+ tokenFor: (installationId: string) => Promise<{
29
+ token: string;
30
+ expiresAt: string;
31
+ }>;
32
+ /**
33
+ * Names an installation as a request from Picked does: on the fake's API, with a fresh token,
34
+ * in organisation `org` and project `proj_1` unless the overrides say otherwise.
35
+ */
36
+ installationRef: (installationId: string, overrides?: Partial<Pick<InstallationRef, 'organizationId' | 'projectId'>>) => Promise<InstallationRef>;
37
+ /** Builds a request Picked sends the app, signed with Picked's key. */
38
+ signedRequest: (url: string, payload: unknown) => Promise<Request>;
39
+ /** Builds an MCP request Picked forwards to the app, signed with Picked's key. */
40
+ mcpRequest: (url: string, ref: InstallationRef, payload: unknown) => Promise<Request>;
41
+ /** Builds a request from a dashboard user viewing an installation's frame. */
42
+ sessionRequest: (params: {
43
+ ref: InstallationRef;
44
+ url: string;
45
+ method?: string;
46
+ body?: unknown;
47
+ }) => Promise<Request>;
48
+ }
49
+ /**
50
+ * Builds a fake Picked API that trusts one app's key.
51
+ *
52
+ * @param {object} options - The app.
53
+ * @param {string} options.appPrivateKey - The app's private key, whose public half the fake trusts.
54
+ * @param {string} [options.apiUrl] - The fake's API origin.
55
+ * @param {boolean} [options.offlineAccess] - Whether every installation holds offline access.
56
+ * @returns {Promise<FakePicked>} The fake.
57
+ * @example const picked = await createFakePicked({ appPrivateKey: privateKey })
58
+ */
59
+ export declare function createFakePicked(options: {
60
+ appPrivateKey: string;
61
+ apiUrl?: string;
62
+ offlineAccess?: boolean;
63
+ }): Promise<FakePicked>;
64
+ /**
65
+ * Builds a workflow tool call to an installation.
66
+ *
67
+ * @param {InstallationRef} ref - The installation.
68
+ * @param {string} tool - The tool.
69
+ * @param {Record<string, unknown>} args - Its arguments.
70
+ * @param {boolean} [test] - Whether the call belongs to a test run.
71
+ * @returns {ToolCall} The call.
72
+ * @example toolCall(ref, 'create_lead', { lastName: 'Lovelace' })
73
+ */
74
+ export declare function toolCall(ref: InstallationRef, tool: string, args: Record<string, unknown>, test?: boolean): ToolCall;
75
+ /**
76
+ * Reads the cookie an OAuth start set, as the `cookie` header the browser sends with the
77
+ * provider's callback.
78
+ *
79
+ * @param {Response} response - The answer to `POST /oauth/start`.
80
+ * @returns {string} The `<name>=<value>` pair, or an empty string when it set none.
81
+ * @example new Request(callbackUrl, { headers: { cookie: oauthCookie(started) } })
82
+ */
83
+ export declare function oauthCookie(response: Response): string;
84
+ //# sourceMappingURL=testing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../src/testing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAaL,KAAK,eAAe,EACpB,KAAK,YAAY,EAEjB,KAAK,QAAQ,EACd,MAAM,sBAAsB,CAAA;AAC7B,OAAO,KAAK,EAAE,QAAQ,EAA+B,MAAM,UAAU,CAAA;AAErE,6CAA6C;AAC7C,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE,MAAM,CAAA;IACrB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC;AAED,qCAAqC;AACrC,MAAM,WAAW,UAAU;IACzB,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAA;IACd,sDAAsD;IACtD,KAAK,EAAE,OAAO,KAAK,CAAA;IACnB,4EAA4E;IAC5E,UAAU,EAAE,YAAY,CAAA;IACxB,mFAAmF;IACnF,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAA;IAC1C,kDAAkD;IAClD,QAAQ,EAAE,iBAAiB,EAAE,CAAA;IAC7B,gFAAgF;IAChF,QAAQ,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACnF;;;OAGG;IACH,eAAe,EAAE,CACf,cAAc,EAAE,MAAM,EACtB,SAAS,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,eAAe,EAAE,gBAAgB,GAAG,WAAW,CAAC,CAAC,KACvE,OAAO,CAAC,eAAe,CAAC,CAAA;IAC7B,uEAAuE;IACvE,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAClE,kFAAkF;IAClF,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,eAAe,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACrF,8EAA8E;IAC9E,cAAc,EAAE,CAAC,MAAM,EAAE;QACvB,GAAG,EAAE,eAAe,CAAA;QACpB,GAAG,EAAE,MAAM,CAAA;QACX,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,IAAI,CAAC,EAAE,OAAO,CAAA;KACf,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CACvB;AAuKD;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE;IAC9C,aAAa,EAAE,MAAM,CAAA;IACrB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB,GAAG,OAAO,CAAC,UAAU,CAAC,CAgItB;AAED;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CACtB,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,IAAI,UAAQ,GACX,QAAQ,CASV;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAEtD"}
@@ -6,5 +6,5 @@
6
6
  * `@picked/app-kit/frame` runs inside a dashboard slot's iframe.
7
7
  */
8
8
  export * from '@picked/app-protocol';
9
- export type { FrameContext, FrameToHostMessage, HostToFrameMessage } from './frame';
9
+ export type { FrameContext, FrameToHostMessage, HostToFrameMessage } from './frame.js';
10
10
  //# sourceMappingURL=index.d.ts.map
@@ -5,8 +5,8 @@
5
5
  */
6
6
  import { type AppEvent, type AppManifest, type InstallationCreatedEvent, type InstallationDeletedEvent, type InstallationRef, type InstallationUpgradedEvent, type PublicKeySet, type SessionClaims, type ToolCall } from '@picked/app-protocol';
7
7
  export * from '@picked/app-protocol';
8
- export * from './client';
9
- export * from './link';
8
+ export * from './client.js';
9
+ export * from './link.js';
10
10
  /** A tool's body: given the call, returns what the manifest's `output` declares. */
11
11
  export type ToolHandler = (call: ToolCall) => Promise<Record<string, unknown>>;
12
12
  /** What an app server handles. */
@@ -6,7 +6,7 @@
6
6
  * Picked and the dashboard send an app, signed with the fake's Picked key.
7
7
  */
8
8
  import { type InstallationRef, type PublicKeySet, type ToolCall } from '@picked/app-protocol';
9
- import type { AppLabel } from './client';
9
+ import type { AppLabel } from './client.js';
10
10
  /** A GraphQL operation the fake received. */
11
11
  export interface ReceivedOperation {
12
12
  operationName: string;
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@picked/app-kit",
3
3
  "description": "Build Picked apps: the manifest, request signing, server handlers and the dashboard frame handshake",
4
- "version": "0.0.1-dev.1794447047683",
4
+ "version": "0.0.117-next.3",
5
5
  "dependencies": {
6
- "@picked/admin-api-client": "0.0.1-dev.1794447047683",
7
- "@picked/app-protocol": "0.0.1-dev.1794447047683"
6
+ "@picked/admin-api-client": "0.0.117-next.3",
7
+ "@picked/app-protocol": "0.0.117-next.3"
8
8
  },
9
9
  "devDependencies": {
10
10
  "@repo/eslint-config": "workspace:*",
@@ -18,39 +18,69 @@
18
18
  },
19
19
  "exports": {
20
20
  ".": {
21
- "types": "./dist/types/index.d.ts",
22
- "import": "./dist/esm/index.js",
23
- "require": "./dist/cjs/index.js",
21
+ "import": {
22
+ "types": "./dist/types/index.d.ts",
23
+ "default": "./dist/esm/index.js"
24
+ },
25
+ "require": {
26
+ "types": "./dist/cjs/index.d.ts",
27
+ "default": "./dist/cjs/index.js"
28
+ },
24
29
  "default": "./dist/esm/index.js"
25
30
  },
26
31
  "./server": {
27
- "types": "./dist/types/server.d.ts",
28
- "import": "./dist/esm/server.js",
29
- "require": "./dist/cjs/server.js",
32
+ "import": {
33
+ "types": "./dist/types/server.d.ts",
34
+ "default": "./dist/esm/server.js"
35
+ },
36
+ "require": {
37
+ "types": "./dist/cjs/server.d.ts",
38
+ "default": "./dist/cjs/server.js"
39
+ },
30
40
  "default": "./dist/esm/server.js"
31
41
  },
32
42
  "./node": {
33
- "types": "./dist/types/node.d.ts",
34
- "import": "./dist/esm/node.js",
35
- "require": "./dist/cjs/node.js",
43
+ "import": {
44
+ "types": "./dist/types/node.d.ts",
45
+ "default": "./dist/esm/node.js"
46
+ },
47
+ "require": {
48
+ "types": "./dist/cjs/node.d.ts",
49
+ "default": "./dist/cjs/node.js"
50
+ },
36
51
  "default": "./dist/esm/node.js"
37
52
  },
38
53
  "./frame": {
39
- "types": "./dist/types/frame.d.ts",
40
- "import": "./dist/esm/frame.js",
41
- "require": "./dist/cjs/frame.js",
54
+ "import": {
55
+ "types": "./dist/types/frame.d.ts",
56
+ "default": "./dist/esm/frame.js"
57
+ },
58
+ "require": {
59
+ "types": "./dist/cjs/frame.d.ts",
60
+ "default": "./dist/cjs/frame.js"
61
+ },
42
62
  "default": "./dist/esm/frame.js"
43
63
  },
44
64
  "./oauth": {
45
- "types": "./dist/types/oauth.d.ts",
46
- "import": "./dist/esm/oauth.js",
47
- "require": "./dist/cjs/oauth.js",
65
+ "import": {
66
+ "types": "./dist/types/oauth.d.ts",
67
+ "default": "./dist/esm/oauth.js"
68
+ },
69
+ "require": {
70
+ "types": "./dist/cjs/oauth.d.ts",
71
+ "default": "./dist/cjs/oauth.js"
72
+ },
48
73
  "default": "./dist/esm/oauth.js"
49
74
  },
50
75
  "./testing": {
51
- "types": "./dist/types/testing.d.ts",
52
- "import": "./dist/esm/testing.js",
53
- "require": "./dist/cjs/testing.js",
76
+ "import": {
77
+ "types": "./dist/types/testing.d.ts",
78
+ "default": "./dist/esm/testing.js"
79
+ },
80
+ "require": {
81
+ "types": "./dist/cjs/testing.d.ts",
82
+ "default": "./dist/cjs/testing.js"
83
+ },
54
84
  "default": "./dist/esm/testing.js"
55
85
  }
56
86
  },
@@ -82,13 +112,14 @@
82
112
  "access": "public"
83
113
  },
84
114
  "scripts": {
85
- "build": "vite build && tsgo -p tsconfig.build.json",
115
+ "build": "vite build && tsgo -p tsconfig.build.json && node ../../scripts/sdk-dist.mjs",
86
116
  "dev": "node ../../scripts/sdk-watch-build.mjs",
87
117
  "lint": "eslint .",
88
118
  "lint-files": "eslint",
89
119
  "lint:report": "eslint . -o './.reports/eslint.json' -f json || true",
90
120
  "test": "vitest run --passWithNoTests",
91
121
  "test:coverage": "../../scripts/vitest-coverage.sh",
122
+ "test:packaged-types": "attw --pack --profile node16",
92
123
  "type-check": "tsgo -p . --noEmit"
93
124
  },
94
125
  "type": "module",