@tailorkit/app 0.1.0-beta.35 → 0.1.0-beta.38
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/README.md +19 -11
- package/dist/{chunk-PJBDA2RU.js → chunk-5B5RGL5W.js} +3 -8
- package/dist/{chunk-2JZOHWYW.js → chunk-Q6X2VQKX.js} +7 -10
- package/dist/client-connection.js +1 -1
- package/dist/client.js +2 -2
- package/dist/index.js +2 -2
- package/dist/server/builder.d.ts +2 -2
- package/dist/server/functions.d.ts +10 -9
- package/dist/server.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
# TailorKit
|
|
1
|
+
# TailorKit app SDK
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Apps require Preact 11. Install `preact@^11` alongside the SDK.
|
|
3
|
+
Use `@tailorkit/app` to build TailorKit extensions. Apps require Preact 11; install `preact@^11` alongside the SDK.
|
|
6
4
|
|
|
7
5
|
## File routing
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
The builder registers views from `src/slots` automatically. Only files ending in `.view.tsx` register views, so supporting components can live beside them:
|
|
10
8
|
|
|
11
9
|
```text
|
|
12
10
|
src/
|
|
@@ -22,10 +20,13 @@ src/
|
|
|
22
20
|
customer-card.tsx
|
|
23
21
|
```
|
|
24
22
|
|
|
25
|
-
The slot directory is its literal host slot name, including dots in names such as `panel.links`. Dots in a view filename separate route segments: `customers.details.view.tsx` registers `/customers/details`. Subdirectories also separate segments. `customer-card.tsx` is an ordinary component and is ignored unless imported.
|
|
23
|
+
The slot directory is its literal host slot name, including dots in names such as `panel.links`. Dots in a view filename separate route segments: `customers.details.view.tsx` registers `/customers/details`. Subdirectories also separate segments. `customer-card.tsx` is an ordinary component and is ignored unless imported.
|
|
24
|
+
|
|
25
|
+
Duplicate view paths in a slot fail the build.
|
|
26
|
+
|
|
27
|
+
For example, `src/slots/panel/customers.details.view.tsx` registers `/customers/details`:
|
|
26
28
|
|
|
27
29
|
```tsx
|
|
28
|
-
// src/slots/panel/customers.details.view.tsx
|
|
29
30
|
import { defineView } from "tailorkit/client";
|
|
30
31
|
|
|
31
32
|
import CustomerCard from "./customer-card";
|
|
@@ -33,10 +34,9 @@ import CustomerCard from "./customer-card";
|
|
|
33
34
|
export default defineView({ component: CustomerCard });
|
|
34
35
|
```
|
|
35
36
|
|
|
36
|
-
The builder supplies the slot and route before compiling.
|
|
37
|
+
The builder supplies the slot and route before compiling. In `src/slots/panel/index.view.tsx`, an explicit `view` gives typed host context and must match `/`:
|
|
37
38
|
|
|
38
39
|
```tsx
|
|
39
|
-
// src/slots/panel/index.view.tsx
|
|
40
40
|
import { defineView } from "tailorkit/client";
|
|
41
41
|
|
|
42
42
|
const view = defineView({ view: "/", component: Home });
|
|
@@ -49,7 +49,11 @@ function Home() {
|
|
|
49
49
|
export default view;
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
`index.view.tsx` maps to `/`. A final `index` segment is omitted, so `customers/index.view.tsx` and `customers.index.view.tsx` both map to `/customers`. Other segments stay literal: `index.details.view.tsx` maps to `/index/details`.
|
|
52
|
+
`index.view.tsx` maps to `/`. A final `index` segment is omitted, so `customers/index.view.tsx` and `customers.index.view.tsx` both map to `/customers`. Other segments stay literal: `index.details.view.tsx` maps to `/index/details`.
|
|
53
|
+
|
|
54
|
+
An explicit `view` or `slot` must be a matching string literal; mismatches fail the build. Use named properties in the inline `defineView` options so the build can check them.
|
|
55
|
+
|
|
56
|
+
For multi-instance views, provide `instances: { dataSchema, resolve }`. The builder extracts resolvers into the private server bundle. Host slot/view support and multiplicity are validated when publishing. An explicit slot also retains the source-level TypeScript checks for that slot's supported views and instances.
|
|
53
57
|
|
|
54
58
|
## Roots and layouts
|
|
55
59
|
|
|
@@ -71,7 +75,11 @@ export default defineRoute({ shellComponent: Shell });
|
|
|
71
75
|
|
|
72
76
|
Each slot can also have a `root.tsx` exporting `defineRoute({ shellComponent })`. It wraps every view in that slot, inside the app shell. A shell can render its `children` prop instead of `<Route />`.
|
|
73
77
|
|
|
74
|
-
`layout.tsx` wraps its directory path: at the slot root it wraps the entire slot; `members/layout.tsx` wraps `/members` and its descendants. `customers.layout.tsx` wraps `/customers` and its descendants, with matching at segment boundaries.
|
|
78
|
+
`layout.tsx` wraps its directory path: at the slot root it wraps the entire slot; `members/layout.tsx` wraps `/members` and its descendants. `customers.layout.tsx` wraps `/customers` and its descendants, with matching at segment boundaries.
|
|
79
|
+
|
|
80
|
+
Unlike view paths, layout paths retain a final `index` segment: `index.layout.tsx` maps to `/index`, and `members/index.layout.tsx` maps to `/members/index`. Layouts do not register views themselves.
|
|
81
|
+
|
|
82
|
+
Export a component as the layout’s default export, or use a `defineRoute({ shellComponent })` definition:
|
|
75
83
|
|
|
76
84
|
```tsx
|
|
77
85
|
import { Route } from "tailorkit/client";
|
|
@@ -269,12 +269,7 @@ var createClient = (options = {}) => {
|
|
|
269
269
|
},
|
|
270
270
|
headers: { authorization: `Bearer ${session.token}` },
|
|
271
271
|
origin: url.origin,
|
|
272
|
-
|
|
273
|
-
url: (
|
|
274
|
-
/* oxlint-disable typescript/no-unsafe-type-assertion -- URL.pathname always starts with a slash for this HTTP session URL, satisfying the transport's absolute route-path type. */
|
|
275
|
-
url.pathname
|
|
276
|
-
)
|
|
277
|
-
/* oxlint-enable typescript/no-unsafe-type-assertion */
|
|
272
|
+
url: `/${url.pathname.slice(1)}`
|
|
278
273
|
})
|
|
279
274
|
);
|
|
280
275
|
if (kind === "mutations") {
|
|
@@ -344,7 +339,7 @@ var createClient = (options = {}) => {
|
|
|
344
339
|
query: async (ref, ...[args]) => await /* oxlint-disable typescript/no-unsafe-type-assertion -- The query reference owns its output type, and the server validates that registered query before the shared transport returns its erased result. */
|
|
345
340
|
call("queries", { args, name: ref.name }),
|
|
346
341
|
/* oxlint-enable typescript/no-unsafe-type-assertion */
|
|
347
|
-
subscribe: (ref, args,
|
|
342
|
+
subscribe: (ref, args, onValue, settings = {}) => {
|
|
348
343
|
if (closed) {
|
|
349
344
|
throw new AppError("UNAVAILABLE", "App client closed");
|
|
350
345
|
}
|
|
@@ -365,7 +360,7 @@ var createClient = (options = {}) => {
|
|
|
365
360
|
if (controller.signal.aborted || closed) {
|
|
366
361
|
break;
|
|
367
362
|
}
|
|
368
|
-
|
|
363
|
+
onValue(
|
|
369
364
|
/* oxlint-disable typescript/no-unsafe-type-assertion -- This subscription was opened with ref.name and args; its listener receives only results from that same registered query, whose output generic is erased by the transport. */
|
|
370
365
|
value
|
|
371
366
|
/* oxlint-enable typescript/no-unsafe-type-assertion */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createClient,
|
|
3
3
|
reference
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-5B5RGL5W.js";
|
|
5
5
|
import {
|
|
6
6
|
AppError,
|
|
7
7
|
appError
|
|
@@ -194,11 +194,7 @@ var QueryStore = class {
|
|
|
194
194
|
return;
|
|
195
195
|
}
|
|
196
196
|
publish({
|
|
197
|
-
data: (
|
|
198
|
-
/* oxlint-disable typescript/no-unsafe-type-assertion -- The entry is created and updated by this query reference's typed subscription; the shared cache erases its output generic. */
|
|
199
|
-
this.state.get().get(key)?.data
|
|
200
|
-
),
|
|
201
|
-
/* oxlint-enable typescript/no-unsafe-type-assertion */
|
|
197
|
+
data: this.state.get().get(key)?.data,
|
|
202
198
|
error,
|
|
203
199
|
status: "error"
|
|
204
200
|
});
|
|
@@ -404,10 +400,9 @@ var useCall = (kind, ref, options) => {
|
|
|
404
400
|
(...args) => {
|
|
405
401
|
void (async () => {
|
|
406
402
|
try {
|
|
407
|
-
|
|
403
|
+
await runAsync(...args);
|
|
408
404
|
} catch {
|
|
409
405
|
}
|
|
410
|
-
return void 0;
|
|
411
406
|
})();
|
|
412
407
|
},
|
|
413
408
|
[runAsync]
|
|
@@ -480,7 +475,8 @@ var createFileClient = (options) => {
|
|
|
480
475
|
...layout,
|
|
481
476
|
shell: shellComponent(layout, false)
|
|
482
477
|
}));
|
|
483
|
-
const definitions =
|
|
478
|
+
const definitions = {};
|
|
479
|
+
Object.setPrototypeOf(definitions, null);
|
|
484
480
|
for (const module of options.views) {
|
|
485
481
|
const view = (
|
|
486
482
|
/* oxlint-disable typescript/no-unsafe-type-assertion -- The generated module registry owns these component and view declarations; the runtime adapter preserves their exported implementations. */
|
|
@@ -513,7 +509,8 @@ var createFileClient = (options) => {
|
|
|
513
509
|
}
|
|
514
510
|
slot[view.path] = view;
|
|
515
511
|
}
|
|
516
|
-
const slots =
|
|
512
|
+
const slots = {};
|
|
513
|
+
Object.setPrototypeOf(slots, null);
|
|
517
514
|
for (const [slot, views] of Object.entries(definitions)) {
|
|
518
515
|
const slotLayouts = layouts.filter((layout) => layout.slot === slot).toSorted(
|
|
519
516
|
(a, b) => a.path.split("/").filter(Boolean).length - b.path.split("/").filter(Boolean).length
|
package/dist/client.js
CHANGED
|
@@ -9,13 +9,13 @@ import {
|
|
|
9
9
|
useAction,
|
|
10
10
|
useMutation,
|
|
11
11
|
useQuery
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-Q6X2VQKX.js";
|
|
13
13
|
import {
|
|
14
14
|
createApi,
|
|
15
15
|
createClient,
|
|
16
16
|
createSessionProvider,
|
|
17
17
|
reference
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-5B5RGL5W.js";
|
|
19
19
|
import {
|
|
20
20
|
AppError,
|
|
21
21
|
appError
|
package/dist/index.js
CHANGED
|
@@ -9,13 +9,13 @@ import {
|
|
|
9
9
|
useAction,
|
|
10
10
|
useMutation,
|
|
11
11
|
useQuery
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-Q6X2VQKX.js";
|
|
13
13
|
import {
|
|
14
14
|
createApi,
|
|
15
15
|
createClient,
|
|
16
16
|
createSessionProvider,
|
|
17
17
|
reference
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-5B5RGL5W.js";
|
|
19
19
|
import {
|
|
20
20
|
action,
|
|
21
21
|
and,
|
package/dist/server/builder.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { AnyRelations, EmptyRelations } from "drizzle-orm/relations";
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import type { DatabaseDefinition } from "#database/definition";
|
|
4
4
|
import type { MutationDatabase, QueryDatabase } from "#database/types";
|
|
5
|
-
import type { ActionContext, FunctionKind, Functions, Identity } from "./functions";
|
|
5
|
+
import type { ActionContext, EmptyFunctions, FunctionKind, Functions, Identity } from "./functions";
|
|
6
6
|
type HandlerContext<K extends FunctionKind, A extends z.ZodType, F extends Functions, D extends AnyRelations> = {
|
|
7
7
|
input: z.output<A>;
|
|
8
8
|
} & (K extends "action" ? ActionContext<F> : {
|
|
@@ -24,7 +24,7 @@ type BuiltFunction<K extends FunctionKind, A extends z.ZodType, R, O, F extends
|
|
|
24
24
|
readonly functions: F;
|
|
25
25
|
} : unknown);
|
|
26
26
|
/** Immutable builders preserve the validated input and wire output types at every step. */
|
|
27
|
-
declare class FunctionBuilder<K extends FunctionKind, A extends z.ZodType, R extends z.ZodType | undefined = undefined, F extends Functions =
|
|
27
|
+
declare class FunctionBuilder<K extends FunctionKind, A extends z.ZodType, R extends z.ZodType | undefined = undefined, F extends Functions = EmptyFunctions, D extends AnyRelations = EmptyRelations> {
|
|
28
28
|
private readonly kind;
|
|
29
29
|
private readonly args;
|
|
30
30
|
private readonly result;
|
|
@@ -3,6 +3,7 @@ import type { z } from "zod";
|
|
|
3
3
|
import type { TailorKitServerTools } from "#client/tools";
|
|
4
4
|
import type { DatabaseDefinition } from "#database/definition";
|
|
5
5
|
import type { QueryDatabase, MutationDatabase } from "#database/types";
|
|
6
|
+
export type EmptyFunctions = Record<never, never>;
|
|
6
7
|
export interface Identity {
|
|
7
8
|
readonly subjectId?: string;
|
|
8
9
|
readonly scope: {
|
|
@@ -36,7 +37,7 @@ export type FunctionCalls<F, K extends "query" | "mutation"> = {
|
|
|
36
37
|
requestId?: string;
|
|
37
38
|
}]) => Promise<FunctionResult<F[N]>> : (...args: undefined extends z.input<A> ? [args?: z.input<A>] : [args: z.input<A>]) => Promise<FunctionResult<F[N]>> : F[N] extends Functions ? FunctionCalls<F[N], K> : never;
|
|
38
39
|
};
|
|
39
|
-
export interface ActionContext<F extends Functions =
|
|
40
|
+
export interface ActionContext<F extends Functions = EmptyFunctions> {
|
|
40
41
|
readonly identity: Identity;
|
|
41
42
|
readonly tools: TailorKitServerTools;
|
|
42
43
|
readonly requestId: string;
|
|
@@ -45,7 +46,7 @@ export interface ActionContext<F extends Functions = Record<never, never>> {
|
|
|
45
46
|
readonly queries: FunctionCalls<F, "query">;
|
|
46
47
|
readonly mutations: FunctionCalls<F, "mutation">;
|
|
47
48
|
}
|
|
48
|
-
export interface FunctionDefinition<K extends FunctionKind, A extends z.ZodType, O, F extends Functions =
|
|
49
|
+
export interface FunctionDefinition<K extends FunctionKind, A extends z.ZodType, O, F extends Functions = EmptyFunctions, D extends AnyRelations = EmptyRelations> {
|
|
49
50
|
readonly kind: K;
|
|
50
51
|
readonly args: A;
|
|
51
52
|
readonly database?: K extends "action" ? never : DatabaseDefinition<D>;
|
|
@@ -57,25 +58,25 @@ export interface FunctionDefinition<K extends FunctionKind, A extends z.ZodType,
|
|
|
57
58
|
identity: Identity;
|
|
58
59
|
})) => K extends "action" ? O | Promise<O> : O;
|
|
59
60
|
}
|
|
60
|
-
export declare const query: <A extends z.ZodType, O, const D extends AnyRelations = EmptyRelations>(definition: Omit<FunctionDefinition<"query", A, O,
|
|
61
|
-
handler: FunctionDefinition<"query", A, O,
|
|
61
|
+
export declare const query: <A extends z.ZodType, O, const D extends AnyRelations = EmptyRelations>(definition: Omit<FunctionDefinition<"query", A, O, EmptyFunctions, D>, "kind"> & {
|
|
62
|
+
handler: FunctionDefinition<"query", A, O, EmptyFunctions, D>["handler"] & ([O] extends [never] ? unknown : O extends PromiseLike<unknown> ? never : unknown);
|
|
62
63
|
}) => Readonly<{
|
|
63
64
|
args: A;
|
|
64
65
|
database?: DatabaseDefinition<D> | undefined;
|
|
65
66
|
result?: z.ZodType<O, unknown, z.core.$ZodTypeInternals<O, unknown>> | undefined;
|
|
66
|
-
handler: FunctionDefinition<"query", A, O,
|
|
67
|
+
handler: FunctionDefinition<"query", A, O, EmptyFunctions, D>["handler"] & ([O] extends [never] ? unknown : O extends PromiseLike<unknown> ? never : unknown);
|
|
67
68
|
kind: "query";
|
|
68
69
|
}>;
|
|
69
|
-
export declare const mutation: <A extends z.ZodType, O, const D extends AnyRelations = EmptyRelations>(definition: Omit<FunctionDefinition<"mutation", A, O,
|
|
70
|
-
handler: FunctionDefinition<"mutation", A, O,
|
|
70
|
+
export declare const mutation: <A extends z.ZodType, O, const D extends AnyRelations = EmptyRelations>(definition: Omit<FunctionDefinition<"mutation", A, O, EmptyFunctions, D>, "kind"> & {
|
|
71
|
+
handler: FunctionDefinition<"mutation", A, O, EmptyFunctions, D>["handler"] & ([O] extends [never] ? unknown : O extends PromiseLike<unknown> ? never : unknown);
|
|
71
72
|
}) => Readonly<{
|
|
72
73
|
args: A;
|
|
73
74
|
database?: DatabaseDefinition<D> | undefined;
|
|
74
75
|
result?: z.ZodType<O, unknown, z.core.$ZodTypeInternals<O, unknown>> | undefined;
|
|
75
|
-
handler: FunctionDefinition<"mutation", A, O,
|
|
76
|
+
handler: FunctionDefinition<"mutation", A, O, EmptyFunctions, D>["handler"] & ([O] extends [never] ? unknown : O extends PromiseLike<unknown> ? never : unknown);
|
|
76
77
|
kind: "mutation";
|
|
77
78
|
}>;
|
|
78
|
-
export declare const action: <A extends z.ZodType, O, const F extends Functions =
|
|
79
|
+
export declare const action: <A extends z.ZodType, O, const F extends Functions = EmptyFunctions>(definition: Omit<FunctionDefinition<"action", A, O, F>, "kind"> & {
|
|
79
80
|
functions?: F;
|
|
80
81
|
}) => Readonly<{
|
|
81
82
|
args: A;
|
package/dist/server.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export type { DatabaseDefinition } from "./database/definition";
|
|
|
4
4
|
export { fn } from "./server/builder";
|
|
5
5
|
export { withInstanceResolvers } from "./server/instances";
|
|
6
6
|
export type { QueryDatabase, MutationDatabase } from "./database/types";
|
|
7
|
-
export type { Identity, FunctionDefinition, AppDefinition, ActionContext, FunctionKind, } from "./server/functions";
|
|
7
|
+
export type { EmptyFunctions, Identity, FunctionDefinition, AppDefinition, ActionContext, FunctionKind, } from "./server/functions";
|
|
8
8
|
export { table, text, integer, real, boolean, eq, ne, gt, gte, lt, lte, and, or, asc, desc, count, isNull, isNotNull, inArray, } from "./database/schema";
|
|
9
9
|
export { AppError } from "./errors";
|
|
10
10
|
export type { ErrorCode } from "./errors";
|