wexts 4.0.0 → 4.1.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.
Files changed (41) hide show
  1. package/dist/chunk-342VRT25.mjs +504 -0
  2. package/dist/chunk-342VRT25.mjs.map +1 -0
  3. package/dist/chunk-7HNQWJWV.js +504 -0
  4. package/dist/chunk-7HNQWJWV.js.map +1 -0
  5. package/dist/chunk-7SSCNCTW.mjs +137 -0
  6. package/dist/chunk-7SSCNCTW.mjs.map +1 -0
  7. package/dist/chunk-7TLSPR65.mjs +95 -0
  8. package/dist/chunk-7TLSPR65.mjs.map +1 -0
  9. package/dist/chunk-AVMQJWYD.js +95 -0
  10. package/dist/chunk-AVMQJWYD.js.map +1 -0
  11. package/dist/chunk-O4II6N34.js +137 -0
  12. package/dist/chunk-O4II6N34.js.map +1 -0
  13. package/dist/cli/index.d.mts +13 -1
  14. package/dist/cli/index.d.ts +13 -1
  15. package/dist/cli/index.js +438 -54
  16. package/dist/cli/index.js.map +1 -1
  17. package/dist/cli/index.mjs +438 -54
  18. package/dist/cli/index.mjs.map +1 -1
  19. package/dist/client/index.js +3 -2
  20. package/dist/client/index.js.map +1 -1
  21. package/dist/client/index.mjs +2 -1
  22. package/dist/codegen/index.js +3 -2
  23. package/dist/codegen/index.js.map +1 -1
  24. package/dist/codegen/index.mjs +2 -1
  25. package/dist/index.d.mts +37 -1
  26. package/dist/index.d.ts +37 -1
  27. package/dist/index.js +22 -8
  28. package/dist/index.js.map +1 -1
  29. package/dist/index.mjs +18 -4
  30. package/dist/index.mjs.map +1 -1
  31. package/dist/next/index.js +68 -5
  32. package/dist/next/index.js.map +1 -1
  33. package/dist/next/index.mjs +68 -5
  34. package/dist/next/index.mjs.map +1 -1
  35. package/dist/runtime/index.js +9 -1
  36. package/dist/runtime/index.js.map +1 -1
  37. package/dist/runtime/index.mjs +9 -1
  38. package/dist/runtime/index.mjs.map +1 -1
  39. package/package.json +1 -1
  40. package/templates/nestjs-api/package-lock.json +0 -5623
  41. package/templates/nextjs-web/package-lock.json +0 -3254
package/dist/cli/index.js CHANGED
@@ -4,6 +4,10 @@
4
4
  var _chunkWCKSKU3Cjs = require('../chunk-WCKSKU3C.js');
5
5
 
6
6
 
7
+
8
+ var _chunkAVMQJWYDjs = require('../chunk-AVMQJWYD.js');
9
+
10
+
7
11
  var _chunkXE4OXN2Wjs = require('../chunk-XE4OXN2W.js');
8
12
 
9
13
  // src/cli/index.ts
@@ -14,8 +18,8 @@ var _child_process = require('child_process');
14
18
  var _module = require('module');
15
19
  function createCliProgram() {
16
20
  const program = new (0, _commander.Command)();
17
- program.name("wexts").description("Wexts - production-focused single-runtime Next.js + NestJS toolkit").version("3.0.3");
18
- program.command("create <project-name>").description("Create a compatibility project from bundled legacy templates").option("-t, --template <template>", "Legacy template to use (monorepo|api|web)", "monorepo").option("--skip-install", "Skip dependency installation", false).action(async (projectName, options) => {
21
+ program.name("wexts").description("Wexts - production-focused single-runtime Next.js + NestJS toolkit").version(readPackageVersion());
22
+ program.command("create <project-name>").description("Create a verified Wexts starter").option("-t, --template <template>", "Template to use (starter|legacy)", "starter").option("--skip-install", "Skip dependency installation", false).action(async (projectName, options) => {
19
23
  await createProject(projectName, options.template, {
20
24
  skipInstall: options.skipInstall
21
25
  });
@@ -31,8 +35,8 @@ function createCliProgram() {
31
35
  useProxy: options.proxy
32
36
  });
33
37
  });
34
- program.command("generate [type] [name]").alias("g").description("Generate RPC manifest/client, or scaffold a minimal RPC service").option("-p, --project <path>", "Path to NestJS project", "./apps/api").option("-o, --output <path>", "Output directory for generated RPC client", "./apps/web/lib/wexts").action(async (type, name, options) => {
35
- if (!type || type === "rpc") {
38
+ program.command("generate [type] [name]").alias("g").description("Generate RPC manifest/client, or scaffold a minimal RPC service").option("-p, --project <path>", "Path to NestJS project", "./apps/api").option("-o, --output <path>", "Output directory for generated RPC client", "./apps/web/lib/wexts").option("--force", "Overwrite generated files if they already exist", false).action(async (type, name, options) => {
39
+ if (!type || type === "rpc" && !name) {
36
40
  const { generateRpcClient } = await Promise.resolve().then(() => _interopRequireWildcard(require("../codegen/index.js")));
37
41
  const manifest = await generateRpcClient({
38
42
  projectPath: path.resolve(options.project),
@@ -41,13 +45,19 @@ function createCliProgram() {
41
45
  _chunkWCKSKU3Cjs.logger.success(`Generated Wexts RPC client for ${manifest.services.length} service(s).`);
42
46
  return;
43
47
  }
44
- if (type === "service") {
45
- if (!name) throw new Error("Service name is required: wexts generate service hello");
46
- await scaffoldRpcService(path.resolve(options.project), name);
47
- _chunkWCKSKU3Cjs.logger.success(`Created RPC service ${name}. Run wexts generate to update the client.`);
48
+ if (isScaffoldGenerator(type)) {
49
+ const targetRoot = type === "config" ? process.cwd() : path.resolve(options.project);
50
+ const changedFiles = await scaffoldGenerator({
51
+ type,
52
+ name,
53
+ targetRoot,
54
+ force: options.force
55
+ });
56
+ for (const file of changedFiles) _chunkWCKSKU3Cjs.logger.info(`created ${path.relative(process.cwd(), file)}`);
57
+ _chunkWCKSKU3Cjs.logger.success(`Generated ${type}${name ? ` ${name}` : ""}.`);
48
58
  return;
49
59
  }
50
- throw new Error(`Unknown generator "${type}". Supported generators: rpc, service.`);
60
+ throw new Error(`Unknown generator "${type}". Supported generators: rpc, service, module, entity, guard, config.`);
51
61
  });
52
62
  program.command("codegen").description("Alias for wexts generate rpc").option("-p, --project <path>", "Path to NestJS project", "./apps/api").option("-o, --output <path>", "Output directory for generated RPC client", "./apps/web/lib/wexts").action(async (options) => {
53
63
  const { generateRpcClient } = await Promise.resolve().then(() => _interopRequireWildcard(require("../codegen/index.js")));
@@ -155,78 +165,438 @@ async function createProject(projectName, template, options) {
155
165
  if (fs.existsSync(projectPath)) {
156
166
  throw new Error(`Directory already exists: ${projectName}`);
157
167
  }
158
- const templatePath = findTemplatePath();
159
- if (!templatePath) {
160
- throw new Error("Template directory not found in package.");
161
- }
162
168
  fs.mkdirSync(projectPath, {
163
169
  recursive: true
164
170
  });
165
- if (template === "monorepo") {
166
- fs.mkdirSync(path.join(projectPath, "apps"), {
167
- recursive: true
168
- });
169
- fs.cpSync(path.join(templatePath, "nestjs-api"), path.join(projectPath, "apps/api"), {
170
- recursive: true
171
- });
172
- fs.cpSync(path.join(templatePath, "nextjs-web"), path.join(projectPath, "apps/web"), {
173
- recursive: true
174
- });
175
- fs.writeFileSync(path.join(projectPath, "pnpm-workspace.yaml"), "packages:\n - 'apps/*'\n");
176
- fs.writeFileSync(path.join(projectPath, "package.json"), JSON.stringify({
171
+ if (template === "starter") {
172
+ await createVerifiedStarter(projectPath, projectName, _nullishCoalesce(options.wextsDependency, () => ( resolveCreateWextsDependency(projectPath))));
173
+ } else if (template === "legacy") {
174
+ createLegacyProject(projectPath, projectName);
175
+ } else {
176
+ throw new Error(`Unknown template "${template}". Supported templates: starter, legacy.`);
177
+ }
178
+ if (!options.skipInstall) {
179
+ runCommand(detectPackageManager(projectPath), [
180
+ "install"
181
+ ], projectPath);
182
+ }
183
+ }
184
+ _chunkXE4OXN2Wjs.__name.call(void 0, createProject, "createProject");
185
+ async function createVerifiedStarter(projectPath, projectName, wextsDependency) {
186
+ const files = {
187
+ "pnpm-workspace.yaml": "packages:\n - 'apps/*'\n",
188
+ "package.json": JSON.stringify({
177
189
  name: projectName,
190
+ version: "0.1.0",
178
191
  private: true,
179
192
  packageManager: "pnpm@10.22.0",
180
193
  scripts: {
181
194
  dev: "wexts dev",
182
- generate: "wexts generate",
183
- build: "wexts build",
184
- start: "wexts start",
185
- doctor: "wexts doctor"
195
+ generate: "wexts generate -p apps/api -o apps/web/lib/wexts",
196
+ build: "pnpm run generate && tsc -p apps/api/tsconfig.json && next build apps/web",
197
+ start: "wexts start -c ./wexts.runtime.js",
198
+ "vercel-build": "wexts vercel-build -p apps/api -o apps/web/lib/wexts -c ./wexts.runtime.js",
199
+ doctor: "wexts doctor",
200
+ "doctor:security": "wexts doctor --security"
201
+ },
202
+ dependencies: {
203
+ "@nestjs/common": "^11.1.19",
204
+ "@nestjs/core": "^11.1.19",
205
+ "@nestjs/platform-fastify": "^11.1.19",
206
+ next: "16.2.4",
207
+ react: "^19.2.5",
208
+ "react-dom": "^19.2.5",
209
+ "reflect-metadata": "^0.2.2",
210
+ rxjs: "^7.8.1",
211
+ wexts: wextsDependency
186
212
  },
187
213
  devDependencies: {
188
- wexts: "latest"
214
+ "@types/node": "^22.19.1",
215
+ "@types/react": "^19.2.14",
216
+ "@types/react-dom": "^19.2.3",
217
+ typescript: "^5.9.3"
189
218
  }
190
- }, null, 2));
191
- } else if (template === "api") {
192
- fs.cpSync(path.join(templatePath, "nestjs-api"), projectPath, {
219
+ }, null, 2),
220
+ "apps/api/package.json": JSON.stringify({
221
+ name: `${projectName}-api`,
222
+ private: true,
223
+ scripts: {
224
+ "start:dev": "tsc -w -p tsconfig.json"
225
+ }
226
+ }, null, 2),
227
+ "apps/api/tsconfig.json": JSON.stringify({
228
+ compilerOptions: {
229
+ target: "ES2023",
230
+ module: "NodeNext",
231
+ moduleResolution: "NodeNext",
232
+ experimentalDecorators: true,
233
+ emitDecoratorMetadata: true,
234
+ strict: true,
235
+ esModuleInterop: true,
236
+ skipLibCheck: true,
237
+ outDir: "dist",
238
+ rootDir: "src"
239
+ },
240
+ include: [
241
+ "src/**/*.ts"
242
+ ]
243
+ }, null, 2),
244
+ "apps/api/src/hello.service.ts": `import { Injectable } from '@nestjs/common';
245
+ import { RpcMethod, RpcService } from 'wexts/nest';
246
+
247
+ @Injectable()
248
+ @RpcService({ name: 'hello', requireAuth: false })
249
+ export class HelloService {
250
+ @RpcMethod()
251
+ async sayHello(name: string): Promise<string> {
252
+ return \`Hello, \${name}!\`;
253
+ }
254
+ }
255
+ `,
256
+ "apps/web/package.json": JSON.stringify({
257
+ name: `${projectName}-web`,
258
+ private: true,
259
+ scripts: {
260
+ dev: "next dev -p 3000"
261
+ }
262
+ }, null, 2),
263
+ "apps/web/tsconfig.json": JSON.stringify({
264
+ compilerOptions: {
265
+ target: "ES2022",
266
+ lib: [
267
+ "dom",
268
+ "dom.iterable",
269
+ "es2022"
270
+ ],
271
+ allowJs: false,
272
+ skipLibCheck: true,
273
+ strict: true,
274
+ noEmit: true,
275
+ esModuleInterop: true,
276
+ module: "esnext",
277
+ moduleResolution: "bundler",
278
+ resolveJsonModule: true,
279
+ isolatedModules: true,
280
+ jsx: "react-jsx",
281
+ incremental: true,
282
+ plugins: [
283
+ {
284
+ name: "next"
285
+ }
286
+ ]
287
+ },
288
+ include: [
289
+ "next-env.d.ts",
290
+ "**/*.ts",
291
+ "**/*.tsx",
292
+ ".next/types/**/*.ts",
293
+ ".next/dev/types/**/*.ts"
294
+ ],
295
+ exclude: [
296
+ "node_modules"
297
+ ]
298
+ }, null, 2),
299
+ "apps/web/next-env.d.ts": `/// <reference types="next" />
300
+ /// <reference types="next/image-types/global" />
301
+
302
+ // This file is generated by Next.js. Do not edit.
303
+ `,
304
+ "apps/web/next.config.ts": `import type { NextConfig } from 'next';
305
+
306
+ const nextConfig: NextConfig = {
307
+ output: 'standalone',
308
+ };
309
+
310
+ export default nextConfig;
311
+ `,
312
+ "apps/web/app/layout.tsx": `import type { ReactNode } from 'react';
313
+ import { WextsProvider } from '../lib/wexts-provider';
314
+
315
+ export default function RootLayout({ children }: { children: ReactNode }) {
316
+ return (
317
+ <html lang="en">
318
+ <body>
319
+ <WextsProvider>{children}</WextsProvider>
320
+ </body>
321
+ </html>
322
+ );
323
+ }
324
+ `,
325
+ "apps/web/app/page.tsx": `'use client';
326
+
327
+ import { useState } from 'react';
328
+ import { useWexts } from '../lib/wexts-provider';
329
+
330
+ export default function Page() {
331
+ const wexts = useWexts();
332
+ const [message, setMessage] = useState('Not called yet');
333
+
334
+ return (
335
+ <main>
336
+ <h1>Wexts Hello RPC</h1>
337
+ <button
338
+ type="button"
339
+ onClick={async () => {
340
+ setMessage(await wexts.hello.sayHello('Bob'));
341
+ }}
342
+ >
343
+ Call RPC
344
+ </button>
345
+ <p>{message}</p>
346
+ </main>
347
+ );
348
+ }
349
+ `,
350
+ "apps/web/lib/wexts-provider.tsx": `'use client';
351
+
352
+ import { FusionProvider, useWexts as useGeneratedWexts } from 'wexts/next';
353
+ import { createWextsClient, type WextsClient } from './wexts/client';
354
+
355
+ export function WextsProvider({ children }: { children: React.ReactNode }) {
356
+ return (
357
+ <FusionProvider rpcClient={createWextsClient({ baseUrl: '/rpc' })}>
358
+ {children}
359
+ </FusionProvider>
360
+ );
361
+ }
362
+
363
+ export function useWexts(): WextsClient {
364
+ return useGeneratedWexts<WextsClient>();
365
+ }
366
+ `,
367
+ "wexts.runtime.js": `const { HelloService } = require('./apps/api/dist/hello.service.js');
368
+
369
+ module.exports = {
370
+ nextDir: './apps/web',
371
+ rpcManifestPath: './apps/web/lib/wexts/wexts.rpc.manifest.json',
372
+ rpcServices: {
373
+ hello: new HelloService(),
374
+ },
375
+ security: {
376
+ allowedOrigins: ['http://localhost:3000'],
377
+ },
378
+ };
379
+ `,
380
+ "README.md": `# ${projectName}
381
+
382
+ Verified Wexts starter with a generated Hello RPC client.
383
+
384
+ \`\`\`bash
385
+ pnpm install
386
+ pnpm run generate
387
+ pnpm run build
388
+ pnpm run doctor
389
+ pnpm run doctor:security
390
+ pnpm run start
391
+ \`\`\`
392
+ `
393
+ };
394
+ for (const [relativePath, content] of Object.entries(files)) {
395
+ const absolutePath = path.join(projectPath, relativePath);
396
+ fs.mkdirSync(path.dirname(absolutePath), {
193
397
  recursive: true
194
398
  });
195
- } else if (template === "web") {
196
- fs.cpSync(path.join(templatePath, "nextjs-web"), projectPath, {
197
- recursive: true
399
+ fs.writeFileSync(absolutePath, content);
400
+ }
401
+ const { generateRpcClient } = await Promise.resolve().then(() => _interopRequireWildcard(require("../codegen/index.js")));
402
+ await generateRpcClient({
403
+ projectPath: path.join(projectPath, "apps/api"),
404
+ outputPath: path.join(projectPath, "apps/web/lib/wexts")
405
+ });
406
+ }
407
+ _chunkXE4OXN2Wjs.__name.call(void 0, createVerifiedStarter, "createVerifiedStarter");
408
+ function createLegacyProject(projectPath, projectName) {
409
+ const templatePath = findTemplatePath();
410
+ if (!templatePath) {
411
+ throw new Error("Template directory not found in package.");
412
+ }
413
+ fs.mkdirSync(path.join(projectPath, "apps"), {
414
+ recursive: true
415
+ });
416
+ fs.cpSync(path.join(templatePath, "nestjs-api"), path.join(projectPath, "apps/api"), {
417
+ recursive: true
418
+ });
419
+ fs.cpSync(path.join(templatePath, "nextjs-web"), path.join(projectPath, "apps/web"), {
420
+ recursive: true
421
+ });
422
+ fs.rmSync(path.join(projectPath, "apps/web/package-lock.json"), {
423
+ force: true
424
+ });
425
+ fs.rmSync(path.join(projectPath, "apps/api/package-lock.json"), {
426
+ force: true
427
+ });
428
+ fs.writeFileSync(path.join(projectPath, "pnpm-workspace.yaml"), "packages:\n - 'apps/*'\n");
429
+ fs.writeFileSync(path.join(projectPath, "package.json"), JSON.stringify({
430
+ name: projectName,
431
+ private: true,
432
+ packageManager: "pnpm@10.22.0",
433
+ scripts: {
434
+ dev: "wexts dev",
435
+ generate: "wexts generate",
436
+ build: "wexts build",
437
+ start: "wexts start",
438
+ doctor: "wexts doctor"
439
+ },
440
+ devDependencies: {
441
+ wexts: `^${readPackageVersion()}`
442
+ }
443
+ }, null, 2));
444
+ }
445
+ _chunkXE4OXN2Wjs.__name.call(void 0, createLegacyProject, "createLegacyProject");
446
+ function resolveCreateWextsDependency(projectPath) {
447
+ const packageRoot = path.resolve(__dirname, "../..");
448
+ const cwdLocalPackage = path.join(process.cwd(), "node_modules/wexts");
449
+ try {
450
+ if (fs.existsSync(cwdLocalPackage) && fs.realpathSync(cwdLocalPackage) === fs.realpathSync(packageRoot)) {
451
+ return `file:${path.relative(projectPath, cwdLocalPackage)}`;
452
+ }
453
+ } catch (e) {
454
+ }
455
+ return `^${readPackageVersion()}`;
456
+ }
457
+ _chunkXE4OXN2Wjs.__name.call(void 0, resolveCreateWextsDependency, "resolveCreateWextsDependency");
458
+ async function scaffoldGenerator(options) {
459
+ if (options.type !== "config" && !options.name) {
460
+ throw new (0, _chunkAVMQJWYDjs.WextsError)({
461
+ code: "WEXTS_CLI_GENERATOR_NAME_REQUIRED",
462
+ message: `Generator "${options.type}" requires a name.`,
463
+ suggestedFix: `Run \`wexts generate ${options.type} hello\` or use \`wexts generate config\`.`,
464
+ docsSlug: "cli"
198
465
  });
199
- } else {
200
- throw new Error(`Unknown template "${template}".`);
201
466
  }
202
- if (!options.skipInstall) {
203
- runCommand(detectPackageManager(projectPath), [
204
- "install"
205
- ], projectPath);
467
+ if (options.type === "config") {
468
+ return writeGeneratedFiles(options.targetRoot, [
469
+ {
470
+ relativePath: "wexts.runtime.js",
471
+ content: `/** @type {import('wexts/runtime').WextsRuntimeConfig} */
472
+ module.exports = {
473
+ rootDir: __dirname,
474
+ port: Number(process.env.PORT || 3000),
475
+ rpcManifestPath: 'apps/web/lib/wexts/wexts.rpc.manifest.json',
476
+ security: {
477
+ enabled: true,
478
+ production: process.env.NODE_ENV === 'production',
479
+ allowedOrigins: process.env.WEXTS_ALLOWED_ORIGINS?.split(',').filter(Boolean) || [],
480
+ },
481
+ };
482
+ `
483
+ }
484
+ ], Boolean(options.force));
485
+ }
486
+ const rawName = options.name;
487
+ const name = toKebabCase(rawName);
488
+ const classBase = toPascalCase(name);
489
+ const srcRoot = path.join(options.targetRoot, "src");
490
+ const filesByType = {
491
+ rpc: rpcServiceFiles(name, classBase),
492
+ service: [
493
+ {
494
+ relativePath: path.join("src", name, `${name}.service.ts`),
495
+ content: `import { Injectable } from '@nestjs/common';
496
+
497
+ @Injectable()
498
+ export class ${classBase}Service {
499
+ async execute(): Promise<string> {
500
+ return '${toCamelCase(name)}';
206
501
  }
207
502
  }
208
- _chunkXE4OXN2Wjs.__name.call(void 0, createProject, "createProject");
209
- async function scaffoldRpcService(apiProjectPath, rawName) {
210
- const serviceName = toKebabCase(rawName);
211
- const className = `${toPascalCase(serviceName)}Service`;
212
- const dir = path.join(apiProjectPath, "src", serviceName);
213
- fs.mkdirSync(dir, {
503
+ `
504
+ }
505
+ ],
506
+ module: [
507
+ {
508
+ relativePath: path.join("src", name, `${name}.module.ts`),
509
+ content: `import { Module } from '@nestjs/common';
510
+
511
+ @Module({})
512
+ export class ${classBase}Module {}
513
+ `
514
+ }
515
+ ],
516
+ entity: [
517
+ {
518
+ relativePath: path.join("src", name, `${name}.entity.ts`),
519
+ content: `export interface ${classBase}Entity {
520
+ id: string;
521
+ createdAt: Date;
522
+ updatedAt: Date;
523
+ }
524
+ `
525
+ }
526
+ ],
527
+ guard: [
528
+ {
529
+ relativePath: path.join("src", name, `${name}.guard.ts`),
530
+ content: `import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
531
+
532
+ @Injectable()
533
+ export class ${classBase}Guard implements CanActivate {
534
+ canActivate(_context: ExecutionContext): boolean {
535
+ return true;
536
+ }
537
+ }
538
+ `
539
+ }
540
+ ]
541
+ };
542
+ fs.mkdirSync(srcRoot, {
214
543
  recursive: true
215
544
  });
216
- fs.writeFileSync(path.join(dir, `${serviceName}.service.ts`), `import { Injectable } from '@nestjs/common';
545
+ return writeGeneratedFiles(options.targetRoot, filesByType[options.type], Boolean(options.force));
546
+ }
547
+ _chunkXE4OXN2Wjs.__name.call(void 0, scaffoldGenerator, "scaffoldGenerator");
548
+ function isScaffoldGenerator(type) {
549
+ return [
550
+ "rpc",
551
+ "service",
552
+ "module",
553
+ "entity",
554
+ "guard",
555
+ "config"
556
+ ].includes(type);
557
+ }
558
+ _chunkXE4OXN2Wjs.__name.call(void 0, isScaffoldGenerator, "isScaffoldGenerator");
559
+ function rpcServiceFiles(serviceName, classBase) {
560
+ return [
561
+ {
562
+ relativePath: path.join("src", serviceName, `${serviceName}.service.ts`),
563
+ content: `import { Injectable } from '@nestjs/common';
217
564
  import { RpcMethod, RpcService } from 'wexts/nest';
218
565
 
219
566
  @Injectable()
220
567
  @RpcService({ name: '${toCamelCase(serviceName)}', requireAuth: false })
221
- export class ${className} {
568
+ export class ${classBase}Service {
222
569
  @RpcMethod()
223
570
  async sayHello(name: string): Promise<string> {
224
571
  return \`Hello, \${name}!\`;
225
572
  }
226
573
  }
227
- `);
574
+ `
575
+ }
576
+ ];
577
+ }
578
+ _chunkXE4OXN2Wjs.__name.call(void 0, rpcServiceFiles, "rpcServiceFiles");
579
+ function writeGeneratedFiles(root, files, force) {
580
+ const changedFiles = [];
581
+ for (const file of files) {
582
+ const absolutePath = path.join(root, file.relativePath);
583
+ if (fs.existsSync(absolutePath) && !force) {
584
+ throw new (0, _chunkAVMQJWYDjs.WextsError)({
585
+ code: "WEXTS_CLI_GENERATOR_FILE_EXISTS",
586
+ message: `Refusing to overwrite existing file: ${absolutePath}`,
587
+ suggestedFix: "Review the file, then rerun with --force if overwriting is intentional.",
588
+ docsSlug: "cli"
589
+ });
590
+ }
591
+ fs.mkdirSync(path.dirname(absolutePath), {
592
+ recursive: true
593
+ });
594
+ fs.writeFileSync(absolutePath, file.content);
595
+ changedFiles.push(absolutePath);
596
+ }
597
+ return changedFiles;
228
598
  }
229
- _chunkXE4OXN2Wjs.__name.call(void 0, scaffoldRpcService, "scaffoldRpcService");
599
+ _chunkXE4OXN2Wjs.__name.call(void 0, writeGeneratedFiles, "writeGeneratedFiles");
230
600
  function runScript(script, options) {
231
601
  const cwd = _nullishCoalesce(options.cwd, () => ( process.cwd()));
232
602
  const packageManager = detectPackageManager(cwd);
@@ -252,7 +622,13 @@ function runCommand(command, args, cwd) {
252
622
  }
253
623
  _chunkXE4OXN2Wjs.__name.call(void 0, runCommand, "runCommand");
254
624
  function detectPackageManager(cwd) {
625
+ const packageJsonPath = path.join(cwd, "package.json");
626
+ if (fs.existsSync(packageJsonPath)) {
627
+ const pkg = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
628
+ if (_optionalChain([pkg, 'access', _4 => _4.packageManager, 'optionalAccess', _5 => _5.startsWith, 'call', _6 => _6("pnpm@")])) return "pnpm";
629
+ }
255
630
  if (fs.existsSync(path.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
631
+ if (fs.existsSync(path.join(cwd, "pnpm-workspace.yaml"))) return "pnpm";
256
632
  return "npm";
257
633
  }
258
634
  _chunkXE4OXN2Wjs.__name.call(void 0, detectPackageManager, "detectPackageManager");
@@ -265,6 +641,12 @@ function findTemplatePath() {
265
641
  return candidates.find((candidate) => fs.existsSync(candidate));
266
642
  }
267
643
  _chunkXE4OXN2Wjs.__name.call(void 0, findTemplatePath, "findTemplatePath");
644
+ function readPackageVersion() {
645
+ const packageJsonPath = path.resolve(__dirname, "../../package.json");
646
+ if (!fs.existsSync(packageJsonPath)) return "0.0.0";
647
+ return JSON.parse(fs.readFileSync(packageJsonPath, "utf8")).version;
648
+ }
649
+ _chunkXE4OXN2Wjs.__name.call(void 0, readPackageVersion, "readPackageVersion");
268
650
  function readAllText(cwd, dirs) {
269
651
  let text = "";
270
652
  for (const dir of dirs) {
@@ -321,12 +703,14 @@ _chunkXE4OXN2Wjs.__name.call(void 0, loadRuntimeConfig, "loadRuntimeConfig");
321
703
  var invokedAsCli = process.argv[1] && (path.basename(process.argv[1]) === "wexts" || path.basename(process.argv[1]) === "wexts.cjs" || path.resolve(process.argv[1]).includes(`${path.sep}dist${path.sep}cli${path.sep}index`));
322
704
  if (invokedAsCli && !process.env.VITEST) {
323
705
  createCliProgram().parseAsync(process.argv).catch((error) => {
324
- _chunkWCKSKU3Cjs.logger.error(error instanceof Error ? error.message : String(error));
706
+ _chunkWCKSKU3Cjs.logger.error(_chunkAVMQJWYDjs.formatWextsError.call(void 0, error));
325
707
  process.exit(1);
326
708
  });
327
709
  }
328
710
 
329
711
 
330
712
 
331
- exports.createCliProgram = createCliProgram; exports.runDoctor = runDoctor;
713
+
714
+
715
+ exports.createCliProgram = createCliProgram; exports.createProject = createProject; exports.runDoctor = runDoctor; exports.scaffoldGenerator = scaffoldGenerator;
332
716
  //# sourceMappingURL=index.js.map