@trypattern/sdk 0.1.0 → 0.1.2

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 (93) hide show
  1. package/dist/api.d.ts +17 -7
  2. package/dist/api.js +34 -8
  3. package/dist/app.d.ts +12 -3
  4. package/dist/app.js +49 -7
  5. package/dist/appInfo.d.ts +35 -0
  6. package/dist/appInfo.js +67 -0
  7. package/dist/appTitle.d.ts +6 -0
  8. package/dist/appTitle.js +3 -0
  9. package/dist/auth/sessionApi.js +2 -1
  10. package/dist/builtins/AppSettings.d.ts +12 -0
  11. package/dist/builtins/AppSettings.js +31 -0
  12. package/dist/builtins/Toasts.d.ts +1 -1
  13. package/dist/builtins/Toasts.js +2 -1
  14. package/dist/cli/app.js +91 -14
  15. package/dist/cli/publishing.d.ts +21 -0
  16. package/dist/cli/publishing.js +502 -0
  17. package/dist/clock.d.ts +6 -0
  18. package/dist/clock.js +31 -0
  19. package/dist/components/AppFrame.js +3 -3
  20. package/dist/components/Button.d.ts +2 -1
  21. package/dist/components/Button.js +6 -3
  22. package/dist/components/CopyButton.d.ts +11 -0
  23. package/dist/components/CopyButton.js +16 -0
  24. package/dist/components/Divider.d.ts +2 -1
  25. package/dist/components/Divider.js +19 -4
  26. package/dist/components/IconButton.js +2 -2
  27. package/dist/components/Link.d.ts +8 -3
  28. package/dist/components/Link.js +11 -2
  29. package/dist/components/ListRow.js +2 -2
  30. package/dist/components/Menu.js +2 -2
  31. package/dist/components/RadioGroup.d.ts +18 -0
  32. package/dist/components/RadioGroup.js +85 -0
  33. package/dist/components/SegmentedControl.js +2 -2
  34. package/dist/components/Sidebar.js +2 -3
  35. package/dist/components/SignInScreen.js +3 -3
  36. package/dist/components/Switch.js +2 -1
  37. package/dist/components/controlLook.d.ts +10 -0
  38. package/dist/components/controlLook.js +14 -1
  39. package/dist/components/icons.d.ts +4 -3
  40. package/dist/components/icons.js +9 -3
  41. package/dist/components/interaction.d.ts +1 -1
  42. package/dist/flows/accessFlows.js +19 -3
  43. package/dist/flows/browser.d.ts +3 -1
  44. package/dist/flows/browser.js +6 -3
  45. package/dist/flows/flowBrowser.d.ts +3 -1
  46. package/dist/flows/flowBrowser.js +4 -2
  47. package/dist/flows/flows.d.ts +6 -0
  48. package/dist/flows/flows.js +32 -5
  49. package/dist/hooks/appContext.d.ts +2 -1
  50. package/dist/index.d.ts +6 -2
  51. package/dist/index.js +4 -2
  52. package/dist/publishWire.d.ts +271 -0
  53. package/dist/publishWire.js +168 -0
  54. package/dist/react.d.ts +3 -0
  55. package/dist/react.js +2 -0
  56. package/dist/registered.d.ts +6 -0
  57. package/dist/registered.js +2 -0
  58. package/dist/rules/checkAllFiles.js +10 -2
  59. package/dist/rules/lintPlugin.js +2 -0
  60. package/dist/rules/messages.d.ts +2 -2
  61. package/dist/rules/messages.js +2 -2
  62. package/dist/schema.d.ts +2 -0
  63. package/dist/schema.js +1 -0
  64. package/dist/server/auth.js +8 -2
  65. package/dist/server/createServer.d.ts +48 -3
  66. package/dist/server/createServer.js +25 -5
  67. package/dist/server/env.d.ts +2 -2
  68. package/dist/server/index.d.ts +6 -1
  69. package/dist/server/index.js +5 -1
  70. package/dist/server/services.d.ts +9 -0
  71. package/dist/server/services.js +47 -0
  72. package/dist/server/session.d.ts +1 -0
  73. package/dist/server/session.js +11 -0
  74. package/dist/server/settings.d.ts +49 -0
  75. package/dist/server/settings.js +25 -0
  76. package/dist/server/signInWire.d.ts +1 -0
  77. package/dist/server/signInWire.js +2 -1
  78. package/dist/serviceClients.d.ts +5 -0
  79. package/dist/serviceClients.js +70 -0
  80. package/dist/services.d.ts +53 -0
  81. package/dist/services.js +30 -0
  82. package/dist/start.js +30 -6
  83. package/dist/store.d.ts +5 -3
  84. package/dist/store.js +13 -3
  85. package/dist/table.d.ts +1 -1
  86. package/dist/vite/localWorker.d.ts +1 -1
  87. package/dist/vite/localWorker.js +5 -4
  88. package/dist/vite/projectFile.d.ts +9 -0
  89. package/dist/vite/projectFile.js +17 -0
  90. package/dist/vite/vite.d.ts +2 -1
  91. package/dist/vite/vite.js +10 -3
  92. package/package.json +5 -1
  93. package/presets/register.d.ts +2 -0
@@ -2,6 +2,7 @@ import { createMemoryRouter } from 'react-router';
2
2
  import { afterAll, expect, inject, test } from 'vitest';
3
3
  import { apiCalls, memoryApi } from "../api.js";
4
4
  import { Cache } from "../cache.js";
5
+ import { manualClock } from "../clock.js";
5
6
  import { Gate } from "../gate.js";
6
7
  import { routeObjects } from "../routes.js";
7
8
  import { screenshotNameProblem } from "./screenshotName.js";
@@ -47,6 +48,12 @@ async function runSteps(name, steps, run) {
47
48
  else if ('restart' in step) {
48
49
  await run.restart();
49
50
  }
51
+ else if ('tick' in step) {
52
+ await run.tick();
53
+ }
54
+ else if ('world' in step) {
55
+ await run.world(step.world);
56
+ }
50
57
  else {
51
58
  expect(await run.snapshot(), `step ${index + 1} of "${name}": expected ${JSON.stringify(step.expect)}`).toMatchObject(step.expect);
52
59
  }
@@ -61,18 +68,30 @@ function withTestParams(path, failing, held) {
61
68
  return `${path}?${params.toString()}`;
62
69
  }
63
70
  export function defineFlow({ App }) {
64
- const { tables, routes } = App.definition;
71
+ const { tables, routes, services, memory } = App.definition;
65
72
  const seed = (inject('patternSeed') ?? {});
66
73
  const admins = inject('patternAdmins') ?? [];
67
- const calls = apiCalls(tables);
74
+ const title = inject('patternTitle') ?? '';
75
+ const startingWorld = inject('patternWorld') ?? {};
76
+ const calls = apiCalls(tables, services);
68
77
  const router = (path) => createMemoryRouter(routeObjects(routes), { initialEntries: [path] });
69
78
  function headless(name, steps, startAt, failing, signedInAs) {
70
79
  test(name, async () => {
71
80
  const gate = new Gate(failing);
81
+ const world = structuredClone(startingWorld);
72
82
  const deps = {
73
- api: memoryApi(tables, seed, { gate, signedInAs, admins }),
83
+ api: memoryApi(tables, seed, {
84
+ gate,
85
+ signedInAs,
86
+ admins,
87
+ title,
88
+ world,
89
+ ...(services === undefined ? {} : { services }),
90
+ ...(memory === undefined ? {} : { memory })
91
+ }),
74
92
  cache: Cache.memory(),
75
- gate
93
+ gate,
94
+ clock: manualClock()
76
95
  };
77
96
  let app = new App(router(startAt), deps);
78
97
  await runSteps(name, steps, {
@@ -86,6 +105,12 @@ export function defineFlow({ App }) {
86
105
  release: async (call) => gate.release(call),
87
106
  restart: async () => {
88
107
  app = new App(router(app.getSnapshot().path), deps);
108
+ },
109
+ tick: async () => {
110
+ app.tick();
111
+ },
112
+ world: async (patch) => {
113
+ Object.assign(Object(world), patch);
89
114
  }
90
115
  });
91
116
  await app.whenIdle();
@@ -109,7 +134,7 @@ export function defineFlow({ App }) {
109
134
  test(`${name} [${viewport}]`, async () => {
110
135
  const { openFlowPage } = await import("./flowBrowser.js");
111
136
  const held = new Set();
112
- const page = await openFlowPage(visual, viewport, withTestParams(startAt, failing, held), signedInAs, seed, admins);
137
+ const page = await openFlowPage(visual, viewport, withTestParams(startAt, failing, held), signedInAs, seed, admins, startingWorld);
113
138
  let stepFailure;
114
139
  try {
115
140
  await runSteps(name, steps, {
@@ -124,6 +149,8 @@ export function defineFlow({ App }) {
124
149
  held.delete(call);
125
150
  await page.release(call);
126
151
  },
152
+ tick: page.tick,
153
+ world: page.world,
127
154
  restart: async () => {
128
155
  const snapshot = await page.snapshot();
129
156
  const path = typeof snapshot === 'object' && snapshot !== null
@@ -1,11 +1,12 @@
1
1
  import type { Toasts } from '../builtins/Toasts.ts';
2
+ import type { AppStore } from '../appInfo.ts';
2
3
  import type { AppModels } from '../registered.ts';
3
4
  import type { AppProviderOf, UseModel } from './appHooks.ts';
4
5
  export type ReactApp = {
5
- readonly name: string;
6
6
  readonly models: AppModels;
7
7
  readonly stores: {
8
8
  readonly toasts: Toasts;
9
+ readonly app: AppStore;
9
10
  };
10
11
  pressKey(key: string): Promise<void> | undefined;
11
12
  };
package/dist/index.d.ts CHANGED
@@ -18,8 +18,12 @@ export { userSchema } from './auth/user.ts';
18
18
  export type { User } from './auth/user.ts';
19
19
  export type { AppClass, AppDefinition, AppDependencies, AppSnapshotShape, DataRouter, ModelServicesOf, NavigateCommand, PressKeyCommand, PublicStores, PlainJsonModel, RunningApp, StoreClasses, StoreInstances, StoresOf, TableStores } from './app.ts';
20
20
  export { defineRoutes } from './routes.ts';
21
+ export { ServiceRefused, refused } from './services.ts';
22
+ export type { ServiceClient, ServiceMemory } from './services.ts';
23
+ export { manualClock, realClock } from './clock.ts';
24
+ export type { Clock } from './clock.ts';
21
25
  export type { PageOf, PathOf, RouteDefinition } from './routes.ts';
22
- export { Model, action, appPath, defineActions } from './registered.ts';
26
+ export { Model, Store, action, appPath, defineActions } from './registered.ts';
23
27
  export type { ActionContext, AppAction, AppActionGroup, AppCommand, AppModels, AppPage, AppPath, AppSnapshot, AppStores, ModelServices, Register } from './registered.ts';
24
28
  export { Cache, Cached } from './cache.ts';
25
29
  export type { CacheStorage } from './cache.ts';
@@ -28,7 +32,7 @@ export type { Entity, EntityApi, EntityCall, EntityDeps, EntitySnapshot, Pending
28
32
  export { Gate } from './gate.ts';
29
33
  export { MemoryEntityApi, MemoryServer } from './memoryApi.ts';
30
34
  export type { MemoryApiOptions } from './memoryApi.ts';
31
- export { Store, StoreBase, keepEqualParts, snapshotsOf } from './store.ts';
35
+ export { StoreBase, keepEqualParts, snapshotsOf } from './store.ts';
32
36
  export type { Snapshots, StoreClass, StoreConfig } from './store.ts';
33
37
  export type { Json, Persisted, StateOf, StateSpec } from './state.ts';
34
38
  export { defineTables } from './table.ts';
package/dist/index.js CHANGED
@@ -8,12 +8,14 @@ export { SessionStore } from "./auth/sessionStore.js";
8
8
  export { HttpSessionApi, MemorySessionApi } from "./auth/sessionApi.js";
9
9
  export { userSchema } from "./auth/user.js";
10
10
  export { defineRoutes } from "./routes.js";
11
- export { Model, action, appPath, defineActions } from "./registered.js";
11
+ export { ServiceRefused, refused } from "./services.js";
12
+ export { manualClock, realClock } from "./clock.js";
13
+ export { Model, Store, action, appPath, defineActions } from "./registered.js";
12
14
  export { Cache, Cached } from "./cache.js";
13
15
  export { EntityStore, WriteRefused, entityCalls } from "./entityStore.js";
14
16
  export { Gate } from "./gate.js";
15
17
  export { MemoryEntityApi, MemoryServer } from "./memoryApi.js";
16
- export { Store, StoreBase, keepEqualParts, snapshotsOf } from "./store.js";
18
+ export { StoreBase, keepEqualParts, snapshotsOf } from "./store.js";
17
19
  export { defineTables } from "./table.js";
18
20
  export { HttpTableApi, MemoryTableApi, PublicTableStore, TableStore, httpTables, memoryTables, publicStoreName, tableCalls } from "./tables.js";
19
21
  export { ModelBase, command, commandsOf, createModels, modelSnapshotsOf, parseMessage, sendMessage, splitType } from "./model.js";
@@ -0,0 +1,271 @@
1
+ import { z } from 'zod';
2
+ import { appTitle } from './appTitle.ts';
3
+ export { appTitle };
4
+ export declare const DASHBOARD_URL = "https://onpattern.app";
5
+ export declare const APPS_DOMAIN = "onpattern.app";
6
+ export declare const UPLOAD_LIMIT_BYTES: number;
7
+ export declare const UPLOAD_LIMIT_PARTS = 5000;
8
+ export declare function nameProblem(name: string): string | undefined;
9
+ export declare const appName: z.ZodString;
10
+ export declare function hostnameOf(name: string): string;
11
+ export declare function isPrivatePath(path: string): boolean;
12
+ export declare function sourcePathProblem(path: string): string | undefined;
13
+ export declare const UPLOAD: {
14
+ readonly worker: "worker/";
15
+ readonly client: "client/";
16
+ readonly migrations: "migrations/";
17
+ readonly source: "source/";
18
+ readonly compatibilityDate: "compatibilityDate";
19
+ readonly sdkVersion: "sdkVersion";
20
+ };
21
+ export declare const publishStep: z.ZodEnum<{
22
+ publish: "publish";
23
+ reserve: "reserve";
24
+ database: "database";
25
+ "sign-in": "sign-in";
26
+ }>;
27
+ export type PublishStep = z.output<typeof publishStep>;
28
+ export declare const publishStatus: z.ZodEnum<{
29
+ failed: "failed";
30
+ running: "running";
31
+ live: "live";
32
+ }>;
33
+ export declare const publishSummary: z.ZodObject<{
34
+ number: z.ZodNumber;
35
+ status: z.ZodEnum<{
36
+ failed: "failed";
37
+ running: "running";
38
+ live: "live";
39
+ }>;
40
+ step: z.ZodEnum<{
41
+ publish: "publish";
42
+ reserve: "reserve";
43
+ database: "database";
44
+ "sign-in": "sign-in";
45
+ }>;
46
+ error: z.ZodNullable<z.ZodString>;
47
+ byEmail: z.ZodString;
48
+ restoredFrom: z.ZodNullable<z.ZodNumber>;
49
+ isStarter: z.ZodBoolean;
50
+ startedAt: z.ZodString;
51
+ finishedAt: z.ZodNullable<z.ZodString>;
52
+ }, z.core.$strip>;
53
+ export type PublishSummary = z.output<typeof publishSummary>;
54
+ export declare const appSummary: z.ZodObject<{
55
+ name: z.ZodString;
56
+ title: z.ZodString;
57
+ url: z.ZodString;
58
+ pulledAt: z.ZodNullable<z.ZodString>;
59
+ latest: z.ZodNullable<z.ZodObject<{
60
+ number: z.ZodNumber;
61
+ status: z.ZodEnum<{
62
+ failed: "failed";
63
+ running: "running";
64
+ live: "live";
65
+ }>;
66
+ step: z.ZodEnum<{
67
+ publish: "publish";
68
+ reserve: "reserve";
69
+ database: "database";
70
+ "sign-in": "sign-in";
71
+ }>;
72
+ error: z.ZodNullable<z.ZodString>;
73
+ byEmail: z.ZodString;
74
+ restoredFrom: z.ZodNullable<z.ZodNumber>;
75
+ isStarter: z.ZodBoolean;
76
+ startedAt: z.ZodString;
77
+ finishedAt: z.ZodNullable<z.ZodString>;
78
+ }, z.core.$strip>>;
79
+ }, z.core.$strip>;
80
+ export type AppSummary = z.output<typeof appSummary>;
81
+ export declare const nameSuggestion: z.ZodObject<{
82
+ name: z.ZodString;
83
+ available: z.ZodBoolean;
84
+ problem: z.ZodNullable<z.ZodString>;
85
+ }, z.core.$strip>;
86
+ export type NameSuggestion = z.output<typeof nameSuggestion>;
87
+ export declare const loginStarted: z.ZodObject<{
88
+ secret: z.ZodString;
89
+ code: z.ZodString;
90
+ url: z.ZodString;
91
+ }, z.core.$strip>;
92
+ export declare const loginPoll: z.ZodUnion<readonly [z.ZodObject<{
93
+ status: z.ZodLiteral<"waiting">;
94
+ }, z.core.$strip>, z.ZodObject<{
95
+ status: z.ZodLiteral<"approved">;
96
+ cookie: z.ZodString;
97
+ }, z.core.$strip>]>;
98
+ export declare const loginToApprove: z.ZodObject<{
99
+ code: z.ZodString;
100
+ label: z.ZodString;
101
+ }, z.core.$strip>;
102
+ export declare const publishServices: {
103
+ readonly apps: {
104
+ readonly list: NoInfer<import("./services.ts").ServiceCall<"/apps", {}, z.ZodArray<z.ZodObject<{
105
+ name: z.ZodString;
106
+ title: z.ZodString;
107
+ url: z.ZodString;
108
+ pulledAt: z.ZodNullable<z.ZodString>;
109
+ latest: z.ZodNullable<z.ZodObject<{
110
+ number: z.ZodNumber;
111
+ status: z.ZodEnum<{
112
+ failed: "failed";
113
+ running: "running";
114
+ live: "live";
115
+ }>;
116
+ step: z.ZodEnum<{
117
+ publish: "publish";
118
+ reserve: "reserve";
119
+ database: "database";
120
+ "sign-in": "sign-in";
121
+ }>;
122
+ error: z.ZodNullable<z.ZodString>;
123
+ byEmail: z.ZodString;
124
+ restoredFrom: z.ZodNullable<z.ZodNumber>;
125
+ isStarter: z.ZodBoolean;
126
+ startedAt: z.ZodString;
127
+ finishedAt: z.ZodNullable<z.ZodString>;
128
+ }, z.core.$strip>>;
129
+ }, z.core.$strip>>>>;
130
+ readonly read: NoInfer<import("./services.ts").ServiceCall<"/apps/:name", {}, z.ZodObject<{
131
+ name: z.ZodString;
132
+ title: z.ZodString;
133
+ url: z.ZodString;
134
+ pulledAt: z.ZodNullable<z.ZodString>;
135
+ latest: z.ZodNullable<z.ZodObject<{
136
+ number: z.ZodNumber;
137
+ status: z.ZodEnum<{
138
+ failed: "failed";
139
+ running: "running";
140
+ live: "live";
141
+ }>;
142
+ step: z.ZodEnum<{
143
+ publish: "publish";
144
+ reserve: "reserve";
145
+ database: "database";
146
+ "sign-in": "sign-in";
147
+ }>;
148
+ error: z.ZodNullable<z.ZodString>;
149
+ byEmail: z.ZodString;
150
+ restoredFrom: z.ZodNullable<z.ZodNumber>;
151
+ isStarter: z.ZodBoolean;
152
+ startedAt: z.ZodString;
153
+ finishedAt: z.ZodNullable<z.ZodString>;
154
+ }, z.core.$strip>>;
155
+ }, z.core.$strip>>>;
156
+ readonly create: NoInfer<import("./services.ts").ServiceCall<"/apps", {
157
+ name: z.ZodString;
158
+ title: z.ZodString;
159
+ }, z.ZodObject<{
160
+ name: z.ZodString;
161
+ title: z.ZodString;
162
+ url: z.ZodString;
163
+ pulledAt: z.ZodNullable<z.ZodString>;
164
+ latest: z.ZodNullable<z.ZodObject<{
165
+ number: z.ZodNumber;
166
+ status: z.ZodEnum<{
167
+ failed: "failed";
168
+ running: "running";
169
+ live: "live";
170
+ }>;
171
+ step: z.ZodEnum<{
172
+ publish: "publish";
173
+ reserve: "reserve";
174
+ database: "database";
175
+ "sign-in": "sign-in";
176
+ }>;
177
+ error: z.ZodNullable<z.ZodString>;
178
+ byEmail: z.ZodString;
179
+ restoredFrom: z.ZodNullable<z.ZodNumber>;
180
+ isStarter: z.ZodBoolean;
181
+ startedAt: z.ZodString;
182
+ finishedAt: z.ZodNullable<z.ZodString>;
183
+ }, z.core.$strip>>;
184
+ }, z.core.$strip>>>;
185
+ };
186
+ readonly names: {
187
+ readonly suggest: NoInfer<import("./services.ts").ServiceCall<"/names", {
188
+ title: z.ZodString;
189
+ }, z.ZodArray<z.ZodObject<{
190
+ name: z.ZodString;
191
+ available: z.ZodBoolean;
192
+ problem: z.ZodNullable<z.ZodString>;
193
+ }, z.core.$strip>>>>;
194
+ readonly check: NoInfer<import("./services.ts").ServiceCall<"/names/:name", {}, z.ZodObject<{
195
+ name: z.ZodString;
196
+ available: z.ZodBoolean;
197
+ problem: z.ZodNullable<z.ZodString>;
198
+ }, z.core.$strip>>>;
199
+ };
200
+ readonly publishes: {
201
+ readonly list: NoInfer<import("./services.ts").ServiceCall<"/apps/:name/publishes", {}, z.ZodArray<z.ZodObject<{
202
+ number: z.ZodNumber;
203
+ status: z.ZodEnum<{
204
+ failed: "failed";
205
+ running: "running";
206
+ live: "live";
207
+ }>;
208
+ step: z.ZodEnum<{
209
+ publish: "publish";
210
+ reserve: "reserve";
211
+ database: "database";
212
+ "sign-in": "sign-in";
213
+ }>;
214
+ error: z.ZodNullable<z.ZodString>;
215
+ byEmail: z.ZodString;
216
+ restoredFrom: z.ZodNullable<z.ZodNumber>;
217
+ isStarter: z.ZodBoolean;
218
+ startedAt: z.ZodString;
219
+ finishedAt: z.ZodNullable<z.ZodString>;
220
+ }, z.core.$strip>>>>;
221
+ readonly read: NoInfer<import("./services.ts").ServiceCall<"/apps/:name/publishes/:number", {}, z.ZodObject<{
222
+ number: z.ZodNumber;
223
+ status: z.ZodEnum<{
224
+ failed: "failed";
225
+ running: "running";
226
+ live: "live";
227
+ }>;
228
+ step: z.ZodEnum<{
229
+ publish: "publish";
230
+ reserve: "reserve";
231
+ database: "database";
232
+ "sign-in": "sign-in";
233
+ }>;
234
+ error: z.ZodNullable<z.ZodString>;
235
+ byEmail: z.ZodString;
236
+ restoredFrom: z.ZodNullable<z.ZodNumber>;
237
+ isStarter: z.ZodBoolean;
238
+ startedAt: z.ZodString;
239
+ finishedAt: z.ZodNullable<z.ZodString>;
240
+ }, z.core.$strip>>>;
241
+ readonly retry: NoInfer<import("./services.ts").ServiceCall<"/apps/:name/publishes/:number/retry", {}, z.ZodObject<{
242
+ number: z.ZodNumber;
243
+ status: z.ZodEnum<{
244
+ failed: "failed";
245
+ running: "running";
246
+ live: "live";
247
+ }>;
248
+ step: z.ZodEnum<{
249
+ publish: "publish";
250
+ reserve: "reserve";
251
+ database: "database";
252
+ "sign-in": "sign-in";
253
+ }>;
254
+ error: z.ZodNullable<z.ZodString>;
255
+ byEmail: z.ZodString;
256
+ restoredFrom: z.ZodNullable<z.ZodNumber>;
257
+ isStarter: z.ZodBoolean;
258
+ startedAt: z.ZodString;
259
+ finishedAt: z.ZodNullable<z.ZodString>;
260
+ }, z.core.$strip>>>;
261
+ };
262
+ readonly logins: {
263
+ readonly read: NoInfer<import("./services.ts").ServiceCall<"/cli/logins/:approval", {}, z.ZodObject<{
264
+ code: z.ZodString;
265
+ label: z.ZodString;
266
+ }, z.core.$strip>>>;
267
+ readonly approve: NoInfer<import("./services.ts").ServiceCall<"/cli/logins/:approval/approve", {}, z.ZodObject<{
268
+ ok: z.ZodBoolean;
269
+ }, z.core.$strip>>>;
270
+ };
271
+ };
@@ -0,0 +1,168 @@
1
+ import { z } from 'zod';
2
+ import { appTitle } from "./appTitle.js";
3
+ export { appTitle };
4
+ import { call, defineServices } from "./services.js";
5
+ export const DASHBOARD_URL = 'https://onpattern.app';
6
+ export const APPS_DOMAIN = 'onpattern.app';
7
+ export const UPLOAD_LIMIT_BYTES = 50 * 1024 * 1024;
8
+ export const UPLOAD_LIMIT_PARTS = 5000;
9
+ const RESERVED_NAMES = new Set([
10
+ 'auth',
11
+ 'www',
12
+ 'api',
13
+ 'admin',
14
+ 'app',
15
+ 'apps',
16
+ 'dashboard',
17
+ 'deploy',
18
+ 'publish',
19
+ 'onpattern',
20
+ 'trypattern',
21
+ 'mail',
22
+ 'login',
23
+ 'help',
24
+ 'docs',
25
+ 'status',
26
+ 'support',
27
+ 'blog',
28
+ 'dev',
29
+ 'test',
30
+ 'staging',
31
+ 'cdn',
32
+ 'static',
33
+ 'assets',
34
+ 'dispatch',
35
+ 'start',
36
+ 'approve'
37
+ ]);
38
+ export function nameProblem(name) {
39
+ if (!/^[a-z][a-z0-9-]{1,28}[a-z0-9]$/.test(name)) {
40
+ return 'Use 3 to 30 lowercase letters, numbers and hyphens, starting with a letter.';
41
+ }
42
+ if (name.includes('--'))
43
+ return 'Use one hyphen at a time.';
44
+ if (RESERVED_NAMES.has(name) || name.startsWith('pattern')) {
45
+ return 'That address is reserved.';
46
+ }
47
+ return undefined;
48
+ }
49
+ export const appName = z.string().superRefine((name, context) => {
50
+ const problem = nameProblem(name);
51
+ if (problem !== undefined)
52
+ context.addIssue({ code: 'custom', message: problem });
53
+ });
54
+ export function hostnameOf(name) {
55
+ return `${name}.${APPS_DOMAIN}`;
56
+ }
57
+ const PRIVATE_NAMES = new Set([
58
+ '.git',
59
+ 'node_modules',
60
+ 'dist',
61
+ '.dev',
62
+ '.wrangler',
63
+ '.dev.vars',
64
+ '.DS_Store'
65
+ ]);
66
+ export function isPrivatePath(path) {
67
+ return path.split('/').some((part) => {
68
+ if (PRIVATE_NAMES.has(part))
69
+ return true;
70
+ if (part.startsWith('.env') && part !== '.env.example')
71
+ return true;
72
+ return part.endsWith('.local') || part.endsWith('.log');
73
+ });
74
+ }
75
+ export function sourcePathProblem(path) {
76
+ if (path === '' || path.startsWith('/') || path.includes('\\')) {
77
+ return `${path} is not a relative path`;
78
+ }
79
+ if (path.split('/').some((part) => part === '' || part === '.' || part === '..')) {
80
+ return `${path} leaves the project`;
81
+ }
82
+ if (isPrivatePath(path))
83
+ return `${path} must never leave the laptop`;
84
+ return undefined;
85
+ }
86
+ export const UPLOAD = {
87
+ worker: 'worker/',
88
+ client: 'client/',
89
+ migrations: 'migrations/',
90
+ source: 'source/',
91
+ compatibilityDate: 'compatibilityDate',
92
+ sdkVersion: 'sdkVersion'
93
+ };
94
+ export const publishStep = z.enum(['reserve', 'database', 'sign-in', 'publish']);
95
+ export const publishStatus = z.enum(['running', 'live', 'failed']);
96
+ export const publishSummary = z.object({
97
+ number: z.number(),
98
+ status: publishStatus,
99
+ step: publishStep,
100
+ error: z.string().nullable(),
101
+ byEmail: z.string(),
102
+ restoredFrom: z.number().nullable(),
103
+ isStarter: z.boolean(),
104
+ startedAt: z.string(),
105
+ finishedAt: z.string().nullable()
106
+ });
107
+ export const appSummary = z.object({
108
+ name: z.string(),
109
+ title: z.string(),
110
+ url: z.string(),
111
+ pulledAt: z.string().nullable(),
112
+ latest: publishSummary.nullable()
113
+ });
114
+ export const nameSuggestion = z.object({
115
+ name: z.string(),
116
+ available: z.boolean(),
117
+ problem: z.string().nullable()
118
+ });
119
+ export const loginStarted = z.object({
120
+ secret: z.string(),
121
+ code: z.string(),
122
+ url: z.string()
123
+ });
124
+ export const loginPoll = z.union([
125
+ z.object({ status: z.literal('waiting') }),
126
+ z.object({ status: z.literal('approved'), cookie: z.string() })
127
+ ]);
128
+ export const loginToApprove = z.object({ code: z.string(), label: z.string() });
129
+ export const publishServices = defineServices({
130
+ apps: {
131
+ list: call({ get: '/apps', reply: z.array(appSummary) }),
132
+ read: call({ get: '/apps/:name', reply: appSummary }),
133
+ create: call({
134
+ post: '/apps',
135
+ input: { name: appName, title: appTitle },
136
+ reply: appSummary
137
+ })
138
+ },
139
+ names: {
140
+ suggest: call({
141
+ get: '/names',
142
+ input: { title: z.string() },
143
+ reply: z.array(nameSuggestion)
144
+ }),
145
+ check: call({ get: '/names/:name', reply: nameSuggestion })
146
+ },
147
+ publishes: {
148
+ list: call({
149
+ get: '/apps/:name/publishes',
150
+ reply: z.array(publishSummary)
151
+ }),
152
+ read: call({
153
+ get: '/apps/:name/publishes/:number',
154
+ reply: publishSummary
155
+ }),
156
+ retry: call({
157
+ post: '/apps/:name/publishes/:number/retry',
158
+ reply: publishSummary
159
+ })
160
+ },
161
+ logins: {
162
+ read: call({ get: '/cli/logins/:approval', reply: loginToApprove }),
163
+ approve: call({
164
+ post: '/cli/logins/:approval/approve',
165
+ reply: z.object({ ok: z.boolean() })
166
+ })
167
+ }
168
+ });
package/dist/react.d.ts CHANGED
@@ -10,6 +10,7 @@ export { CommandPalette } from './components/CommandPalette.tsx';
10
10
  export type { CommandMenuItem } from './components/CommandMenu.tsx';
11
11
  export { Content } from './components/Content.tsx';
12
12
  export { ContextMenu } from './components/ContextMenu.tsx';
13
+ export { CopyButton } from './components/CopyButton.tsx';
13
14
  export { Dialog } from './components/Dialog.tsx';
14
15
  export { Divider } from './components/Divider.tsx';
15
16
  export { EmptyState } from './components/EmptyState.tsx';
@@ -26,6 +27,8 @@ export type { MenuEntry } from './components/MenuItems.tsx';
26
27
  export type { SidebarLink } from './components/Sidebar.tsx';
27
28
  export type { Placement } from './components/Placement.ts';
28
29
  export { PropertyRow } from './components/PropertyRow.tsx';
30
+ export { RadioGroup } from './components/RadioGroup.tsx';
31
+ export type { RadioOption } from './components/RadioGroup.tsx';
29
32
  export { Row } from './components/Row.tsx';
30
33
  export { Screen } from './components/Screen.tsx';
31
34
  export { ScrollArea } from './components/ScrollArea.tsx';
package/dist/react.js CHANGED
@@ -9,6 +9,7 @@ export { CommandMenu } from "./components/CommandMenu.js";
9
9
  export { CommandPalette } from "./components/CommandPalette.js";
10
10
  export { Content } from "./components/Content.js";
11
11
  export { ContextMenu } from "./components/ContextMenu.js";
12
+ export { CopyButton } from "./components/CopyButton.js";
12
13
  export { Dialog } from "./components/Dialog.js";
13
14
  export { Divider } from "./components/Divider.js";
14
15
  export { EmptyState } from "./components/EmptyState.js";
@@ -21,6 +22,7 @@ export { ListRow } from "./components/ListRow.js";
21
22
  export { LoadingRows } from "./components/LoadingRows.js";
22
23
  export { Menu } from "./components/Menu.js";
23
24
  export { PropertyRow } from "./components/PropertyRow.js";
25
+ export { RadioGroup } from "./components/RadioGroup.js";
24
26
  export { Row } from "./components/Row.js";
25
27
  export { Screen } from "./components/Screen.js";
26
28
  export { ScrollArea } from "./components/ScrollArea.js";
@@ -1,9 +1,11 @@
1
1
  import type { AppSnapshotShape, ModelServicesOf, NavigateCommand, PressKeyCommand, StoreClasses, StoreInstances, StoresOf } from './app.ts';
2
2
  import { z } from 'zod';
3
3
  import type { Action, DefineActions } from './actions.ts';
4
+ import type { ServiceClient, Services } from './services.ts';
4
5
  import type { Instances, MessagesOf, ModelClassLike, ModelSnapshots } from './model.ts';
5
6
  import type { BUILT_IN_GROUPS } from './builtins/actions.ts';
6
7
  import type { Account } from './builtins/Account.ts';
8
+ import type { AppSettings } from './builtins/AppSettings.ts';
7
9
  import type { Palette } from './builtins/Palette.ts';
8
10
  import type { SignIn } from './builtins/SignIn.ts';
9
11
  import type { IconName } from './components/icons.ts';
@@ -16,6 +18,8 @@ type Empty = Record<never, never>;
16
18
  type RegisteredModels = Registered<'models', Empty> extends infer Classes extends Record<string, ModelClassLike> ? Classes : Empty;
17
19
  type RegisteredTables = Registered<'tables', Empty> extends infer Group extends Tables ? Group : Empty;
18
20
  type RegisteredStores = Registered<'stores', Empty> extends infer Classes extends StoreClasses ? Classes : Empty;
21
+ type RegisteredServices = Registered<'services', Empty> extends infer Group extends Services ? Group : Empty;
22
+ export type AppServices = ServiceClient<RegisteredServices>;
19
23
  type RegisteredActionGroups = Registered<'actionGroups', readonly string[]> extends infer Groups extends readonly string[] ? Groups : readonly string[];
20
24
  export type AppActionGroup = RegisteredActionGroups[number] | (typeof BUILT_IN_GROUPS)[number];
21
25
  export type AppAction = Action & {
@@ -28,6 +32,7 @@ type RegisteredIcons = Registered<'icons', Empty> extends infer Icons extends Re
28
32
  export type AppIconName = keyof RegisteredIcons & string;
29
33
  export type BuiltInModels = {
30
34
  account: typeof Account;
35
+ appSettings: typeof AppSettings;
31
36
  palette: typeof Palette;
32
37
  signIn: typeof SignIn;
33
38
  };
@@ -43,6 +48,7 @@ export type ActionContext = {
43
48
  };
44
49
  export type ModelServices = ModelServicesOf<AppPath>;
45
50
  export declare const Model: <S extends import("./state.ts").StateSpec = Record<never, never>, const P extends readonly (keyof S & string)[] = []>(config?: import("./model.ts").ModelConfig<S, P>) => import("./model.ts").ModelClass<AppStores, ModelServices, S, P>;
51
+ export declare const Store: <S extends import("./state.ts").StateSpec = Record<never, never>, const P extends readonly (keyof S & string)[] = []>(config: import("./store.ts").StoreConfig<S, P>) => import("./store.ts").StoreClass<S, P, ServiceClient<Empty>>;
46
52
  export declare const defineActions: DefineActions<ActionContext, RegisteredAction, AppCommand>;
47
53
  export declare const appPath: z.ZodCustom<AppPath, AppPath>;
48
54
  type ActionInput = Pick<AppAction, 'id' | 'label' | 'group' | 'icon'> & Partial<Pick<AppAction, 'keys' | 'keywords' | 'isDanger' | 'isSearchOnly' | 'isHidden'>> & {
@@ -1,8 +1,10 @@
1
1
  import { z } from 'zod';
2
2
  import { bindActions } from "./actions.js";
3
3
  import { defineModel } from "./model.js";
4
+ import { defineStore } from "./store.js";
4
5
  import { isRoutedPath } from "./routes.js";
5
6
  export const Model = defineModel();
7
+ export const Store = defineStore();
6
8
  export const defineActions = bindActions();
7
9
  export const appPath = z.custom((value) => typeof value === 'string' && isRoutedPath(value), { error: 'Not a page in src/routes.tsx' });
8
10
  export function action(input) {