@trypattern/sdk 0.0.0-stage → 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 (273) hide show
  1. package/README.md +127 -2
  2. package/dist/access.d.ts +31 -0
  3. package/dist/access.js +72 -0
  4. package/dist/actions.d.ts +57 -0
  5. package/dist/actions.js +198 -0
  6. package/dist/api.d.ts +30 -0
  7. package/dist/api.js +60 -0
  8. package/dist/app.d.ts +115 -0
  9. package/dist/app.js +266 -0
  10. package/dist/appInfo.d.ts +35 -0
  11. package/dist/appInfo.js +67 -0
  12. package/dist/appTitle.d.ts +6 -0
  13. package/dist/appTitle.js +3 -0
  14. package/dist/appearance.d.ts +7 -0
  15. package/dist/appearance.js +2 -0
  16. package/dist/auth/sessionApi.d.ts +41 -0
  17. package/dist/auth/sessionApi.js +158 -0
  18. package/dist/auth/sessionStore.d.ts +20 -0
  19. package/dist/auth/sessionStore.js +40 -0
  20. package/dist/auth/user.d.ts +11 -0
  21. package/dist/auth/user.js +9 -0
  22. package/dist/builtins/Account.d.ts +25 -0
  23. package/dist/builtins/Account.js +15 -0
  24. package/dist/builtins/AppSettings.d.ts +12 -0
  25. package/dist/builtins/AppSettings.js +31 -0
  26. package/dist/builtins/Palette.d.ts +29 -0
  27. package/dist/builtins/Palette.js +63 -0
  28. package/dist/builtins/SignIn.d.ts +28 -0
  29. package/dist/builtins/SignIn.js +60 -0
  30. package/dist/builtins/Toasts.d.ts +32 -0
  31. package/dist/builtins/Toasts.js +25 -0
  32. package/dist/builtins/actions.d.ts +2 -0
  33. package/dist/builtins/actions.js +45 -0
  34. package/dist/cache.d.ts +24 -0
  35. package/dist/cache.js +112 -0
  36. package/dist/cli/app.d.ts +2 -0
  37. package/dist/cli/app.js +1406 -0
  38. package/dist/cli/publishing.d.ts +21 -0
  39. package/dist/cli/publishing.js +493 -0
  40. package/dist/cli/screenshot.d.ts +1 -0
  41. package/dist/cli/screenshot.js +96 -0
  42. package/dist/cli/tools.d.ts +12 -0
  43. package/dist/cli/tools.js +35 -0
  44. package/dist/clock.d.ts +6 -0
  45. package/dist/clock.js +31 -0
  46. package/dist/components/AppFrame.d.ts +14 -0
  47. package/dist/components/AppFrame.js +64 -0
  48. package/dist/components/AppearancePicker.d.ts +1 -0
  49. package/dist/components/AppearancePicker.js +12 -0
  50. package/dist/components/Avatar.d.ts +9 -0
  51. package/dist/components/Avatar.js +63 -0
  52. package/dist/components/Badge.d.ts +11 -0
  53. package/dist/components/Badge.js +87 -0
  54. package/dist/components/Button.d.ts +24 -0
  55. package/dist/components/Button.js +252 -0
  56. package/dist/components/Card.d.ts +12 -0
  57. package/dist/components/Card.js +38 -0
  58. package/dist/components/CommandMenu.d.ts +23 -0
  59. package/dist/components/CommandMenu.js +214 -0
  60. package/dist/components/CommandPalette.d.ts +1 -0
  61. package/dist/components/CommandPalette.js +7 -0
  62. package/dist/components/Content.d.ts +7 -0
  63. package/dist/components/Content.js +24 -0
  64. package/dist/components/ContextMenu.d.ts +8 -0
  65. package/dist/components/ContextMenu.js +23 -0
  66. package/dist/components/CopyButton.d.ts +11 -0
  67. package/dist/components/CopyButton.js +16 -0
  68. package/dist/components/Dialog.d.ts +11 -0
  69. package/dist/components/Dialog.js +81 -0
  70. package/dist/components/Divider.d.ts +7 -0
  71. package/dist/components/Divider.js +30 -0
  72. package/dist/components/EmptyState.d.ts +8 -0
  73. package/dist/components/EmptyState.js +24 -0
  74. package/dist/components/Form.d.ts +9 -0
  75. package/dist/components/Form.js +23 -0
  76. package/dist/components/Icon.d.ts +10 -0
  77. package/dist/components/Icon.js +22 -0
  78. package/dist/components/IconButton.d.ts +14 -0
  79. package/dist/components/IconButton.js +53 -0
  80. package/dist/components/Kbd.d.ts +6 -0
  81. package/dist/components/Kbd.js +67 -0
  82. package/dist/components/Link.d.ts +14 -0
  83. package/dist/components/Link.js +44 -0
  84. package/dist/components/ListRow.d.ts +12 -0
  85. package/dist/components/ListRow.js +62 -0
  86. package/dist/components/LoadingRows.d.ts +5 -0
  87. package/dist/components/LoadingRows.js +6 -0
  88. package/dist/components/Menu.d.ts +12 -0
  89. package/dist/components/Menu.js +33 -0
  90. package/dist/components/MenuItems.d.ts +21 -0
  91. package/dist/components/MenuItems.js +32 -0
  92. package/dist/components/Placement.d.ts +21 -0
  93. package/dist/components/Placement.js +1 -0
  94. package/dist/components/Popup.d.ts +8 -0
  95. package/dist/components/Popup.js +43 -0
  96. package/dist/components/PopupItem.d.ts +8 -0
  97. package/dist/components/PopupItem.js +51 -0
  98. package/dist/components/PropertyRow.d.ts +7 -0
  99. package/dist/components/PropertyRow.js +23 -0
  100. package/dist/components/RadioGroup.d.ts +18 -0
  101. package/dist/components/RadioGroup.js +85 -0
  102. package/dist/components/Row.d.ts +16 -0
  103. package/dist/components/Row.js +27 -0
  104. package/dist/components/Screen.d.ts +13 -0
  105. package/dist/components/Screen.js +56 -0
  106. package/dist/components/Scrim.d.ts +8 -0
  107. package/dist/components/Scrim.js +40 -0
  108. package/dist/components/ScrollArea.d.ts +15 -0
  109. package/dist/components/ScrollArea.js +13 -0
  110. package/dist/components/SegmentedControl.d.ts +17 -0
  111. package/dist/components/SegmentedControl.js +68 -0
  112. package/dist/components/Select.d.ts +17 -0
  113. package/dist/components/Select.js +107 -0
  114. package/dist/components/SettingsRow.d.ts +8 -0
  115. package/dist/components/SettingsRow.js +32 -0
  116. package/dist/components/Sidebar.d.ts +20 -0
  117. package/dist/components/Sidebar.js +137 -0
  118. package/dist/components/SignInScreen.d.ts +1 -0
  119. package/dist/components/SignInScreen.js +40 -0
  120. package/dist/components/Size.d.ts +1 -0
  121. package/dist/components/Size.js +1 -0
  122. package/dist/components/Skeleton.d.ts +8 -0
  123. package/dist/components/Skeleton.js +48 -0
  124. package/dist/components/Spinner.d.ts +6 -0
  125. package/dist/components/Spinner.js +54 -0
  126. package/dist/components/Stack.d.ts +14 -0
  127. package/dist/components/Stack.js +19 -0
  128. package/dist/components/Switch.d.ts +10 -0
  129. package/dist/components/Switch.js +72 -0
  130. package/dist/components/Text.d.ts +21 -0
  131. package/dist/components/Text.js +77 -0
  132. package/dist/components/TextField.d.ts +25 -0
  133. package/dist/components/TextField.js +68 -0
  134. package/dist/components/Toaster.d.ts +1 -0
  135. package/dist/components/Toaster.js +83 -0
  136. package/dist/components/Tooltip.d.ts +8 -0
  137. package/dist/components/Tooltip.js +43 -0
  138. package/dist/components/controlLook.d.ts +70 -0
  139. package/dist/components/controlLook.js +80 -0
  140. package/dist/components/frame.d.ts +4 -0
  141. package/dist/components/frame.js +2 -0
  142. package/dist/components/icons.d.ts +59 -0
  143. package/dist/components/icons.js +111 -0
  144. package/dist/components/interaction.d.ts +12 -0
  145. package/dist/components/interaction.js +22 -0
  146. package/dist/components/spacing.d.ts +118 -0
  147. package/dist/components/spacing.js +46 -0
  148. package/dist/components/tones.d.ts +28 -0
  149. package/dist/components/tones.js +12 -0
  150. package/dist/entityStore.d.ts +46 -0
  151. package/dist/entityStore.js +160 -0
  152. package/dist/flows/accessFlows.d.ts +9 -0
  153. package/dist/flows/accessFlows.js +167 -0
  154. package/dist/flows/browser.d.ts +34 -0
  155. package/dist/flows/browser.js +167 -0
  156. package/dist/flows/contactSheet.d.ts +1 -0
  157. package/dist/flows/contactSheet.js +63 -0
  158. package/dist/flows/flowBrowser.d.ts +25 -0
  159. package/dist/flows/flowBrowser.js +23 -0
  160. package/dist/flows/flowSetup.d.ts +3 -0
  161. package/dist/flows/flowSetup.js +35 -0
  162. package/dist/flows/flows.d.ts +47 -0
  163. package/dist/flows/flows.js +175 -0
  164. package/dist/flows/screenshotName.d.ts +1 -0
  165. package/dist/flows/screenshotName.js +6 -0
  166. package/dist/gate.d.ts +8 -0
  167. package/dist/gate.js +52 -0
  168. package/dist/hooks/appContext.d.ts +15 -0
  169. package/dist/hooks/appContext.js +5 -0
  170. package/dist/hooks/appHooks.d.ts +21 -0
  171. package/dist/hooks/appHooks.js +24 -0
  172. package/dist/hooks/useAnimatesOnChange.d.ts +1 -0
  173. package/dist/hooks/useAnimatesOnChange.js +14 -0
  174. package/dist/hooks/useStoreState.d.ts +6 -0
  175. package/dist/hooks/useStoreState.js +5 -0
  176. package/dist/index.d.ts +44 -0
  177. package/dist/index.js +21 -0
  178. package/dist/memoryApi.d.ts +19 -0
  179. package/dist/memoryApi.js +42 -0
  180. package/dist/model.d.ts +94 -0
  181. package/dist/model.js +243 -0
  182. package/dist/page.d.ts +11 -0
  183. package/dist/page.js +9 -0
  184. package/dist/platform.d.ts +1 -0
  185. package/dist/platform.js +5 -0
  186. package/dist/publishWire.d.ts +271 -0
  187. package/dist/publishWire.js +168 -0
  188. package/dist/react.d.ts +49 -0
  189. package/dist/react.js +40 -0
  190. package/dist/registered.d.ts +60 -0
  191. package/dist/registered.js +19 -0
  192. package/dist/routes.d.ts +38 -0
  193. package/dist/routes.js +21 -0
  194. package/dist/rules/checkAllFiles.d.ts +1 -0
  195. package/dist/rules/checkAllFiles.js +749 -0
  196. package/dist/rules/checkApiRouting.d.ts +1 -0
  197. package/dist/rules/checkApiRouting.js +112 -0
  198. package/dist/rules/lintPlugin.d.ts +252 -0
  199. package/dist/rules/lintPlugin.js +1159 -0
  200. package/dist/rules/messages.d.ts +48 -0
  201. package/dist/rules/messages.js +48 -0
  202. package/dist/rules/themeTokens.d.ts +6 -0
  203. package/dist/rules/themeTokens.js +64 -0
  204. package/dist/schema.d.ts +4 -0
  205. package/dist/schema.js +2 -0
  206. package/dist/server/auth.d.ts +115 -0
  207. package/dist/server/auth.js +134 -0
  208. package/dist/server/authService.d.ts +9 -0
  209. package/dist/server/authService.js +50 -0
  210. package/dist/server/createServer.d.ts +402 -0
  211. package/dist/server/createServer.js +82 -0
  212. package/dist/server/env.d.ts +15 -0
  213. package/dist/server/env.js +1 -0
  214. package/dist/server/index.d.ts +13 -0
  215. package/dist/server/index.js +9 -0
  216. package/dist/server/services.d.ts +9 -0
  217. package/dist/server/services.js +47 -0
  218. package/dist/server/session.d.ts +29 -0
  219. package/dist/server/session.js +65 -0
  220. package/dist/server/sessions.d.ts +92 -0
  221. package/dist/server/sessions.js +47 -0
  222. package/dist/server/settings.d.ts +49 -0
  223. package/dist/server/settings.js +25 -0
  224. package/dist/server/signInWire.d.ts +53 -0
  225. package/dist/server/signInWire.js +23 -0
  226. package/dist/server/tables.d.ts +242 -0
  227. package/dist/server/tables.js +246 -0
  228. package/dist/server/users.d.ts +189 -0
  229. package/dist/server/users.js +49 -0
  230. package/dist/serviceClients.d.ts +5 -0
  231. package/dist/serviceClients.js +70 -0
  232. package/dist/services.d.ts +53 -0
  233. package/dist/services.js +30 -0
  234. package/dist/shortcuts.d.ts +3 -0
  235. package/dist/shortcuts.js +40 -0
  236. package/dist/start.d.ts +20 -0
  237. package/dist/start.js +145 -0
  238. package/dist/state.d.ts +14 -0
  239. package/dist/state.js +17 -0
  240. package/dist/store.d.ts +45 -0
  241. package/dist/store.js +208 -0
  242. package/dist/subscribers.d.ts +5 -0
  243. package/dist/subscribers.js +13 -0
  244. package/dist/table.d.ts +143 -0
  245. package/dist/table.js +91 -0
  246. package/dist/tables.d.ts +77 -0
  247. package/dist/tables.js +216 -0
  248. package/dist/theme/reset.css +84 -0
  249. package/dist/theme/scales.d.ts +76 -0
  250. package/dist/theme/scales.js +82 -0
  251. package/dist/theme/tokens.stylex.d.ts +218 -0
  252. package/dist/theme/tokens.stylex.js +233 -0
  253. package/dist/vite/commandBridge.d.ts +2 -0
  254. package/dist/vite/commandBridge.js +46 -0
  255. package/dist/vite/designManifest.d.ts +25 -0
  256. package/dist/vite/designManifest.js +191 -0
  257. package/dist/vite/localWorker.d.ts +4 -0
  258. package/dist/vite/localWorker.js +60 -0
  259. package/dist/vite/projectFile.d.ts +9 -0
  260. package/dist/vite/projectFile.js +17 -0
  261. package/dist/vite/rootAlias.d.ts +2 -0
  262. package/dist/vite/rootAlias.js +15 -0
  263. package/dist/vite/vite.d.ts +8 -0
  264. package/dist/vite/vite.js +95 -0
  265. package/dist/wire.d.ts +7 -0
  266. package/dist/wire.js +1 -0
  267. package/package.json +103 -3
  268. package/presets/lintPlugin.js +7 -0
  269. package/presets/oxlint.json +167 -0
  270. package/presets/register.d.ts +21 -0
  271. package/presets/server.d.ts +2 -0
  272. package/presets/tsconfig.app.json +29 -0
  273. package/presets/tsconfig.server.json +27 -0
@@ -0,0 +1,191 @@
1
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
2
+ import { basename, extname, join, relative } from 'node:path';
3
+ import ts from 'typescript';
4
+ import { builtInIconNames } from "../components/icons.js";
5
+ import { themeTokens } from "../rules/themeTokens.js";
6
+ const PRIMITIVES_MODULE = '@trypattern/sdk/react';
7
+ const TOKENS_MODULE = '@trypattern/sdk/tokens.stylex';
8
+ const LOOK_PROPS = new Set([
9
+ 'variant',
10
+ 'tone',
11
+ 'size',
12
+ 'surface',
13
+ 'padding',
14
+ 'paddingBlock',
15
+ 'paddingInline',
16
+ 'gap',
17
+ 'align',
18
+ 'justify',
19
+ 'width',
20
+ 'as',
21
+ 'name',
22
+ 'icon',
23
+ 'trailingIcon',
24
+ 'placement'
25
+ ]);
26
+ const DYNAMIC = 'dynamic';
27
+ const SDK_PACKAGE = new URL('../../package.json', import.meta.url);
28
+ function sourceFiles(folder) {
29
+ if (!existsSync(folder))
30
+ return [];
31
+ return readdirSync(folder, { withFileTypes: true }).flatMap((entry) => {
32
+ const path = join(folder, entry.name);
33
+ if (entry.isDirectory())
34
+ return sourceFiles(path);
35
+ return /\.tsx?$/.test(entry.name) ? [path] : [];
36
+ });
37
+ }
38
+ function parse(path) {
39
+ return ts.createSourceFile(path, readFileSync(path, 'utf8'), ts.ScriptTarget.Latest, true, path.endsWith('.tsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TS);
40
+ }
41
+ function importsFrom(source, module) {
42
+ const names = new Map();
43
+ for (const statement of source.statements) {
44
+ if (!ts.isImportDeclaration(statement) ||
45
+ !ts.isStringLiteral(statement.moduleSpecifier) ||
46
+ statement.moduleSpecifier.text !== module) {
47
+ continue;
48
+ }
49
+ const bindings = statement.importClause?.namedBindings;
50
+ if (bindings === undefined || !ts.isNamedImports(bindings))
51
+ continue;
52
+ for (const element of bindings.elements) {
53
+ names.set(element.name.text, element.propertyName?.text ?? element.name.text);
54
+ }
55
+ }
56
+ return names;
57
+ }
58
+ function literalValues(expression) {
59
+ if (ts.isStringLiteralLike(expression))
60
+ return [expression.text];
61
+ if (ts.isParenthesizedExpression(expression)) {
62
+ return literalValues(expression.expression);
63
+ }
64
+ if (ts.isConditionalExpression(expression)) {
65
+ return [
66
+ ...literalValues(expression.whenTrue),
67
+ ...literalValues(expression.whenFalse)
68
+ ];
69
+ }
70
+ return [DYNAMIC];
71
+ }
72
+ function attributeValues(attribute) {
73
+ const initializer = attribute.initializer;
74
+ if (initializer === undefined)
75
+ return ['true'];
76
+ if (ts.isStringLiteral(initializer))
77
+ return [initializer.text];
78
+ if (ts.isJsxExpression(initializer) && initializer.expression !== undefined) {
79
+ return literalValues(initializer.expression);
80
+ }
81
+ return [DYNAMIC];
82
+ }
83
+ function countPrimitives(source, primitives) {
84
+ const imported = importsFrom(source, PRIMITIVES_MODULE);
85
+ const visit = (node) => {
86
+ const element = ts.isJsxSelfClosingElement(node) || ts.isJsxOpeningElement(node)
87
+ ? node
88
+ : undefined;
89
+ const name = element !== undefined && ts.isIdentifier(element.tagName)
90
+ ? imported.get(element.tagName.text)
91
+ : undefined;
92
+ if (element !== undefined && name !== undefined) {
93
+ const use = (primitives[name] ??= { uses: 0, props: {} });
94
+ use.uses += 1;
95
+ for (const attribute of element.attributes.properties) {
96
+ if (!ts.isJsxAttribute(attribute))
97
+ continue;
98
+ const prop = attribute.name.getText(source);
99
+ if (!LOOK_PROPS.has(prop))
100
+ continue;
101
+ if (prop === 'name' && name !== 'Icon')
102
+ continue;
103
+ const counts = (use.props[prop] ??= {});
104
+ for (const value of new Set(attributeValues(attribute))) {
105
+ counts[value] = (counts[value] ?? 0) + 1;
106
+ }
107
+ }
108
+ }
109
+ ts.forEachChild(node, visit);
110
+ };
111
+ visit(source);
112
+ }
113
+ function customPiece(root, path, source) {
114
+ const tokenGroups = new Set(importsFrom(source, TOKENS_MODULE).keys());
115
+ const tokens = new Set();
116
+ let draws = false;
117
+ const visit = (node) => {
118
+ if (ts.isCallExpression(node) &&
119
+ node.expression.getText(source) === 'stylex.create') {
120
+ draws = true;
121
+ }
122
+ if (ts.isPropertyAccessExpression(node) &&
123
+ ts.isIdentifier(node.expression) &&
124
+ tokenGroups.has(node.expression.text)) {
125
+ tokens.add(`${node.expression.text}.${node.name.text}`);
126
+ }
127
+ ts.forEachChild(node, visit);
128
+ };
129
+ visit(source);
130
+ return draws
131
+ ? [
132
+ {
133
+ name: basename(path, extname(path)),
134
+ file: relative(root, path),
135
+ tokens: [...tokens].toSorted()
136
+ }
137
+ ]
138
+ : [];
139
+ }
140
+ function appIcons(root) {
141
+ const path = join(root, 'src', 'theme', 'icons.ts');
142
+ if (!existsSync(path))
143
+ return [];
144
+ const names = [];
145
+ const visit = (node) => {
146
+ if (ts.isCallExpression(node) &&
147
+ node.expression.getText() === 'defineIcons' &&
148
+ node.arguments[0] !== undefined &&
149
+ ts.isObjectLiteralExpression(node.arguments[0])) {
150
+ for (const property of node.arguments[0].properties) {
151
+ if (property.name !== undefined)
152
+ names.push(property.name.getText());
153
+ }
154
+ }
155
+ ts.forEachChild(node, visit);
156
+ };
157
+ visit(parse(path));
158
+ return names;
159
+ }
160
+ function tokensOf(root) {
161
+ const tokens = {};
162
+ for (const [name, { value, offset }] of themeTokens(root)) {
163
+ const [group = '', key = ''] = name.split('.');
164
+ tokens[group] = {
165
+ ...tokens[group],
166
+ [key]: { value, isOverridden: offset !== undefined }
167
+ };
168
+ }
169
+ return tokens;
170
+ }
171
+ export function designManifest(root) {
172
+ const primitives = {};
173
+ const customPieces = [];
174
+ for (const path of sourceFiles(join(root, 'src'))) {
175
+ const source = parse(path);
176
+ countPrimitives(source, primitives);
177
+ if (path.startsWith(join(root, 'src', 'components'))) {
178
+ customPieces.push(...customPiece(root, path, source));
179
+ }
180
+ }
181
+ const sdk = JSON.parse(readFileSync(SDK_PACKAGE, 'utf8'));
182
+ return {
183
+ sdk: typeof sdk === 'object' && sdk !== null && 'version' in sdk
184
+ ? String(sdk.version)
185
+ : 'unknown',
186
+ tokens: tokensOf(root),
187
+ primitives: Object.fromEntries(Object.entries(primitives).toSorted(([a], [b]) => a.localeCompare(b))),
188
+ customPieces,
189
+ icons: { builtIn: builtInIconNames, app: appIcons(root) }
190
+ };
191
+ }
@@ -0,0 +1,4 @@
1
+ import type { Plugin } from 'vite';
2
+ import type { Seed, Tables } from '../table.ts';
3
+ export declare function resetLocalDatabase(root: string, tables: Tables, seed: Seed<Tables>): void;
4
+ export declare function localWorker<Group extends Tables>(tables: Group, seed: Seed<Group>, title: string): Plugin;
@@ -0,0 +1,60 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import { randomBytes } from 'node:crypto';
3
+ import { appendFileSync, existsSync, readFileSync } from 'node:fs';
4
+ import { join } from 'node:path';
5
+ import { seedTitleSql } from "../server/settings.js";
6
+ import { seedSql } from "../server/tables.js";
7
+ import { snakeCase } from "../table.js";
8
+ import { toolBin } from "../cli/tools.js";
9
+ function ensureLocalSessionSecret(root) {
10
+ const DEV_VARS = join(root, '.dev.vars');
11
+ const current = existsSync(DEV_VARS) ? readFileSync(DEV_VARS, 'utf8') : '';
12
+ if (/^SESSION_SECRET=/m.test(current))
13
+ return;
14
+ const separator = current === '' || current.endsWith('\n') ? '' : '\n';
15
+ appendFileSync(DEV_VARS, `${separator}SESSION_SECRET=${randomBytes(32).toString('hex')}\n`);
16
+ }
17
+ function wrangler(root, args) {
18
+ execFileSync(process.execPath, [toolBin('wrangler'), ...args], {
19
+ cwd: root,
20
+ stdio: 'pipe',
21
+ env: { ...process.env, CI: '1' }
22
+ });
23
+ }
24
+ export function resetLocalDatabase(root, tables, seed) {
25
+ wrangler(root, ['d1', 'migrations', 'apply', 'DB', '--local']);
26
+ wrangler(root, [
27
+ 'd1',
28
+ 'execute',
29
+ 'DB',
30
+ '--local',
31
+ '--command',
32
+ [
33
+ ...Object.values(tables).map((table) => `DELETE FROM ${snakeCase(table.name)};`),
34
+ seedSql(tables, seed)
35
+ ].join('\n')
36
+ ]);
37
+ }
38
+ function prepareLocalDatabase(root, tables, seed, title) {
39
+ wrangler(root, ['d1', 'migrations', 'apply', 'DB', '--local']);
40
+ wrangler(root, [
41
+ 'd1',
42
+ 'execute',
43
+ 'DB',
44
+ '--local',
45
+ '--command',
46
+ [seedTitleSql(title), seedSql(tables, seed)].join('\n')
47
+ ]);
48
+ }
49
+ export function localWorker(tables, seed, title) {
50
+ return {
51
+ name: 'pattern-local-worker',
52
+ config(config, { command }) {
53
+ if (command !== 'serve')
54
+ return;
55
+ const root = config.root ?? process.cwd();
56
+ ensureLocalSessionSecret(root);
57
+ prepareLocalDatabase(root, tables, seed, title);
58
+ }
59
+ };
60
+ }
@@ -0,0 +1,9 @@
1
+ import { z } from 'zod';
2
+ export declare const PROJECT_FILE = "pattern.json";
3
+ declare const projectFile: z.ZodObject<{
4
+ name: z.ZodString;
5
+ title: z.ZodString;
6
+ }, z.core.$strip>;
7
+ export type ProjectFile = z.output<typeof projectFile>;
8
+ export declare function readProjectFile(root: string): ProjectFile;
9
+ export {};
@@ -0,0 +1,17 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { z } from 'zod';
4
+ import { appTitle } from "../appTitle.js";
5
+ export const PROJECT_FILE = 'pattern.json';
6
+ const projectFile = z.object({ name: z.string().min(1), title: appTitle });
7
+ export function readProjectFile(root) {
8
+ const path = join(root, PROJECT_FILE);
9
+ if (!existsSync(path)) {
10
+ throw new Error(`${PROJECT_FILE} is missing. It holds the app's address and title: { "name": "acme", "title": "Acme" }`);
11
+ }
12
+ const parsed = projectFile.safeParse(JSON.parse(readFileSync(path, 'utf8')));
13
+ if (!parsed.success) {
14
+ throw new Error(`${PROJECT_FILE} needs "name" (the address) and "title" (1 to 60 characters): ${z.prettifyError(parsed.error)}`);
15
+ }
16
+ return parsed.data;
17
+ }
@@ -0,0 +1,2 @@
1
+ import type { Plugin } from 'vite';
2
+ export declare function rootAlias(): Plugin;
@@ -0,0 +1,15 @@
1
+ import { resolve } from 'node:path';
2
+ export function rootAlias() {
3
+ return {
4
+ name: 'pattern-root-alias',
5
+ config(config) {
6
+ const root = resolve(config.root ?? process.cwd());
7
+ return {
8
+ resolve: {
9
+ alias: [{ find: /^@\//, replacement: `${root}/` }],
10
+ dedupe: ['react', 'react-dom', 'react-router', 'zod']
11
+ }
12
+ };
13
+ }
14
+ };
15
+ }
@@ -0,0 +1,8 @@
1
+ import type { Seed, Tables } from '../table.ts';
2
+ export type PatternOptions<Group extends Tables> = {
3
+ tables: Group;
4
+ admins: readonly string[];
5
+ seed?: Seed<Group>;
6
+ world?: object;
7
+ };
8
+ export declare function pattern<Group extends Tables>({ tables, admins, seed, world }: PatternOptions<Group>): import("vite").UserConfig;
@@ -0,0 +1,95 @@
1
+ import { mkdirSync, writeFileSync } from 'node:fs';
2
+ import { extname, join } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { cloudflare } from '@cloudflare/vite-plugin';
5
+ import stylex from '@stylexjs/unplugin';
6
+ import react from '@vitejs/plugin-react';
7
+ import { defineConfig } from 'vitest/config';
8
+ import { commandBridge } from "./commandBridge.js";
9
+ import { designManifest } from "./designManifest.js";
10
+ import { localWorker } from "./localWorker.js";
11
+ import { readProjectFile } from "./projectFile.js";
12
+ import { rootAlias } from "./rootAlias.js";
13
+ const DEV_SERVER_PORT = 5173;
14
+ const VISUAL_FLOW_TIMEOUT_MS = 30_000;
15
+ const CSS_LAYERS_BEFORE_STYLEX = ['reset'];
16
+ const browsersWithNativeLightDark = {
17
+ chrome: 123 << 16,
18
+ firefox: 120 << 16,
19
+ safari: (17 << 16) | (5 << 8)
20
+ };
21
+ const minifyStylexCssAppendedAfterViteMinifies = {
22
+ minify: true,
23
+ targets: browsersWithNativeLightDark
24
+ };
25
+ const reactCompilerSkippingUnchangedRendersAndLoggingWhereItCannot = {
26
+ compiler: { logDiagnostics: true }
27
+ };
28
+ const FLOW_SETUP = fileURLToPath(new URL(`../flows/flowSetup${extname(import.meta.filename)}`, import.meta.url));
29
+ export function pattern({ tables, admins, seed = {}, world = {} }) {
30
+ const isVitest = process.env['VITEST'] !== undefined;
31
+ const { title } = readProjectFile(process.cwd());
32
+ const isVisualFlowRun = process.env['PATTERN_VISUAL_URL'] !== undefined;
33
+ const stylexPlugin = stylex.vite({
34
+ useCSSLayers: { before: CSS_LAYERS_BEFORE_STYLEX },
35
+ aliases: { '@/*': [join(process.cwd(), '*')] },
36
+ sxPropName: false,
37
+ lightningcssOptions: minifyStylexCssAppendedAfterViteMinifies
38
+ });
39
+ const stylexWithoutDevCssPollerThatKeepsVitestFromExiting = {
40
+ ...stylexPlugin,
41
+ configureServer: undefined
42
+ };
43
+ const stylexBeforeReactToKeepFastRefresh = [
44
+ isVitest
45
+ ? stylexWithoutDevCssPollerThatKeepsVitestFromExiting
46
+ : stylexPlugin,
47
+ react(reactCompilerSkippingUnchangedRendersAndLoggingWhereItCannot)
48
+ ];
49
+ const workerServingApiInDevAndBuild = isVitest
50
+ ? []
51
+ : [localWorker(tables, seed, title), cloudflare()];
52
+ return defineConfig({
53
+ plugins: [
54
+ ...stylexBeforeReactToKeepFastRefresh,
55
+ ...workerServingApiInDevAndBuild,
56
+ commandBridge(),
57
+ rootAlias(),
58
+ designFile()
59
+ ],
60
+ clearScreen: false,
61
+ optimizeDeps: { exclude: ['@trypattern/sdk'] },
62
+ build: {
63
+ cssTarget: ['chrome123', 'firefox120', 'safari17.5']
64
+ },
65
+ server: {
66
+ port: DEV_SERVER_PORT,
67
+ strictPort: true
68
+ },
69
+ test: {
70
+ include: ['flows/**/*.flow.ts'],
71
+ server: { deps: { inline: ['@trypattern/sdk'] } },
72
+ provide: {
73
+ patternSeed: seed,
74
+ patternAdmins: admins,
75
+ patternTitle: title,
76
+ patternWorld: world
77
+ },
78
+ ...(isVisualFlowRun && {
79
+ globalSetup: [FLOW_SETUP],
80
+ testTimeout: VISUAL_FLOW_TIMEOUT_MS
81
+ })
82
+ }
83
+ });
84
+ }
85
+ function designFile() {
86
+ return {
87
+ name: 'pattern:design',
88
+ apply: 'build',
89
+ closeBundle() {
90
+ const root = process.cwd();
91
+ mkdirSync(join(root, 'dist'), { recursive: true });
92
+ writeFileSync(join(root, 'dist', 'design.json'), `${JSON.stringify(designManifest(root), null, 2)}\n`);
93
+ }
94
+ };
95
+ }
package/dist/wire.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import type { z } from 'zod';
2
+ type StaticTypeError<Message extends string> = Message;
3
+ type NotSameOnTheWire = StaticTypeError<'Command inputs and table columns must be the same on the wire and in code: no .transform(), .default() or .pipe()'>;
4
+ export type SameOnTheWire<S extends z.ZodRawShape> = {
5
+ [Key in keyof S]: [z.input<S[Key]>] extends [z.output<S[Key]>] ? [z.output<S[Key]>] extends [z.input<S[Key]>] ? S[Key] : NotSameOnTheWire : NotSameOnTheWire;
6
+ };
7
+ export {};
package/dist/wire.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,106 @@
1
1
  {
2
2
  "name": "@trypattern/sdk",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.1",
4
+ "type": "module",
5
+ "files": [
6
+ "dist",
7
+ "presets"
8
+ ],
9
+ "bin": {
10
+ "app": "./dist/cli/app.js"
11
+ },
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "default": "./dist/index.js"
16
+ },
17
+ "./react": {
18
+ "types": "./dist/react.d.ts",
19
+ "default": "./dist/react.js"
20
+ },
21
+ "./schema": {
22
+ "types": "./dist/schema.d.ts",
23
+ "default": "./dist/schema.js"
24
+ },
25
+ "./server": {
26
+ "types": "./dist/server/index.d.ts",
27
+ "default": "./dist/server/index.js"
28
+ },
29
+ "./publish": {
30
+ "types": "./dist/publishWire.d.ts",
31
+ "default": "./dist/publishWire.js"
32
+ },
33
+ "./flows": {
34
+ "types": "./dist/flows/flows.d.ts",
35
+ "default": "./dist/flows/flows.js"
36
+ },
37
+ "./vite": {
38
+ "types": "./dist/vite/vite.d.ts",
39
+ "default": "./dist/vite/vite.js"
40
+ },
41
+ "./lint": {
42
+ "types": "./dist/rules/lintPlugin.d.ts",
43
+ "default": "./dist/rules/lintPlugin.js"
44
+ },
45
+ "./tsconfig/app.json": "./presets/tsconfig.app.json",
46
+ "./tsconfig/server.json": "./presets/tsconfig.server.json",
47
+ "./tokens.stylex": {
48
+ "types": "./dist/theme/tokens.stylex.d.ts",
49
+ "default": "./dist/theme/tokens.stylex.js"
50
+ }
51
+ },
52
+ "publishConfig": {
53
+ "access": "public"
54
+ },
55
+ "dependencies": {
56
+ "@cloudflare/vite-plugin": "1.64.0",
57
+ "@cloudflare/workers-types": "5.20261015.1",
58
+ "@stylexjs/eslint-plugin": "0.19.1",
59
+ "@stylexjs/unplugin": "0.19.1",
60
+ "@types/node": "^24.19.2",
61
+ "@vitejs/plugin-react": "^6.1.2",
62
+ "drizzle-kit": "0.31.11",
63
+ "drizzle-orm": "0.45.4",
64
+ "hono": "4.13.13",
65
+ "oxc-transform-react": "0.152.0",
66
+ "oxlint": "^1.88.0",
67
+ "playwright-core": "1.63.0",
68
+ "prettier": "3.9.10",
69
+ "typescript": "~6.0.3",
70
+ "unplugin": "2.3.11",
71
+ "vite": "^8.3.4",
72
+ "vitest": "5.0.3",
73
+ "wrangler": "4.151.0",
74
+ "@base-ui/react": "1.8.0"
75
+ },
76
+ "peerDependencies": {
77
+ "react": "^19.3.0",
78
+ "react-router": "8.4.0",
79
+ "zod": "4.6.7",
80
+ "@stylexjs/stylex": "0.19.1",
81
+ "react-dom": "^19.3.0"
82
+ },
83
+ "devDependencies": {
84
+ "@types/react": "^19.3.0",
85
+ "react": "^19.3.0",
86
+ "react-router": "8.4.0",
87
+ "zod": "4.6.7",
88
+ "@stylexjs/stylex": "0.19.1",
89
+ "react-dom": "^19.3.0",
90
+ "@types/react-dom": "^19.3.0"
91
+ },
92
+ "prettier": {
93
+ "semi": false,
94
+ "singleQuote": true,
95
+ "trailingComma": "none"
96
+ },
97
+ "scripts": {
98
+ "check": "tsc -p . && oxlint -c oxlint.sdk.json src/components src/hooks src/theme && node tests/check-types.ts && vitest run --root tests/server && prettier --check src tests presets *.json",
99
+ "typecheck": "tsc -p .",
100
+ "test:types": "node tests/check-types.ts",
101
+ "test:server": "vitest run --root tests/server",
102
+ "format": "prettier --write src tests presets *.json",
103
+ "lint": "oxlint -c oxlint.sdk.json src/components src/hooks src/theme",
104
+ "build": "rm -rf dist && tsc -p tsconfig.build.json && cp src/theme/reset.css dist/theme/reset.css"
105
+ }
6
106
  }
@@ -0,0 +1,7 @@
1
+ import { existsSync } from 'node:fs'
2
+
3
+ const source = new URL('../src/rules/lintPlugin.ts', import.meta.url)
4
+ const built = new URL('../dist/rules/lintPlugin.js', import.meta.url)
5
+ const plugin = await import(existsSync(source) ? source.href : built.href)
6
+
7
+ export default plugin.default