@trypattern/sdk 0.1.0 → 0.1.1

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 (92) 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/builtins/AppSettings.d.ts +12 -0
  10. package/dist/builtins/AppSettings.js +31 -0
  11. package/dist/builtins/Toasts.d.ts +1 -1
  12. package/dist/builtins/Toasts.js +2 -1
  13. package/dist/cli/app.js +91 -14
  14. package/dist/cli/publishing.d.ts +21 -0
  15. package/dist/cli/publishing.js +493 -0
  16. package/dist/clock.d.ts +6 -0
  17. package/dist/clock.js +31 -0
  18. package/dist/components/AppFrame.js +3 -3
  19. package/dist/components/Button.d.ts +2 -1
  20. package/dist/components/Button.js +6 -3
  21. package/dist/components/CopyButton.d.ts +11 -0
  22. package/dist/components/CopyButton.js +16 -0
  23. package/dist/components/Divider.d.ts +2 -1
  24. package/dist/components/Divider.js +19 -4
  25. package/dist/components/IconButton.js +2 -2
  26. package/dist/components/Link.d.ts +8 -3
  27. package/dist/components/Link.js +11 -2
  28. package/dist/components/ListRow.js +2 -2
  29. package/dist/components/Menu.js +2 -2
  30. package/dist/components/RadioGroup.d.ts +18 -0
  31. package/dist/components/RadioGroup.js +85 -0
  32. package/dist/components/SegmentedControl.js +2 -2
  33. package/dist/components/Sidebar.js +2 -3
  34. package/dist/components/SignInScreen.js +3 -3
  35. package/dist/components/Switch.js +2 -1
  36. package/dist/components/controlLook.d.ts +10 -0
  37. package/dist/components/controlLook.js +14 -1
  38. package/dist/components/icons.d.ts +4 -3
  39. package/dist/components/icons.js +9 -3
  40. package/dist/components/interaction.d.ts +1 -1
  41. package/dist/flows/accessFlows.js +19 -3
  42. package/dist/flows/browser.d.ts +3 -1
  43. package/dist/flows/browser.js +6 -3
  44. package/dist/flows/flowBrowser.d.ts +3 -1
  45. package/dist/flows/flowBrowser.js +4 -2
  46. package/dist/flows/flows.d.ts +6 -0
  47. package/dist/flows/flows.js +32 -5
  48. package/dist/hooks/appContext.d.ts +2 -1
  49. package/dist/index.d.ts +6 -2
  50. package/dist/index.js +4 -2
  51. package/dist/publishWire.d.ts +271 -0
  52. package/dist/publishWire.js +168 -0
  53. package/dist/react.d.ts +3 -0
  54. package/dist/react.js +2 -0
  55. package/dist/registered.d.ts +6 -0
  56. package/dist/registered.js +2 -0
  57. package/dist/rules/checkAllFiles.js +10 -2
  58. package/dist/rules/lintPlugin.js +2 -0
  59. package/dist/rules/messages.d.ts +2 -2
  60. package/dist/rules/messages.js +2 -2
  61. package/dist/schema.d.ts +2 -0
  62. package/dist/schema.js +1 -0
  63. package/dist/server/auth.js +4 -1
  64. package/dist/server/createServer.d.ts +48 -3
  65. package/dist/server/createServer.js +25 -5
  66. package/dist/server/env.d.ts +2 -2
  67. package/dist/server/index.d.ts +6 -1
  68. package/dist/server/index.js +5 -1
  69. package/dist/server/services.d.ts +9 -0
  70. package/dist/server/services.js +47 -0
  71. package/dist/server/session.d.ts +1 -0
  72. package/dist/server/session.js +11 -0
  73. package/dist/server/settings.d.ts +49 -0
  74. package/dist/server/settings.js +25 -0
  75. package/dist/server/signInWire.d.ts +1 -0
  76. package/dist/server/signInWire.js +2 -1
  77. package/dist/serviceClients.d.ts +5 -0
  78. package/dist/serviceClients.js +70 -0
  79. package/dist/services.d.ts +53 -0
  80. package/dist/services.js +30 -0
  81. package/dist/start.js +30 -6
  82. package/dist/store.d.ts +5 -3
  83. package/dist/store.js +13 -3
  84. package/dist/table.d.ts +1 -1
  85. package/dist/vite/localWorker.d.ts +1 -1
  86. package/dist/vite/localWorker.js +5 -4
  87. package/dist/vite/projectFile.d.ts +9 -0
  88. package/dist/vite/projectFile.js +17 -0
  89. package/dist/vite/vite.d.ts +2 -1
  90. package/dist/vite/vite.js +10 -3
  91. package/package.json +5 -1
  92. package/presets/register.d.ts +2 -0
@@ -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) {
@@ -332,6 +332,7 @@ const SRC_ENTRY_FILES = new Set([
332
332
  'App.ts',
333
333
  'models/index.ts',
334
334
  'stores/index.ts',
335
+ 'services/index.ts',
335
336
  'actions/index.ts',
336
337
  'main.tsx',
337
338
  'routes.tsx',
@@ -345,6 +346,7 @@ const SRC_FOLDER_PATTERNS = [
345
346
  /^layouts\/[A-Z][A-Za-z]*Layout\.tsx$/,
346
347
  /^models\/[A-Z][A-Za-z]*\.ts$/,
347
348
  /^stores\/[A-Z][A-Za-z]*\.ts$/,
349
+ /^services\/[a-z][A-Za-z]*\.ts$/,
348
350
  /^actions\/[a-z][A-Za-z]*\.ts$/
349
351
  ];
350
352
  const PREFIXED_FOLDER_FILE = /^(components)\/([A-Z][A-Za-z]*)\/([A-Z][A-Za-z]*)\.tsx?$/;
@@ -362,6 +364,7 @@ const MODULE_FILE = /\.(ts|tsx|mts|cts)$/;
362
364
  const CLASS_HOMES = [
363
365
  { pattern: /\bextends\s+Model\s*\(/, folder: 'models/' },
364
366
  { pattern: /\bextends\s+Store\s*\(/, folder: 'stores/' },
367
+ { pattern: /\bdefineServices\s*\(/, folder: 'services/' },
365
368
  { pattern: /\bdefineActions\s*\(/, folder: 'actions/' }
366
369
  ];
367
370
  function isInItsFolder(path) {
@@ -474,6 +477,7 @@ function runsAccessFlows() {
474
477
  return (/from '@trypattern\/sdk\/flows'/.test(text) &&
475
478
  /accessFlows\(\s*\{\s*App\s*\}\s*\)/.test(text));
476
479
  }
480
+ const WORKER_ENTRY = 'server/worker.ts';
477
481
  const CONVENTION_EXPORTS = {
478
482
  'schema.ts': ['tables', 'admins'],
479
483
  'seed.ts': ['seed'],
@@ -611,14 +615,18 @@ function exportFindings() {
611
615
  return [...modules].flatMap(([path, facts]) => {
612
616
  const kept = CONVENTION_EXPORTS[relative(ROOT, path)] ?? [];
613
617
  const names = used.get(path) ?? new Set();
618
+ const isWorkerEntry = relative(ROOT, path) === WORKER_ENTRY;
614
619
  return [
615
- ...facts.passedThrough.map(({ offset }) => ({
620
+ ...(isWorkerEntry ? [] : facts.passedThrough).map(({ offset }) => ({
616
621
  path,
617
622
  offset,
618
623
  rule: 'no-re-exports'
619
624
  })),
620
625
  ...facts.exported
621
- .filter(({ name }) => !kept.includes(name) && !names.has(name) && !names.has(EVERYTHING))
626
+ .filter(({ name }) => !isWorkerEntry &&
627
+ !kept.includes(name) &&
628
+ !names.has(name) &&
629
+ !names.has(EVERYTHING))
622
630
  .map(({ offset }) => ({ path, offset, rule: 'no-unused-exports' }))
623
631
  ];
624
632
  });
@@ -55,6 +55,7 @@ const PRIMITIVES = new Set([
55
55
  'ContextMenu',
56
56
  'Dialog',
57
57
  'Divider',
58
+ 'CopyButton',
58
59
  'EmptyState',
59
60
  'Form',
60
61
  'Icon',
@@ -65,6 +66,7 @@ const PRIMITIVES = new Set([
65
66
  'LoadingRows',
66
67
  'Menu',
67
68
  'PropertyRow',
69
+ 'RadioGroup',
68
70
  'Row',
69
71
  'Screen',
70
72
  'ScrollArea',