@trypattern/sdk 0.1.12 → 0.1.14

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.
Files changed (84) hide show
  1. package/README.md +73 -12
  2. package/dist/access.d.ts +0 -4
  3. package/dist/access.js +0 -5
  4. package/dist/api.d.ts +3 -1
  5. package/dist/api.js +5 -23
  6. package/dist/app.d.ts +20 -5
  7. package/dist/app.js +32 -2
  8. package/dist/blocks.d.ts +18 -0
  9. package/dist/blocks.js +36 -0
  10. package/dist/bookings.d.ts +400 -0
  11. package/dist/bookings.js +300 -0
  12. package/dist/bookingsMemory.d.ts +9 -0
  13. package/dist/bookingsMemory.js +79 -0
  14. package/dist/bookingsStore.d.ts +698 -0
  15. package/dist/bookingsStore.js +129 -0
  16. package/dist/cli/app.js +144 -59
  17. package/dist/cli/publishing.d.ts +3 -1
  18. package/dist/cli/publishing.js +45 -10
  19. package/dist/cli/starter.d.ts +17 -0
  20. package/dist/cli/starter.js +140 -0
  21. package/dist/components/Calendar.d.ts +20 -0
  22. package/dist/components/Calendar.js +195 -0
  23. package/dist/components/Card.d.ts +1 -1
  24. package/dist/components/Card.js +7 -29
  25. package/dist/components/Choice.js +27 -13
  26. package/dist/components/ChoiceGroup.d.ts +3 -1
  27. package/dist/components/ChoiceGroup.js +3 -4
  28. package/dist/components/Dialog.d.ts +1 -1
  29. package/dist/components/Dialog.js +3 -1
  30. package/dist/components/ListRow.js +2 -1
  31. package/dist/components/RadioDescribed.d.ts +4 -0
  32. package/dist/components/RadioDescribed.js +20 -0
  33. package/dist/components/RadioGroup.d.ts +4 -1
  34. package/dist/components/RadioGroup.js +28 -3
  35. package/dist/components/Text.d.ts +1 -1
  36. package/dist/components/Text.js +43 -2
  37. package/dist/components/calendarDates.d.ts +14 -0
  38. package/dist/components/calendarDates.js +84 -0
  39. package/dist/components/controlLook.js +11 -11
  40. package/dist/components/icons.d.ts +2 -0
  41. package/dist/components/icons.js +2 -0
  42. package/dist/components/interaction.d.ts +1 -1
  43. package/dist/flows/browser.d.ts +7 -1
  44. package/dist/flows/browser.js +25 -7
  45. package/dist/flows/flowBrowser.d.ts +2 -2
  46. package/dist/flows/flowBrowser.js +2 -2
  47. package/dist/flows/flows.js +8 -2
  48. package/dist/index.d.ts +4 -1
  49. package/dist/index.js +1 -0
  50. package/dist/media.d.ts +11 -1
  51. package/dist/patternAccess.d.ts +11 -2
  52. package/dist/patternAccess.js +8 -4
  53. package/dist/publishWire.d.ts +35 -2
  54. package/dist/publishWire.js +26 -3
  55. package/dist/react.d.ts +2 -0
  56. package/dist/react.js +1 -0
  57. package/dist/rules/checkAllFiles.js +16 -2
  58. package/dist/rules/lintPlugin.js +1 -0
  59. package/dist/schema.d.ts +3 -1
  60. package/dist/schema.js +1 -0
  61. package/dist/server/bookings.d.ts +12 -0
  62. package/dist/server/bookings.js +142 -0
  63. package/dist/server/createServer.d.ts +3 -2
  64. package/dist/server/createServer.js +13 -4
  65. package/dist/server/env.d.ts +8 -0
  66. package/dist/server/index.d.ts +3 -1
  67. package/dist/server/index.js +1 -0
  68. package/dist/server/media.d.ts +16 -3
  69. package/dist/server/media.js +72 -23
  70. package/dist/server/patternViewer.js +16 -10
  71. package/dist/server/tables.d.ts +2 -0
  72. package/dist/server/tables.js +17 -1
  73. package/dist/start.js +12 -0
  74. package/dist/table.js +9 -3
  75. package/dist/theme/scales.d.ts +1 -1
  76. package/dist/theme/scales.js +1 -0
  77. package/dist/theme/tokens.stylex.d.ts +18 -0
  78. package/dist/theme/tokens.stylex.js +19 -1
  79. package/dist/vite/localWorker.d.ts +2 -0
  80. package/dist/vite/localWorker.js +48 -3
  81. package/dist/vite/projectFile.d.ts +5 -0
  82. package/dist/vite/projectFile.js +19 -1
  83. package/dist/vite/vite.js +5 -1
  84. package/package.json +1 -1
@@ -1,25 +1,31 @@
1
- import { verifiedTablesAssertion } from "../patternAccess.js";
1
+ import { MEDIA_WRITE, TABLES_READ, verifiedAssertion } from "../patternAccess.js";
2
2
  import { PATTERN_KEYS } from "./patternKeys.js";
3
3
  const BEARER = /^bearer\s+/i;
4
4
  const SCHEMA_PATH = '/api/schema';
5
5
  const TABLES_PATH = '/api/tables/';
6
+ const MEDIA_PATH = '/api/media';
6
7
  export function bearerOf(c) {
7
8
  const header = c.req.header('authorization') ?? '';
8
9
  return BEARER.test(header) ? header.replace(BEARER, '').trim() : undefined;
9
10
  }
10
- function isReadByPattern(c) {
11
- const { path } = c.req;
12
- return (c.req.method === 'GET' &&
13
- (path === SCHEMA_PATH || path.startsWith(TABLES_PATH)));
11
+ function scopeOf(c) {
12
+ const { path, method } = c.req;
13
+ if (method === 'GET' &&
14
+ (path === SCHEMA_PATH || path.startsWith(TABLES_PATH))) {
15
+ return TABLES_READ;
16
+ }
17
+ return method === 'POST' && path === MEDIA_PATH ? MEDIA_WRITE : undefined;
14
18
  }
15
19
  export async function attachPatternViewer(c, next, token) {
16
- const email = isReadByPattern(c)
17
- ? await verifiedTablesAssertion(token, {
20
+ const scope = scopeOf(c);
21
+ const email = scope === undefined
22
+ ? undefined
23
+ : await verifiedAssertion(token, {
18
24
  hostname: new URL(c.req.url).hostname,
19
25
  keys: PATTERN_KEYS,
20
- now: Math.floor(Date.now() / 1000)
21
- })
22
- : undefined;
26
+ now: Math.floor(Date.now() / 1000),
27
+ scope
28
+ });
23
29
  if (email === undefined)
24
30
  return c.json({ error: 'Signed out' }, 401);
25
31
  c.set('viewer', { userId: `pattern:${email}`, isAdmin: true });
@@ -10,7 +10,9 @@ type SqlTable = SQLiteTableWithColumns<{
10
10
  }>;
11
11
  export declare function sqlTable(table: Table): SqlTable;
12
12
  export declare function sqlTables<Group extends Tables>(tables: Group): Record<keyof Group, SqlTable>;
13
+ export declare function column(target: SqlTable, key: string): SqlTable["_"]["columns"][string];
13
14
  export declare function seedSql<Group extends Tables>(tables: Group, seed: Seed<Group>): string;
15
+ export declare function starterSql<Group extends Tables>(tables: Group, rows: Seed<Group>): string;
14
16
  export declare function readRows(d1: D1Database, table: Table): Promise<readonly Record<string, unknown>[]>;
15
17
  export declare function readRow(d1: D1Database, table: Table, id: string): Promise<Record<string, unknown> | undefined>;
16
18
  export declare function serveTables<Group extends Tables>(tables: Group): import("hono/hono-base").HonoBase<ServerEnv, {
@@ -47,7 +47,7 @@ export function sqlTable(table) {
47
47
  export function sqlTables(tables) {
48
48
  return Object.fromEntries(Object.entries(tables).map(([key, table]) => [key, sqlTable(table)]));
49
49
  }
50
- function column(target, key) {
50
+ export function column(target, key) {
51
51
  const found = Reflect.get(target, key);
52
52
  if (found === undefined)
53
53
  throw new Error(`No column ${key}`);
@@ -99,6 +99,22 @@ export function seedSql(tables, seed) {
99
99
  });
100
100
  return [...users, ...rowsSql].join('\n');
101
101
  }
102
+ export function starterSql(tables, rows) {
103
+ return Object.values(tables)
104
+ .flatMap((table) => {
105
+ const listed = seededRows(rows, table.name);
106
+ if (listed.length === 0 || table.owned)
107
+ return [];
108
+ const keys = ['id', 'createdAt', ...Object.keys(table.columns)];
109
+ const values = listed
110
+ .map((row) => `(${keys.map((key) => sqlLiteral((row[key] ?? null))).join(', ')})`)
111
+ .join(',\n ');
112
+ return [
113
+ `INSERT OR IGNORE INTO ${snakeCase(table.name)} (${keys.map(snakeCase).join(', ')}) VALUES\n ${values};`
114
+ ];
115
+ })
116
+ .join('\n');
117
+ }
102
118
  function selection(table, target) {
103
119
  return Object.fromEntries([
104
120
  'id',
package/dist/start.js CHANGED
@@ -17,6 +17,8 @@ const TEST_SEED = 'patternSeed';
17
17
  const INLINE_DATA_ID = 'pattern-data';
18
18
  const TEST_ADMINS = 'patternAdmins';
19
19
  const TEST_WORLD = 'patternWorld';
20
+ const TEST_TITLE = 'patternTitle';
21
+ const TEST_SIGNED_IN_AS = 'patternSignedInAs';
20
22
  function testSeed() {
21
23
  const seed = Reflect.get(window, TEST_SEED);
22
24
  return typeof seed === 'object' && seed !== null ? seed : {};
@@ -27,6 +29,14 @@ function testAdmins() {
27
29
  ? admins.filter((email) => typeof email === 'string')
28
30
  : [];
29
31
  }
32
+ function testTitle() {
33
+ const title = Reflect.get(window, TEST_TITLE);
34
+ return typeof title === 'string' ? title : '';
35
+ }
36
+ function testSignedInAs() {
37
+ const email = Reflect.get(window, TEST_SIGNED_IN_AS);
38
+ return typeof email === 'string' ? email : null;
39
+ }
30
40
  function readInlineData() {
31
41
  const text = document.getElementById(INLINE_DATA_ID)?.textContent ?? '';
32
42
  if (text === '')
@@ -58,7 +68,9 @@ export function startApp(App, { theme = [], icons = {}, onInteraction } = {}) {
58
68
  const app = new App(router, {
59
69
  api: browserApi(tables, inMemory ? testSeed() : {}, gate, {
60
70
  inMemory,
71
+ signedInAs: inMemory ? testSignedInAs() : null,
61
72
  admins: inMemory ? testAdmins() : [],
73
+ title: inMemory ? testTitle() : '',
62
74
  ...(services === undefined ? {} : { services }),
63
75
  ...(memory === undefined ? {} : { memory }),
64
76
  world
package/dist/table.js CHANGED
@@ -2,7 +2,12 @@ import { z } from 'zod';
2
2
  const NAME = /^[a-z][a-zA-Z0-9]*$/;
3
3
  const RESERVED = ['id', 'createdAt', 'ownerId'];
4
4
  const RESERVED_TABLES = ['users', 'sessions', 'session'];
5
- const SDK_TABLES = ['media'];
5
+ const SDK_TABLES = {
6
+ media: 'media',
7
+ bookingRules: '...bookingTables',
8
+ bookingBlackouts: '...bookingTables',
9
+ bookingRequests: '...bookingTables'
10
+ };
6
11
  const SEEDED_AT = Date.UTC(2000, 0, 1);
7
12
  function problemIn(name, definition) {
8
13
  const { access, columns } = definition;
@@ -39,8 +44,9 @@ function table(name, definition, isPatterns = false) {
39
44
  if (RESERVED_TABLES.includes(name)) {
40
45
  throw new Error(`A table can't be called "${name}": Pattern keeps its own ${name} for sign-in`);
41
46
  }
42
- if (!isPatterns && SDK_TABLES.includes(name)) {
43
- throw new Error(`A table can't be called "${name}": Pattern has its own ${name} table. Add it with import { ${name} } from '@trypattern/sdk/schema'`);
47
+ const own = Object.hasOwn(SDK_TABLES, name) ? SDK_TABLES[name] : undefined;
48
+ if (!isPatterns && own !== undefined) {
49
+ throw new Error(`A table can't be called "${name}": Pattern has its own ${name} table. Add it to tables with ${own} from '@trypattern/sdk/schema'`);
44
50
  }
45
51
  const reserved = RESERVED.find((key) => key in columns);
46
52
  if (reserved !== undefined) {
@@ -5,7 +5,7 @@ export declare const ascendingScales: {
5
5
  readonly controlGaps: readonly ["gapXs", "gapSm", "gapMd", "gapLg", "gapXl"];
6
6
  readonly contentWidths: readonly ["contentXs", "contentSm", "contentMd", "contentLg"];
7
7
  readonly iconSizes: readonly ["xs", "sm", "md", "lg", "xl"];
8
- readonly fontSizes: readonly ["captionXs", "captionSm", "captionBase", "captionLg", "bodySm", "bodyBase", "bodyLg", "heading6", "heading5", "heading4", "heading3", "heading2", "heading1"];
8
+ readonly fontSizes: readonly ["captionXs", "captionSm", "captionBase", "captionLg", "bodySm", "bodyMd", "bodyBase", "bodyLg", "heading6", "heading5", "heading4", "heading3", "heading2", "heading1"];
9
9
  readonly lineHeights: readonly ["captionXs", "caption", "title", "bodySm", "body", "heading6", "heading5", "heading4", "heading3", "heading2", "heading1"];
10
10
  };
11
11
  export declare const scaleGroups: {
@@ -17,6 +17,7 @@ export const ascendingScales = {
17
17
  'captionBase',
18
18
  'captionLg',
19
19
  'bodySm',
20
+ 'bodyMd',
20
21
  'bodyBase',
21
22
  'bodyLg',
22
23
  'heading6',
@@ -116,6 +116,16 @@ export declare const controls: stylex.VarGroup<Readonly<{
116
116
  gapMd: string;
117
117
  gapLg: string;
118
118
  gapXl: string;
119
+ fontSizeXs: string;
120
+ fontSizeSm: string;
121
+ fontSizeMd: string;
122
+ fontSizeLg: string;
123
+ fontSizeXl: string;
124
+ lineHeightXs: string;
125
+ lineHeightSm: string;
126
+ lineHeightMd: string;
127
+ lineHeightLg: string;
128
+ lineHeightXl: string;
119
129
  }>, symbol>;
120
130
  export declare const iconSizes: stylex.VarGroup<Readonly<{
121
131
  xs: string;
@@ -161,6 +171,7 @@ export declare const fontSizes: stylex.VarGroup<Readonly<{
161
171
  captionBase: string;
162
172
  captionLg: string;
163
173
  bodySm: string;
174
+ bodyMd: string;
164
175
  bodyBase: string;
165
176
  bodyLg: string;
166
177
  heading6: string;
@@ -170,12 +181,19 @@ export declare const fontSizes: stylex.VarGroup<Readonly<{
170
181
  heading2: string;
171
182
  heading1: string;
172
183
  }>, symbol>;
184
+ export declare const trackings: stylex.VarGroup<Readonly<{
185
+ hero: string;
186
+ display: string;
187
+ section: string;
188
+ heading: string;
189
+ }>, symbol>;
173
190
  export declare const lineHeights: stylex.VarGroup<Readonly<{
174
191
  captionXs: string;
175
192
  caption: string;
176
193
  title: string;
177
194
  bodySm: string;
178
195
  body: string;
196
+ bodyLg: string;
179
197
  heading6: string;
180
198
  heading5: string;
181
199
  heading4: string;
@@ -115,7 +115,17 @@ export const controls = stylex.defineVars({
115
115
  gapSm: '4px',
116
116
  gapMd: '6px',
117
117
  gapLg: '6px',
118
- gapXl: '8px'
118
+ gapXl: '8px',
119
+ fontSizeXs: '12px',
120
+ fontSizeSm: '13px',
121
+ fontSizeMd: '13px',
122
+ fontSizeLg: '13px',
123
+ fontSizeXl: '13px',
124
+ lineHeightXs: '16px',
125
+ lineHeightSm: '20px',
126
+ lineHeightMd: '20px',
127
+ lineHeightLg: '20px',
128
+ lineHeightXl: '20px'
119
129
  });
120
130
  export const iconSizes = stylex.defineVars({
121
131
  xs: '12px',
@@ -161,6 +171,7 @@ export const fontSizes = stylex.defineVars({
161
171
  captionBase: '11px',
162
172
  captionLg: '12px',
163
173
  bodySm: '13px',
174
+ bodyMd: '14px',
164
175
  bodyBase: '15px',
165
176
  bodyLg: '18px',
166
177
  heading6: '20px',
@@ -170,12 +181,19 @@ export const fontSizes = stylex.defineVars({
170
181
  heading2: '44px',
171
182
  heading1: '56px'
172
183
  });
184
+ export const trackings = stylex.defineVars({
185
+ hero: '-0.04em',
186
+ display: '-0.03em',
187
+ section: '-0.02em',
188
+ heading: '-0.01em'
189
+ });
173
190
  export const lineHeights = stylex.defineVars({
174
191
  captionXs: '12px',
175
192
  caption: '16px',
176
193
  title: '18px',
177
194
  bodySm: '20px',
178
195
  body: '24px',
196
+ bodyLg: '28px',
179
197
  heading6: '24px',
180
198
  heading5: '32px',
181
199
  heading4: '36px',
@@ -1,4 +1,6 @@
1
1
  import type { Plugin } from 'vite';
2
2
  import type { Seed, Tables } from '../table.ts';
3
+ import type { StarterPhotoFile } from '../cli/starter.ts';
4
+ export declare function putLocalPhotos(root: string, photos: readonly StarterPhotoFile[]): void;
3
5
  export declare function resetLocalDatabase(root: string, tables: Tables, seed: Seed<Tables>): void;
4
6
  export declare function localWorker<Group extends Tables>(tables: Group, seed: Seed<Group>, title: string): Plugin;
@@ -1,11 +1,14 @@
1
1
  import { execFileSync } from 'node:child_process';
2
2
  import { randomBytes } from 'node:crypto';
3
- import { appendFileSync, existsSync, readFileSync } from 'node:fs';
3
+ import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
4
4
  import { join } from 'node:path';
5
+ import { IMMUTABLE } from "../server/media.js";
5
6
  import { seedTitleSql } from "../server/settings.js";
6
7
  import { seedSql } from "../server/tables.js";
7
8
  import { snakeCase } from "../table.js";
9
+ import { readStarter, withStarter } from "../cli/starter.js";
8
10
  import { toolBin } from "../cli/tools.js";
11
+ const NO_BUCKET = 'starter/ has photos, but wrangler.jsonc binds no R2 bucket as MEDIA. Add "r2_buckets": [{ "binding": "MEDIA", "bucket_name": "media" }].';
9
12
  function ensureLocalSessionSecret(root) {
10
13
  const DEV_VARS = join(root, '.dev.vars');
11
14
  const current = existsSync(DEV_VARS) ? readFileSync(DEV_VARS, 'utf8') : '';
@@ -21,6 +24,46 @@ function wrangler(root, args) {
21
24
  env: { ...process.env, CI: '1' }
22
25
  });
23
26
  }
27
+ function localMediaBucket(root) {
28
+ try {
29
+ const config = JSON.parse(readFileSync(join(root, 'wrangler.jsonc'), 'utf8'));
30
+ const buckets = Reflect.get(Object(config), 'r2_buckets');
31
+ const bound = (Array.isArray(buckets) ? buckets : []).find((bucket) => Reflect.get(Object(bucket), 'binding') === 'MEDIA');
32
+ const name = Reflect.get(Object(bound), 'bucket_name');
33
+ return typeof name === 'string' ? name : undefined;
34
+ }
35
+ catch {
36
+ return undefined;
37
+ }
38
+ }
39
+ export function putLocalPhotos(root, photos) {
40
+ if (photos.length === 0)
41
+ return;
42
+ const bucket = localMediaBucket(root);
43
+ if (bucket === undefined)
44
+ throw new Error(NO_BUCKET);
45
+ const directory = join(root, '.dev');
46
+ mkdirSync(directory, { recursive: true });
47
+ const list = join(directory, 'starter-photos.json');
48
+ for (const type of new Set(photos.map((photo) => photo.type))) {
49
+ writeFileSync(list, JSON.stringify(photos
50
+ .filter((photo) => photo.type === type)
51
+ .map((photo) => ({ key: photo.key, file: join(root, photo.path) }))));
52
+ wrangler(root, [
53
+ 'r2',
54
+ 'bulk',
55
+ 'put',
56
+ bucket,
57
+ '--local',
58
+ '--filename',
59
+ list,
60
+ '--content-type',
61
+ type,
62
+ '--cache-control',
63
+ IMMUTABLE
64
+ ]);
65
+ }
66
+ }
24
67
  export function resetLocalDatabase(root, tables, seed) {
25
68
  wrangler(root, ['d1', 'migrations', 'apply', 'DB', '--local']);
26
69
  wrangler(root, [
@@ -49,12 +92,14 @@ function prepareLocalDatabase(root, tables, seed, title) {
49
92
  export function localWorker(tables, seed, title) {
50
93
  return {
51
94
  name: 'pattern-local-worker',
52
- config(config, { command }) {
95
+ async config(config, { command }) {
53
96
  if (command !== 'serve')
54
97
  return;
55
98
  const root = config.root ?? process.cwd();
56
99
  ensureLocalSessionSecret(root);
57
- prepareLocalDatabase(root, tables, seed, title);
100
+ const starter = await readStarter(root, tables);
101
+ prepareLocalDatabase(root, tables, withStarter(seed, starter), title);
102
+ putLocalPhotos(root, starter?.photos ?? []);
58
103
  }
59
104
  };
60
105
  }
@@ -3,7 +3,12 @@ export declare const PROJECT_FILE = "pattern.json";
3
3
  declare const projectFile: z.ZodObject<{
4
4
  name: z.ZodString;
5
5
  title: z.ZodString;
6
+ blueprint: z.ZodOptional<z.ZodEnum<{
7
+ website: "website";
8
+ "web-app": "web-app";
9
+ }>>;
6
10
  }, z.core.$strip>;
7
11
  export type ProjectFile = z.output<typeof projectFile>;
8
12
  export declare function readProjectFile(root: string): ProjectFile;
13
+ export declare function blueprintOf(root: string): "website" | "web-app" | undefined;
9
14
  export {};
@@ -2,8 +2,13 @@ import { existsSync, readFileSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  import { z } from 'zod';
4
4
  import { appTitle } from "../appTitle.js";
5
+ import { blueprintName } from "../publishWire.js";
5
6
  export const PROJECT_FILE = 'pattern.json';
6
- const projectFile = z.object({ name: z.string().min(1), title: appTitle });
7
+ const projectFile = z.object({
8
+ name: z.string().min(1),
9
+ title: appTitle,
10
+ blueprint: blueprintName.optional()
11
+ });
7
12
  export function readProjectFile(root) {
8
13
  const path = join(root, PROJECT_FILE);
9
14
  if (!existsSync(path)) {
@@ -15,3 +20,16 @@ export function readProjectFile(root) {
15
20
  }
16
21
  return parsed.data;
17
22
  }
23
+ export function blueprintOf(root) {
24
+ const path = join(root, PROJECT_FILE);
25
+ if (!existsSync(path))
26
+ return undefined;
27
+ try {
28
+ const raw = JSON.parse(readFileSync(path, 'utf8'));
29
+ const parsed = blueprintName.safeParse(Reflect.get(Object(raw), 'blueprint'));
30
+ return parsed.success ? parsed.data : undefined;
31
+ }
32
+ catch {
33
+ return undefined;
34
+ }
35
+ }
package/dist/vite/vite.js CHANGED
@@ -5,6 +5,7 @@ import { cloudflare } from '@cloudflare/vite-plugin';
5
5
  import stylex from '@stylexjs/unplugin';
6
6
  import react from '@vitejs/plugin-react';
7
7
  import { defineConfig } from 'vitest/config';
8
+ import { hostnameOf } from "../publishWire.js";
8
9
  import { commandBridge } from "./commandBridge.js";
9
10
  import { designManifest } from "./designManifest.js";
10
11
  import { localWorker } from "./localWorker.js";
@@ -57,7 +58,7 @@ const reactCompilerSkippingUnchangedRendersAndLoggingWhereItCannot = {
57
58
  const FLOW_SETUP = fileURLToPath(new URL(`../flows/flowSetup${extname(import.meta.filename)}`, import.meta.url));
58
59
  export function pattern({ tables, admins, seed = {}, world = {} }) {
59
60
  const isVitest = process.env['VITEST'] !== undefined;
60
- const { title } = readProjectFile(process.cwd());
61
+ const { name, title } = readProjectFile(process.cwd());
61
62
  const isVisualFlowRun = process.env['PATTERN_VISUAL_URL'] !== undefined;
62
63
  const stylexPlugin = stylex.vite({
63
64
  useCSSLayers: { before: CSS_LAYERS_BEFORE_STYLEX },
@@ -87,6 +88,9 @@ export function pattern({ tables, admins, seed = {}, world = {} }) {
87
88
  designFile()
88
89
  ],
89
90
  clearScreen: false,
91
+ define: {
92
+ 'import.meta.env.PATTERN_LIVE_ORIGIN': JSON.stringify(`https://${hostnameOf(name)}`)
93
+ },
90
94
  optimizeDeps: sdkCompiledByStyleXButItsDependenciesPrebundled,
91
95
  build: {
92
96
  cssTarget: ['chrome123', 'firefox120', 'safari17.5']
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trypattern/sdk",
3
- "version": "0.1.12",
3
+ "version": "0.1.14",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",