@tailorkit/app 0.1.0-beta.25 → 0.1.0-beta.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/builder.js CHANGED
@@ -219,7 +219,7 @@ async function readAppMigrations(directory, optional = false) {
219
219
  // src/server/bundle.ts
220
220
  var runtimeManifest = {
221
221
  apiVersion: 1,
222
- requires: ["database", "actions", "database-relations"]
222
+ requires: ["database", "actions", "database-relations", "tools"]
223
223
  };
224
224
 
225
225
  // src/builder/schema-check.ts
@@ -10,6 +10,13 @@ import { RPCLink } from "@orpc/client/websocket";
10
10
 
11
11
  // src/client/session.ts
12
12
  var APP_SESSION_RENEWAL_MS = 6e4;
13
+ function freezeIdentity(value) {
14
+ if (value && typeof value === "object" && !Object.isFrozen(value)) {
15
+ for (const child of Object.values(value)) freezeIdentity(child);
16
+ Object.freeze(value);
17
+ }
18
+ return value;
19
+ }
13
20
  function sessionRenewalDelay(session) {
14
21
  return Math.max(500, session.expiresAt - Date.now() - APP_SESSION_RENEWAL_MS);
15
22
  }
@@ -21,7 +28,7 @@ function createSessionProvider(options) {
21
28
  let cached;
22
29
  let pending;
23
30
  return (input) => {
24
- if (!input.refresh && cached && cached.expiresAt > Date.now() + APP_SESSION_RENEWAL_MS) {
31
+ if (options.subjectId !== void 0 && !input.refresh && cached && cached.subjectId === options.subjectId && cached.expiresAt > Date.now() + APP_SESSION_RENEWAL_MS) {
25
32
  return Promise.resolve(cached);
26
33
  }
27
34
  pending ??= (async () => {
@@ -44,7 +51,16 @@ function createSessionProvider(options) {
44
51
  if (typeof value.token !== "string" || typeof value.expiresAt !== "number" || typeof value.url !== "string") {
45
52
  throw new AppError("UNAVAILABLE", "Invalid app session");
46
53
  }
47
- cached = { token: value.token, expiresAt: value.expiresAt, url: value.url };
54
+ if (options.subjectId !== void 0 && value.subjectId !== options.subjectId)
55
+ throw new AppError("UNAUTHORIZED", "Authenticated principal changed");
56
+ cached = {
57
+ ...value.toolUrl !== void 0 ? { toolUrl: value.toolUrl } : {},
58
+ ...value.identity !== void 0 ? { identity: freezeIdentity(value.identity) } : {},
59
+ token: value.token,
60
+ expiresAt: value.expiresAt,
61
+ url: value.url,
62
+ ...value.subjectId !== void 0 ? { subjectId: value.subjectId } : {}
63
+ };
48
64
  return cached;
49
65
  })().finally(() => {
50
66
  pending = void 0;
@@ -1,8 +1,9 @@
1
1
  import {
2
2
  createClient,
3
3
  reference
4
- } from "./chunk-LIPODQ7B.js";
4
+ } from "./chunk-4PGMCBMJ.js";
5
5
  import {
6
+ AppError,
6
7
  appError
7
8
  } from "./chunk-IJBQ77AH.js";
8
9
 
@@ -424,6 +425,30 @@ function createFileClient(options) {
424
425
  };
425
426
  }
426
427
 
428
+ // src/client/tools.ts
429
+ function callTool(kind, path, input) {
430
+ const bridge = globalThis.__tailorkitTools;
431
+ if (!bridge) return Promise.reject(new AppError("UNAVAILABLE", "Tool bridge unavailable"));
432
+ if (kind === "client") return bridge.client(path, input);
433
+ return bridge.session(path).then((session) => executeServerTool(session, path, input));
434
+ }
435
+ async function executeServerTool(session, path, input, request = globalThis.fetch, signal) {
436
+ const response = await request(session.url, {
437
+ method: "POST",
438
+ redirect: "error",
439
+ credentials: "omit",
440
+ signal,
441
+ headers: { authorization: `Bearer ${session.token}`, "content-type": "application/json" },
442
+ body: JSON.stringify({ path, input, requestId: crypto.randomUUID() })
443
+ });
444
+ if (!response.ok)
445
+ throw new AppError(
446
+ response.status === 401 ? "UNAUTHORIZED" : response.status === 400 ? "BAD_REQUEST" : "UNAVAILABLE",
447
+ "Tool call failed"
448
+ );
449
+ return (await response.json()).output;
450
+ }
451
+
427
452
  export {
428
453
  defineView,
429
454
  createRemoteComponent,
@@ -433,5 +458,6 @@ export {
433
458
  useAction,
434
459
  defineRoute,
435
460
  Route,
436
- createFileClient
461
+ createFileClient,
462
+ callTool
437
463
  };
@@ -1,4 +1,8 @@
1
+ import type { Identity } from "../server/functions";
1
2
  export interface Session {
3
+ toolUrl?: string;
4
+ identity?: Identity;
5
+ subjectId?: string;
2
6
  token: string;
3
7
  expiresAt: number;
4
8
  url: string;
@@ -8,6 +12,8 @@ export declare function sessionRenewalDelay(session: Session): number;
8
12
  export declare function createSessionProvider(options: {
9
13
  baseUrl: string | URL;
10
14
  appId: string;
15
+ /** Product principal used solely to partition the host credential cache. */
16
+ subjectId?: string;
11
17
  fetch?: typeof fetch;
12
18
  }): (input: {
13
19
  refresh: boolean;
@@ -0,0 +1,10 @@
1
+ import type { Session } from "./session";
2
+ export interface ToolBridge {
3
+ client(path: string, input: unknown): Promise<unknown>;
4
+ session(path: string): Promise<Session>;
5
+ }
6
+ export interface TailorKitServerTools {
7
+ }
8
+ /** Generated callers delegate only transport; host/server declarations validate both directions. */
9
+ export declare function callTool(kind: "client" | "server", path: string, input?: unknown): Promise<unknown>;
10
+ export declare function executeServerTool(session: Session, path: string, input: unknown, request?: typeof fetch, signal?: AbortSignal): Promise<unknown>;
@@ -2,7 +2,7 @@ import {
2
2
  createClient,
3
3
  createSessionProvider,
4
4
  reference
5
- } from "./chunk-LIPODQ7B.js";
5
+ } from "./chunk-4PGMCBMJ.js";
6
6
  import {
7
7
  AppError
8
8
  } from "./chunk-IJBQ77AH.js";
package/dist/client.d.ts CHANGED
@@ -7,3 +7,5 @@ export { createApi } from "./client/reference";
7
7
  export type { Client, Session, Reference, References } from "./client/connection";
8
8
  export { AppError, appError } from "./errors";
9
9
  export type { ErrorCode } from "./errors";
10
+ export { callTool } from "./client/tools";
11
+ export type { TailorKitServerTools, ToolBridge } from "./client/tools";
package/dist/client.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  ClientProvider,
3
3
  Route,
4
+ callTool,
4
5
  createFileClient,
5
6
  createRemoteComponent,
6
7
  defineRoute,
@@ -8,13 +9,13 @@ import {
8
9
  useAction,
9
10
  useMutation,
10
11
  useQuery
11
- } from "./chunk-O3M4EOCQ.js";
12
+ } from "./chunk-S3KZ3Z2U.js";
12
13
  import {
13
14
  createApi,
14
15
  createClient,
15
16
  createSessionProvider,
16
17
  reference
17
- } from "./chunk-LIPODQ7B.js";
18
+ } from "./chunk-4PGMCBMJ.js";
18
19
  import {
19
20
  AppError,
20
21
  appError
@@ -24,6 +25,7 @@ export {
24
25
  ClientProvider,
25
26
  Route,
26
27
  appError,
28
+ callTool,
27
29
  createApi,
28
30
  createClient,
29
31
  createFileClient,
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  ClientProvider,
3
3
  Route,
4
+ callTool,
4
5
  createFileClient,
5
6
  createRemoteComponent,
6
7
  defineRoute,
@@ -8,13 +9,13 @@ import {
8
9
  useAction,
9
10
  useMutation,
10
11
  useQuery
11
- } from "./chunk-O3M4EOCQ.js";
12
+ } from "./chunk-S3KZ3Z2U.js";
12
13
  import {
13
14
  createApi,
14
15
  createClient,
15
16
  createSessionProvider,
16
17
  reference
17
- } from "./chunk-LIPODQ7B.js";
18
+ } from "./chunk-4PGMCBMJ.js";
18
19
  import {
19
20
  action,
20
21
  and,
@@ -56,6 +57,7 @@ export {
56
57
  appError,
57
58
  asc,
58
59
  boolean,
60
+ callTool,
59
61
  count,
60
62
  createApi,
61
63
  createClient,
@@ -13,5 +13,5 @@ export interface ApplicationModule {
13
13
  /** Emitted by this SDK's builder; breaking interface changes increment apiVersion. */
14
14
  export declare const runtimeManifest: {
15
15
  readonly apiVersion: 1;
16
- readonly requires: readonly ["database", "actions", "database-relations"];
16
+ readonly requires: readonly ["database", "actions", "database-relations", "tools"];
17
17
  };
@@ -1,9 +1,15 @@
1
+ import type { TailorKitServerTools } from "../client/tools";
1
2
  import type { z } from "zod";
2
3
  import type { AnyRelations, EmptyRelations } from "drizzle-orm/relations";
3
4
  import type { DatabaseDefinition } from "../database/definition";
4
5
  import type { QueryDatabase, MutationDatabase } from "../database/types";
5
6
  export interface Identity {
6
- readonly userId: string;
7
+ readonly subjectId?: string;
8
+ readonly scope: {
9
+ name: string;
10
+ value: Record<string, unknown>;
11
+ };
12
+ readonly toolUrl: string;
7
13
  readonly projectId: string;
8
14
  readonly appId: string;
9
15
  readonly installationId: string;
@@ -32,6 +38,9 @@ export type FunctionCalls<F, K extends "query" | "mutation"> = {
32
38
  };
33
39
  export interface ActionContext<F extends Functions = Record<never, never>> {
34
40
  readonly identity: Identity;
41
+ readonly tools: TailorKitServerTools;
42
+ readonly requestId: string;
43
+ readonly scope: Identity["scope"];
35
44
  readonly signal: AbortSignal;
36
45
  readonly queries: FunctionCalls<F, "query">;
37
46
  readonly mutations: FunctionCalls<F, "mutation">;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tailorkit/app",
3
- "version": "0.1.0-beta.25",
3
+ "version": "0.1.0-beta.26",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",