@notis_ai/cli 0.2.0-beta.19.1 → 0.2.0-beta.191.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.
- package/README.md +421 -133
- package/bin/check-runtime.js +15 -0
- package/bin/notis.js +2 -0
- package/config/notis_app_boundary_rules.json +50 -0
- package/config/notis_app_design_rules.json +135 -0
- package/dist/agent-hooks/notis-agent-hook.mjs +19299 -0
- package/dist/base-skills/notis-apps/SKILL.md +72 -0
- package/dist/base-skills/notis-apps/references/architecture.md +167 -0
- package/dist/base-skills/notis-apps/references/context.md +81 -0
- package/dist/base-skills/notis-apps/references/design.md +178 -0
- package/dist/base-skills/notis-apps/references/reading.md +89 -0
- package/dist/base-skills/notis-apps/references/release.md +145 -0
- package/dist/base-skills/notis-apps/references/sdk.md +63 -0
- package/dist/base-skills/notis-apps/references/troubleshooting.md +23 -0
- package/dist/base-skills/notis-cli/SKILL.md +154 -0
- package/dist/base-skills/notis-cli/references/app-delivery.md +18 -0
- package/dist/base-skills/notis-cli/references/intelligence.md +94 -0
- package/dist/base-skills/notis-cli/references/native-databases.md +21 -0
- package/dist/base-skills/notis-cli/references/tool-examples.md +56 -0
- package/dist/base-skills/notis-cli/references/troubleshooting.md +39 -0
- package/dist/base-skills/notis-query/SKILL.md +67 -0
- package/dist/base-skills/notis-query/references/database-discovery.md +70 -0
- package/dist/base-skills/notis-query/references/documents.md +50 -0
- package/dist/base-skills/notis-query/references/query.md +543 -0
- package/{template/packages/notis-sdk → dist/sdk}/package.json +14 -4
- package/dist/sdk/src/agentContext.ts +36 -0
- package/dist/sdk/src/components/Dialog.tsx +46 -0
- package/dist/sdk/src/components/DocumentEditor.tsx +103 -0
- package/dist/sdk/src/components/Markdown.tsx +60 -0
- package/dist/sdk/src/components/MarkdownEditor.tsx +121 -0
- package/dist/sdk/src/components/MultiSelectActionBar.tsx +285 -0
- package/dist/sdk/src/components/MultiSelectCheckbox.tsx +97 -0
- package/dist/sdk/src/components/MultiSelectDragOverlay.tsx +39 -0
- package/dist/sdk/src/components/NotisCommentBoundary.tsx +172 -0
- package/dist/sdk/src/components/NotisSelectionBoundary.tsx +59 -0
- package/dist/sdk/src/components/ShortcutHints.tsx +56 -0
- package/dist/sdk/src/components/Skeleton.tsx +24 -0
- package/dist/sdk/src/config.ts +261 -0
- package/dist/sdk/src/documents.ts +256 -0
- package/dist/sdk/src/hooks/useActiveResource.ts +19 -0
- package/dist/sdk/src/hooks/useAgentContext.ts +23 -0
- package/dist/sdk/src/hooks/useCloudComputer.ts +64 -0
- package/dist/sdk/src/hooks/useCollectionInteractions.ts +838 -0
- package/dist/sdk/src/hooks/useDatabaseSchema.ts +49 -0
- package/dist/sdk/src/hooks/useDatabaseSubscription.ts +76 -0
- package/dist/sdk/src/hooks/useDocument.ts +43 -0
- package/dist/sdk/src/hooks/useDocuments.ts +84 -0
- package/dist/sdk/src/hooks/useHandover.ts +77 -0
- package/dist/sdk/src/hooks/useLongPressSelection.ts +79 -0
- package/dist/sdk/src/hooks/useMultiSelect.ts +95 -0
- package/{template/packages/notis-sdk → dist/sdk}/src/hooks/useNotis.ts +12 -4
- package/{template/packages/notis-sdk → dist/sdk}/src/hooks/useNotisNavigation.ts +11 -8
- package/dist/sdk/src/hooks/useQuery.ts +71 -0
- package/dist/sdk/src/hooks/useTool.ts +65 -0
- package/dist/sdk/src/hooks/useToolQuery.ts +12 -0
- package/dist/sdk/src/hooks/useTopBarSearch.ts +81 -0
- package/dist/sdk/src/hooks/useUpsertDocument.ts +95 -0
- package/dist/sdk/src/index.ts +164 -0
- package/dist/sdk/src/interactions/actions.ts +59 -0
- package/dist/sdk/src/interactions/shortcuts.tsx +726 -0
- package/dist/sdk/src/interactions/visibility.ts +13 -0
- package/dist/sdk/src/interactions.ts +45 -0
- package/dist/sdk/src/provider.tsx +44 -0
- package/dist/sdk/src/queryCache.ts +170 -0
- package/dist/sdk/src/runtime.ts +465 -0
- package/dist/sdk/src/styles.css +266 -0
- package/dist/sdk/src/tailwind.ts +66 -0
- package/dist/sdk/src/vite.ts +73 -0
- package/dist/skill-sync/index.js +1753 -0
- package/dist/skill-sync/index.js.map +7 -0
- package/dist/skill-sync-worker.mjs +3113 -0
- package/package.json +18 -7
- package/skills/notis-apps/cli.md +299 -0
- package/skills/notis-cli/AGENT_INSTRUCTIONS.md +39 -0
- package/skills/notis-onboarding/BRIEF.md +129 -0
- package/skills/notis-query/cli.md +39 -0
- package/src/agent-hook-entry.js +5 -0
- package/src/cli.js +294 -25
- package/src/command-specs/agents.js +392 -0
- package/src/command-specs/apps.js +1483 -203
- package/src/command-specs/auth.js +114 -137
- package/src/command-specs/diagnostics.js +730 -0
- package/src/command-specs/handover.js +374 -0
- package/src/command-specs/helpers.js +85 -82
- package/src/command-specs/index.js +25 -6
- package/src/command-specs/meta.js +150 -18
- package/src/command-specs/onboarding.js +290 -0
- package/src/command-specs/profile.js +358 -0
- package/src/command-specs/reports.js +97 -0
- package/src/command-specs/skills.js +75 -0
- package/src/command-specs/smoke.js +386 -0
- package/src/command-specs/tools.js +455 -139
- package/src/runtime/agent-browser.js +677 -0
- package/src/runtime/agent-memory-state.js +126 -0
- package/src/runtime/agent-setup.js +383 -0
- package/src/runtime/app-boundary-validator.js +404 -0
- package/src/runtime/app-changelog.js +79 -0
- package/src/runtime/app-platform.js +2652 -205
- package/src/runtime/app-registry-scaffolds.js +367 -0
- package/src/runtime/app-test-server.js +293 -0
- package/src/runtime/assets/store-screenshot-dark.png +0 -0
- package/src/runtime/auth-recovery.js +110 -0
- package/src/runtime/base-skills.d.ts +20 -0
- package/src/runtime/base-skills.js +167 -0
- package/src/runtime/channel.js +133 -0
- package/src/runtime/delegated-context.js +68 -0
- package/src/runtime/errors.js +1 -0
- package/src/runtime/git.js +233 -0
- package/src/runtime/login-listener.js +15 -0
- package/src/runtime/oauth.js +2622 -0
- package/src/runtime/output.js +37 -5
- package/src/runtime/ports.js +31 -0
- package/src/runtime/profiles.js +906 -55
- package/src/runtime/screenshot-framing.js +85 -0
- package/src/runtime/skill-sync/cloud-client.ts +99 -0
- package/src/runtime/skill-sync/index.ts +786 -0
- package/src/runtime/skill-sync/local-scanner.ts +1151 -0
- package/src/runtime/skill-sync/symlink-manager.ts +433 -0
- package/src/runtime/skill-sync/sync-plan.ts +47 -0
- package/src/runtime/skill-sync/types.ts +131 -0
- package/src/runtime/skill-sync/write-cloud-skill.ts +50 -0
- package/src/runtime/skill-sync-service.js +109 -0
- package/src/runtime/store-screenshot.js +146 -0
- package/src/runtime/sync-skills.d.ts +37 -0
- package/src/runtime/sync-skills.js +231 -0
- package/src/runtime/telemetry.js +92 -0
- package/src/runtime/transport.js +324 -45
- package/src/skill-sync-worker-entry.js +2 -0
- package/src/skill-sync-worker.js +50 -0
- package/template/.harness/index.html.tmpl +435 -0
- package/template/CHANGELOG.md +5 -0
- package/template/app/globals.css +28 -3
- package/template/app/layout.tsx +6 -3
- package/template/app/page.tsx +49 -42
- package/template/components/page-heading.tsx +23 -0
- package/template/components/ui/badge.tsx +7 -4
- package/template/components/ui/button.tsx +1 -1
- package/template/components/ui/card.tsx +24 -11
- package/template/components/ui/native-select.tsx +24 -0
- package/template/notis.config.ts +24 -6
- package/template/package-lock.json +3642 -0
- package/template/package.json +19 -16
- package/template/postcss.config.mjs +1 -1
- package/template/tailwind.config.ts +1 -6
- package/template/tsconfig.json +1 -0
- package/src/command-specs/db.js +0 -163
- package/src/runtime/app-preview-server.js +0 -312
- package/template/packages/notis-sdk/src/config.ts +0 -48
- package/template/packages/notis-sdk/src/helpers.ts +0 -131
- package/template/packages/notis-sdk/src/hooks/useAppState.ts +0 -50
- package/template/packages/notis-sdk/src/hooks/useCollectionItem.ts +0 -58
- package/template/packages/notis-sdk/src/hooks/useDatabase.ts +0 -87
- package/template/packages/notis-sdk/src/hooks/useDocument.ts +0 -61
- package/template/packages/notis-sdk/src/hooks/useTool.ts +0 -49
- package/template/packages/notis-sdk/src/hooks/useUpsertDocument.ts +0 -57
- package/template/packages/notis-sdk/src/index.ts +0 -47
- package/template/packages/notis-sdk/src/provider.tsx +0 -44
- package/template/packages/notis-sdk/src/runtime.ts +0 -159
- package/template/packages/notis-sdk/src/styles.css +0 -123
- package/template/packages/notis-sdk/src/vite.ts +0 -54
- package/template/packages/notis-sdk/tsconfig.json +0 -15
- /package/{template/packages/notis-sdk → dist/sdk}/src/hooks/useBackend.ts +0 -0
- /package/{template/packages/notis-sdk → dist/sdk}/src/hooks/useTools.ts +0 -0
- /package/{template/packages/notis-sdk → dist/sdk}/src/ui.ts +0 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Notis theme CSS variables.
|
|
3
|
+
*
|
|
4
|
+
* Import this in your app layout:
|
|
5
|
+
*
|
|
6
|
+
* import '@notis/sdk/styles.css';
|
|
7
|
+
*
|
|
8
|
+
* The portal injects the live Notis theme variables at render time.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/* Top-layer surfaces must remain distinct from the app's flat content panels. */
|
|
12
|
+
dialog.notis-dialog {
|
|
13
|
+
position: fixed;
|
|
14
|
+
inset: 0;
|
|
15
|
+
margin: auto;
|
|
16
|
+
box-sizing: border-box;
|
|
17
|
+
width: min(28rem, calc(100% - 2rem));
|
|
18
|
+
max-height: calc(100dvh - 2rem);
|
|
19
|
+
overflow: auto;
|
|
20
|
+
padding: 1.25rem;
|
|
21
|
+
border: 1px solid hsl(var(--border));
|
|
22
|
+
border-radius: 0.75rem;
|
|
23
|
+
background: hsl(var(--popover));
|
|
24
|
+
color: hsl(var(--popover-foreground));
|
|
25
|
+
box-shadow: 0 16px 48px rgb(0 0 0 / 0.2);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
dialog.notis-dialog::backdrop { background: rgb(0 0 0 / 0.45); }
|
|
29
|
+
.notis-dialog-title { margin: 0; font-size: 1rem; font-weight: 600; line-height: 1.5; }
|
|
30
|
+
.notis-dialog-description { margin: 0.5rem 0 0; color: hsl(var(--muted-foreground)); font-size: 0.875rem; line-height: 1.5; }
|
|
31
|
+
|
|
32
|
+
/* Framework-neutral styles: the app owns its Tailwind entry point. This file
|
|
33
|
+
* is also consumed in shadow roots and by apps on older Tailwind versions.
|
|
34
|
+
* Keep rules outside Tailwind-owned @layer blocks: Vite processes this import
|
|
35
|
+
* separately from the app stylesheet, so Tailwind 3 has no matching directives. */
|
|
36
|
+
* {
|
|
37
|
+
border-color: hsl(var(--border));
|
|
38
|
+
}
|
|
39
|
+
[data-notis-app-root] {
|
|
40
|
+
color: hsl(var(--foreground));
|
|
41
|
+
display: block;
|
|
42
|
+
min-height: 100%;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.notis-app-shell {
|
|
46
|
+
margin-inline: auto;
|
|
47
|
+
width: 100%;
|
|
48
|
+
max-width: var(--portal-page-max-width);
|
|
49
|
+
padding: 1.5rem 1rem;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/* Flat panel: no border or shadow around items. */
|
|
53
|
+
.notis-app-surface {
|
|
54
|
+
border-radius: 1rem;
|
|
55
|
+
background-color: hsl(var(--muted));
|
|
56
|
+
color: hsl(var(--card-foreground));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.list-row {
|
|
60
|
+
border-radius: 0.75rem;
|
|
61
|
+
background-color: hsl(var(--muted));
|
|
62
|
+
padding: 0.75rem 1rem;
|
|
63
|
+
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
|
|
64
|
+
transition-duration: 150ms;
|
|
65
|
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.list-row-selected {
|
|
69
|
+
background-color: hsl(var(--primary) / 0.06);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/* Split pages are full-bleed; only the list pane carries a hairline. */
|
|
73
|
+
.notis-app-split {
|
|
74
|
+
display: flex;
|
|
75
|
+
height: 100%;
|
|
76
|
+
min-height: 0;
|
|
77
|
+
width: 100%;
|
|
78
|
+
max-width: none;
|
|
79
|
+
flex-direction: column;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.notis-app-pane-list {
|
|
83
|
+
width: 100%;
|
|
84
|
+
flex-shrink: 0;
|
|
85
|
+
background-color: hsl(var(--muted) / 0.4);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.notis-app-pane-detail {
|
|
89
|
+
min-width: 0;
|
|
90
|
+
flex: 1 1 0%;
|
|
91
|
+
background-color: hsl(var(--background));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.notis-app-section {
|
|
95
|
+
padding: 1.25rem;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@media (min-width: 768px) {
|
|
99
|
+
.notis-app-shell { padding-block: 2rem; }
|
|
100
|
+
.notis-app-section { padding: 1.5rem; }
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
@media (min-width: 1024px) {
|
|
104
|
+
.list-row { background-color: transparent; }
|
|
105
|
+
.list-row:hover { background-color: hsl(var(--muted) / 0.6); }
|
|
106
|
+
.list-row-selected,
|
|
107
|
+
.list-row-selected:hover { background-color: hsl(var(--primary) / 0.06); }
|
|
108
|
+
.notis-app-split { flex-direction: row; }
|
|
109
|
+
.notis-app-pane-list {
|
|
110
|
+
width: 20rem;
|
|
111
|
+
border-right-width: 1px;
|
|
112
|
+
border-right-color: hsl(var(--border));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
@media (min-width: 1280px) {
|
|
117
|
+
.notis-app-pane-list { width: 24rem; }
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/*
|
|
121
|
+
* Markdown value-type rendering (see the `Markdown` component). Plain CSS on
|
|
122
|
+
* theme variables so it works inside the portal shadow root and the dev
|
|
123
|
+
* harness without depending on the app's Tailwind content scan.
|
|
124
|
+
*/
|
|
125
|
+
.notis-markdown {
|
|
126
|
+
font-size: 14px;
|
|
127
|
+
line-height: 1.65;
|
|
128
|
+
color: hsl(var(--foreground));
|
|
129
|
+
overflow-wrap: break-word;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.notis-markdown--sm {
|
|
133
|
+
font-size: 13px;
|
|
134
|
+
line-height: 1.55;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.notis-markdown > :first-child {
|
|
138
|
+
margin-top: 0;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.notis-markdown > :last-child {
|
|
142
|
+
margin-bottom: 0;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.notis-markdown p {
|
|
146
|
+
margin: 0.625em 0;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.notis-markdown h1,
|
|
150
|
+
.notis-markdown h2,
|
|
151
|
+
.notis-markdown h3,
|
|
152
|
+
.notis-markdown h4,
|
|
153
|
+
.notis-markdown h5,
|
|
154
|
+
.notis-markdown h6 {
|
|
155
|
+
margin: 1.25em 0 0.5em;
|
|
156
|
+
font-weight: 650;
|
|
157
|
+
letter-spacing: -0.01em;
|
|
158
|
+
line-height: 1.3;
|
|
159
|
+
color: hsl(var(--foreground));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.notis-markdown h1 { font-size: 1.5em; }
|
|
163
|
+
.notis-markdown h2 { font-size: 1.25em; }
|
|
164
|
+
.notis-markdown h3 { font-size: 1.1em; }
|
|
165
|
+
.notis-markdown h4,
|
|
166
|
+
.notis-markdown h5,
|
|
167
|
+
.notis-markdown h6 { font-size: 1em; }
|
|
168
|
+
|
|
169
|
+
.notis-markdown ul,
|
|
170
|
+
.notis-markdown ol {
|
|
171
|
+
margin: 0.625em 0;
|
|
172
|
+
padding-left: 1.5em;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.notis-markdown ul { list-style-type: disc; }
|
|
176
|
+
.notis-markdown ol { list-style-type: decimal; }
|
|
177
|
+
|
|
178
|
+
.notis-markdown li {
|
|
179
|
+
margin: 0.25em 0;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.notis-markdown li > ul,
|
|
183
|
+
.notis-markdown li > ol {
|
|
184
|
+
margin: 0.25em 0;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.notis-markdown ul.contains-task-list {
|
|
188
|
+
list-style: none;
|
|
189
|
+
padding-left: 0.375em;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.notis-markdown li.task-list-item input[type='checkbox'] {
|
|
193
|
+
margin-right: 0.5em;
|
|
194
|
+
accent-color: hsl(var(--primary));
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.notis-markdown blockquote {
|
|
198
|
+
margin: 0.75em 0;
|
|
199
|
+
padding: 0.125em 0 0.125em 0.875em;
|
|
200
|
+
border-left: 3px solid hsl(var(--border));
|
|
201
|
+
color: hsl(var(--muted-foreground));
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.notis-markdown a {
|
|
205
|
+
color: hsl(var(--primary));
|
|
206
|
+
text-decoration: underline;
|
|
207
|
+
text-decoration-color: hsl(var(--primary) / 0.35);
|
|
208
|
+
text-underline-offset: 2px;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.notis-markdown a:hover {
|
|
212
|
+
text-decoration-color: hsl(var(--primary));
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.notis-markdown code {
|
|
216
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
217
|
+
font-size: 0.875em;
|
|
218
|
+
padding: 0.125em 0.375em;
|
|
219
|
+
border-radius: 0.25rem;
|
|
220
|
+
background: hsl(var(--muted));
|
|
221
|
+
color: hsl(var(--foreground));
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.notis-markdown pre {
|
|
225
|
+
margin: 0.75em 0;
|
|
226
|
+
padding: 0.75em 1em;
|
|
227
|
+
border-radius: 0.5rem;
|
|
228
|
+
background: hsl(var(--muted));
|
|
229
|
+
overflow-x: auto;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.notis-markdown pre code {
|
|
233
|
+
padding: 0;
|
|
234
|
+
background: transparent;
|
|
235
|
+
font-size: 0.875em;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.notis-markdown hr {
|
|
239
|
+
margin: 1.25em 0;
|
|
240
|
+
border: 0;
|
|
241
|
+
border-top: 1px solid hsl(var(--border));
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.notis-markdown img {
|
|
245
|
+
max-width: 100%;
|
|
246
|
+
border-radius: 0.5rem;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.notis-markdown table {
|
|
250
|
+
margin: 0.75em 0;
|
|
251
|
+
width: 100%;
|
|
252
|
+
border-collapse: collapse;
|
|
253
|
+
font-size: 0.95em;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.notis-markdown th,
|
|
257
|
+
.notis-markdown td {
|
|
258
|
+
padding: 0.375em 0.75em;
|
|
259
|
+
border: 1px solid hsl(var(--border));
|
|
260
|
+
text-align: left;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.notis-markdown th {
|
|
264
|
+
background: hsl(var(--muted));
|
|
265
|
+
font-weight: 600;
|
|
266
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/** Build-only SDK content discovery. Author configuration and PostCSS plugins stay intact. */
|
|
2
|
+
import { existsSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { dirname, join, relative, resolve } from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
|
|
7
|
+
export function notisTailwindContent() {
|
|
8
|
+
let root = process.cwd();
|
|
9
|
+
let temporary: string | undefined;
|
|
10
|
+
const wrappers = new Map<string, string>();
|
|
11
|
+
const cleanup = () => {
|
|
12
|
+
if (temporary) rmSync(temporary, { recursive: true, force: true });
|
|
13
|
+
temporary = undefined;
|
|
14
|
+
wrappers.clear();
|
|
15
|
+
};
|
|
16
|
+
return {
|
|
17
|
+
name: 'notis-sdk-tailwind-content',
|
|
18
|
+
enforce: 'pre' as const,
|
|
19
|
+
configResolved(config: { root: string }) { root = config.root; },
|
|
20
|
+
transform(source: string, id: string) {
|
|
21
|
+
const stylesheet = id.split('?')[0];
|
|
22
|
+
if (!stylesheet.endsWith('.css')) return null;
|
|
23
|
+
// Tailwind 4 discovers dependency sources through CSS, not config.content.
|
|
24
|
+
// Keep the author's imports, configuration and PostCSS pipeline untouched.
|
|
25
|
+
if (/@import\s+(?:url\(\s*)?(['"])tailwindcss(?:\/[^'"]*)?\1/.test(source)) {
|
|
26
|
+
const sdkSource = dirname(fileURLToPath(import.meta.url));
|
|
27
|
+
const relativeSource = './' + relative(dirname(stylesheet), sdkSource).replaceAll('\\', '/');
|
|
28
|
+
const directive = `@source ${JSON.stringify(relativeSource)};`;
|
|
29
|
+
return source.includes(directive) ? null : { code: `${source}\n${directive}\n`, map: null };
|
|
30
|
+
}
|
|
31
|
+
if (!/@tailwind\s/.test(source)) return null;
|
|
32
|
+
const explicit = source.match(/@config\s+(['"])(.*?)\1\s*;/);
|
|
33
|
+
const config = explicit
|
|
34
|
+
? resolve(dirname(id.split('?')[0]), explicit[2])
|
|
35
|
+
: ['ts', 'js', 'cjs', 'mjs'].map(ext => join(root, `tailwind.config.${ext}`)).find(existsSync);
|
|
36
|
+
if (!config) return null;
|
|
37
|
+
let wrapper = wrappers.get(config);
|
|
38
|
+
if (!wrapper) {
|
|
39
|
+
temporary ||= mkdtempSync(join(tmpdir(), 'notis-tailwind-'));
|
|
40
|
+
wrapper = join(temporary, `config-${wrappers.size}.ts`);
|
|
41
|
+
const sdkGlob = join(dirname(fileURLToPath(import.meta.url)), '**/*.{ts,tsx}').replaceAll('\\', '/');
|
|
42
|
+
writeFileSync(wrapper, `import config from ${JSON.stringify(config)};
|
|
43
|
+
import { resolve } from 'node:path';
|
|
44
|
+
const content = config.content || [];
|
|
45
|
+
const files = Array.isArray(content) ? content : (content.files || []);
|
|
46
|
+
const base = ${JSON.stringify(root)};
|
|
47
|
+
const relativeBase = ${JSON.stringify(dirname(config))};
|
|
48
|
+
export default { ...config, content: {
|
|
49
|
+
...(Array.isArray(content) ? {} : content),
|
|
50
|
+
relative: false,
|
|
51
|
+
files: [...files.map(file => typeof file !== 'string' ? file :
|
|
52
|
+
(file.startsWith('!') ? '!' : '') + resolve(content.relative ? relativeBase : base, file.replace(/^!/, ''))),
|
|
53
|
+
${JSON.stringify(sdkGlob)}],
|
|
54
|
+
} };
|
|
55
|
+
`);
|
|
56
|
+
wrappers.set(config, wrapper);
|
|
57
|
+
}
|
|
58
|
+
const directive = `@config ${JSON.stringify('./' + relative(dirname(id.split('?')[0]), wrapper).replaceAll('\\', '/'))};`;
|
|
59
|
+
// Imports must remain before @config. Vite resolves them before PostCSS.
|
|
60
|
+
const code = explicit ? source.replace(explicit[0], directive) : `${source}\n${directive}\n`;
|
|
61
|
+
return { code, map: null };
|
|
62
|
+
},
|
|
63
|
+
closeBundle: cleanup,
|
|
64
|
+
closeWatcher: cleanup,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vite config builder for Notis apps.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* ```ts
|
|
6
|
+
* // vite.config.ts
|
|
7
|
+
* import { notisViteConfig } from '@notis/sdk/vite';
|
|
8
|
+
* import appConfig from './notis.config';
|
|
9
|
+
* export default notisViteConfig(appConfig);
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* Produces a library-mode ES module bundle with React externalized.
|
|
13
|
+
* Output: .notis/output/bundle/app.js + app.css
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import * as vite from 'vite';
|
|
17
|
+
import type { NotisAppConfig } from './config';
|
|
18
|
+
import { notisTailwindContent } from './tailwind';
|
|
19
|
+
|
|
20
|
+
const externalReact = ['react', 'react-dom', 'react-dom/client', 'react/jsx-runtime', 'react/jsx-dev-runtime'];
|
|
21
|
+
|
|
22
|
+
export function notisViteConfig(appConfig: NotisAppConfig): vite.UserConfig {
|
|
23
|
+
// Vite 8 preserves external require() calls. App bundles run in a browser
|
|
24
|
+
// with an ESM import map, so bundled CommonJS dependencies must import React.
|
|
25
|
+
// Older pulled apps also receive this SDK; their Vite already does this.
|
|
26
|
+
const externalRequirePlugin = 'esmExternalRequirePlugin' in vite
|
|
27
|
+
&& typeof vite.esmExternalRequirePlugin === 'function'
|
|
28
|
+
? vite.esmExternalRequirePlugin({ external: externalReact })
|
|
29
|
+
: null;
|
|
30
|
+
return {
|
|
31
|
+
plugins: [
|
|
32
|
+
notisTailwindContent(),
|
|
33
|
+
...(externalRequirePlugin ? [externalRequirePlugin] : []),
|
|
34
|
+
// @vitejs/plugin-react is added by the consumer's vite.config.ts
|
|
35
|
+
// or auto-detected. We provide the config shape only.
|
|
36
|
+
],
|
|
37
|
+
build: {
|
|
38
|
+
lib: {
|
|
39
|
+
entry: '.notis/_entry.tsx',
|
|
40
|
+
formats: ['es'],
|
|
41
|
+
fileName: () => 'app.js',
|
|
42
|
+
},
|
|
43
|
+
// Keep Vite's compatibility alias: SDK refresh also serves historical
|
|
44
|
+
// Vite 5/6/7 apps, which do not understand rolldownOptions.
|
|
45
|
+
rollupOptions: {
|
|
46
|
+
// On Vite 8 the plugin must own externalization as well as conversion:
|
|
47
|
+
// a top-level external match bypasses its require-to-import transform.
|
|
48
|
+
external: externalRequirePlugin ? [] : externalReact,
|
|
49
|
+
output: {
|
|
50
|
+
globals: {
|
|
51
|
+
react: 'window.React',
|
|
52
|
+
'react-dom': 'window.ReactDOM',
|
|
53
|
+
'react-dom/client': 'window.ReactDOMClient',
|
|
54
|
+
'react/jsx-runtime': 'window.React',
|
|
55
|
+
},
|
|
56
|
+
assetFileNames: 'app[extname]',
|
|
57
|
+
inlineDynamicImports: true,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
outDir: '.notis/output/bundle',
|
|
61
|
+
emptyOutDir: true,
|
|
62
|
+
cssCodeSplit: false,
|
|
63
|
+
},
|
|
64
|
+
resolve: {
|
|
65
|
+
alias: {
|
|
66
|
+
'@': process.cwd(),
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
define: {
|
|
70
|
+
'process.env.NODE_ENV': JSON.stringify('production'),
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|