@tailorkit/app 0.1.0-beta.23 → 0.1.0-beta.24

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 CHANGED
@@ -3,3 +3,114 @@
3
3
  The SDK for building TailorKit extensions.
4
4
 
5
5
  Apps require Preact 11. Install `preact@^11` alongside the SDK.
6
+
7
+ ## File routing
8
+
9
+ New apps register views from `src/slots` automatically. Only files ending in
10
+ `.view.tsx` are views, so supporting components can live beside them.
11
+
12
+ ```text
13
+ src/
14
+ root.tsx
15
+ slots/
16
+ panel/
17
+ root.tsx
18
+ layout.tsx
19
+ home.view.tsx
20
+ customers.view.tsx
21
+ customers.layout.tsx
22
+ customers.details.view.tsx
23
+ customer-card.tsx
24
+ ```
25
+
26
+ The slot directory is its literal host slot name, including dots in names such
27
+ as `panel.links`. Dots in a view filename separate route segments:
28
+ `customers.details.view.tsx` registers `/customers/details`. Subdirectories also
29
+ separate segments. `customer-card.tsx` is an ordinary component and is ignored
30
+ unless imported. Duplicate view paths in a slot fail the build.
31
+
32
+ ```tsx
33
+ // src/slots/panel/customers.details.view.tsx
34
+ import { defineView } from "tailorkit/client";
35
+ import CustomerCard from "./customer-card";
36
+
37
+ export default defineView({ component: CustomerCard });
38
+ ```
39
+
40
+ The builder supplies the slot and route before compiling. You can keep an
41
+ explicit `view` to override the filename and infer the precise host context type:
42
+
43
+ ```tsx
44
+ // src/slots/panel/home.view.tsx
45
+ import { defineView } from "tailorkit/client";
46
+
47
+ const view = defineView({ view: "/", component: Home });
48
+
49
+ function Home() {
50
+ const context = view.useContext();
51
+ return <>Welcome</>;
52
+ }
53
+
54
+ export default view;
55
+ ```
56
+
57
+ There are no special view filenames: `index.view.tsx` maps to `/index`.
58
+ Use a descriptive filename with `view: "/"` for the slot's home view.
59
+ An explicit slot, if supplied, must match the containing slot directory.
60
+ Multi-instance views still provide `instances: { dataSchema, resolve }`;
61
+ resolvers are extracted into the private server bundle. Host slot/view support
62
+ and multiplicity are validated when publishing. An explicit slot also retains
63
+ the source-level TypeScript checks for that slot's supported views and instances.
64
+
65
+ ## Roots and layouts
66
+
67
+ `src/root.tsx` is the optional app shell. Init generates a shell with the backend
68
+ provider:
69
+
70
+ ```tsx
71
+ import { ClientProvider, defineRoute, Route } from "tailorkit/client";
72
+
73
+ function Shell() {
74
+ return (
75
+ <ClientProvider>
76
+ <Route />
77
+ </ClientProvider>
78
+ );
79
+ }
80
+
81
+ export default defineRoute({ shellComponent: Shell });
82
+ ```
83
+
84
+ Each slot can also have a `root.tsx` exporting `defineRoute({ shellComponent })`.
85
+ It wraps every view in that slot, inside the app shell. A shell can render its
86
+ `children` prop instead of `<Route />`.
87
+
88
+ `layout.tsx` wraps the entire slot. `customers.layout.tsx` wraps `/customers` and
89
+ its descendants, with matching at segment boundaries. Layouts follow the
90
+ resolved view path, including an explicit `view` override. They do not register
91
+ views themselves. A layout default-exports an ordinary component (or a
92
+ `defineRoute({ shellComponent })` definition):
93
+
94
+ ```tsx
95
+ import { Route } from "tailorkit/client";
96
+
97
+ export default function CustomersLayout() {
98
+ return <Route />;
99
+ }
100
+ ```
101
+
102
+ For `/customers/details`, the order is app root → slot root → slot layout →
103
+ customers layout → details view. Shared shells and layouts stay mounted as the
104
+ selected view changes; layouts mount and unmount when entering or leaving their
105
+ route subtree. Layouts do not automatically receive a leaf view's typed context.
106
+
107
+ Each mounted slot instance has its own shell, provider, and layout state. Two
108
+ separate host mounts do not share provider state. A provider is disposed when
109
+ its slot mount is removed.
110
+
111
+ ## Build and preview
112
+
113
+ File routing is the app client entry point. Build and deploy discover the same
114
+ roots, layouts, and views. Preview watches route additions, renames, removals,
115
+ and source edits. Generated entries live only in the build output and are
116
+ cleaned up after builds or when the watcher closes.
@@ -0,0 +1,4 @@
1
+ export declare function appDatabasePaths(root: string, migrations?: string): {
2
+ schema: string;
3
+ migrations: string;
4
+ };
@@ -0,0 +1,3 @@
1
+ import type { ESTree } from "vite";
2
+ /** Recognize the same SDK calls in route inference and instance extraction. */
3
+ export declare function createDefineViewMatcher(program: ESTree.Program): (node: ESTree.Node) => node is ESTree.CallExpression;
@@ -0,0 +1,34 @@
1
+ import type { Plugin } from "vite";
2
+ export declare function fileViewLocation(filename: string, root: string): {
3
+ slot: string;
4
+ path: string;
5
+ } | undefined;
6
+ /** Fill missing defineView options before instance extraction, on both build sides. */
7
+ export declare function inferFileView(source: string, filename: string, root: string): string;
8
+ export declare function discoverFileRoutes(root: string): Promise<{
9
+ root: {
10
+ filename: string;
11
+ } | undefined;
12
+ roots: {
13
+ filename: string;
14
+ slot: string;
15
+ }[];
16
+ layouts: {
17
+ filename: string;
18
+ slot: string;
19
+ path: string;
20
+ }[];
21
+ views: {
22
+ filename: string;
23
+ slot: string;
24
+ }[];
25
+ }>;
26
+ /** Root, layout, view and binding sources to check before deployment. */
27
+ export declare function getClientSourceFiles(root: string): Promise<string[]>;
28
+ /** A generated entry in build output lets the bundler track imports normally.
29
+ * Directory watching also covers routes that did not exist at the first build. */
30
+ export declare function createFileRouteEntry(root: string, output: string, watching: boolean): Promise<{
31
+ entry: string;
32
+ close(): Promise<void>;
33
+ }>;
34
+ export declare function fileRoutesPlugin(root: string): Plugin;
@@ -1,5 +1,6 @@
1
1
  export { createTailorKitUploadManifest, tailorkitUploadManifestSchema, type TailorKitUploadManifest, } from "./upload-manifest";
2
2
  export { generateAppMigrations, type GenerateAppMigrationsOptions } from "./generate-migrations";
3
+ export { getClientSourceFiles } from "./file-routes";
3
4
  export interface BuildAppOptions {
4
5
  configPath?: string;
5
6
  cwd?: string;