@tailorkit/app 0.1.0-beta.6 → 0.1.0-beta.8

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.
@@ -2,8 +2,12 @@ import { z } from "zod";
2
2
  export declare const tailorkitUploadManifestSchema: z.ZodObject<{
3
3
  assets: z.ZodObject<{
4
4
  client: z.ZodLiteral<"client.js">;
5
+ logos: z.ZodOptional<z.ZodObject<{
6
+ dark: z.ZodOptional<z.ZodString>;
7
+ light: z.ZodOptional<z.ZodString>;
8
+ }, z.core.$strip>>;
5
9
  }, z.core.$strip>;
6
10
  version: z.ZodLiteral<1>;
7
11
  }, z.core.$strip>;
8
12
  export type TailorKitUploadManifest = z.output<typeof tailorkitUploadManifestSchema>;
9
- export declare const createTailorKitUploadManifest: () => TailorKitUploadManifest;
13
+ export declare const createTailorKitUploadManifest: (logos?: TailorKitUploadManifest["assets"]["logos"]) => TailorKitUploadManifest;
package/dist/builder.js CHANGED
@@ -1,12 +1,77 @@
1
1
  import {
2
2
  loadTailorKitConfig
3
- } from "./chunk-7L6ZZHCK.js";
4
- import "./chunk-AGGRUUWG.js";
3
+ } from "./chunk-EKCUETAV.js";
4
+ import "./chunk-ZFYKVXDO.js";
5
5
 
6
6
  // src/builder/index.ts
7
7
  import path from "path";
8
8
  import { createRequire } from "module";
9
- import { writeFile } from "fs/promises";
9
+ import { readFile, writeFile } from "fs/promises";
10
+
11
+ // ../asset-delivery/dist/logo-validation.mjs
12
+ var maxLogoBytes = 262144;
13
+ var maxLogoDimension = 2048;
14
+ var readPngDimensions = (content) => {
15
+ if (content.length < 33 || ![
16
+ 137,
17
+ 80,
18
+ 78,
19
+ 71,
20
+ 13,
21
+ 10,
22
+ 26,
23
+ 10
24
+ ].every((byte, index) => content[index] === byte)) throw new Error("Logo content is not a valid PNG file.");
25
+ const view = new DataView(content.buffer, content.byteOffset, content.byteLength);
26
+ const isIhdr = content[12] === 73 && content[13] === 72 && content[14] === 68 && content[15] === 82;
27
+ if (view.getUint32(8) !== 13 || !isIhdr) throw new Error("Logo content is not a valid PNG file.");
28
+ return {
29
+ width: view.getUint32(16),
30
+ height: view.getUint32(20)
31
+ };
32
+ };
33
+ var readWebpDimensions = (content) => {
34
+ const text = (start, end) => new TextDecoder().decode(content.subarray(start, end));
35
+ if (content.length < 30 || text(0, 4) !== "RIFF" || text(8, 12) !== "WEBP") throw new Error("Logo content is not a valid WebP file.");
36
+ const view = new DataView(content.buffer, content.byteOffset, content.byteLength);
37
+ const chunk = text(12, 16);
38
+ if (chunk === "VP8X") return {
39
+ width: 1 + view.getUint16(24, true) + (content[26] ?? 0) * 65536,
40
+ height: 1 + view.getUint16(27, true) + (content[29] ?? 0) * 65536
41
+ };
42
+ if (chunk === "VP8L" && content[20] === 47) {
43
+ const bits = view.getUint32(21, true);
44
+ return {
45
+ width: bits % 16384 + 1,
46
+ height: Math.floor(bits / 16384) % 16384 + 1
47
+ };
48
+ }
49
+ if (chunk === "VP8 " && content[23] === 157 && content[24] === 1 && content[25] === 42) return {
50
+ width: view.getUint16(26, true) % 16384,
51
+ height: view.getUint16(28, true) % 16384
52
+ };
53
+ throw new Error("Logo content is not a supported WebP file.");
54
+ };
55
+ var validateSvg = (content) => {
56
+ const svg = new TextDecoder("utf-8", {
57
+ fatal: true,
58
+ ignoreBOM: false
59
+ }).decode(content);
60
+ if (!/<svg(?:\s|>)/iu.test(svg)) throw new Error("Logo content is not a valid SVG file.");
61
+ if (/<(?:script|foreignObject|iframe|object|embed)(?:\s|>)/iu.test(svg) || /\son[a-z]+\s*=/iu.test(svg) || /(?:href|src)\s*=\s*["'](?!#)/iu.test(svg) || /(?:@import|url\(\s*(?!["']?#))/iu.test(svg) || /<!DOCTYPE|<!ENTITY|<\?xml-stylesheet/iu.test(svg)) throw new Error("SVG logos cannot contain scripts or external resources.");
62
+ };
63
+ function validateLogoAsset(content, contentType) {
64
+ if (content.byteLength < 1 || content.byteLength > 262144) throw new Error(`Logo must be between 1 and ${maxLogoBytes} bytes.`);
65
+ if (contentType === "image/svg+xml") {
66
+ validateSvg(content);
67
+ return {};
68
+ }
69
+ const dimensions = contentType === "image/png" ? readPngDimensions(content) : readWebpDimensions(content);
70
+ if (dimensions.width < 1 || dimensions.height < 1 || dimensions.width > 2048 || dimensions.height > 2048) throw new Error(`Raster logos cannot exceed ${maxLogoDimension} by ${maxLogoDimension} pixels.`);
71
+ return dimensions;
72
+ }
73
+
74
+ // src/builder/index.ts
10
75
  import { build as viteBuild } from "vite";
11
76
 
12
77
  // src/preact-version.ts
@@ -35,19 +100,23 @@ var assertSupportedPreactVersion = (version) => {
35
100
  import { z } from "zod";
36
101
  var tailorkitUploadManifestSchema = z.object({
37
102
  assets: z.object({
38
- client: z.literal("client.js")
103
+ client: z.literal("client.js"),
104
+ logos: z.object({
105
+ dark: z.string().regex(/^logo-dark\.(?:png|svg|webp)$/u).optional(),
106
+ light: z.string().regex(/^logo-light\.(?:png|svg|webp)$/u).optional()
107
+ }).optional()
39
108
  }),
40
109
  version: z.literal(1)
41
110
  });
42
- var createTailorKitUploadManifest = () => tailorkitUploadManifestSchema.parse({
111
+ var createTailorKitUploadManifest = (logos) => tailorkitUploadManifestSchema.parse({
43
112
  assets: {
44
- client: "client.js"
113
+ client: "client.js",
114
+ ...logos && Object.keys(logos).length > 0 ? { logos } : {}
45
115
  },
46
116
  version: 1
47
117
  });
48
118
 
49
119
  // src/builder/index.ts
50
- var preactExternal = /^preact(?:\/.*)?$/u;
51
120
  var preactPackageJson = "preact/package.json";
52
121
  var preactPackageJsonModuleId = "\0tailorkit-preact-package-json";
53
122
  var buildApp = async (options = {}) => {
@@ -69,7 +138,6 @@ var buildApp = async (options = {}) => {
69
138
  watch: options.watch ? {} : null,
70
139
  minify: "oxc",
71
140
  rollupOptions: {
72
- external: (id) => id !== preactPackageJson && id !== preactPackageJsonModuleId && preactExternal.test(id),
73
141
  output: {
74
142
  comments: {
75
143
  annotation: false,
@@ -104,9 +172,30 @@ var buildApp = async (options = {}) => {
104
172
  ],
105
173
  root: loaded.root
106
174
  });
175
+ const logoManifest = {};
176
+ for (const variant of ["light", "dark"]) {
177
+ const configuredPath = loaded.config.logos?.[variant];
178
+ if (!configuredPath) {
179
+ continue;
180
+ }
181
+ const extension = path.extname(configuredPath).toLowerCase().slice(1);
182
+ const contentType = {
183
+ png: "image/png",
184
+ svg: "image/svg+xml",
185
+ webp: "image/webp"
186
+ }[extension];
187
+ if (!contentType) {
188
+ throw new Error(`The ${variant} logo must be an SVG, PNG, or WebP file.`);
189
+ }
190
+ const content = await readFile(path.resolve(loaded.root, configuredPath));
191
+ validateLogoAsset(content, contentType);
192
+ const filename = `logo-${variant}.${extension}`;
193
+ await writeFile(path.join(resolvedOutDir, filename), content);
194
+ logoManifest[variant] = filename;
195
+ }
107
196
  await writeFile(
108
197
  path.join(resolvedOutDir, "tailorkit-upload.json"),
109
- `${JSON.stringify(createTailorKitUploadManifest(), null, 2)}
198
+ `${JSON.stringify(createTailorKitUploadManifest(logoManifest), null, 2)}
110
199
  `,
111
200
  "utf-8"
112
201
  );
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  tailorkitConfigSchema
3
- } from "./chunk-AGGRUUWG.js";
3
+ } from "./chunk-ZFYKVXDO.js";
4
4
 
5
5
  // src/config/loader.ts
6
6
  import { cosmiconfig } from "cosmiconfig";
@@ -6,11 +6,16 @@ var clientConfigSchema = z.object({
6
6
  var buildConfigSchema = z.object({
7
7
  outDir: z.string().default(".tailorkit")
8
8
  });
9
+ var logosConfigSchema = z.object({
10
+ dark: z.string().min(1).optional(),
11
+ light: z.string().min(1).optional()
12
+ });
9
13
  var tailorkitConfigSchema = z.object({
10
14
  appId: z.string().min(1).optional(),
11
15
  build: buildConfigSchema.optional(),
12
16
  client: clientConfigSchema.optional(),
13
- host: z.string().url()
17
+ host: z.string().url(),
18
+ logos: logosConfigSchema.optional()
14
19
  });
15
20
  var defineConfig = (config) => config;
16
21
  var defineTailorKitConfig = defineConfig;
@@ -8,6 +8,10 @@ declare const tailorkitConfigSchema: z.ZodObject<{
8
8
  entry: z.ZodDefault<z.ZodString>;
9
9
  }, z.core.$strip>>;
10
10
  host: z.ZodString;
11
+ logos: z.ZodOptional<z.ZodObject<{
12
+ dark: z.ZodOptional<z.ZodString>;
13
+ light: z.ZodOptional<z.ZodString>;
14
+ }, z.core.$strip>>;
11
15
  }, z.core.$strip>;
12
16
  export type TailorKitConfig = z.input<typeof tailorkitConfigSchema>;
13
17
  export type ResolvedTailorKitConfig = z.output<typeof tailorkitConfigSchema>;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  loadTailorKitConfig
3
- } from "./chunk-7L6ZZHCK.js";
4
- import "./chunk-AGGRUUWG.js";
3
+ } from "./chunk-EKCUETAV.js";
4
+ import "./chunk-ZFYKVXDO.js";
5
5
  export {
6
6
  loadTailorKitConfig
7
7
  };
package/dist/config.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  defineConfig,
3
3
  defineTailorKitConfig
4
- } from "./chunk-AGGRUUWG.js";
4
+ } from "./chunk-ZFYKVXDO.js";
5
5
  export {
6
6
  defineConfig,
7
7
  defineTailorKitConfig
package/dist/index.d.ts CHANGED
@@ -62,10 +62,10 @@ export declare const createScreen: <const TPath extends AppScreenPath>(path: TPa
62
62
  loading?: View<Record<string, never>>;
63
63
  }) => ScreenDefinition<TPath>;
64
64
  export declare const defineClient: <const TScreens extends ScreenDefinitions>(client: TailorKitClient<TScreens> & RequireScreenPaths<TScreens> & RequireMatchingScreenKeys<TScreens>) => TailorKitClientWithMeta<TScreens>;
65
- export declare const createRemoteComponent: <TProps extends object, TSlots extends readonly string[]>(name: string, options: {
65
+ export declare const createRemoteComponent: <TProps extends object, TChildren extends boolean = false>(name: string, options?: {
66
66
  callbacks?: Record<string, number>;
67
- slots: TSlots;
67
+ children?: TChildren;
68
68
  }) => View<TProps & {
69
- children?: ComponentChildren;
69
+ children?: TChildren extends true ? ComponentChildren : never;
70
70
  }>;
71
71
  export {};
package/dist/index.js CHANGED
@@ -43,14 +43,9 @@ var componentTagPrefix = "tailorkit-";
43
43
  var toComponentTagName = (name) => `${componentTagPrefix}${name.replaceAll(/([a-z0-9])([A-Z])/gu, "$1-$2").replaceAll(/[\s_]+/gu, "-").toLowerCase()}`;
44
44
  var toCallbackEventName = (name) => `tailorkitcallback${name.replaceAll(/[^A-Za-z0-9_$]/gu, "").toLowerCase()}`;
45
45
  var toEventProp = (event) => `on${event}`;
46
- var createRemoteComponent = (name, options) => {
46
+ var createRemoteComponent = (name, options = {}) => {
47
47
  const tagName = toComponentTagName(name);
48
- const callbacks = options.callbacks;
49
- if (!callbacks || Object.keys(callbacks).length === 0) {
50
- return function RemoteComponent({ children, ...props }) {
51
- return h(tagName, props, children);
52
- };
53
- }
48
+ const callbacks = options.callbacks ?? {};
54
49
  return function RemoteComponent({ children, ...props }) {
55
50
  const nextProps = { ...props };
56
51
  const callbackMap = {};
@@ -66,10 +61,14 @@ var createRemoteComponent = (name, options) => {
66
61
  callback(...(event.detail ?? []).slice(0, inputCount));
67
62
  };
68
63
  }
64
+ const serializedProps = Object.fromEntries(
65
+ Object.entries(nextProps).filter(([, value]) => typeof value !== "function")
66
+ );
67
+ nextProps["data-tailorkit-props"] = JSON.stringify(serializedProps);
69
68
  if (Object.keys(callbackMap).length > 0) {
70
69
  nextProps["data-tailorkit-callbacks"] = JSON.stringify(callbackMap);
71
70
  }
72
- return h(tagName, nextProps, children);
71
+ return h(tagName, nextProps, options.children ? children : void 0);
73
72
  };
74
73
  };
75
74
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tailorkit/app",
3
- "version": "0.1.0-beta.6",
3
+ "version": "0.1.0-beta.8",
4
4
  "license": "AGPL-3.0-only",
5
5
  "repository": {
6
6
  "type": "git",
@@ -33,12 +33,13 @@
33
33
  "access": "public"
34
34
  },
35
35
  "dependencies": {
36
- "@tailorkit/core": "0.1.0-beta.6",
36
+ "@tailorkit/core": "0.1.0-beta.8",
37
37
  "cosmiconfig": "^10.0.0",
38
38
  "vite": "^8.2.2",
39
39
  "zod": "^4.4.3"
40
40
  },
41
41
  "devDependencies": {
42
+ "@tailorkit/asset-delivery": "0.0.0",
42
43
  "@tailorkit/config": "0.0.0",
43
44
  "@types/node": "26.2.0",
44
45
  "preact": "^10.29.8",