@tailorkit/app 0.1.0-beta.19 → 0.1.0-beta.20

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
@@ -94,7 +94,7 @@ Auth signing and verification use Effect v4. `issueAppTokenEffect`, `appTokenVer
94
94
 
95
95
  Add `server: {}` to `tailorkit.config.ts` to build the backend from `src/server.ts`. The client builds from `src/client.ts` by default. `client.entry` and `server.entry` override these source entry points while output filenames stay the same. `tailorkit build` emits `.tailorkit/client/client.js` and `.tailorkit/server/server.js`, and copies committed Drizzle migration files into `.tailorkit/migrations/`. Intermediate server entries are created under the output root’s `tmp/` directory and removed after builds or when the watcher closes; `server/` contains the upload artifact. The server exports the application definition and embedded migrations; Cloudflare bootstrap code belongs to the runtime worker. The builder writes no backend reference source files. The browser builder rejects server implementation imports. `build.outDir` and `--out-dir` change the common output root for all artifacts; preview serves only its `client/` directory.
96
96
 
97
- `tailorkit deploy` uploads the client and private server artifact through existing platform-issued blob upload URLs. Apps need no Cloudflare credentials. R2 stores them under separate `client/` and `server/` prefixes; only client assets are public. Client-only apps continue to build without a server artifact. Watch mode watches both builds.
97
+ `tailorkit deploy` gzips the client and private server artifacts before uploading them through platform-issued blob upload URLs. Checksums and content lengths describe the compressed bytes stored in R2. The runtime verifies and decompresses server code before loading it; client delivery serves gzip to browsers that accept it. The platform checks that decoded client bundles fit within 3 MiB before publication, and decoded delivery streams enforce the same limit. Existing uncompressed deployments remain supported. Apps need no Cloudflare credentials. R2 stores them under separate `client/` and `server/` prefixes; only client assets are public. Client-only apps continue to build without a server artifact. Watch mode watches both builds.
98
98
 
99
99
  The legacy `app-storage` SDK, `storage` config and storage CLI commands have been removed. Use `server` config and this SDK. The host session endpoint `/backend/session` uses the existing host `authenticate` callback. The platform verifies scope access and resolves the installation and runtime URL automatically; no extra host backend configuration is required.
100
100
 
package/dist/builder.js CHANGED
@@ -563,7 +563,7 @@ async function extractInstances(filename, source, root, includedNames) {
563
563
  if (statement.type !== "ImportDeclaration" || !clientImports.has(String(statement.source.value)))
564
564
  continue;
565
565
  for (const s of statement.specifiers) {
566
- if (s.type === "ImportSpecifier" && s.imported.type === "Identifier" && s.imported.name === "createView")
566
+ if (s.type === "ImportSpecifier" && s.imported.type === "Identifier" && s.imported.name === "defineView")
567
567
  aliases.add(s.local.name);
568
568
  }
569
569
  }
@@ -571,7 +571,7 @@ async function extractInstances(filename, source, root, includedNames) {
571
571
  walk(program, (node, ancestors) => {
572
572
  if (node.type !== "CallExpression" || node.callee.type !== "Identifier" || !aliases.has(node.callee.name))
573
573
  return;
574
- const options = node.arguments[1];
574
+ const options = node.arguments[0];
575
575
  if (options?.type !== "ObjectExpression") return;
576
576
  const instances = property(options, "instances");
577
577
  if (!instances) return;
@@ -579,10 +579,10 @@ async function extractInstances(filename, source, root, includedNames) {
579
579
  throw new Error(`${filename}: ${message}`);
580
580
  };
581
581
  if (ancestors.some(isFunction))
582
- fail("createView with instances must be declared at module scope.");
582
+ fail("defineView with instances must be declared at module scope.");
583
583
  const owner = ancestors.findLast((n) => n.type === "VariableDeclarator");
584
584
  const viewName = owner?.type === "VariableDeclarator" && owner.id.type === "Identifier" ? owner.id.name : "default";
585
- const view = node.arguments[0];
585
+ const view = property(options, "view")?.value;
586
586
  if (view?.type !== "Literal" || typeof view.value !== "string")
587
587
  fail("Instance view paths must be string literals.");
588
588
  if (instances.value.type !== "ObjectExpression")
@@ -7,7 +7,8 @@ import {
7
7
  import { createContext, h, render } from "preact";
8
8
  import { useContext } from "preact/hooks";
9
9
  var preactVersion = "10.29.8";
10
- var createView = (path, options) => {
10
+ var defineView = (options) => {
11
+ const path = options.view;
11
12
  const Context2 = createContext(
12
13
  null
13
14
  );
@@ -33,6 +34,7 @@ var createView = (path, options) => {
33
34
  return {
34
35
  component: View,
35
36
  path,
37
+ slot: options.slot,
36
38
  ...instances?.resolver ? { instances: { resolver: instances.resolver } } : {},
37
39
  useContext: () => {
38
40
  const context = useContext(Context2);
@@ -51,14 +53,25 @@ var createView = (path, options) => {
51
53
  }
52
54
  };
53
55
  };
54
- var defineClient = (client) => ({
55
- ...client,
56
- $meta: { preactVersion },
57
- $runtime: {
58
- h,
59
- render: (vnode, parent) => render(vnode && client.component ? h(client.component, { children: vnode }) : vnode, parent)
56
+ var defineClient = (client) => {
57
+ for (const [slot, views] of Object.entries(client.slots)) {
58
+ for (const [path, view] of Object.entries(views ?? {})) {
59
+ if (view !== false && view.slot !== slot)
60
+ throw new Error(`View "${path}" was created for slot "${view.slot}", not "${slot}".`);
61
+ }
60
62
  }
61
- });
63
+ return {
64
+ ...client,
65
+ $meta: { preactVersion },
66
+ $runtime: {
67
+ h,
68
+ render: (vnode, parent) => render(
69
+ vnode && client.component ? h(client.component, { children: vnode }) : vnode,
70
+ parent
71
+ )
72
+ }
73
+ };
74
+ };
62
75
  var componentTagPrefix = "tailorkit-";
63
76
  var toComponentTagName = (name) => `${componentTagPrefix}${name.replaceAll(/([a-z0-9])([A-Z])/gu, "$1-$2").replaceAll(/[\s_]+/gu, "-").toLowerCase()}`;
64
77
  var toCallbackEventName = (name) => `tailorkitcallback${name.replaceAll(/[^A-Za-z0-9_$]/gu, "").toLowerCase()}`;
@@ -618,7 +631,7 @@ function useAction(ref, options = {}) {
618
631
  }
619
632
 
620
633
  export {
621
- createView,
634
+ defineView,
622
635
  defineClient,
623
636
  createRemoteComponent,
624
637
  createSessionProvider,
package/dist/client.js CHANGED
@@ -4,13 +4,13 @@ import {
4
4
  createClient,
5
5
  createRemoteComponent,
6
6
  createSessionProvider,
7
- createView,
8
7
  defineClient,
8
+ defineView,
9
9
  reference,
10
10
  useAction,
11
11
  useMutation,
12
12
  useQuery
13
- } from "./chunk-43L6XVW6.js";
13
+ } from "./chunk-RHCGWGSG.js";
14
14
  import {
15
15
  AppError,
16
16
  appError
@@ -23,8 +23,8 @@ export {
23
23
  createClient,
24
24
  createRemoteComponent,
25
25
  createSessionProvider,
26
- createView,
27
26
  defineClient,
27
+ defineView,
28
28
  reference,
29
29
  useAction,
30
30
  useMutation,
package/dist/index.js CHANGED
@@ -4,13 +4,13 @@ import {
4
4
  createClient,
5
5
  createRemoteComponent,
6
6
  createSessionProvider,
7
- createView,
8
7
  defineClient,
8
+ defineView,
9
9
  reference,
10
10
  useAction,
11
11
  useMutation,
12
12
  useQuery
13
- } from "./chunk-43L6XVW6.js";
13
+ } from "./chunk-RHCGWGSG.js";
14
14
  import {
15
15
  action,
16
16
  and,
@@ -55,9 +55,9 @@ export {
55
55
  createClient,
56
56
  createRemoteComponent,
57
57
  createSessionProvider,
58
- createView,
59
58
  defineClient,
60
59
  defineServer,
60
+ defineView,
61
61
  desc,
62
62
  eq,
63
63
  gt,
package/dist/views.d.ts CHANGED
@@ -49,9 +49,10 @@ export type ViewRuntimeProps<TPath extends AppViewPath, TData = unknown> = {
49
49
  status: "error";
50
50
  instance?: never;
51
51
  };
52
- export interface ViewDefinition<TPath extends AppViewPath = AppViewPath, TData = unknown> {
52
+ export interface ViewDefinition<TPath extends AppViewPath = AppViewPath, TData = unknown, TSlot extends SlotName = SlotName> {
53
53
  component: View<ViewRuntimeProps<TPath>>;
54
54
  path: TPath;
55
+ slot: TSlot;
55
56
  useContext: () => ViewContext<TPath>;
56
57
  /** The selected instance, with data inferred from instances.dataSchema. */
57
58
  useInstance: () => ViewInstance<TData>;
@@ -60,12 +61,6 @@ export interface ViewDefinition<TPath extends AppViewPath = AppViewPath, TData =
60
61
  resolver: string;
61
62
  };
62
63
  }
63
- type RegisteredViews = {
64
- [TPath in AppViewPath]: ViewDefinition<TPath>;
65
- };
66
- type ViewDefinitions = Partial<{
67
- [P in AppViewPath]: RegisteredViews[P] | false;
68
- }>;
69
64
  type InvalidViewPath<TViews> = Exclude<keyof TViews & string, AppViewPath>;
70
65
  type RequireViewPaths<TViews> = InvalidViewPath<TViews> extends never ? unknown : {
71
66
  readonly __tailorkit_error__: `View paths must be declared by the host. Invalid view: ${InvalidViewPath<TViews>}`;
@@ -74,11 +69,24 @@ type ViewKeyPathMismatch<TViews> = {
74
69
  [TPath in keyof TViews & string]: TViews[TPath] extends false ? never : TViews[TPath] extends ViewDefinition<infer TViewPath> ? TViewPath extends TPath ? never : TPath : TPath;
75
70
  }[keyof TViews & string];
76
71
  type RequireMatchingViewKeys<TViews> = ViewKeyPathMismatch<TViews> extends never ? unknown : {
77
- readonly __tailorkit_error__: `View key must match createView path. Invalid view: ${ViewKeyPathMismatch<TViews>}`;
72
+ readonly __tailorkit_error__: `View key must match defineView path. Invalid view: ${ViewKeyPathMismatch<TViews>}`;
73
+ };
74
+ export type SlotView<TSlot extends SlotName> = TailorKitSlots[TSlot] extends {
75
+ views: infer TViews;
76
+ } ? Extract<TViews, AppViewPath> : never;
77
+ type SlotInstanceDefinition<TSlot extends SlotName> = TailorKitSlots[TSlot] extends {
78
+ multiple: true;
79
+ } ? {
80
+ instances: {
81
+ resolver: string;
82
+ };
83
+ } : {
84
+ instances?: never;
78
85
  };
79
- export type SlotView<TSlot extends SlotName> = Extract<TailorKitSlots[TSlot], AppViewPath>;
80
86
  type SlotDefinitions = {
81
- [V in SlotName]?: Pick<ViewDefinitions, SlotView<V>>;
87
+ [V in SlotName]?: Partial<{
88
+ [P in SlotView<V>]: (ViewDefinition<P, unknown, V> & SlotInstanceDefinition<V>) | false;
89
+ }>;
82
90
  };
83
91
  type RequireSlotViews<V, S> = V extends SlotName ? Exclude<keyof S, SlotView<V>> extends never ? unknown : {
84
92
  readonly __tailorkit_error__: "View is not supported by this slot";
@@ -101,10 +109,22 @@ export type TailorKitClientWithMeta<TViews extends SlotDefinitions = SlotDefinit
101
109
  $meta: TailorKitClientMeta;
102
110
  $runtime: TailorKitClientRuntime;
103
111
  };
104
- export declare const createView: <const TPath extends AppViewPath, TSchema extends z.ZodType>(path: TPath, options: {
105
- component: View<Record<string, never>>;
106
- instances?: ViewInstances<TPath, TSchema>;
107
- }) => ViewDefinition<TPath, z.output<TSchema>>;
112
+ type ViewOptions<TPath extends AppViewPath, TSlot extends SlotName, TSchema extends z.ZodType> = {
113
+ [S in TSlot]: {
114
+ slot: S;
115
+ view: TPath;
116
+ component: View<Record<string, never>>;
117
+ } & (TPath extends SlotView<S> ? unknown : {
118
+ readonly __tailorkit_error__: "View is not supported by this slot";
119
+ }) & (TailorKitSlots[S] extends {
120
+ multiple: true;
121
+ } ? {
122
+ instances: ViewInstances<TPath, TSchema>;
123
+ } : {
124
+ instances?: never;
125
+ });
126
+ }[TSlot];
127
+ export declare const defineView: <const TPath extends AppViewPath, const TSlot extends SlotName, TSchema extends z.ZodType>(options: ViewOptions<TPath, TSlot, TSchema>) => ViewDefinition<TPath, z.output<TSchema>, TSlot> & SlotInstanceDefinition<TSlot>;
108
128
  export declare const defineClient: <const TSlots extends SlotDefinitions>(client: TailorKitClient<TSlots> & {
109
129
  slots: { [V in keyof TSlots]: TSlots[V] & RequireViewPaths<TSlots[V]> & RequireMatchingViewKeys<TSlots[V]> & RequireSlotViews<V, TSlots[V]>; };
110
130
  } & (Exclude<keyof TSlots, SlotName> extends never ? unknown : {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tailorkit/app",
3
- "version": "0.1.0-beta.19",
3
+ "version": "0.1.0-beta.20",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",