stonyx 0.2.3-beta.57 → 0.2.3-beta.59

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/dist/cli/new.d.ts CHANGED
@@ -8,9 +8,18 @@ export declare function generateDbSchema(): string;
8
8
  export declare function generatePackageJson(name: string, selectedModules: ModuleOption[]): string;
9
9
  export declare function generateAppTs(): string;
10
10
  export declare function generateEnvironmentTs(): string;
11
+ export declare function generateTestEnvironmentTs(): string;
12
+ export declare function generateSetupTs(): string;
13
+ export declare function generateZzExitTestTs(): string;
11
14
  export declare function generateEnvironmentExampleTs(): string;
12
15
  export declare function generateGitignore(): string;
13
16
  export declare function generateTsConfig(): string;
17
+ /**
18
+ * Write every scaffolded file to disk given a resolved project directory,
19
+ * app name, and pre-selected module options. Factored out of `newCommand`
20
+ * so tests can exercise the file-writing path without interactive prompts.
21
+ */
22
+ export declare function scaffoldProject(projectDir: string, appName: string, selectedModules: ModuleOption[]): Promise<void>;
14
23
  export default function newCommand({ args }: {
15
24
  args: string[];
16
25
  }): Promise<void>;
package/dist/cli/new.js CHANGED
@@ -50,7 +50,9 @@ export default class DBModel extends Model {
50
50
  }
51
51
  export function generatePackageJson(name, selectedModules) {
52
52
  const devDependencies = {
53
+ qunit: '^2.24.1',
53
54
  stonyx: 'latest',
55
+ tsx: '^4.21.0',
54
56
  typescript: '^5.8.3'
55
57
  };
56
58
  for (const mod of selectedModules) {
@@ -65,8 +67,9 @@ export function generatePackageJson(name, selectedModules) {
65
67
  private: true,
66
68
  scripts: {
67
69
  build: 'tsc',
70
+ serve: 'stonyx serve',
68
71
  start: 'stonyx serve',
69
- test: 'stonyx test'
72
+ test: "NODE_ENV=test node --import tsx/esm --import ./test/setup.ts node_modules/qunit/bin/qunit.js 'test/**/*-test.ts'"
70
73
  },
71
74
  devDependencies: sorted
72
75
  }, null, 2) + '\n';
@@ -96,8 +99,53 @@ export default class App {
96
99
  `;
97
100
  }
98
101
  export function generateEnvironmentTs() {
99
- return `export default {
102
+ return `import type { StoynxConfig } from 'stonyx';
103
+
104
+ const config: StoynxConfig = {
105
+ };
106
+
107
+ export default config;
108
+ `;
109
+ }
110
+ export function generateTestEnvironmentTs() {
111
+ return `import type { StoynxConfig } from 'stonyx';
112
+
113
+ // Test-specific config overrides
114
+ const config: Partial<StoynxConfig> = {
115
+ };
116
+
117
+ export default config;
118
+ `;
119
+ }
120
+ export function generateSetupTs() {
121
+ return `// Test setup: bootstrap Stonyx with the consumer config before qunit runs.
122
+ // Sprint 44 pattern — loaded via \`node --import ./test/setup.ts\`.
123
+ import { pathToFileURL } from 'url';
124
+
125
+ const cwd = process.cwd();
126
+
127
+ const { default: Stonyx } = await import('stonyx');
128
+ const { default: config } = await import(pathToFileURL(\`\${cwd}/config/environment.ts\`).href);
129
+
130
+ new Stonyx(config, cwd);
131
+
132
+ await Stonyx.ready;
133
+ `;
100
134
  }
135
+ export function generateZzExitTestTs() {
136
+ return `// Force-exit hook for qunit runs.
137
+ //
138
+ // Stonyx modules may keep listeners/servers open that would otherwise
139
+ // block the process from exiting after tests complete, causing CI to
140
+ // hit timeouts even though all tests passed.
141
+ //
142
+ // Named \`zz-\` so alphabetical test-file order places it last, after
143
+ // all real test files have registered with QUnit.
144
+ import QUnit from 'qunit';
145
+
146
+ QUnit.on('runEnd', () => {
147
+ setImmediate(() => process.exit(process.exitCode ?? 0));
148
+ });
101
149
  `;
102
150
  }
103
151
  export function generateEnvironmentExampleTs() {
@@ -124,8 +172,6 @@ db.json
124
172
  *.js
125
173
  *.d.ts
126
174
  *.js.map
127
- # Keep test config (JavaScript)
128
- !test/**/*.js
129
175
  `;
130
176
  }
131
177
  export function generateTsConfig() {
@@ -160,29 +206,12 @@ function runPnpmInstall(projectDir) {
160
206
  child.on('error', reject);
161
207
  });
162
208
  }
163
- export default async function newCommand({ args }) {
164
- let appName = args[0];
165
- if (!appName) {
166
- appName = await prompt('Project name:');
167
- }
168
- if (!appName) {
169
- console.error('Project name is required.');
170
- process.exit(1);
171
- }
172
- const projectDir = path.resolve(process.cwd(), appName);
173
- if (await fileExists(projectDir)) {
174
- console.error(`Directory "${appName}" already exists.`);
175
- process.exit(1);
176
- }
177
- console.log(`\nScaffolding new Stonyx project: ${appName}\n`);
178
- // Prompt for module selection
179
- const selectedModules = [];
180
- for (const mod of MODULE_OPTIONS) {
181
- if (await confirm(mod.question)) {
182
- selectedModules.push(mod);
183
- }
184
- }
185
- console.log('\nCreating project structure...\n');
209
+ /**
210
+ * Write every scaffolded file to disk given a resolved project directory,
211
+ * app name, and pre-selected module options. Factored out of `newCommand`
212
+ * so tests can exercise the file-writing path without interactive prompts.
213
+ */
214
+ export async function scaffoldProject(projectDir, appName, selectedModules) {
186
215
  // Create project directory
187
216
  await createDirectory(projectDir);
188
217
  // Copy .nvmrc from monorepo root
@@ -221,8 +250,36 @@ export default async function newCommand({ args }) {
221
250
  await createFile(path.join(projectDir, 'test', 'integration', '.gitkeep'), '');
222
251
  await createDirectory(path.join(projectDir, 'test', 'acceptance'));
223
252
  await createFile(path.join(projectDir, 'test', 'acceptance', '.gitkeep'), '');
224
- // Create test config
225
- await createFile(path.join(projectDir, 'test', 'config', 'environment.js'), `export default {\n // Test-specific config overrides\n}\n`);
253
+ // Create test config (TS)
254
+ await createFile(path.join(projectDir, 'test', 'config', 'environment.ts'), generateTestEnvironmentTs());
255
+ // Create Sprint 44 test harness files (setup bootstraps Stonyx, zz-exit-test drains event loop)
256
+ await createFile(path.join(projectDir, 'test', 'setup.ts'), generateSetupTs());
257
+ await createFile(path.join(projectDir, 'test', 'zz-exit-test.ts'), generateZzExitTestTs());
258
+ }
259
+ export default async function newCommand({ args }) {
260
+ let appName = args[0];
261
+ if (!appName) {
262
+ appName = await prompt('Project name:');
263
+ }
264
+ if (!appName) {
265
+ console.error('Project name is required.');
266
+ process.exit(1);
267
+ }
268
+ const projectDir = path.resolve(process.cwd(), appName);
269
+ if (await fileExists(projectDir)) {
270
+ console.error(`Directory "${appName}" already exists.`);
271
+ process.exit(1);
272
+ }
273
+ console.log(`\nScaffolding new Stonyx project: ${appName}\n`);
274
+ // Prompt for module selection
275
+ const selectedModules = [];
276
+ for (const mod of MODULE_OPTIONS) {
277
+ if (await confirm(mod.question)) {
278
+ selectedModules.push(mod);
279
+ }
280
+ }
281
+ console.log('\nCreating project structure...\n');
282
+ await scaffoldProject(projectDir, appName, selectedModules);
226
283
  console.log('Installing dependencies...\n');
227
284
  try {
228
285
  await runPnpmInstall(projectDir);
@@ -1,3 +1,4 @@
1
+ export declare const DEFAULT_TEST_GLOB = "test/**/*-test.{js,ts}";
1
2
  export default function test({ args }: {
2
3
  args: string[];
3
4
  }): Promise<void>;
package/dist/cli/test.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import { spawn } from 'child_process';
2
2
  import { fileURLToPath, pathToFileURL } from 'url';
3
3
  import path from 'path';
4
+ export const DEFAULT_TEST_GLOB = 'test/**/*-test.{js,ts}';
4
5
  export default async function test({ args }) {
5
6
  const cwd = process.cwd();
6
7
  const setupFile = path.resolve(path.dirname(fileURLToPath(import.meta.url)), 'test-setup.js');
7
8
  const setupFileUrl = pathToFileURL(setupFile).href;
8
9
  const qunitBin = path.resolve(cwd, 'node_modules/qunit/bin/qunit.js');
9
- // Default to conventional test glob if no args provided
10
- const testArgs = args.length > 0 ? args : ['test/**/*-test.js'];
10
+ const testArgs = args.length > 0 ? args : [DEFAULT_TEST_GLOB];
11
11
  const child = spawn(process.execPath, [
12
12
  '--import', setupFileUrl,
13
13
  qunitBin,
@@ -1,2 +1,2 @@
1
- declare const _default: import("../modules.js").StoynxConfig;
1
+ declare const _default: import("stonyx").StoynxConfig;
2
2
  export default _default;
package/dist/main.d.ts CHANGED
@@ -19,3 +19,4 @@ export default class Stonyx {
19
19
  static get config(): StoynxConfig;
20
20
  }
21
21
  export { waitForModule } from './modules.js';
22
+ export type { StoynxConfig } from './modules.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stonyx",
3
- "version": "0.2.3-beta.57",
3
+ "version": "0.2.3-beta.59",
4
4
  "description": "Base stonyx framework module",
5
5
  "main": "dist/main.js",
6
6
  "types": "dist/main.d.ts",