Skip to content

Commit 294e016

Browse files
authored
feat: allow loading using require() (#258)
* fix: test if yeoman-test can be loaded using require(). * fix: drop temp-dir dependency due to top level await * feat: rework top level await to allow loading using require()
1 parent 3dd806e commit 294e016

10 files changed

+47
-29
lines changed

eslint.config.js

+1
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ export default config(...configs, {
88
'unicorn/no-thenable': 'off',
99
'unicorn/prefer-event-target': 'off',
1010
'unicorn/no-object-as-default-parameter': 'off',
11+
'unicorn/prefer-top-level-await': 'off',
1112
},
1213
});

package-lock.json

-9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
},
1818
".": {
1919
"types": "./dist/index.d.ts",
20-
"default": "./dist/index.js"
20+
"require": "./dist/index.js",
21+
"default": "./dist/import.js"
2122
}
2223
},
2324
"main": "./dist/index.js",
@@ -46,14 +47,13 @@
4647
"lodash-es": "^4.17.21",
4748
"mem-fs-editor": "^11.1.1",
4849
"signal-exit": "^4.1.0",
49-
"temp-dir": "^3.0.0",
5050
"type-fest": "^4.25.0"
5151
},
5252
"devDependencies": {
53-
"@yeoman/adapter": "^2.0.0",
5453
"@types/lodash-es": "^4.17.12",
5554
"@types/node": ">=18.19.46",
5655
"@vitest/coverage-v8": "^3.0.2",
56+
"@yeoman/adapter": "^2.0.0",
5757
"@yeoman/eslint": "0.2.0",
5858
"coveralls": "^3.1.1",
5959
"husky": "^9.1.5",

src/helpers.ts

+12-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { existsSync, mkdirSync, rmSync } from 'node:fs';
2+
import { createRequire } from 'node:module';
23
import { resolve } from 'node:path';
34
import process from 'node:process';
45
import { mock } from 'node:test';
@@ -18,13 +19,15 @@ import RunContext, { BasicRunContext, type RunContextSettings } from './run-cont
1819
import testContext from './test-context.js';
1920
import { createEnv as createEnvironment } from './default-environment.js';
2021

21-
let GeneratorImplementation;
22-
try {
23-
const GeneratorImport = await import('yeoman-generator');
24-
GeneratorImplementation = GeneratorImport.default ?? GeneratorImport;
25-
} catch {
26-
// Ignore error
27-
}
22+
let dummyParentClass;
23+
export const setDefaultDummyParentClass = parentClass => {
24+
dummyParentClass = parentClass;
25+
};
26+
27+
const getDummyParentClass = () => {
28+
dummyParentClass ??= createRequire(import.meta.url)('yeoman-generator').default;
29+
return dummyParentClass;
30+
};
2831

2932
export type CreateEnv = (options: BaseEnvironmentOptions) => Promise<BaseEnvironment>;
3033

@@ -145,7 +148,7 @@ export class YeomanTest {
145148
/**
146149
* Create a mocked generator
147150
*/
148-
createMockedGenerator(GeneratorClass = GeneratorImplementation): ReturnType<typeof mock.fn> {
151+
createMockedGenerator(GeneratorClass = getDummyParentClass()): ReturnType<typeof mock.fn> {
149152
class MockedGenerator extends GeneratorClass {}
150153
const generator = mock.fn(MockedGenerator);
151154
for (const methodName of ['run', 'queueTasks', 'runWithOptions', 'queueOwnTasks']) {
@@ -161,7 +164,7 @@ export class YeomanTest {
161164
* Create a simple, dummy generator
162165
*/
163166
createDummyGenerator<GenParameter extends BaseGenerator = DefaultGeneratorApi>(
164-
Generator: GetGeneratorConstructor<GenParameter> = GeneratorImplementation,
167+
Generator: GetGeneratorConstructor<GenParameter> = getDummyParentClass(),
165168
contents: Record<string, (...arguments_: any[]) => void> = {
166169
test(this: any) {
167170
this.shouldRun = true;

src/import.ts

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { setDefaultDummyParentClass } from './helpers.js';
2+
3+
let GeneratorImplementation;
4+
try {
5+
const GeneratorImport = await import('yeoman-generator');
6+
GeneratorImplementation = GeneratorImport.default ?? GeneratorImport;
7+
setDefaultDummyParentClass(GeneratorImplementation);
8+
} catch {
9+
// ignore
10+
}
11+
12+
export * from './index.js';
13+
export { default } from './index.js';

src/run-context.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import crypto from 'node:crypto';
2-
import { existsSync, rmSync } from 'node:fs';
2+
import { existsSync, realpathSync, rmSync } from 'node:fs';
33
import path, { isAbsolute, join as pathJoin, resolve } from 'node:path';
44
import assert from 'node:assert';
55
import { EventEmitter } from 'node:events';
6+
import { tmpdir } from 'node:os';
67
import process from 'node:process';
78
import { mock } from 'node:test';
89
import { camelCase, kebabCase, merge as lodashMerge, set as lodashSet } from 'lodash-es';
910
import { resetFileCommitStates } from 'mem-fs-editor/state';
1011
import { type Store, create as createMemFs } from 'mem-fs';
11-
import tempDirectory from 'temp-dir';
1212
import type {
1313
BaseEnvironmentOptions,
1414
BaseGenerator,
@@ -24,6 +24,8 @@ import defaultHelpers, { type CreateEnv as CreateEnvironment, type Dependency, t
2424
import { type AskedQuestions, type DummyPromptCallback, type DummyPromptOptions, type TestAdapterOptions } from './adapter.js';
2525
import testContext from './test-context.js';
2626

27+
const tempDirectory = realpathSync(tmpdir());
28+
2729
/**
2830
* Provides settings for creating a `RunContext`.
2931
*/

test/helpers.spec.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ import Generator from 'yeoman-generator';
1010
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
1111
import type Environment from 'yeoman-environment';
1212
import { createEnv as createEnvironment } from '../src/default-environment.js';
13-
import helpers from '../src/helpers.js';
13+
import helpers from '../src/import.js';
1414
import { TestAdapter } from '../src/adapter.js';
1515
import RunContext from '../src/run-context.js';
1616

17+
const [major, minor] = process.versions.node.split('.').map(Number);
18+
1719
/* Remove argument from promisify return */
1820
const promisify = function_ => () => promisify_(function_)();
1921
const require = createRequire(import.meta.url);
@@ -31,6 +33,10 @@ describe('yeoman-test', () => {
3133
StubGenerator = class extends Generator {};
3234
});
3335

36+
it.skipIf(major < 22 || (major == 22 && minor < 12))('yeoman-test should allow to be required', () => {
37+
require('../').default.createMockedGenerator();
38+
});
39+
3440
describe('.createGenerator()', () => {
3541
it('create a new generator', async () => {
3642
const generator = await helpers.createGenerator('unicorn:app', {

test/run-context-environment.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { createRequire } from 'node:module';
66
import { mock } from 'node:test';
77
import { type LookupOptions } from '@yeoman/types';
88
import { afterAll, afterEach, beforeAll, beforeEach, describe, it } from 'vitest';
9-
import helpers from '../src/helpers.js';
9+
import helpers from '../src/import.js';
1010
import RunContext from '../src/run-context.js';
1111
import RunResult from '../src/run-result.js';
1212
import SimpleApp from './fixtures/generator-simple/app/index.js';

test/run-context.spec.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
1-
import fs from 'node:fs';
1+
import fs, { realpathSync } from 'node:fs';
22
import path, { dirname } from 'node:path';
33
import assert from 'node:assert';
44
import { fileURLToPath } from 'node:url';
55
import process from 'node:process';
66
import { createRequire } from 'node:module';
7+
import os from 'node:os';
78
import { mock } from 'node:test';
89
import { promisify as promisify_ } from 'node:util';
910
import { afterEach, beforeAll, beforeEach, describe, expect, it } from 'vitest';
1011
import Generator from 'yeoman-generator';
11-
import tempDirectory from 'temp-dir';
1212
import { RunContextBase as RunContext } from '../src/run-context.js';
13-
import helpers from '../src/helpers.js';
13+
import helpers from '../src/import.js';
1414
import { BaseEnvironmentOptions } from '@yeoman/types';
1515

16+
const tempDirectory = realpathSync(os.tmpdir());
17+
1618
/* Remove argument from promisify return */
1719
const promisify = function_ => () => promisify_(function_)();
1820
const require = createRequire(import.meta.url);

test/run-result.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { create as createMemFsEditor } from 'mem-fs-editor';
88
import { afterEach, beforeAll, beforeEach, describe, it } from 'vitest';
99
import RunContext from '../src/run-context.js';
1010
import RunResult from '../src/run-result.js';
11-
import helpers from '../src/helpers.js';
11+
import helpers from '../src/import.js';
1212
import testContext, { result } from '../src/test-context.js';
1313

1414
describe('run-result', () => {

0 commit comments

Comments
 (0)