@codeyam/codeyam-cli 0.1.22 → 0.1.24
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.
- package/analyzer-template/.build-info.json +7 -7
- package/analyzer-template/log.txt +3 -3
- package/analyzer-template/packages/ai/src/lib/astScopes/methodSemantics.ts +135 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/nodeToSource.ts +19 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/paths.ts +11 -4
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateDataStructure.ts +5 -1
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +1632 -1554
- package/analyzer-template/packages/database/src/lib/loadAnalysis.ts +7 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js +7 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js.map +1 -1
- package/analyzer-template/project/runMultiScenarioServer.ts +26 -3
- package/background/src/lib/virtualized/project/runMultiScenarioServer.js +23 -3
- package/background/src/lib/virtualized/project/runMultiScenarioServer.js.map +1 -1
- package/codeyam-cli/src/commands/__tests__/editor.analyzeImportsArgs.test.js +47 -0
- package/codeyam-cli/src/commands/__tests__/editor.analyzeImportsArgs.test.js.map +1 -0
- package/codeyam-cli/src/commands/__tests__/editor.auditNoAutoAnalysis.test.js +17 -9
- package/codeyam-cli/src/commands/__tests__/editor.auditNoAutoAnalysis.test.js.map +1 -1
- package/codeyam-cli/src/commands/__tests__/editor.designSystem.test.js +30 -0
- package/codeyam-cli/src/commands/__tests__/editor.designSystem.test.js.map +1 -0
- package/codeyam-cli/src/commands/editor.js +207 -41
- package/codeyam-cli/src/commands/editor.js.map +1 -1
- package/codeyam-cli/src/commands/editorAnalyzeImportsArgs.js +23 -0
- package/codeyam-cli/src/commands/editorAnalyzeImportsArgs.js.map +1 -0
- package/codeyam-cli/src/data/designSystems.js +27 -0
- package/codeyam-cli/src/data/designSystems.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/editorApi.test.js +44 -0
- package/codeyam-cli/src/utils/__tests__/editorApi.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorAudit.test.js +103 -1
- package/codeyam-cli/src/utils/__tests__/editorAudit.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js +140 -1
- package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorSeedAdapter.test.js +50 -1
- package/codeyam-cli/src/utils/__tests__/editorSeedAdapter.test.js.map +1 -1
- package/codeyam-cli/src/utils/editorApi.js +16 -0
- package/codeyam-cli/src/utils/editorApi.js.map +1 -1
- package/codeyam-cli/src/utils/editorAudit.js +38 -2
- package/codeyam-cli/src/utils/editorAudit.js.map +1 -1
- package/codeyam-cli/src/utils/editorScenarios.js +60 -0
- package/codeyam-cli/src/utils/editorScenarios.js.map +1 -1
- package/codeyam-cli/src/utils/editorSeedAdapter.js +42 -2
- package/codeyam-cli/src/utils/editorSeedAdapter.js.map +1 -1
- package/codeyam-cli/src/utils/queue/__tests__/job.interactiveStart.test.js +159 -0
- package/codeyam-cli/src/utils/queue/__tests__/job.interactiveStart.test.js.map +1 -0
- package/codeyam-cli/src/utils/queue/job.js +9 -1
- package/codeyam-cli/src/utils/queue/job.js.map +1 -1
- package/codeyam-cli/src/webserver/__tests__/api.interactive-switch-scenario.test.js +98 -0
- package/codeyam-cli/src/webserver/__tests__/api.interactive-switch-scenario.test.js.map +1 -0
- package/codeyam-cli/src/webserver/__tests__/editorProxy.test.js +30 -11
- package/codeyam-cli/src/webserver/__tests__/editorProxy.test.js.map +1 -1
- package/codeyam-cli/src/webserver/app/routes/api.interactive-switch-scenario.js +34 -0
- package/codeyam-cli/src/webserver/app/routes/api.interactive-switch-scenario.js.map +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-CKeQT5Ty.js → InteractivePreview-DtYTSPL2.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-DUMfcNVK.js → ScenarioViewer-CefgqbCr.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/Spinner-Bc8BG-Lw.js +34 -0
- package/codeyam-cli/src/webserver/build/client/assets/{_index-BAWd-Xjf.js → _index-C1YkzTAV.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{activity.(_tab)-BOARiB-g.js → activity.(_tab)-yH46LLUz.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/api.editor-verify-routes-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.interactive-switch-scenario-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{dev.empty-C8y4mmyv.js → dev.empty-CRepiabR.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{editor.entity.(_sha)-aIHKLB-m.js → editor.entity.(_sha)-oBrbke_R.js} +19 -19
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-ByHz6rAQ.js → entity._sha._-DYJRGiDI.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.dev-CmLO432x.js → entity._sha.scenarios._scenarioId.dev-wdiwx5-Z.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.fullscreen-Bz9sCUF_.js → entity._sha.scenarios._scenarioId.fullscreen-BrkN-40Y.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.create-scenario-DQM8E7L4.js → entity._sha_.create-scenario-DxfhekTZ.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.edit._scenarioId-CAoXLsQr.js → entity._sha_.edit._scenarioId-CRXJWmpB.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-694b698a.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{root-D2_tktnk.js → root-DXjFYOxD.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/useLastLogLine-D9QZKaLJ.js +2 -0
- package/codeyam-cli/src/webserver/build/server/assets/{analysisRunner-DjF-soOH.js → analysisRunner-zEYtiv0T.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/{index-nAvHGWbz.js → index-CcHPEbhi.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/{init-XhpIt-OT.js → init-D68IyWbU.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/{server-build-DVwiibFu.js → server-build-Cxzo0Zp2.js} +192 -148
- package/codeyam-cli/src/webserver/build/server/index.js +1 -1
- package/codeyam-cli/src/webserver/build-info.json +5 -5
- package/codeyam-cli/src/webserver/editorProxy.js +55 -3
- package/codeyam-cli/src/webserver/editorProxy.js.map +1 -1
- package/codeyam-cli/src/webserver/terminalServer.js +1 -2
- package/codeyam-cli/src/webserver/terminalServer.js.map +1 -1
- package/codeyam-cli/templates/codeyam-editor-reference.md +8 -6
- package/codeyam-cli/templates/design-systems/clean-dashboard-design-system.md +255 -0
- package/codeyam-cli/templates/design-systems/editorial-design-system.md +267 -0
- package/codeyam-cli/templates/design-systems/mono-brutalist-design-system.md +256 -0
- package/codeyam-cli/templates/design-systems/neo-brutalist-design-system.md +294 -0
- package/codeyam-cli/templates/nextjs-prisma-sqlite/seed-adapter.ts +47 -34
- package/codeyam-cli/templates/seed-adapters/supabase.ts +14 -5
- package/package.json +1 -1
- package/packages/ai/src/lib/astScopes/methodSemantics.js +99 -0
- package/packages/ai/src/lib/astScopes/methodSemantics.js.map +1 -1
- package/packages/ai/src/lib/astScopes/nodeToSource.js +16 -0
- package/packages/ai/src/lib/astScopes/nodeToSource.js.map +1 -1
- package/packages/ai/src/lib/astScopes/paths.js +12 -3
- package/packages/ai/src/lib/astScopes/paths.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js +5 -1
- package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +1330 -1270
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
- package/packages/database/src/lib/loadAnalysis.js +7 -1
- package/packages/database/src/lib/loadAnalysis.js.map +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/Spinner-D0LgAaSa.js +0 -34
- package/codeyam-cli/src/webserver/build/client/assets/manifest-bcbb3d49.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/useLastLogLine-BNd5hYuW.js +0 -2
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# Mono-Brutalist Design System
|
|
2
|
+
|
|
3
|
+
> Raw, typographic, terminal-warm UI. Monospace identity, dashed borders, single mint-green accent. For any web or mobile app.
|
|
4
|
+
|
|
5
|
+
## Philosophy
|
|
6
|
+
|
|
7
|
+
Brutalism's exposed skeleton — visible grids, raw type, no embellishment — warmed with organic off-whites, sage greens, and monospaced type. Feels like a well-worn notebook: structured but human.
|
|
8
|
+
|
|
9
|
+
**Rules:**
|
|
10
|
+
|
|
11
|
+
1. Monospace font carries the identity — labels, tags, metadata, inputs, buttons, nav all use mono
|
|
12
|
+
2. Dashed borders are the signature element — used on tags, chips, empty states, never on structural containers
|
|
13
|
+
3. Single chromatic accent (mint green) — resist adding secondary colors
|
|
14
|
+
4. Never use pure black (`#000`) or pure white (`#fff`) — everything lives between warm off-white and dark olive
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Colors
|
|
19
|
+
|
|
20
|
+
### Light Mode
|
|
21
|
+
|
|
22
|
+
```css
|
|
23
|
+
[data-theme='light'] {
|
|
24
|
+
--bg-base: #eeece6; /* warm off-white page bg */
|
|
25
|
+
--bg-surface: #fafaf7; /* cards, panels */
|
|
26
|
+
--bg-surface-raised: #ffffff; /* modals, overlays */
|
|
27
|
+
--bg-inverse: #2d3228; /* dark olive — inverted accent blocks, headers */
|
|
28
|
+
|
|
29
|
+
--text-primary: #2d3228; /* headings, primary content */
|
|
30
|
+
--text-secondary: #555550; /* body, descriptions */
|
|
31
|
+
--text-muted: #777772; /* labels, metadata */
|
|
32
|
+
--text-faint: #999994; /* placeholders, disabled */
|
|
33
|
+
|
|
34
|
+
--border: #e2dfd6; /* solid borders — cards, panels, dividers */
|
|
35
|
+
--border-dashed: #999690; /* dashed borders — tags, chips, empty states */
|
|
36
|
+
|
|
37
|
+
--shadow-sm: none; /* no shadows in this system — borders do the work */
|
|
38
|
+
--shadow-md: none;
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Dark Mode
|
|
43
|
+
|
|
44
|
+
```css
|
|
45
|
+
[data-theme='dark'] {
|
|
46
|
+
--bg-base: #1a1e18;
|
|
47
|
+
--bg-surface: #222820;
|
|
48
|
+
--bg-surface-raised: #2a3028;
|
|
49
|
+
--bg-inverse: #2d3228; /* unchanged — constant anchor */
|
|
50
|
+
|
|
51
|
+
--text-primary: #e0ddd6;
|
|
52
|
+
--text-secondary: #a8a89e;
|
|
53
|
+
--text-muted: #6a7a64;
|
|
54
|
+
--text-faint: #4a5a44;
|
|
55
|
+
|
|
56
|
+
--border: #2e3628;
|
|
57
|
+
--border-dashed: #3e4a38;
|
|
58
|
+
/* Accent unchanged. Inverse surfaces unchanged. */
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Respect `@media (prefers-color-scheme: dark)` on `:root:not([data-theme="light"])`.
|
|
63
|
+
|
|
64
|
+
### Accents
|
|
65
|
+
|
|
66
|
+
```css
|
|
67
|
+
/* Mint green — the only chromatic accent. Unchanged between modes. */
|
|
68
|
+
--accent: #b8e0a0; /* primary: on dark surfaces, active indicators */
|
|
69
|
+
--accent-soft: #c5e8b0; /* light mode soft fill; dark mode: #1e3a18 */
|
|
70
|
+
--accent-dark: #82b870; /* darker variant for emphasis */
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Semantic
|
|
74
|
+
|
|
75
|
+
```css
|
|
76
|
+
--success-bg: #dff0d4;
|
|
77
|
+
--success-text: #3a5c2a;
|
|
78
|
+
--danger-bg: #f0d4d4;
|
|
79
|
+
--danger-text: #5c2a2a;
|
|
80
|
+
/* Dark mode: --success-bg: #1e3018; --success-text: #82b870; */
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Ordered Palette
|
|
84
|
+
|
|
85
|
+
```css
|
|
86
|
+
/* Single-accent system — categorical sequence uses value/opacity variations */
|
|
87
|
+
--palette-1: #2d3228; /* ink */
|
|
88
|
+
--palette-2: #82b870; /* accent dark */
|
|
89
|
+
--palette-3: #b8e0a0; /* accent */
|
|
90
|
+
--palette-4: #555550; /* secondary */
|
|
91
|
+
--palette-5: #999690; /* muted */
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Typography
|
|
97
|
+
|
|
98
|
+
**Font stack:** `'Courier New', Courier, monospace` (identity — labels, tags, inputs, buttons, nav), `system-ui, -apple-system, sans-serif` (headings and body prose only). Optional upgrade: `'DM Mono'` for mono.
|
|
99
|
+
|
|
100
|
+
| Style | Size | Weight | Font | Notes |
|
|
101
|
+
| ----------- | ------------------------ | ------ | ---- | ------------------------------------------------------------ |
|
|
102
|
+
| Display | `clamp(28px, 5vw, 56px)` | 300 | Sans | `letter-spacing: -0.02em; line-height: 1.2` |
|
|
103
|
+
| H1 | `clamp(22px, 3vw, 36px)` | 400 | Sans | `letter-spacing: -0.02em` |
|
|
104
|
+
| H2 | 18px | 500 | Sans | Card titles |
|
|
105
|
+
| H3 | 14px | 500 | Sans | Panel titles |
|
|
106
|
+
| Body | 13px | 400 | Sans | `line-height: 1.6` |
|
|
107
|
+
| Mono L | 13px | 400 | Mono | Large mono labels |
|
|
108
|
+
| Mono M | 12px | 400 | Mono | Default — inputs, content text |
|
|
109
|
+
| Mono S | 11px | 400 | Mono | Tags, metadata, table cells. `letter-spacing: 0.03em` |
|
|
110
|
+
| Mono XS | 10px | 400 | Mono | Section labels, footers. `uppercase; letter-spacing: 0.12em` |
|
|
111
|
+
| Large Value | `clamp(28px, 4vw, 44px)` | 300 | Sans | Emphasized numbers. `letter-spacing: -0.02em` |
|
|
112
|
+
|
|
113
|
+
**Key distinctions:**
|
|
114
|
+
|
|
115
|
+
- ALL CAPS labels always use `letter-spacing: 0.10em` minimum
|
|
116
|
+
- Wrapping user-generated content in quotes (`"text like this"`) is a signature pattern
|
|
117
|
+
- Mono for everything structural/interactive; sans only for headings and prose
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Spacing & Radius
|
|
122
|
+
|
|
123
|
+
Base unit: 4px. Scale: 4, 8, 12, 16, 20, 24, 32, 40, 48px.
|
|
124
|
+
|
|
125
|
+
| Context | Value |
|
|
126
|
+
| ---------------------- | ------ |
|
|
127
|
+
| Card padding (compact) | `16px` |
|
|
128
|
+
| Card padding (default) | `24px` |
|
|
129
|
+
| Grid gap (cards) | 10px |
|
|
130
|
+
| Section gap | 32px |
|
|
131
|
+
|
|
132
|
+
```css
|
|
133
|
+
--radius-sm: 8px; /* badges */
|
|
134
|
+
--radius-md: 12px; /* inputs, small cards */
|
|
135
|
+
--radius-lg: 16px; /* cards, panels */
|
|
136
|
+
--radius-xl: 20px; /* modals */
|
|
137
|
+
--radius-pill: 100px; /* buttons, tag pills */
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Layout
|
|
143
|
+
|
|
144
|
+
### Common Patterns
|
|
145
|
+
|
|
146
|
+
- **Sidebar/Header:** Dark olive (`--bg-inverse`), same in both modes — constant anchor
|
|
147
|
+
- **Top bar:** Sticky, dark olive bg, mint accent for active nav
|
|
148
|
+
- **Bottom nav (mobile):** Dark olive bg, mint accent active indicator
|
|
149
|
+
- **Main content:** flex-1, `--bg-base`, 40px padding (desktop), 20px (mobile)
|
|
150
|
+
|
|
151
|
+
### Navigation States
|
|
152
|
+
|
|
153
|
+
- Section labels: Mono XS, uppercase, `letter-spacing: 0.12em`, `--text-muted`
|
|
154
|
+
- Nav items: Mono M, `--text-secondary`. Hover → `--bg-surface` bg. Active → mint accent text on inverse bg
|
|
155
|
+
- Dark olive header is always present — `--bg-inverse`, `z-index: 20`
|
|
156
|
+
|
|
157
|
+
### Mobile / Small Viewport
|
|
158
|
+
|
|
159
|
+
- Single column, 20px padding
|
|
160
|
+
- Cards full-width, `--radius-lg`
|
|
161
|
+
- Tag pills in horizontal scroll row (no wrap)
|
|
162
|
+
- Tap targets minimum 44px height
|
|
163
|
+
- Display type scales down via clamp
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Components
|
|
168
|
+
|
|
169
|
+
### Card
|
|
170
|
+
|
|
171
|
+
```css
|
|
172
|
+
.card {
|
|
173
|
+
background: var(--bg-surface);
|
|
174
|
+
border: 1px solid var(--border);
|
|
175
|
+
border-radius: var(--radius-lg);
|
|
176
|
+
padding: 24px;
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**Variants:** `default` (surface), `inverted` (ink bg, no border), `accent` (accent-soft bg, accent border).
|
|
181
|
+
|
|
182
|
+
**Interactive states:** hover → subtle bg shift only. No transforms, no shadows.
|
|
183
|
+
|
|
184
|
+
**Card anatomy:** Label row (ALL CAPS mono) → content → footer (timestamp + tag pill).
|
|
185
|
+
|
|
186
|
+
### Value Card
|
|
187
|
+
|
|
188
|
+
Card with: label (Mono XS, uppercase), emphasized value (Large Value style), optional trend indicator (`--success-text` for up, `--danger-text` for down, italic). Stats row: grid with thin border gaps between cards.
|
|
189
|
+
|
|
190
|
+
### Button
|
|
191
|
+
|
|
192
|
+
```css
|
|
193
|
+
.btn {
|
|
194
|
+
font-family: var(--font-mono);
|
|
195
|
+
font-size: 12px;
|
|
196
|
+
padding: 12px 22px;
|
|
197
|
+
border-radius: var(--radius-pill);
|
|
198
|
+
letter-spacing: 0.04em;
|
|
199
|
+
cursor: pointer;
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
| Variant | Background | Text | Border |
|
|
204
|
+
| --------- | -------------- | ---------------- | ----------------------------------- |
|
|
205
|
+
| Primary | `--bg-inverse` | `--accent` | none |
|
|
206
|
+
| Secondary | transparent | `--text-primary` | `1.5px dashed var(--border-dashed)` |
|
|
207
|
+
| Ghost | transparent | `--text-muted` | `1px solid var(--border)` |
|
|
208
|
+
|
|
209
|
+
Primary: always dark bg + mint text. All buttons use mono font, pill radius.
|
|
210
|
+
|
|
211
|
+
### Tag / Pill (signature element)
|
|
212
|
+
|
|
213
|
+
`font-family: mono; font-size: 11px; padding: 4px 11px; border-radius: 100px; border: 1.5px dashed var(--border-dashed); letter-spacing: 0.03em; background: transparent`. Active → solid border + inverse bg + white text. Accent variant → accent-dark border + accent-dark text.
|
|
214
|
+
|
|
215
|
+
### Badge
|
|
216
|
+
|
|
217
|
+
`font-family: mono; font-size: 10px; padding: 3px 10px; border-radius: 100px; letter-spacing: 0.04em`. Variants: trending (inverse bg + accent text), rising (success bg + success text), default (base bg + muted text).
|
|
218
|
+
|
|
219
|
+
### Input
|
|
220
|
+
|
|
221
|
+
`font-family: mono; font-size: 12px; padding: 12px 16px; border-radius: var(--radius-md); border: 1px solid var(--border); background: var(--bg-base)`. Focus: `border-color: var(--border-dashed)`. Placeholder: `--text-faint`, mono.
|
|
222
|
+
|
|
223
|
+
### Table
|
|
224
|
+
|
|
225
|
+
Header: Mono XS uppercase labels, `--text-muted`. Rows: Mono S, `--text-secondary`, `border-bottom: 1px solid var(--border)`. Hover → `--bg-base`. Numbers: `--text-primary`, weight 500.
|
|
226
|
+
|
|
227
|
+
### Empty State
|
|
228
|
+
|
|
229
|
+
Centered dashed circle (`1.5px dotted var(--accent-dark)`, 50px, `+` inside) on accent-soft background. Lowercase conversational text: `"no items here yet"`.
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## Motion
|
|
234
|
+
|
|
235
|
+
```css
|
|
236
|
+
--transition-fast: 100ms ease; /* button/tag hover */
|
|
237
|
+
--transition-base: 120ms ease; /* card hover, general */
|
|
238
|
+
--transition-slow: 200ms ease-out; /* modals, panels */
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Grounded and minimal — things slide and fade, never bounce. No spring physics, parallax, rotation, or scale-up on hover. Page load: staggered fade-up, 40ms delay per item.
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## Checklist
|
|
246
|
+
|
|
247
|
+
- [ ] Background is warm off-white (`#eeece6`) or dark olive (`#1a1e18`) — never pure black or white
|
|
248
|
+
- [ ] Monospace font on all labels, tags, inputs, buttons, and nav — sans only for headings/prose
|
|
249
|
+
- [ ] Tags/pills use dashed borders — structural containers use solid borders
|
|
250
|
+
- [ ] Only one chromatic accent (mint green) — no secondary colors
|
|
251
|
+
- [ ] Primary buttons: dark bg + mint text, always pill-shaped
|
|
252
|
+
- [ ] ALL CAPS labels have letter-spacing 0.10em+
|
|
253
|
+
- [ ] Dark olive inverse surfaces are the same in both light and dark mode
|
|
254
|
+
- [ ] No box-shadows — borders and background contrast only
|
|
255
|
+
- [ ] User content wrapped in quotes (`"..."`) where applicable
|
|
256
|
+
- [ ] Motion is grounded — fade and slide only, no bounce
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
# Neo-Brutalist Design System
|
|
2
|
+
|
|
3
|
+
> Hard-edged, warm, editorial UI. Offset shadows, bold borders, hot pink accent. For any web or mobile app.
|
|
4
|
+
|
|
5
|
+
## Philosophy
|
|
6
|
+
|
|
7
|
+
Heavy black borders and offset box shadows create a "printed" feel. Warm off-white base (never pure white or grey). Typography is heavy and confident. No gradients. No rounded corners over 18px.
|
|
8
|
+
|
|
9
|
+
**Rules:**
|
|
10
|
+
|
|
11
|
+
1. Cards always have `border: 2px solid` + offset box shadow
|
|
12
|
+
2. Interactive elements "press" on hover/active (`translate(2px, 2px)`, shadow removed)
|
|
13
|
+
3. Dark mode inverts backgrounds but keeps accent colors identical
|
|
14
|
+
4. Dark cards/sidebar stay dark in both modes
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Colors
|
|
19
|
+
|
|
20
|
+
### Light Mode
|
|
21
|
+
|
|
22
|
+
```css
|
|
23
|
+
[data-theme='light'] {
|
|
24
|
+
--bg-base: #f5f0e8; /* warm off-white page bg */
|
|
25
|
+
--bg-surface: #ffffff; /* cards, panels */
|
|
26
|
+
--bg-muted: #ede8de; /* subtle sections, table headers */
|
|
27
|
+
--bg-inverse: #0d0d0d; /* dark surfaces */
|
|
28
|
+
|
|
29
|
+
--text-primary: #0d0d0d;
|
|
30
|
+
--text-secondary: #666666;
|
|
31
|
+
--text-muted: #999999;
|
|
32
|
+
--text-inverse: #ffffff;
|
|
33
|
+
|
|
34
|
+
--border: #0d0d0d;
|
|
35
|
+
--border-light: #e5ddd0; /* internal dividers */
|
|
36
|
+
|
|
37
|
+
--shadow-sm: 2px 2px 0px #0d0d0d;
|
|
38
|
+
--shadow-md: 4px 4px 0px #0d0d0d;
|
|
39
|
+
--shadow-lg: 6px 6px 0px #0d0d0d;
|
|
40
|
+
--shadow-accent: 4px 4px 0px #ff90e8;
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Dark Mode
|
|
45
|
+
|
|
46
|
+
```css
|
|
47
|
+
[data-theme='dark'] {
|
|
48
|
+
--bg-base: #111111;
|
|
49
|
+
--bg-surface: #1a1a1a;
|
|
50
|
+
--bg-muted: #222222;
|
|
51
|
+
--text-primary: #f5f0e8;
|
|
52
|
+
--text-secondary: #aaaaaa;
|
|
53
|
+
--text-muted: #666666;
|
|
54
|
+
--text-inverse: #0d0d0d;
|
|
55
|
+
--border: #f5f0e8;
|
|
56
|
+
--border-light: #2a2a2a;
|
|
57
|
+
--shadow-sm: 2px 2px 0px #f5f0e8;
|
|
58
|
+
--shadow-md: 4px 4px 0px #f5f0e8;
|
|
59
|
+
--shadow-lg: 6px 6px 0px #f5f0e8;
|
|
60
|
+
/* Accents unchanged. Dark cards/sidebar unchanged. */
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Respect `@media (prefers-color-scheme: dark)` on `:root:not([data-theme="light"])`.
|
|
65
|
+
|
|
66
|
+
### Accents
|
|
67
|
+
|
|
68
|
+
```css
|
|
69
|
+
/* These don't change between modes */
|
|
70
|
+
--pink: #ff90e8; /* primary: CTAs, active nav, highlights */
|
|
71
|
+
--pink-light: #ffe4f8;
|
|
72
|
+
--teal: #14b8a6; /* secondary: success states, live data */
|
|
73
|
+
--teal-light: #ccfbf1;
|
|
74
|
+
--teal-dark: #0f766e;
|
|
75
|
+
--yellow: #facc15; /* tertiary: alerts, featured labels */
|
|
76
|
+
--yellow-light: #fef9c3;
|
|
77
|
+
--yellow-dark: #ca8a04;
|
|
78
|
+
--orange: #fb923c; /* quaternary: warnings */
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Semantic
|
|
82
|
+
|
|
83
|
+
```css
|
|
84
|
+
--success-bg: #d1fae5;
|
|
85
|
+
--success-text: #065f46;
|
|
86
|
+
--danger-bg: #fee2e2;
|
|
87
|
+
--danger-text: #991b1b;
|
|
88
|
+
--warning-bg: #fef9c3;
|
|
89
|
+
--warning-text: #854d0e;
|
|
90
|
+
/* Dark mode: --success-bg: #052e16; --success-text: #86efac; etc. */
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Ordered Palette
|
|
94
|
+
|
|
95
|
+
```css
|
|
96
|
+
/* For any categorical sequence: tags, categories, avatars, etc. */
|
|
97
|
+
--palette-1: #ff90e8; /* pink */
|
|
98
|
+
--palette-2: #14b8a6; /* teal */
|
|
99
|
+
--palette-3: #facc15; /* yellow */
|
|
100
|
+
--palette-4: #fb923c; /* orange */
|
|
101
|
+
--palette-5: #818cf8; /* purple */
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Typography
|
|
107
|
+
|
|
108
|
+
**Font stack:** `'DM Sans', sans-serif` (body), `'DM Serif Display', serif` (display/h1), `'DM Mono', monospace` (code)
|
|
109
|
+
|
|
110
|
+
| Style | Size | Weight | Notes |
|
|
111
|
+
| ----------- | ------------------------ | ------------------- | ----------------------------------------------------- |
|
|
112
|
+
| Display | `clamp(28px, 4vw, 48px)` | 400 (Serif Display) | `letter-spacing: -1.5px; line-height: 1.1` |
|
|
113
|
+
| H1 | `clamp(22px, 3vw, 36px)` | 900 | `letter-spacing: -1px` |
|
|
114
|
+
| H2 | 20px | 900 | `letter-spacing: -0.5px` |
|
|
115
|
+
| H3 | 15px | 700 | |
|
|
116
|
+
| Label | 11px | 700 | `uppercase; letter-spacing: 1px; color: --text-muted` |
|
|
117
|
+
| Body | 14px | 400 | `line-height: 1.6` |
|
|
118
|
+
| Body SM | 13px | 400 | `line-height: 1.5` |
|
|
119
|
+
| Large Value | `clamp(22px, 3vw, 32px)` | 900 | `letter-spacing: -1px` — for emphasized numbers |
|
|
120
|
+
|
|
121
|
+
**Common pattern — eyebrow + title:** Label above H2 in almost every section.
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Spacing & Radius
|
|
126
|
+
|
|
127
|
+
Base unit: 4px. Scale: 4, 8, 12, 16, 20, 24, 28, 32, 40, 48px.
|
|
128
|
+
|
|
129
|
+
| Context | Value |
|
|
130
|
+
| ---------------------- | ----------- |
|
|
131
|
+
| Card padding (compact) | `16px 18px` |
|
|
132
|
+
| Card padding (default) | `22px 24px` |
|
|
133
|
+
| Card padding (large) | `28px 28px` |
|
|
134
|
+
| Grid gap | 18px |
|
|
135
|
+
|
|
136
|
+
```css
|
|
137
|
+
--radius-sm: 8px;
|
|
138
|
+
--radius-md: 12px;
|
|
139
|
+
--radius-lg: 18px; /* cards — max radius in the system */
|
|
140
|
+
--radius-pill: 999px; /* badges, avatars */
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Layout
|
|
146
|
+
|
|
147
|
+
### Common Patterns
|
|
148
|
+
|
|
149
|
+
- **Sidebar:** 220px fixed left, `--bg-inverse`, always dark in both modes
|
|
150
|
+
- **Top nav:** Sticky, 64px height, `--bg-base`, bottom border
|
|
151
|
+
- **Bottom nav (mobile):** Fixed, 64px, `--pink-light` active bg. Add `env(safe-area-inset-bottom)` padding
|
|
152
|
+
- **Main content:** flex-1, `--bg-base`, padding `36px 40px`
|
|
153
|
+
|
|
154
|
+
### Navigation States
|
|
155
|
+
|
|
156
|
+
- Logo mark: 36px accent square + bold name
|
|
157
|
+
- Nav items: 14px, `10px 14px` padding, rounded 10px. Hover/active → `--pink` bg + dark text
|
|
158
|
+
- Top nav active link: inverse bg pill
|
|
159
|
+
|
|
160
|
+
### Mobile / Small Viewport
|
|
161
|
+
|
|
162
|
+
- Single column, 16px padding
|
|
163
|
+
- Cards stack vertically, buttons full-width in forms
|
|
164
|
+
- Reduce shadows to `--shadow-sm`
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Components
|
|
169
|
+
|
|
170
|
+
### Card
|
|
171
|
+
|
|
172
|
+
```css
|
|
173
|
+
.card {
|
|
174
|
+
background: var(--bg-surface);
|
|
175
|
+
border: 2px solid var(--border);
|
|
176
|
+
border-radius: var(--radius-lg);
|
|
177
|
+
padding: 22px 24px;
|
|
178
|
+
box-shadow: var(--shadow-md);
|
|
179
|
+
position: relative;
|
|
180
|
+
overflow: hidden;
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Variants:** `default` (white), `dark` (inverse bg + accent shadow), `pink`, `teal`, `yellow`, `muted` (base bg).
|
|
185
|
+
|
|
186
|
+
**Interactive states:** hover → `translateY(-3px)` + `shadow-lg`. Active → `translate(2px, 2px)` + `shadow-sm`.
|
|
187
|
+
|
|
188
|
+
### Value Card
|
|
189
|
+
|
|
190
|
+
Card with: decorative accent circle (top-right, 64px, 20% opacity), icon box (40px, accent bg, 2px border, rounded 10px), label (eyebrow), emphasized value (Large Value style), optional trend badge (pill, success/danger colors).
|
|
191
|
+
|
|
192
|
+
### Button
|
|
193
|
+
|
|
194
|
+
```css
|
|
195
|
+
.btn {
|
|
196
|
+
padding: 11px 22px;
|
|
197
|
+
border-radius: var(--radius-md);
|
|
198
|
+
font-weight: 700;
|
|
199
|
+
font-size: 14px;
|
|
200
|
+
border: 2px solid var(--border);
|
|
201
|
+
}
|
|
202
|
+
.btn:hover {
|
|
203
|
+
transform: translate(-1px, -1px);
|
|
204
|
+
}
|
|
205
|
+
.btn:active {
|
|
206
|
+
transform: translate(2px, 2px);
|
|
207
|
+
box-shadow: none;
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
| Variant | Background | Text | Border/Shadow |
|
|
212
|
+
| --------- | -------------- | ---------------- | ------------------------- |
|
|
213
|
+
| Primary | `--pink` | `--text-primary` | `--shadow-md` |
|
|
214
|
+
| Secondary | `--bg-surface` | `--text-primary` | `--shadow-sm` |
|
|
215
|
+
| Teal | `--teal` | `--text-primary` | `--shadow-md` |
|
|
216
|
+
| Yellow | `--yellow` | `--text-primary` | `--shadow-md` |
|
|
217
|
+
| Dark | `--bg-inverse` | `--text-inverse` | `--shadow-accent` |
|
|
218
|
+
| Ghost | transparent | `--text-primary` | none; hover: `--bg-muted` |
|
|
219
|
+
|
|
220
|
+
| Size | Padding | Font Size |
|
|
221
|
+
| ------------ | ----------- | --------- |
|
|
222
|
+
| SM | `7px 14px` | 12px |
|
|
223
|
+
| MD (default) | `11px 22px` | 14px |
|
|
224
|
+
| LG | `15px 30px` | 16px |
|
|
225
|
+
|
|
226
|
+
Icon-only: 40x40, no padding, `--radius-sm`.
|
|
227
|
+
|
|
228
|
+
### Badge / Pill
|
|
229
|
+
|
|
230
|
+
`padding: 3px 10px; border-radius: 999px; font-size: 11px; font-weight: 700; border: 1.5px solid currentColor`. Semantic variants: success, danger, warning, pink, teal, yellow, neutral. Solid variant: inverse bg+text.
|
|
231
|
+
|
|
232
|
+
### Input
|
|
233
|
+
|
|
234
|
+
`padding: 11px 16px; border: 2px solid var(--border); border-radius: var(--radius-md); font-size: 14px`. Focus: `box-shadow: 0 0 0 3px var(--pink)`. Input-group: input + button joined with zero'd inner radii.
|
|
235
|
+
|
|
236
|
+
### Table
|
|
237
|
+
|
|
238
|
+
Container: card shell (border, radius-lg, shadow-md, overflow hidden). Header: `--bg-muted`, 11px uppercase labels. Rows: `16px 28px` padding, `--border-light` divider, hover → muted bg.
|
|
239
|
+
|
|
240
|
+
### Progress Bar
|
|
241
|
+
|
|
242
|
+
Track: 12px height, `--bg-muted`, pill radius, 2px border. Fill: pill radius, accent color. Animate: `width 0.8s cubic-bezier(0.34, 1.56, 0.64, 1)`.
|
|
243
|
+
|
|
244
|
+
### Avatar
|
|
245
|
+
|
|
246
|
+
Square-ish (`--radius-sm`), 2px border. Sizes: 28/36/48px. Cycle through ordered palette colors.
|
|
247
|
+
|
|
248
|
+
### Tag / Chip
|
|
249
|
+
|
|
250
|
+
`padding: 5px 12px; border-radius: 999px; border: 2px solid var(--border); font-size: 13px; font-weight: 600`. Hover → pink bg. Active → inverse bg+text.
|
|
251
|
+
|
|
252
|
+
### Tooltip
|
|
253
|
+
|
|
254
|
+
`background: --bg-inverse; border: 2px solid --pink; border-radius: --radius-md; padding: 10px 16px; color: --text-inverse; font-size: 13px`. Bold label + bold value.
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## Motion
|
|
259
|
+
|
|
260
|
+
```css
|
|
261
|
+
--transition-fast: 120ms ease; /* button press */
|
|
262
|
+
--transition-base: 180ms ease; /* card hover, general */
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Bouncy and tactile — elements lift and press. Staggered fade-up on page load:
|
|
266
|
+
|
|
267
|
+
```css
|
|
268
|
+
@keyframes fadeUp {
|
|
269
|
+
from {
|
|
270
|
+
opacity: 0;
|
|
271
|
+
transform: translateY(12px);
|
|
272
|
+
}
|
|
273
|
+
to {
|
|
274
|
+
opacity: 1;
|
|
275
|
+
transform: translateY(0);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
/* animation: fadeUp 0.4s ease forwards; delay: n * 0.05s */
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## Checklist
|
|
284
|
+
|
|
285
|
+
- [ ] Background is `#F5F0E8` (light) or `#111111` (dark) — never pure white or grey
|
|
286
|
+
- [ ] Every card has 2px border + offset box shadow
|
|
287
|
+
- [ ] Interactive elements press-shift on :active
|
|
288
|
+
- [ ] DM Sans (body) + DM Serif Display (headlines) + DM Mono (code)
|
|
289
|
+
- [ ] At least one pink element visible on every screen
|
|
290
|
+
- [ ] Labels: 11px uppercase, letter-spacing 1px
|
|
291
|
+
- [ ] Badges are pill-shaped with border
|
|
292
|
+
- [ ] Dark sidebar/cards unchanged in dark mode
|
|
293
|
+
- [ ] No gradients anywhere
|
|
294
|
+
- [ ] Spacing follows 4px grid
|
|
@@ -37,49 +37,62 @@ async function main() {
|
|
|
37
37
|
const data = JSON.parse(raw);
|
|
38
38
|
const seed = data.seed || data;
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
// Discover ALL models from the Prisma schema — not just the tables in the seed data.
|
|
41
|
+
// This ensures FK-dependent tables (e.g., Passenger → Flight) are cleared even when
|
|
42
|
+
// the seed only contains the parent table's data.
|
|
43
|
+
const allModels = Prisma.dmmf.datamodel.models.map(
|
|
44
|
+
(m) => m.name.charAt(0).toLowerCase() + m.name.slice(1),
|
|
45
|
+
);
|
|
41
46
|
|
|
42
|
-
//
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
// Run everything in a single transaction for atomicity and speed.
|
|
48
|
+
// SQLite auto-commits each statement by default — wrapping in a transaction
|
|
49
|
+
// avoids per-statement fsync and is significantly faster for bulk operations.
|
|
50
|
+
await prisma.$transaction(async (tx) => {
|
|
51
|
+
// Disable foreign key checks during wipe+insert — allows deleting in any
|
|
52
|
+
// order and avoids FK constraint errors during the brief window between
|
|
53
|
+
// clearing parent and child tables.
|
|
54
|
+
await tx.$executeRawUnsafe('PRAGMA foreign_keys = OFF');
|
|
55
|
+
|
|
56
|
+
// Wipe ALL tables in the schema (not just seeded ones)
|
|
57
|
+
for (const table of [...allModels].reverse()) {
|
|
58
|
+
try {
|
|
59
|
+
await (tx as any)[table].deleteMany();
|
|
60
|
+
} catch {
|
|
61
|
+
// Table may not exist in current schema — skip
|
|
62
|
+
}
|
|
52
63
|
}
|
|
53
|
-
}
|
|
54
64
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
65
|
+
// Batch-reset auto-increment counters for ALL tables.
|
|
66
|
+
// Without this, SQLite IDs keep climbing across scenario switches,
|
|
67
|
+
// causing hardcoded URLs like /drinks/1 to 404.
|
|
68
|
+
const seqNames = allModels
|
|
69
|
+
.flatMap((t) => [`'${t}'`, `'${t.charAt(0).toUpperCase() + t.slice(1)}'`])
|
|
70
|
+
.join(', ');
|
|
59
71
|
try {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
await prisma.$executeRawUnsafe(
|
|
63
|
-
`DELETE FROM sqlite_sequence WHERE name = '${table}' OR name = '${table.charAt(0).toUpperCase() + table.slice(1)}'`,
|
|
72
|
+
await tx.$executeRawUnsafe(
|
|
73
|
+
`DELETE FROM sqlite_sequence WHERE name IN (${seqNames})`,
|
|
64
74
|
);
|
|
65
75
|
} catch {
|
|
66
|
-
// sqlite_sequence may not exist
|
|
76
|
+
// sqlite_sequence may not exist — safe to ignore
|
|
67
77
|
}
|
|
68
|
-
}
|
|
69
78
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
// Insert seed data
|
|
80
|
+
for (const [table, rows] of Object.entries(seed)) {
|
|
81
|
+
if (!Array.isArray(rows) || rows.length === 0) continue;
|
|
82
|
+
try {
|
|
83
|
+
await (tx as any)[table].createMany({ data: rows });
|
|
84
|
+
console.log(` Seeded ${rows.length} rows into ${table}`);
|
|
85
|
+
} catch (err) {
|
|
86
|
+
console.error(
|
|
87
|
+
` Failed to seed ${table}: ${err instanceof Error ? err.message : err}`,
|
|
88
|
+
);
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
81
91
|
}
|
|
82
|
-
|
|
92
|
+
|
|
93
|
+
// Re-enable foreign key checks
|
|
94
|
+
await tx.$executeRawUnsafe('PRAGMA foreign_keys = ON');
|
|
95
|
+
});
|
|
83
96
|
|
|
84
97
|
console.log('Seed complete');
|
|
85
98
|
}
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
30
|
import { createClient } from '@supabase/supabase-js';
|
|
31
|
+
import { Prisma } from '@prisma/client';
|
|
31
32
|
import * as fs from 'fs';
|
|
32
33
|
import * as path from 'path';
|
|
33
34
|
|
|
@@ -109,13 +110,21 @@ function getProjectRef(): string {
|
|
|
109
110
|
}
|
|
110
111
|
|
|
111
112
|
async function seedTables(seed: Record<string, unknown[]>) {
|
|
112
|
-
|
|
113
|
-
if (tableNames.length === 0) return;
|
|
113
|
+
if (Object.keys(seed).length === 0) return;
|
|
114
114
|
|
|
115
|
-
|
|
115
|
+
// Discover ALL models from the Prisma schema — not just the tables in the seed data.
|
|
116
|
+
// This ensures FK-dependent tables are cleared even when the seed only contains
|
|
117
|
+
// the parent table's data. Every editor project has Prisma installed.
|
|
118
|
+
const allModels = Prisma.dmmf.datamodel.models.map(
|
|
119
|
+
(m) => m.name.charAt(0).toLowerCase() + m.name.slice(1),
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
console.log(
|
|
123
|
+
`Clearing ${allModels.length} tables, seeding: ${Object.keys(seed).join(', ')}`,
|
|
124
|
+
);
|
|
116
125
|
|
|
117
|
-
//
|
|
118
|
-
for (const table of [...
|
|
126
|
+
// Clear ALL tables in reverse order (children before parents for FK safety)
|
|
127
|
+
for (const table of [...allModels].reverse()) {
|
|
119
128
|
const { error } = await supabase.from(table).delete().gte('id', 0);
|
|
120
129
|
if (error) {
|
|
121
130
|
const { error: error2 } = await supabase
|