@happyvertical/smrt-workbench 0.40.66
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/AGENTS.md +28 -0
- package/CLAUDE.md +1 -0
- package/LICENSE +7 -0
- package/README.md +31 -0
- package/dist/chunks/discovery-G9-foyW8.js +979 -0
- package/dist/chunks/discovery-G9-foyW8.js.map +1 -0
- package/dist/chunks/runtime-BTiu5fuP.js +93 -0
- package/dist/chunks/runtime-BTiu5fuP.js.map +1 -0
- package/dist/discovery.d.ts +14 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/runtime.d.ts +10 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +2 -0
- package/dist/svelte/MarkdownDocument.svelte +200 -0
- package/dist/svelte/MarkdownDocument.svelte.d.ts +7 -0
- package/dist/svelte/MarkdownDocument.svelte.d.ts.map +1 -0
- package/dist/svelte/WorkbenchHost.svelte +2058 -0
- package/dist/svelte/WorkbenchHost.svelte.d.ts +13 -0
- package/dist/svelte/WorkbenchHost.svelte.d.ts.map +1 -0
- package/dist/svelte/command.d.ts +6 -0
- package/dist/svelte/command.d.ts.map +1 -0
- package/dist/svelte/command.js +18 -0
- package/dist/svelte/index.d.ts +2 -0
- package/dist/svelte/index.d.ts.map +1 -0
- package/dist/svelte/index.js +1 -0
- package/dist/types.d.ts +202 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +0 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/vite.d.ts +6 -0
- package/dist/vite.d.ts.map +1 -0
- package/dist/vite.js +124 -0
- package/dist/vite.js.map +1 -0
- package/host/README.md +12 -0
- package/host/package.json +21 -0
- package/host/src/app.html +11 -0
- package/host/src/hooks.client.ts +5 -0
- package/host/src/routes/+error.svelte +44 -0
- package/host/src/routes/+page.svelte +15 -0
- package/host/svelte.config.js +12 -0
- package/host/tsconfig.json +10 -0
- package/host/vite.config.ts +202 -0
- package/package.json +96 -0
- package/src/discovery.ts +1748 -0
- package/src/runtime.ts +165 -0
- package/src/types.ts +243 -0
- package/src/utils.ts +16 -0
- package/src/vite.ts +303 -0
package/src/vite.ts
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, isAbsolute, join, resolve } from 'node:path';
|
|
3
|
+
import fg from 'fast-glob';
|
|
4
|
+
import { normalizePath, type Plugin } from 'vite';
|
|
5
|
+
import {
|
|
6
|
+
buildWorkbenchProject,
|
|
7
|
+
detectWorkbenchMode,
|
|
8
|
+
discoverWorkbenchTargets,
|
|
9
|
+
findWorkspaceRoot,
|
|
10
|
+
resolveWorkbenchScope,
|
|
11
|
+
} from './discovery.js';
|
|
12
|
+
import type {
|
|
13
|
+
DiscoveredWorkbenchTarget,
|
|
14
|
+
SmrtWorkbenchVitePluginOptions,
|
|
15
|
+
} from './types.js';
|
|
16
|
+
|
|
17
|
+
const VIRTUAL_WORKBENCH_PROJECT_MODULE_ID = 'virtual:smrt-workbench/project';
|
|
18
|
+
const RESOLVED_VIRTUAL_WORKBENCH_PROJECT_MODULE_ID = `\0${VIRTUAL_WORKBENCH_PROJECT_MODULE_ID}`;
|
|
19
|
+
|
|
20
|
+
interface PlaygroundSpecifier {
|
|
21
|
+
packageName?: string;
|
|
22
|
+
specifier: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function toViteImportSpecifier(specifier: string): string {
|
|
26
|
+
if (!isAbsolute(specifier)) {
|
|
27
|
+
return specifier;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return `/@fs/${normalizePath(specifier)}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function targetSpecifier(target: DiscoveredWorkbenchTarget): string | null {
|
|
34
|
+
return (
|
|
35
|
+
target.importSpecifier || target.sourcePath || target.runtimePath || null
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function readJson(path: string): Record<string, unknown> {
|
|
40
|
+
return JSON.parse(readFileSync(path, 'utf-8')) as Record<string, unknown>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function exportKeys(exportsField: unknown): string[] {
|
|
44
|
+
if (typeof exportsField === 'string') {
|
|
45
|
+
return ['.'];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (
|
|
49
|
+
exportsField &&
|
|
50
|
+
typeof exportsField === 'object' &&
|
|
51
|
+
!Array.isArray(exportsField)
|
|
52
|
+
) {
|
|
53
|
+
return Object.keys(exportsField).sort();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function dependencyNames(packageJson: Record<string, unknown>): string[] {
|
|
60
|
+
return Object.keys({
|
|
61
|
+
...(packageJson.dependencies as Record<string, string> | undefined),
|
|
62
|
+
...(packageJson.devDependencies as Record<string, string> | undefined),
|
|
63
|
+
...(packageJson.peerDependencies as Record<string, string> | undefined),
|
|
64
|
+
}).sort();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function discoverWorkspacePlaygroundSpecifiers(
|
|
68
|
+
workspaceRoot: string,
|
|
69
|
+
packageName?: string,
|
|
70
|
+
): Promise<PlaygroundSpecifier[]> {
|
|
71
|
+
const matches = await fg('packages/*/src/svelte/playground.ts', {
|
|
72
|
+
cwd: workspaceRoot,
|
|
73
|
+
absolute: true,
|
|
74
|
+
onlyFiles: true,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
return matches
|
|
78
|
+
.sort()
|
|
79
|
+
.map((sourcePath) => {
|
|
80
|
+
const packageDir = dirname(dirname(dirname(sourcePath)));
|
|
81
|
+
const packageJson = readJson(join(packageDir, 'package.json'));
|
|
82
|
+
return {
|
|
83
|
+
packageName:
|
|
84
|
+
typeof packageJson.name === 'string' ? packageJson.name : undefined,
|
|
85
|
+
specifier: normalizePath(sourcePath),
|
|
86
|
+
};
|
|
87
|
+
})
|
|
88
|
+
.filter((target) =>
|
|
89
|
+
packageName ? target.packageName === packageName : true,
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async function discoverConsumerPlaygroundSpecifiers(
|
|
94
|
+
projectRoot: string,
|
|
95
|
+
localPlaygroundPath: string,
|
|
96
|
+
packageName?: string,
|
|
97
|
+
): Promise<PlaygroundSpecifier[]> {
|
|
98
|
+
const packageJsonPath = resolve(projectRoot, 'package.json');
|
|
99
|
+
if (!existsSync(packageJsonPath)) {
|
|
100
|
+
return [];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const packageJson = readJson(packageJsonPath);
|
|
104
|
+
const specifiers: PlaygroundSpecifier[] = [];
|
|
105
|
+
|
|
106
|
+
for (const dependencyName of dependencyNames(packageJson)) {
|
|
107
|
+
if (
|
|
108
|
+
!dependencyName.startsWith('@happyvertical/smrt-') ||
|
|
109
|
+
dependencyName === '@happyvertical/smrt-playground' ||
|
|
110
|
+
dependencyName === '@happyvertical/smrt-workbench'
|
|
111
|
+
) {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (packageName && dependencyName !== packageName) {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const dependencyPackageJsonPath = resolve(
|
|
120
|
+
projectRoot,
|
|
121
|
+
'node_modules',
|
|
122
|
+
dependencyName,
|
|
123
|
+
'package.json',
|
|
124
|
+
);
|
|
125
|
+
if (!existsSync(dependencyPackageJsonPath)) {
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const dependencyPackageJson = readJson(dependencyPackageJsonPath);
|
|
130
|
+
if (exportKeys(dependencyPackageJson.exports).includes('./playground')) {
|
|
131
|
+
specifiers.push({
|
|
132
|
+
packageName: dependencyName,
|
|
133
|
+
specifier: `${dependencyName}/playground`,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const localPlayground = resolve(projectRoot, localPlaygroundPath);
|
|
139
|
+
if (!packageName && existsSync(localPlayground)) {
|
|
140
|
+
specifiers.push({
|
|
141
|
+
specifier: normalizePath(localPlayground),
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return specifiers;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function buildVirtualModuleCode(
|
|
149
|
+
projectJson: string,
|
|
150
|
+
workbenchSpecifiers: string[],
|
|
151
|
+
playgroundSpecifiers: string[],
|
|
152
|
+
): string {
|
|
153
|
+
const workbenchImports = workbenchSpecifiers
|
|
154
|
+
.map(
|
|
155
|
+
(specifier, index) =>
|
|
156
|
+
`import workbench${index} from ${JSON.stringify(toViteImportSpecifier(specifier))};`,
|
|
157
|
+
)
|
|
158
|
+
.join('\n');
|
|
159
|
+
const playgroundImports = playgroundSpecifiers
|
|
160
|
+
.map(
|
|
161
|
+
(specifier, index) =>
|
|
162
|
+
`import playground${index} from ${JSON.stringify(toViteImportSpecifier(specifier))};`,
|
|
163
|
+
)
|
|
164
|
+
.join('\n');
|
|
165
|
+
const workbenchList = workbenchSpecifiers
|
|
166
|
+
.map((_, index) => `...toModules(workbench${index})`)
|
|
167
|
+
.join(', ');
|
|
168
|
+
const playgroundList = playgroundSpecifiers
|
|
169
|
+
.map((_, index) => `...toModules(playground${index})`)
|
|
170
|
+
.join(', ');
|
|
171
|
+
|
|
172
|
+
return `${workbenchImports}
|
|
173
|
+
${playgroundImports}
|
|
174
|
+
|
|
175
|
+
const toModules = (value) => {
|
|
176
|
+
if (!value) return [];
|
|
177
|
+
if (Array.isArray(value)) return value.filter(Boolean);
|
|
178
|
+
if (Array.isArray(value.modules)) return value.modules.filter(Boolean);
|
|
179
|
+
return [value];
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
export const workbenchProject = ${projectJson};
|
|
183
|
+
export const workbenchModules = [${workbenchList}].filter(Boolean);
|
|
184
|
+
export const playgroundModules = [${playgroundList}].filter(Boolean);
|
|
185
|
+
export default { workbenchProject, workbenchModules, playgroundModules };
|
|
186
|
+
`;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function envValue(name: string): string | undefined {
|
|
190
|
+
const value = process.env[name];
|
|
191
|
+
return value && value.length > 0 ? value : undefined;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function addWatchFileIfExists(
|
|
195
|
+
context: { addWatchFile(path: string): void },
|
|
196
|
+
path: string,
|
|
197
|
+
) {
|
|
198
|
+
if (existsSync(path)) {
|
|
199
|
+
context.addWatchFile(path);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export function smrtWorkbenchVitePlugin(
|
|
204
|
+
options: SmrtWorkbenchVitePluginOptions = {},
|
|
205
|
+
): Plugin {
|
|
206
|
+
return {
|
|
207
|
+
name: 'smrt-workbench-vite-plugin',
|
|
208
|
+
enforce: 'pre',
|
|
209
|
+
resolveId(id) {
|
|
210
|
+
if (id === VIRTUAL_WORKBENCH_PROJECT_MODULE_ID) {
|
|
211
|
+
return RESOLVED_VIRTUAL_WORKBENCH_PROJECT_MODULE_ID;
|
|
212
|
+
}
|
|
213
|
+
return null;
|
|
214
|
+
},
|
|
215
|
+
async load(id) {
|
|
216
|
+
if (id !== RESOLVED_VIRTUAL_WORKBENCH_PROJECT_MODULE_ID) {
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const cwd =
|
|
221
|
+
options.cwd || envValue('SMRT_WORKBENCH_CWD') || process.cwd();
|
|
222
|
+
const projectRoot =
|
|
223
|
+
options.projectRoot || envValue('SMRT_WORKBENCH_PROJECT_ROOT') || cwd;
|
|
224
|
+
const packageName =
|
|
225
|
+
options.packageName || envValue('SMRT_WORKBENCH_PACKAGE');
|
|
226
|
+
const scope = resolveWorkbenchScope(cwd, {
|
|
227
|
+
projectRoot,
|
|
228
|
+
workspaceRoot: options.workspaceRoot,
|
|
229
|
+
packageName,
|
|
230
|
+
});
|
|
231
|
+
const effectiveMode =
|
|
232
|
+
options.mode === 'auto' || !options.mode
|
|
233
|
+
? detectWorkbenchMode(scope.projectRoot)
|
|
234
|
+
: options.mode;
|
|
235
|
+
const project = await buildWorkbenchProject(scope);
|
|
236
|
+
const workbenchTargets = await discoverWorkbenchTargets(
|
|
237
|
+
scope.projectRoot,
|
|
238
|
+
effectiveMode,
|
|
239
|
+
options.localWorkbenchPath || 'src/workbench.ts',
|
|
240
|
+
scope.packageName,
|
|
241
|
+
options.packagesPattern,
|
|
242
|
+
);
|
|
243
|
+
const playgroundTargetSpecifiers =
|
|
244
|
+
effectiveMode === 'workspace'
|
|
245
|
+
? await discoverWorkspacePlaygroundSpecifiers(
|
|
246
|
+
scope.projectRoot,
|
|
247
|
+
scope.packageName,
|
|
248
|
+
)
|
|
249
|
+
: await discoverConsumerPlaygroundSpecifiers(
|
|
250
|
+
scope.projectRoot,
|
|
251
|
+
options.localPlaygroundPath || 'src/playground.ts',
|
|
252
|
+
scope.packageName,
|
|
253
|
+
);
|
|
254
|
+
const workbenchSpecifiers = workbenchTargets
|
|
255
|
+
.map(targetSpecifier)
|
|
256
|
+
.filter((specifier): specifier is string => Boolean(specifier));
|
|
257
|
+
const playgroundSpecifiers = playgroundTargetSpecifiers.map(
|
|
258
|
+
(target) => target.specifier,
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
addWatchFileIfExists(this, resolve(scope.projectRoot, 'package.json'));
|
|
262
|
+
addWatchFileIfExists(
|
|
263
|
+
this,
|
|
264
|
+
resolve(scope.projectRoot, 'pnpm-workspace.yaml'),
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
const workspaceRoot =
|
|
268
|
+
options.workspaceRoot || findWorkspaceRoot(scope.projectRoot);
|
|
269
|
+
if (workspaceRoot) {
|
|
270
|
+
addWatchFileIfExists(
|
|
271
|
+
this,
|
|
272
|
+
resolve(workspaceRoot, 'pnpm-workspace.yaml'),
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
for (const packageSummary of project.packages) {
|
|
277
|
+
if (packageSummary.directory) {
|
|
278
|
+
addWatchFileIfExists(
|
|
279
|
+
this,
|
|
280
|
+
resolve(packageSummary.directory, 'package.json'),
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
for (const specifier of [
|
|
286
|
+
...workbenchSpecifiers,
|
|
287
|
+
...playgroundSpecifiers,
|
|
288
|
+
]) {
|
|
289
|
+
if (isAbsolute(specifier)) {
|
|
290
|
+
this.addWatchFile(specifier);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return buildVirtualModuleCode(
|
|
295
|
+
JSON.stringify(project),
|
|
296
|
+
workbenchSpecifiers,
|
|
297
|
+
playgroundSpecifiers,
|
|
298
|
+
);
|
|
299
|
+
},
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export { VIRTUAL_WORKBENCH_PROJECT_MODULE_ID };
|