@bagelink/workspace 1.7.3 ā 1.8.0
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 +101 -8
- package/bin/bgl.ts +34 -4
- package/dist/bin/bgl.cjs +30 -5
- package/dist/bin/bgl.mjs +30 -5
- package/dist/index.cjs +13 -42
- package/dist/index.d.cts +14 -1
- package/dist/index.d.mts +14 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.mjs +4 -36
- package/dist/shared/workspace.Bwsdwbt-.cjs +575 -0
- package/dist/shared/workspace.Dq-27S1f.mjs +560 -0
- package/package.json +1 -1
- package/src/index.ts +2 -0
- package/src/init.ts +36 -9
- package/src/workspace.ts +432 -0
- package/dist/shared/workspace.BaaKkm9b.mjs +0 -182
- package/dist/shared/workspace.CkP5t0--.cjs +0 -190
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
import { writeFileSync, existsSync, readFileSync, mkdirSync, readdirSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import process from 'node:process';
|
|
4
|
+
import prompts from 'prompts';
|
|
5
|
+
|
|
6
|
+
function generateNetlifyRedirect(config) {
|
|
7
|
+
const redirect = `[[redirects]]
|
|
8
|
+
from = "${config.proxy}/*"
|
|
9
|
+
to = "${config.host}/:splat"
|
|
10
|
+
status = 200
|
|
11
|
+
force = true
|
|
12
|
+
headers = {X-From = "Netlify"}
|
|
13
|
+
`;
|
|
14
|
+
return redirect;
|
|
15
|
+
}
|
|
16
|
+
function generateNetlifyConfig(config, additionalConfig) {
|
|
17
|
+
const redirect = generateNetlifyRedirect(config);
|
|
18
|
+
if (additionalConfig !== void 0 && additionalConfig !== "") {
|
|
19
|
+
return `${redirect}
|
|
20
|
+
${additionalConfig}`;
|
|
21
|
+
}
|
|
22
|
+
return redirect;
|
|
23
|
+
}
|
|
24
|
+
function writeNetlifyConfig(config, outPath = "./netlify.toml", additionalConfig) {
|
|
25
|
+
const content = generateNetlifyConfig(config, additionalConfig);
|
|
26
|
+
const resolvedPath = resolve(outPath);
|
|
27
|
+
writeFileSync(resolvedPath, content, "utf-8");
|
|
28
|
+
console.log(`\u2713 Generated netlify.toml at ${resolvedPath}`);
|
|
29
|
+
}
|
|
30
|
+
function setBuildEnvVars(config) {
|
|
31
|
+
process.env.BGL_PROXY_PATH = config.proxy;
|
|
32
|
+
process.env.BGL_API_HOST = config.host;
|
|
33
|
+
if (config.openapi_url !== void 0 && config.openapi_url !== "") {
|
|
34
|
+
process.env.BGL_OPENAPI_URL = config.openapi_url;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function generateWorkspaceConfig(root = process.cwd(), configFile = "bgl.config.ts") {
|
|
39
|
+
console.log("\n\u{1F527} No bgl.config.ts found. Let's create one!\n");
|
|
40
|
+
const response = await prompts([
|
|
41
|
+
{
|
|
42
|
+
type: "text",
|
|
43
|
+
name: "projectId",
|
|
44
|
+
message: "What is your Bagel project ID?",
|
|
45
|
+
initial: "my-project",
|
|
46
|
+
validate: (value) => value.length > 0 ? true : "Project ID is required"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
type: "confirm",
|
|
50
|
+
name: "useCustomHost",
|
|
51
|
+
message: "Use custom production host?",
|
|
52
|
+
initial: false
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
type: (prev) => prev ? "text" : null,
|
|
56
|
+
name: "customHost",
|
|
57
|
+
message: "Enter production host URL:",
|
|
58
|
+
initial: "https://api.example.com"
|
|
59
|
+
}
|
|
60
|
+
]);
|
|
61
|
+
if (!response || !response.projectId) {
|
|
62
|
+
console.log("\n\u274C Config generation cancelled.\n");
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
const productionHost = response.useCustomHost === true ? response.customHost : `https://${response.projectId}.bagel.to`;
|
|
66
|
+
const configContent = `import { defineWorkspace } from '@bagelink/workspace'
|
|
67
|
+
import type { WorkspaceConfig, WorkspaceEnvironment } from '@bagelink/workspace'
|
|
68
|
+
|
|
69
|
+
const configs: Record<WorkspaceEnvironment, WorkspaceConfig> = {
|
|
70
|
+
localhost: {
|
|
71
|
+
host: 'http://localhost:8000',
|
|
72
|
+
proxy: '/api',
|
|
73
|
+
openapi_url: 'http://localhost:8000/openapi.json',
|
|
74
|
+
},
|
|
75
|
+
development: {
|
|
76
|
+
host: '${productionHost}',
|
|
77
|
+
proxy: '/api',
|
|
78
|
+
openapi_url: '${productionHost}/openapi.json',
|
|
79
|
+
},
|
|
80
|
+
production: {
|
|
81
|
+
host: '${productionHost}',
|
|
82
|
+
proxy: '/api',
|
|
83
|
+
openapi_url: '${productionHost}/openapi.json',
|
|
84
|
+
},
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export default defineWorkspace(configs)
|
|
88
|
+
`;
|
|
89
|
+
const configPath = resolve(root, configFile);
|
|
90
|
+
writeFileSync(configPath, configContent, "utf-8");
|
|
91
|
+
console.log(`
|
|
92
|
+
\u2705 Created ${configFile}`);
|
|
93
|
+
console.log(` Production host: ${productionHost}`);
|
|
94
|
+
console.log(` Local dev host: http://localhost:8000
|
|
95
|
+
`);
|
|
96
|
+
const setupResponse = await prompts([
|
|
97
|
+
{
|
|
98
|
+
type: "confirm",
|
|
99
|
+
name: "updatePackageJson",
|
|
100
|
+
message: "Add/update dev scripts in package.json?",
|
|
101
|
+
initial: true
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
type: "confirm",
|
|
105
|
+
name: "updateViteConfig",
|
|
106
|
+
message: "Create/update vite.config.ts?",
|
|
107
|
+
initial: true
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
type: "confirm",
|
|
111
|
+
name: "generateNetlify",
|
|
112
|
+
message: "Generate netlify.toml for deployment?",
|
|
113
|
+
initial: true
|
|
114
|
+
}
|
|
115
|
+
]);
|
|
116
|
+
if (setupResponse.updatePackageJson) {
|
|
117
|
+
updatePackageJsonScripts(root);
|
|
118
|
+
}
|
|
119
|
+
if (setupResponse.updateViteConfig) {
|
|
120
|
+
updateViteConfig(root);
|
|
121
|
+
}
|
|
122
|
+
if (setupResponse.generateNetlify) {
|
|
123
|
+
const prodConfig = {
|
|
124
|
+
host: productionHost,
|
|
125
|
+
proxy: "/api"
|
|
126
|
+
};
|
|
127
|
+
writeNetlifyConfig(prodConfig, resolve(root, "netlify.toml"));
|
|
128
|
+
}
|
|
129
|
+
console.log("\n\u{1F4A1} You can edit these files to customize your configuration.\n");
|
|
130
|
+
}
|
|
131
|
+
function generateWorkspaceConfigSync(projectId, root = process.cwd(), configFile = "bgl.config.ts", customHost) {
|
|
132
|
+
const productionHost = customHost ?? `https://${projectId}.bagel.to`;
|
|
133
|
+
const configContent = `import { defineWorkspace } from '@bagelink/workspace'
|
|
134
|
+
import type { WorkspaceConfig, WorkspaceEnvironment } from '@bagelink/workspace'
|
|
135
|
+
|
|
136
|
+
const configs: Record<WorkspaceEnvironment, WorkspaceConfig> = {
|
|
137
|
+
localhost: {
|
|
138
|
+
host: 'http://localhost:8000',
|
|
139
|
+
proxy: '/api',
|
|
140
|
+
openapi_url: 'http://localhost:8000/openapi.json',
|
|
141
|
+
},
|
|
142
|
+
development: {
|
|
143
|
+
host: '${productionHost}',
|
|
144
|
+
proxy: '/api',
|
|
145
|
+
openapi_url: '${productionHost}/openapi.json',
|
|
146
|
+
},
|
|
147
|
+
production: {
|
|
148
|
+
host: '${productionHost}',
|
|
149
|
+
proxy: '/api',
|
|
150
|
+
openapi_url: '${productionHost}/openapi.json',
|
|
151
|
+
},
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export default defineWorkspace(configs)
|
|
155
|
+
`;
|
|
156
|
+
const configPath = resolve(root, configFile);
|
|
157
|
+
writeFileSync(configPath, configContent, "utf-8");
|
|
158
|
+
console.log(`\u2705 Created ${configPath}`);
|
|
159
|
+
}
|
|
160
|
+
function updatePackageJsonScripts(root) {
|
|
161
|
+
const packageJsonPath = resolve(root, "package.json");
|
|
162
|
+
if (!existsSync(packageJsonPath)) {
|
|
163
|
+
console.log("\u26A0\uFE0F No package.json found, skipping script update");
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
try {
|
|
167
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
168
|
+
if (!packageJson.scripts) {
|
|
169
|
+
packageJson.scripts = {};
|
|
170
|
+
}
|
|
171
|
+
const scriptsToAdd = {
|
|
172
|
+
"dev": "vite",
|
|
173
|
+
"dev:local": "vite --mode localhost",
|
|
174
|
+
"build": "vite build",
|
|
175
|
+
"preview": "vite preview"
|
|
176
|
+
};
|
|
177
|
+
let modified = false;
|
|
178
|
+
for (const [key, value] of Object.entries(scriptsToAdd)) {
|
|
179
|
+
if (key === "dev" || key === "dev:local") {
|
|
180
|
+
if (packageJson.scripts[key] !== value) {
|
|
181
|
+
packageJson.scripts[key] = value;
|
|
182
|
+
modified = true;
|
|
183
|
+
}
|
|
184
|
+
} else {
|
|
185
|
+
if (!packageJson.scripts[key]) {
|
|
186
|
+
packageJson.scripts[key] = value;
|
|
187
|
+
modified = true;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (modified) {
|
|
192
|
+
writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}
|
|
193
|
+
`, "utf-8");
|
|
194
|
+
console.log("\u2705 Updated package.json with dev scripts");
|
|
195
|
+
} else {
|
|
196
|
+
console.log("\u2139\uFE0F Scripts already up to date in package.json");
|
|
197
|
+
}
|
|
198
|
+
} catch (error) {
|
|
199
|
+
console.error("\u274C Failed to update package.json:", error);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function updateViteConfig(root) {
|
|
203
|
+
const viteConfigPath = resolve(root, "vite.config.ts");
|
|
204
|
+
const viteConfigExists = existsSync(viteConfigPath);
|
|
205
|
+
if (viteConfigExists) {
|
|
206
|
+
const existingConfig = readFileSync(viteConfigPath, "utf-8");
|
|
207
|
+
if (existingConfig.includes("@bagelink/workspace")) {
|
|
208
|
+
console.log("\u2139\uFE0F vite.config.ts already configured");
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
console.log("\u26A0\uFE0F vite.config.ts exists. Please manually add the workspace configuration.");
|
|
212
|
+
console.log(" See: https://github.com/bageldb/bagelink/tree/master/packages/workspace#readme");
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
const viteConfigContent = `import { defineConfig } from 'vite'
|
|
216
|
+
import { createViteProxy } from '@bagelink/workspace'
|
|
217
|
+
import workspace from './bgl.config'
|
|
218
|
+
|
|
219
|
+
// https://vitejs.dev/config/
|
|
220
|
+
export default defineConfig(({ mode }) => {
|
|
221
|
+
const config = workspace(mode as 'localhost' | 'development' | 'production')
|
|
222
|
+
|
|
223
|
+
return {
|
|
224
|
+
server: {
|
|
225
|
+
proxy: createViteProxy(config),
|
|
226
|
+
},
|
|
227
|
+
}
|
|
228
|
+
})
|
|
229
|
+
`;
|
|
230
|
+
writeFileSync(viteConfigPath, viteConfigContent, "utf-8");
|
|
231
|
+
console.log("\u2705 Created vite.config.ts");
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
async function initWorkspace(root = process.cwd()) {
|
|
235
|
+
console.log("\n\u{1F680} Creating Bagel workspace...\n");
|
|
236
|
+
const response = await prompts([
|
|
237
|
+
{
|
|
238
|
+
type: "text",
|
|
239
|
+
name: "workspaceName",
|
|
240
|
+
message: "Workspace name:",
|
|
241
|
+
initial: "my-workspace"
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
type: "text",
|
|
245
|
+
name: "projectId",
|
|
246
|
+
message: "Bagel project ID:",
|
|
247
|
+
initial: "my-project"
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
type: "confirm",
|
|
251
|
+
name: "createFirstProject",
|
|
252
|
+
message: "Create first project?",
|
|
253
|
+
initial: true
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
type: (prev) => prev ? "text" : null,
|
|
257
|
+
name: "firstProjectName",
|
|
258
|
+
message: "First project name:",
|
|
259
|
+
initial: "web"
|
|
260
|
+
}
|
|
261
|
+
]);
|
|
262
|
+
if (!response || !response.workspaceName) {
|
|
263
|
+
console.log("\n\u274C Workspace creation cancelled.\n");
|
|
264
|
+
process.exit(1);
|
|
265
|
+
}
|
|
266
|
+
const { workspaceName, projectId, createFirstProject, firstProjectName } = response;
|
|
267
|
+
createWorkspaceRoot(root, workspaceName, projectId);
|
|
268
|
+
createSharedPackage(root);
|
|
269
|
+
if (createFirstProject && firstProjectName) {
|
|
270
|
+
await addProject(firstProjectName, root);
|
|
271
|
+
}
|
|
272
|
+
console.log("\n\u2705 Workspace created successfully!");
|
|
273
|
+
console.log("\nNext steps:");
|
|
274
|
+
console.log(` cd ${workspaceName}`);
|
|
275
|
+
console.log(" bun install");
|
|
276
|
+
if (createFirstProject) {
|
|
277
|
+
console.log(` bun run dev:${firstProjectName}`);
|
|
278
|
+
} else {
|
|
279
|
+
console.log(" bgl add <project-name> # Add a project");
|
|
280
|
+
}
|
|
281
|
+
console.log("");
|
|
282
|
+
}
|
|
283
|
+
function createWorkspaceRoot(root, name, projectId) {
|
|
284
|
+
const workspaceDir = resolve(root, name);
|
|
285
|
+
if (existsSync(workspaceDir)) {
|
|
286
|
+
console.error(`\u274C Directory ${name} already exists`);
|
|
287
|
+
process.exit(1);
|
|
288
|
+
}
|
|
289
|
+
mkdirSync(workspaceDir, { recursive: true });
|
|
290
|
+
const packageJson = {
|
|
291
|
+
name,
|
|
292
|
+
private: true,
|
|
293
|
+
workspaces: ["*", "!node_modules"],
|
|
294
|
+
scripts: {
|
|
295
|
+
dev: "bun run --filter './[!shared]*' dev",
|
|
296
|
+
build: "bun run --filter './[!shared]*' build",
|
|
297
|
+
typecheck: "tsc --noEmit"
|
|
298
|
+
},
|
|
299
|
+
devDependencies: {
|
|
300
|
+
"@bagelink/workspace": "latest",
|
|
301
|
+
typescript: "^5.0.0",
|
|
302
|
+
vite: "latest"
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
writeFileSync(
|
|
306
|
+
resolve(workspaceDir, "package.json"),
|
|
307
|
+
`${JSON.stringify(packageJson, null, 2)}
|
|
308
|
+
`
|
|
309
|
+
);
|
|
310
|
+
const bglConfig = `import { defineWorkspace } from '@bagelink/workspace'
|
|
311
|
+
|
|
312
|
+
export default defineWorkspace({
|
|
313
|
+
localhost: {
|
|
314
|
+
host: 'http://localhost:8000',
|
|
315
|
+
proxy: '/api',
|
|
316
|
+
openapi_url: 'http://localhost:8000/openapi.json',
|
|
317
|
+
},
|
|
318
|
+
development: {
|
|
319
|
+
host: 'https://${projectId}.bagel.to',
|
|
320
|
+
proxy: '/api',
|
|
321
|
+
openapi_url: 'https://${projectId}.bagel.to/openapi.json',
|
|
322
|
+
},
|
|
323
|
+
production: {
|
|
324
|
+
host: 'https://${projectId}.bagel.to',
|
|
325
|
+
proxy: '/api',
|
|
326
|
+
openapi_url: 'https://${projectId}.bagel.to/openapi.json',
|
|
327
|
+
},
|
|
328
|
+
})
|
|
329
|
+
`;
|
|
330
|
+
writeFileSync(resolve(workspaceDir, "bgl.config.ts"), bglConfig);
|
|
331
|
+
const tsConfig = {
|
|
332
|
+
compilerOptions: {
|
|
333
|
+
target: "ES2020",
|
|
334
|
+
useDefineForClassFields: true,
|
|
335
|
+
module: "ESNext",
|
|
336
|
+
lib: ["ES2020", "DOM", "DOM.Iterable"],
|
|
337
|
+
skipLibCheck: true,
|
|
338
|
+
moduleResolution: "bundler",
|
|
339
|
+
allowImportingTsExtensions: true,
|
|
340
|
+
resolveJsonModule: true,
|
|
341
|
+
isolatedModules: true,
|
|
342
|
+
noEmit: true,
|
|
343
|
+
jsx: "preserve",
|
|
344
|
+
strict: true,
|
|
345
|
+
noUnusedLocals: true,
|
|
346
|
+
noUnusedParameters: true,
|
|
347
|
+
noFallthroughCasesInSwitch: true,
|
|
348
|
+
baseUrl: ".",
|
|
349
|
+
paths: {
|
|
350
|
+
"shared/*": ["./shared/*"]
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
writeFileSync(
|
|
355
|
+
resolve(workspaceDir, "tsconfig.json"),
|
|
356
|
+
`${JSON.stringify(tsConfig, null, 2)}
|
|
357
|
+
`
|
|
358
|
+
);
|
|
359
|
+
const gitignore = `node_modules
|
|
360
|
+
dist
|
|
361
|
+
.DS_Store
|
|
362
|
+
*.local
|
|
363
|
+
.env.local
|
|
364
|
+
.vite
|
|
365
|
+
`;
|
|
366
|
+
writeFileSync(resolve(workspaceDir, ".gitignore"), gitignore);
|
|
367
|
+
console.log(`\u2705 Created workspace: ${name}`);
|
|
368
|
+
}
|
|
369
|
+
function createSharedPackage(root) {
|
|
370
|
+
const sharedDir = resolve(root, "shared");
|
|
371
|
+
mkdirSync(sharedDir, { recursive: true });
|
|
372
|
+
const packageJson = {
|
|
373
|
+
name: "shared",
|
|
374
|
+
version: "1.0.0",
|
|
375
|
+
type: "module",
|
|
376
|
+
exports: {
|
|
377
|
+
".": "./index.ts",
|
|
378
|
+
"./utils": "./utils/index.ts",
|
|
379
|
+
"./types": "./types/index.ts"
|
|
380
|
+
}
|
|
381
|
+
};
|
|
382
|
+
writeFileSync(
|
|
383
|
+
resolve(sharedDir, "package.json"),
|
|
384
|
+
`${JSON.stringify(packageJson, null, 2)}
|
|
385
|
+
`
|
|
386
|
+
);
|
|
387
|
+
writeFileSync(
|
|
388
|
+
resolve(sharedDir, "index.ts"),
|
|
389
|
+
"// Shared utilities and exports\nexport * from './utils'\n"
|
|
390
|
+
);
|
|
391
|
+
mkdirSync(resolve(sharedDir, "utils"), { recursive: true });
|
|
392
|
+
writeFileSync(
|
|
393
|
+
resolve(sharedDir, "utils", "index.ts"),
|
|
394
|
+
"// Shared utility functions\nexport function formatDate(date: Date): string {\n return date.toISOString()\n}\n"
|
|
395
|
+
);
|
|
396
|
+
mkdirSync(resolve(sharedDir, "types"), { recursive: true });
|
|
397
|
+
writeFileSync(
|
|
398
|
+
resolve(sharedDir, "types", "index.ts"),
|
|
399
|
+
"// Shared types\nexport interface User {\n id: string\n name: string\n}\n"
|
|
400
|
+
);
|
|
401
|
+
console.log("\u2705 Created shared package");
|
|
402
|
+
}
|
|
403
|
+
async function addProject(name, root = process.cwd()) {
|
|
404
|
+
const projectDir = resolve(root, name);
|
|
405
|
+
if (existsSync(projectDir)) {
|
|
406
|
+
console.error(`\u274C Project ${name} already exists`);
|
|
407
|
+
process.exit(1);
|
|
408
|
+
}
|
|
409
|
+
console.log(`
|
|
410
|
+
\u{1F4E6} Creating project: ${name}
|
|
411
|
+
`);
|
|
412
|
+
mkdirSync(projectDir, { recursive: true });
|
|
413
|
+
const isWorkspace = existsSync(resolve(root, "bgl.config.ts"));
|
|
414
|
+
const packageJson = {
|
|
415
|
+
name,
|
|
416
|
+
type: "module",
|
|
417
|
+
scripts: {
|
|
418
|
+
dev: "vite",
|
|
419
|
+
build: "vite build",
|
|
420
|
+
preview: "vite preview"
|
|
421
|
+
},
|
|
422
|
+
dependencies: {},
|
|
423
|
+
devDependencies: {
|
|
424
|
+
"@vitejs/plugin-vue": "latest",
|
|
425
|
+
vite: "latest",
|
|
426
|
+
vue: "latest"
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
if (isWorkspace) {
|
|
430
|
+
packageJson.dependencies.shared = "workspace:*";
|
|
431
|
+
}
|
|
432
|
+
writeFileSync(
|
|
433
|
+
resolve(projectDir, "package.json"),
|
|
434
|
+
`${JSON.stringify(packageJson, null, 2)}
|
|
435
|
+
`
|
|
436
|
+
);
|
|
437
|
+
const bglConfigContent = isWorkspace ? `import { defineWorkspace } from '@bagelink/workspace'
|
|
438
|
+
import rootWorkspace from '../bgl.config'
|
|
439
|
+
|
|
440
|
+
export default defineWorkspace({
|
|
441
|
+
localhost: rootWorkspace('localhost'),
|
|
442
|
+
development: rootWorkspace('development'),
|
|
443
|
+
production: rootWorkspace('production'),
|
|
444
|
+
})
|
|
445
|
+
` : `import { defineWorkspace } from '@bagelink/workspace'
|
|
446
|
+
|
|
447
|
+
export default defineWorkspace({
|
|
448
|
+
localhost: {
|
|
449
|
+
host: 'http://localhost:8000',
|
|
450
|
+
proxy: '/api',
|
|
451
|
+
},
|
|
452
|
+
development: {
|
|
453
|
+
host: 'https://my-project.bagel.to',
|
|
454
|
+
proxy: '/api',
|
|
455
|
+
},
|
|
456
|
+
production: {
|
|
457
|
+
host: 'https://my-project.bagel.to',
|
|
458
|
+
proxy: '/api',
|
|
459
|
+
},
|
|
460
|
+
})
|
|
461
|
+
`;
|
|
462
|
+
writeFileSync(resolve(projectDir, "bgl.config.ts"), bglConfigContent);
|
|
463
|
+
const viteConfig = `import { defineConfig } from 'vite'
|
|
464
|
+
import vue from '@vitejs/plugin-vue'
|
|
465
|
+
import { createViteProxy } from '@bagelink/workspace'
|
|
466
|
+
import workspace from './bgl.config'
|
|
467
|
+
|
|
468
|
+
export default defineConfig(({ mode }) => {
|
|
469
|
+
const config = workspace(mode as 'localhost' | 'development' | 'production')
|
|
470
|
+
|
|
471
|
+
return {
|
|
472
|
+
plugins: [vue()],
|
|
473
|
+
server: {
|
|
474
|
+
proxy: createViteProxy(config),
|
|
475
|
+
},
|
|
476
|
+
}
|
|
477
|
+
})
|
|
478
|
+
`;
|
|
479
|
+
writeFileSync(resolve(projectDir, "vite.config.ts"), viteConfig);
|
|
480
|
+
const srcDir = resolve(projectDir, "src");
|
|
481
|
+
mkdirSync(srcDir, { recursive: true });
|
|
482
|
+
const indexHtml = `<!DOCTYPE html>
|
|
483
|
+
<html lang="en">
|
|
484
|
+
<head>
|
|
485
|
+
<meta charset="UTF-8">
|
|
486
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
487
|
+
<title>${name}</title>
|
|
488
|
+
</head>
|
|
489
|
+
<body>
|
|
490
|
+
<div id="app"></div>
|
|
491
|
+
<script type="module" src="/src/main.ts"><\/script>
|
|
492
|
+
</body>
|
|
493
|
+
</html>
|
|
494
|
+
`;
|
|
495
|
+
writeFileSync(resolve(projectDir, "index.html"), indexHtml);
|
|
496
|
+
const mainTs = `import { createApp } from 'vue'
|
|
497
|
+
import App from './App.vue'
|
|
498
|
+
|
|
499
|
+
createApp(App).mount('#app')
|
|
500
|
+
`;
|
|
501
|
+
writeFileSync(resolve(srcDir, "main.ts"), mainTs);
|
|
502
|
+
const appVue = `<script setup lang="ts">
|
|
503
|
+
import { ref } from 'vue'
|
|
504
|
+
${isWorkspace ? "import { formatDate } from 'shared/utils'\n" : ""}
|
|
505
|
+
const count = ref(0)
|
|
506
|
+
<\/script>
|
|
507
|
+
|
|
508
|
+
<template>
|
|
509
|
+
<div>
|
|
510
|
+
<h1>${name}</h1>
|
|
511
|
+
<button @click="count++">Count: {{ count }}</button>
|
|
512
|
+
${isWorkspace ? "<p>{{ formatDate(new Date()) }}</p>" : ""}
|
|
513
|
+
</div>
|
|
514
|
+
</template>
|
|
515
|
+
`;
|
|
516
|
+
writeFileSync(resolve(srcDir, "App.vue"), appVue);
|
|
517
|
+
console.log(`\u2705 Created project: ${name}`);
|
|
518
|
+
if (isWorkspace) {
|
|
519
|
+
updateWorkspaceScripts(root, name);
|
|
520
|
+
}
|
|
521
|
+
console.log("\nNext steps:");
|
|
522
|
+
console.log(` cd ${name}`);
|
|
523
|
+
console.log(" bun install");
|
|
524
|
+
console.log(" bun run dev");
|
|
525
|
+
console.log("");
|
|
526
|
+
}
|
|
527
|
+
function updateWorkspaceScripts(root, projectName) {
|
|
528
|
+
const packageJsonPath = resolve(root, "package.json");
|
|
529
|
+
if (!existsSync(packageJsonPath)) return;
|
|
530
|
+
try {
|
|
531
|
+
const packageJson = JSON.parse(
|
|
532
|
+
require("fs").readFileSync(packageJsonPath, "utf-8")
|
|
533
|
+
);
|
|
534
|
+
if (!packageJson.scripts) {
|
|
535
|
+
packageJson.scripts = {};
|
|
536
|
+
}
|
|
537
|
+
packageJson.scripts[`dev:${projectName}`] = `bun --filter ${projectName} dev`;
|
|
538
|
+
packageJson.scripts[`build:${projectName}`] = `bun --filter ${projectName} build`;
|
|
539
|
+
writeFileSync(
|
|
540
|
+
packageJsonPath,
|
|
541
|
+
`${JSON.stringify(packageJson, null, 2)}
|
|
542
|
+
`
|
|
543
|
+
);
|
|
544
|
+
console.log(`\u2705 Added scripts: dev:${projectName}, build:${projectName}`);
|
|
545
|
+
} catch (error) {
|
|
546
|
+
console.warn("\u26A0\uFE0F Could not update workspace scripts");
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
function listProjects(root = process.cwd()) {
|
|
550
|
+
try {
|
|
551
|
+
const items = readdirSync(root, { withFileTypes: true });
|
|
552
|
+
return items.filter(
|
|
553
|
+
(item) => item.isDirectory() && item.name !== "node_modules" && item.name !== "shared" && item.name !== ".git" && !item.name.startsWith(".")
|
|
554
|
+
).map((item) => item.name);
|
|
555
|
+
} catch {
|
|
556
|
+
return [];
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
export { generateNetlifyConfig as a, generateNetlifyRedirect as b, generateWorkspaceConfigSync as c, addProject as d, generateWorkspaceConfig as g, initWorkspace as i, listProjects as l, setBuildEnvVars as s, writeNetlifyConfig as w };
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
package/src/init.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import type { WorkspaceConfig } from './types'
|
|
1
2
|
import { existsSync, readFileSync, writeFileSync } from 'node:fs'
|
|
2
3
|
import { resolve } from 'node:path'
|
|
3
4
|
import process from 'node:process'
|
|
4
5
|
import prompts from 'prompts'
|
|
6
|
+
import { writeNetlifyConfig } from './netlify'
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* Generate bgl.config.ts file interactively
|
|
@@ -75,12 +77,12 @@ export default defineWorkspace(configs)
|
|
|
75
77
|
console.log(` Production host: ${productionHost}`)
|
|
76
78
|
console.log(` Local dev host: http://localhost:8000\n`)
|
|
77
79
|
|
|
78
|
-
// Ask if they want to update package.json and
|
|
80
|
+
// Ask if they want to update package.json, vite.config, and netlify.toml
|
|
79
81
|
const setupResponse = await prompts([
|
|
80
82
|
{
|
|
81
83
|
type: 'confirm',
|
|
82
84
|
name: 'updatePackageJson',
|
|
83
|
-
message: 'Add dev scripts
|
|
85
|
+
message: 'Add/update dev scripts in package.json?',
|
|
84
86
|
initial: true,
|
|
85
87
|
},
|
|
86
88
|
{
|
|
@@ -89,6 +91,12 @@ export default defineWorkspace(configs)
|
|
|
89
91
|
message: 'Create/update vite.config.ts?',
|
|
90
92
|
initial: true,
|
|
91
93
|
},
|
|
94
|
+
{
|
|
95
|
+
type: 'confirm',
|
|
96
|
+
name: 'generateNetlify',
|
|
97
|
+
message: 'Generate netlify.toml for deployment?',
|
|
98
|
+
initial: true,
|
|
99
|
+
},
|
|
92
100
|
])
|
|
93
101
|
|
|
94
102
|
if (setupResponse.updatePackageJson) {
|
|
@@ -99,6 +107,14 @@ export default defineWorkspace(configs)
|
|
|
99
107
|
updateViteConfig(root)
|
|
100
108
|
}
|
|
101
109
|
|
|
110
|
+
if (setupResponse.generateNetlify) {
|
|
111
|
+
const prodConfig: WorkspaceConfig = {
|
|
112
|
+
host: productionHost,
|
|
113
|
+
proxy: '/api',
|
|
114
|
+
}
|
|
115
|
+
writeNetlifyConfig(prodConfig, resolve(root, 'netlify.toml'))
|
|
116
|
+
}
|
|
117
|
+
|
|
102
118
|
console.log('\nš” You can edit these files to customize your configuration.\n')
|
|
103
119
|
}
|
|
104
120
|
|
|
@@ -160,7 +176,7 @@ function updatePackageJsonScripts(root: string): void {
|
|
|
160
176
|
packageJson.scripts = {}
|
|
161
177
|
}
|
|
162
178
|
|
|
163
|
-
// Add scripts
|
|
179
|
+
// Add/overwrite dev scripts
|
|
164
180
|
const scriptsToAdd = {
|
|
165
181
|
'dev': 'vite',
|
|
166
182
|
'dev:local': 'vite --mode localhost',
|
|
@@ -168,20 +184,31 @@ function updatePackageJsonScripts(root: string): void {
|
|
|
168
184
|
'preview': 'vite preview',
|
|
169
185
|
}
|
|
170
186
|
|
|
171
|
-
|
|
187
|
+
// Always overwrite dev and dev:local, preserve others if they exist
|
|
188
|
+
let modified = false
|
|
172
189
|
for (const [key, value] of Object.entries(scriptsToAdd)) {
|
|
173
|
-
if (
|
|
174
|
-
|
|
175
|
-
|
|
190
|
+
if (key === 'dev' || key === 'dev:local') {
|
|
191
|
+
// Always overwrite these
|
|
192
|
+
if (packageJson.scripts[key] !== value) {
|
|
193
|
+
packageJson.scripts[key] = value
|
|
194
|
+
modified = true
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
// Only add if doesn't exist
|
|
199
|
+
if (!packageJson.scripts[key]) {
|
|
200
|
+
packageJson.scripts[key] = value
|
|
201
|
+
modified = true
|
|
202
|
+
}
|
|
176
203
|
}
|
|
177
204
|
}
|
|
178
205
|
|
|
179
|
-
if (
|
|
206
|
+
if (modified) {
|
|
180
207
|
writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`, 'utf-8')
|
|
181
208
|
console.log('ā
Updated package.json with dev scripts')
|
|
182
209
|
}
|
|
183
210
|
else {
|
|
184
|
-
console.log('ā¹ļø Scripts already
|
|
211
|
+
console.log('ā¹ļø Scripts already up to date in package.json')
|
|
185
212
|
}
|
|
186
213
|
}
|
|
187
214
|
catch (error) {
|