@form8ion/javascript 16.0.0-beta.1 → 16.0.0-beta.3

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/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@form8ion/javascript",
3
3
  "description": "JavaScript language plugin for the @form8ion toolset",
4
4
  "license": "MIT",
5
- "version": "16.0.0-beta.1",
5
+ "version": "16.0.0-beta.3",
6
6
  "type": "module",
7
7
  "engines": {
8
8
  "node": "^22.21.0 || >=24.12"
@@ -59,7 +59,7 @@
59
59
  "access": "public",
60
60
  "provenance": true
61
61
  },
62
- "packageManager": "npm@11.15.0+sha512.fa4d2d93b9519e93143e70bb913b94ff2ad5fe69c5a0f84943be557cbb59e9fc1bcce55768fb1313f225f4f9f50c78b8f366f2332aa41effd7b10efa98d8d72f",
62
+ "packageManager": "npm@11.16.0+sha512.03be172fc3b199c7a06433163e459be5b110a6983c1dd6305b7ac10f6b0fa12e1440755a8df6b1064ab2ccb789df0474919fb9c684e322dc57685ede21752ccb",
63
63
  "dependencies": {
64
64
  "@form8ion/c8": "^1.0.0-beta.2",
65
65
  "@form8ion/codecov": "^7.0.0-beta.1",
@@ -68,7 +68,7 @@
68
68
  "@form8ion/core": "^5.0.0-beta.9",
69
69
  "@form8ion/eslint": "^7.0.0-beta.1",
70
70
  "@form8ion/husky": "^7.0.0-beta.1",
71
- "@form8ion/javascript-core": "^12.0.0-beta.1",
71
+ "@form8ion/javascript-core": "^13.0.0",
72
72
  "@form8ion/overridable-prompts": "^1.2.0",
73
73
  "@form8ion/prettier": "^3.0.0",
74
74
  "@hapi/hoek": "^11.0.0",
@@ -86,23 +86,23 @@
86
86
  },
87
87
  "devDependencies": {
88
88
  "@cucumber/cucumber": "12.9.0",
89
- "@form8ion/commitlint-config": "2.0.15",
89
+ "@form8ion/commitlint-config": "2.0.16",
90
90
  "@form8ion/eslint-config": "7.1.0-beta.1",
91
91
  "@form8ion/eslint-config-cucumber": "1.4.1",
92
92
  "@form8ion/eslint-config-vitest": "1.1.0",
93
93
  "@form8ion/remark-lint-preset": "6.0.7",
94
94
  "@rollup/plugin-node-resolve": "16.0.3",
95
95
  "@travi/any": "3.3.0",
96
- "@vitest/coverage-v8": "4.1.7",
96
+ "@vitest/coverage-v8": "4.1.8",
97
97
  "ban-sensitive-files": "1.10.11",
98
98
  "chai": "6.2.2",
99
99
  "cz-conventional-changelog": "3.3.0",
100
100
  "debug": "4.4.3",
101
101
  "gplint": "2.5.2",
102
102
  "husky": "9.1.7",
103
- "js-yaml": "4.1.1",
103
+ "js-yaml": "4.2.0",
104
104
  "lockfile-lint": "5.0.0",
105
- "ls-engines": "0.9.4",
105
+ "ls-engines": "0.10.0",
106
106
  "mock-fs": "5.5.0",
107
107
  "npm-run-all2": "9.0.1",
108
108
  "publint": "0.3.21",
@@ -110,10 +110,10 @@
110
110
  "remark-toc": "9.0.0",
111
111
  "remark-usage": "11.0.1",
112
112
  "rimraf": "6.1.3",
113
- "rollup": "4.60.4",
113
+ "rollup": "4.61.1",
114
114
  "rollup-plugin-auto-external": "2.0.0",
115
115
  "testdouble": "3.20.2",
116
- "vitest": "4.1.7",
116
+ "vitest": "4.1.8",
117
117
  "vitest-when": "0.10.0"
118
118
  }
119
119
  }
@@ -1,5 +1,3 @@
1
1
  export {default as scaffold} from './scaffolder.js';
2
2
  export {default as test} from './tester.js';
3
3
  export {default as lift} from './lifter.js';
4
- export {default as read} from './reader.js';
5
- export {default as write} from './writer.js';
@@ -1,14 +1,13 @@
1
- import read from './reader.js';
2
- import write from './writer.js';
1
+ import {loadNpmrc, writeNpmrc} from '@form8ion/javascript-core';
3
2
 
4
3
  export default async function liftNpmConfig({projectRoot}) {
5
4
  const {
6
5
  provenance,
7
6
  'engines-strict': enginesStrict,
8
7
  ...remainingProperties
9
- } = await read({projectRoot});
8
+ } = await loadNpmrc({projectRoot});
10
9
 
11
- await write({projectRoot, config: remainingProperties});
10
+ await writeNpmrc({projectRoot, config: remainingProperties});
12
11
 
13
12
  return {};
14
13
  }
@@ -1,23 +1,22 @@
1
+ import {loadNpmrc, writeNpmrc} from '@form8ion/javascript-core';
2
+
1
3
  import {describe, expect, it, vi} from 'vitest';
2
4
  import any from '@travi/any';
3
5
  import {when} from 'vitest-when';
4
6
 
5
- import read from './reader.js';
6
- import write from './writer.js';
7
7
  import liftNpmConfig from './lifter.js';
8
8
 
9
- vi.mock('./reader.js');
10
- vi.mock('./writer.js');
9
+ vi.mock('@form8ion/javascript-core');
11
10
 
12
11
  describe('npm config lifter', () => {
13
12
  it('should remove `provenance` and `engines-strict` properties from the config', async () => {
14
13
  const projectRoot = any.string();
15
14
  const desiredProperties = any.simpleObject();
16
- when(read)
15
+ when(loadNpmrc)
17
16
  .calledWith({projectRoot})
18
17
  .thenResolve({...desiredProperties, provenance: true, 'engines-strict': true});
19
18
 
20
19
  expect(await liftNpmConfig({projectRoot})).toEqual({});
21
- expect(write).toHaveBeenCalledWith({projectRoot, config: desiredProperties});
20
+ expect(writeNpmrc).toHaveBeenCalledWith({projectRoot, config: desiredProperties});
22
21
  });
23
22
  });
@@ -1,13 +1,11 @@
1
- import {projectTypes} from '@form8ion/javascript-core';
2
-
3
- import write from './writer.js';
1
+ import {projectTypes, writeNpmrc} from '@form8ion/javascript-core';
4
2
 
5
3
  function projectWillNotBeConsumed(projectType) {
6
4
  return projectTypes.APPLICATION === projectType || projectTypes.CLI === projectType;
7
5
  }
8
6
 
9
7
  export default async function scaffoldNpmConfiguration({projectRoot, projectType}) {
10
- await write({
8
+ await writeNpmrc({
11
9
  projectRoot,
12
10
  config: {'update-notifier': false, ...projectWillNotBeConsumed(projectType) && {'save-exact': true}}
13
11
  });
@@ -1,25 +1,20 @@
1
- import {projectTypes} from '@form8ion/javascript-core';
1
+ import {projectTypes, writeNpmrc} from '@form8ion/javascript-core';
2
2
 
3
- import {describe, vi, it, expect, afterEach} from 'vitest';
3
+ import {describe, expect, it, vi} from 'vitest';
4
4
  import any from '@travi/any';
5
5
 
6
- import write from './writer.js';
7
6
  import scaffoldNpmConfig from './scaffolder.js';
8
7
 
9
8
  vi.mock('node:fs');
10
- vi.mock('./writer.js');
9
+ vi.mock('@form8ion/javascript-core');
11
10
 
12
11
  describe('npm config scaffolder', () => {
13
12
  const projectRoot = any.string();
14
13
 
15
- afterEach(() => {
16
- vi.clearAllMocks();
17
- });
18
-
19
14
  it('should save exact versions of dependencies for applications', async () => {
20
15
  await scaffoldNpmConfig({projectRoot, projectType: projectTypes.APPLICATION});
21
16
 
22
- expect(write).toHaveBeenCalledWith({
17
+ expect(writeNpmrc).toHaveBeenCalledWith({
23
18
  projectRoot,
24
19
  config: {
25
20
  'update-notifier': false,
@@ -31,7 +26,7 @@ describe('npm config scaffolder', () => {
31
26
  it('should save exact versions of dependencies for cli applications', async () => {
32
27
  await scaffoldNpmConfig({projectRoot, projectType: projectTypes.CLI});
33
28
 
34
- expect(write).toHaveBeenCalledWith({
29
+ expect(writeNpmrc).toHaveBeenCalledWith({
35
30
  projectRoot,
36
31
  config: {
37
32
  'update-notifier': false,
@@ -43,7 +38,7 @@ describe('npm config scaffolder', () => {
43
38
  it('should allow semver ranges for dependencies of packages', async () => {
44
39
  await scaffoldNpmConfig({projectRoot, projectType: projectTypes.PACKAGE});
45
40
 
46
- expect(write).toHaveBeenCalledWith({projectRoot, config: {'update-notifier': false}});
41
+ expect(writeNpmrc).toHaveBeenCalledWith({projectRoot, config: {'update-notifier': false}});
47
42
  });
48
43
 
49
44
  it('should define the script to enforce peer-dependency compatibility', async () => {
@@ -122,7 +122,7 @@ describe('options schemas', () => {
122
122
  expect(validateOptions(visibilitySchema, visibility)).toEqual(visibility);
123
123
  });
124
124
 
125
- it('should consider values other than `Public` and `Private` as invalid', () => {
125
+ it('should consider values other than `OSS`, `ISS` and `CS` as invalid', () => {
126
126
  expect(() => validateOptions(visibilitySchema, any.word()))
127
127
  .toThrowError('"value" must be one of [OSS, ISS, CS]');
128
128
  });
@@ -38,7 +38,8 @@ export function validate(options) {
38
38
  packageTypes: pluginsSchema,
39
39
  monorepoTypes: pluginsSchema,
40
40
  hosts: pluginsSchema,
41
- ciServices: pluginsSchema
41
+ ciServices: pluginsSchema,
42
+ registries: pluginsSchema
42
43
  }
43
44
  }).required();
44
45
 
@@ -68,7 +68,8 @@ describe('options validator', () => {
68
68
  packageTypes: pluginsSchema,
69
69
  monorepoTypes: pluginsSchema,
70
70
  hosts: pluginsSchema,
71
- ciServices: pluginsSchema
71
+ ciServices: pluginsSchema,
72
+ registries: pluginsSchema
72
73
  }
73
74
  })
74
75
  .thenReturn({required: joiRequiredObject});
@@ -8,7 +8,7 @@ describe('package access level', () => {
8
8
  expect(determinePackageAccessLevelFromProjectVisibility({projectVisibility: 'OSS'})).toEqual('public');
9
9
  });
10
10
 
11
- it('should return `restricted` when the project visibility is `Private`', () => {
11
+ it('should return `restricted` when the project visibility is `ISS` or `CS`', () => {
12
12
  expect(determinePackageAccessLevelFromProjectVisibility({projectVisibility: any.fromList(['ISS', 'CS'])}))
13
13
  .toEqual('restricted');
14
14
  });
@@ -16,7 +16,7 @@ export function projectIsApplication(answers) {
16
16
  }
17
17
 
18
18
  function packageShouldBeScoped(visibility, answers) {
19
- return 'Private' === visibility || answers[questionNames.SHOULD_BE_SCOPED];
19
+ return ['ISS', 'CS'].includes(visibility) || answers[questionNames.SHOULD_BE_SCOPED];
20
20
  }
21
21
 
22
22
  function willBePublishedToNpm(answers) {
@@ -33,8 +33,15 @@ describe('javascript prompt conditionals', () => {
33
33
  })).toBe(true);
34
34
  });
35
35
 
36
- it('should present a scope prompt when a package is private, because they must be scoped', () => {
37
- expect(scopePromptShouldBePresentedFactory('Private')({
36
+ it('should present a scope prompt when a package is inner source, because they must be scoped', () => {
37
+ expect(scopePromptShouldBePresentedFactory('ISS')({
38
+ [questionNames.SHOULD_BE_SCOPED]: false,
39
+ [questionNames.PROJECT_TYPE]: projectTypes.PACKAGE
40
+ })).toBe(true);
41
+ });
42
+
43
+ it('should present a scope prompt when a package is closed source, because they must be scoped', () => {
44
+ expect(scopePromptShouldBePresentedFactory('CS')({
38
45
  [questionNames.SHOULD_BE_SCOPED]: false,
39
46
  [questionNames.PROJECT_TYPE]: projectTypes.PACKAGE
40
47
  })).toBe(true);
@@ -47,15 +54,29 @@ describe('javascript prompt conditionals', () => {
47
54
  })).toBe(true);
48
55
  });
49
56
 
50
- it('should present a scope prompt when a CLI is private, because they must be scoped', () => {
51
- expect(scopePromptShouldBePresentedFactory('Private')({
57
+ it('should present a scope prompt when a CLI is closed source, because they must be scoped', () => {
58
+ expect(scopePromptShouldBePresentedFactory('CS')({
52
59
  [questionNames.SHOULD_BE_SCOPED]: false,
53
60
  [questionNames.PROJECT_TYPE]: projectTypes.CLI
54
61
  })).toBe(true);
55
62
  });
56
63
 
57
- it('should not present a scope prompt when an application is private', () => {
58
- expect(scopePromptShouldBePresentedFactory('Private')({
64
+ it('should present a scope prompt when a CLI is inner source, because they must be scoped', () => {
65
+ expect(scopePromptShouldBePresentedFactory('ISS')({
66
+ [questionNames.SHOULD_BE_SCOPED]: false,
67
+ [questionNames.PROJECT_TYPE]: projectTypes.CLI
68
+ })).toBe(true);
69
+ });
70
+
71
+ it('should not present a scope prompt when an application is closed source', () => {
72
+ expect(scopePromptShouldBePresentedFactory('CS')({
73
+ [questionNames.SHOULD_BE_SCOPED]: false,
74
+ [questionNames.PROJECT_TYPE]: projectTypes.APPLICATION
75
+ })).toBe(false);
76
+ });
77
+
78
+ it('should not present a scope prompt when an application is inner source', () => {
79
+ expect(scopePromptShouldBePresentedFactory('ISS')({
59
80
  [questionNames.SHOULD_BE_SCOPED]: false,
60
81
  [questionNames.PROJECT_TYPE]: projectTypes.APPLICATION
61
82
  })).toBe(false);
@@ -101,7 +101,7 @@ export async function prompt(
101
101
  choices: [...Object.values(projectTypes), 'Other'],
102
102
  default: projectTypes.PACKAGE
103
103
  },
104
- ...'Private' === visibility ? [] : [{
104
+ ...['ISS', 'CS'].includes(visibility) ? [] : [{
105
105
  name: questionNames.SHOULD_BE_SCOPED,
106
106
  message: 'Should this package be scoped?',
107
107
  type: 'confirm',
@@ -212,13 +212,13 @@ describe('prompts', () => {
212
212
  .thenReturn(commonQuestions);
213
213
  prompts.prompt.mockResolvedValue(answers);
214
214
 
215
- await prompt(ciServices, {}, 'Private', vcs, null, null, pathWithinParent, {logger});
215
+ await prompt(ciServices, {}, 'CS', vcs, null, null, pathWithinParent, {logger});
216
216
 
217
217
  const [questions] = prompts.prompt.mock.lastCall;
218
218
  expect(questions.filter(question => questionNames.NODE_VERSION_CATEGORY === question.name).length).toEqual(0);
219
219
  });
220
220
 
221
- it('should not ask whether private packages should be scoped', async () => {
221
+ it('should not ask whether closed source packages should be scoped', async () => {
222
222
  when(execa).calledWith('npm', ['whoami']).thenResolve({stdout: any.word()});
223
223
  npmConfFactory.mockReturnValue({get: () => undefined});
224
224
  when(commonPrompts.questions)
@@ -226,7 +226,21 @@ describe('prompts', () => {
226
226
  .thenReturn(commonQuestions);
227
227
  prompts.prompt.mockResolvedValue(answers);
228
228
 
229
- await prompt(ciServices, {}, 'Private', vcs, null, null, pathWithinParent, {logger});
229
+ await prompt(ciServices, {}, 'CS', vcs, null, null, pathWithinParent, {logger});
230
+
231
+ const [questions] = prompts.prompt.mock.lastCall;
232
+ expect(questions.filter(question => questionNames.SHOULD_BE_SCOPED === question.name).length).toEqual(0);
233
+ });
234
+
235
+ it('should not ask whether inner source packages should be scoped', async () => {
236
+ when(execa).calledWith('npm', ['whoami']).thenResolve({stdout: any.word()});
237
+ npmConfFactory.mockReturnValue({get: () => undefined});
238
+ when(commonPrompts.questions)
239
+ .calledWith({vcs, ciServices, pathWithinParent})
240
+ .thenReturn(commonQuestions);
241
+ prompts.prompt.mockResolvedValue(answers);
242
+
243
+ await prompt(ciServices, {}, 'ISS', vcs, null, null, pathWithinParent, {logger});
230
244
 
231
245
  const [questions] = prompts.prompt.mock.lastCall;
232
246
  expect(questions.filter(question => questionNames.SHOULD_BE_SCOPED === question.name).length).toEqual(0);
@@ -240,7 +254,7 @@ describe('prompts', () => {
240
254
  .thenReturn(commonQuestions);
241
255
  prompts.prompt.mockResolvedValue(answers);
242
256
 
243
- await prompt(ciServices, {}, 'Public', vcs, {}, null, pathWithinParent, {logger});
257
+ await prompt(ciServices, {}, 'OSS', vcs, {}, null, pathWithinParent, {logger});
244
258
 
245
259
  const [questions] = prompts.prompt.mock.lastCall;
246
260
  expect(questions.filter(question => questionNames.SHOULD_BE_SCOPED === question.name).length).toEqual(1);
@@ -1,7 +1,12 @@
1
1
  export function scope(visibility) {
2
2
  return input => {
3
- if (!input && 'Private' === visibility) {
4
- return 'Private packages must be scoped (https://docs.npmjs.com/private-modules/intro#setting-up-your-package)';
3
+ if (!input) {
4
+ if ('CS' === visibility) {
5
+ return 'Closed source packages must be scoped';
6
+ }
7
+ if ('ISS' === visibility) {
8
+ return 'Inner source packages must be scoped';
9
+ }
5
10
  }
6
11
 
7
12
  return true;
@@ -1,19 +1,22 @@
1
1
  import {expect, it, describe} from 'vitest';
2
+ import any from '@travi/any';
2
3
 
3
4
  import {scope} from './validators.js';
4
5
 
5
6
  describe('question validators', () => {
6
- it('should require a scope for private project', () => {
7
- expect(scope('Private')()).toEqual(
8
- 'Private packages must be scoped (https://docs.npmjs.com/private-modules/intro#setting-up-your-package)'
9
- );
7
+ it('should require a scope for a closed-source project', () => {
8
+ expect(scope('CS')()).toEqual('Closed source packages must be scoped');
9
+ });
10
+
11
+ it('should require a scope for an inner-source project', () => {
12
+ expect(scope('ISS')()).toEqual('Inner source packages must be scoped');
10
13
  });
11
14
 
12
15
  it('it should consider a provided value to be a valid answer to private projects', () => {
13
- expect(scope('Public')()).toBe(true);
16
+ expect(scope('OSS')(any.word())).toBe(true);
14
17
  });
15
18
 
16
19
  it('it should consider an empty value to be a valid answer to public projects', () => {
17
- expect(scope('Public')()).toBe(true);
20
+ expect(scope('OSS')()).toBe(true);
18
21
  });
19
22
  });
@@ -1,20 +1,21 @@
1
+ import {loadNpmrc, writeNpmrc} from '@form8ion/javascript-core';
2
+
1
3
  import {
2
4
  scaffold as scaffoldLockfileLint,
3
5
  test as lockfileLintIsAlreadyConfigured,
4
6
  read as readLockfileLintConfig,
5
7
  write as writeLockfileLintConfig
6
8
  } from '../lockfile-lint/index.js';
7
- import {read as readNpmConfig, write as writeNpmConfig} from '../npm-config/index.js';
8
9
  import buildRegistriesConfig from './npm-config/list-builder.js';
9
10
  import buildAllowedHostsList from '../lockfile-lint/allowed-hosts-builder.js';
10
11
 
11
12
  async function updateRegistriesInNpmConfig(registries, projectRoot) {
12
13
  const registriesForNpmConfig = buildRegistriesConfig(registries);
13
14
 
14
- await writeNpmConfig({
15
+ await writeNpmrc({
15
16
  projectRoot,
16
17
  config: {
17
- ...(await readNpmConfig({projectRoot})),
18
+ ...(await loadNpmrc({projectRoot})),
18
19
  ...registriesForNpmConfig
19
20
  }
20
21
  });
@@ -1,3 +1,5 @@
1
+ import {loadNpmrc, writeNpmrc} from '@form8ion/javascript-core';
2
+
1
3
  import any from '@travi/any';
2
4
  import {beforeEach, describe, expect, it, vi} from 'vitest';
3
5
  import {when} from 'vitest-when';
@@ -9,14 +11,13 @@ import {
9
11
  read as readLockfileLintConfig,
10
12
  write as writeLockfileLintConfig
11
13
  } from '../lockfile-lint/index.js';
12
- import {read as readNpmConfig, write as writeNpmConfig} from '../npm-config/index.js';
13
14
  import buildRegistriesConfig from './npm-config/list-builder.js';
14
15
  import liftRegistries from './lifter.js';
15
16
 
17
+ vi.mock('@form8ion/javascript-core');
16
18
  vi.mock('../lockfile-lint/allowed-hosts-builder.js');
17
19
  vi.mock('../lockfile-lint/index.js');
18
20
  vi.mock('../registries/npm-config/list-builder.js');
19
- vi.mock('../npm-config/index.js');
20
21
 
21
22
  describe('registries lifter', () => {
22
23
  const projectRoot = any.string();
@@ -27,7 +28,7 @@ describe('registries lifter', () => {
27
28
  const existingNpmConfig = any.simpleObject();
28
29
 
29
30
  beforeEach(() => {
30
- when(readNpmConfig).calledWith({projectRoot}).thenResolve(existingNpmConfig);
31
+ when(loadNpmrc).calledWith({projectRoot}).thenResolve(existingNpmConfig);
31
32
  when(buildRegistriesConfig).calledWith(registries).thenReturn(processedRegistryDetails);
32
33
  });
33
34
 
@@ -40,7 +41,7 @@ describe('registries lifter', () => {
40
41
 
41
42
  expect(await liftRegistries({projectRoot, packageManager, configs})).toEqual({});
42
43
 
43
- expect(writeNpmConfig).toHaveBeenCalledWith({
44
+ expect(writeNpmrc).toHaveBeenCalledWith({
44
45
  projectRoot,
45
46
  config: {...existingNpmConfig, ...processedRegistryDetails}
46
47
  });
@@ -1,11 +0,0 @@
1
- import {parse} from 'ini';
2
- import {promises as fs} from 'node:fs';
3
- import {fileExists} from '@form8ion/core';
4
-
5
- export default async function readNpmConfig({projectRoot}) {
6
- const pathToConfig = `${projectRoot}/.npmrc`;
7
-
8
- if (!(await fileExists(pathToConfig))) return {};
9
-
10
- return parse(await fs.readFile(pathToConfig, 'utf-8'));
11
- }
@@ -1,33 +0,0 @@
1
- import {promises as fs} from 'node:fs';
2
- import {stringify} from 'ini';
3
- import {fileExists} from '@form8ion/core';
4
-
5
- import {describe, expect, it, vi} from 'vitest';
6
- import {when} from 'vitest-when';
7
- import any from '@travi/any';
8
-
9
- import readConfig from './reader.js';
10
-
11
- vi.mock('node:fs');
12
- vi.mock('@form8ion/core');
13
-
14
- describe('npm config reader', () => {
15
- const projectRoot = any.string();
16
- const pathToConfig = `${projectRoot}/.npmrc`;
17
-
18
- it('should read the .npmrc file', async () => {
19
- const existingProperties = any.simpleObject();
20
- when(fileExists).calledWith(pathToConfig).thenResolve(true);
21
- when(fs.readFile)
22
- .calledWith(pathToConfig, 'utf-8')
23
- .thenReturn(stringify(existingProperties));
24
-
25
- expect(await readConfig({projectRoot})).toEqual(existingProperties);
26
- });
27
-
28
- it('should return empty when the file does not exist', async () => {
29
- when(fileExists).calledWith(pathToConfig).thenResolve(false);
30
-
31
- expect(await readConfig({projectRoot})).toEqual({});
32
- });
33
- });
@@ -1,6 +0,0 @@
1
- import {promises as fs} from 'node:fs';
2
- import {stringify} from 'ini';
3
-
4
- export default async function writeNpmConfig({projectRoot, config}) {
5
- await fs.writeFile(`${projectRoot}/.npmrc`, stringify(config));
6
- }
@@ -1,24 +0,0 @@
1
- import {promises as fs} from 'node:fs';
2
- import {stringify} from 'ini';
3
-
4
- import {describe, expect, vi, it} from 'vitest';
5
- import any from '@travi/any';
6
- import {when} from 'vitest-when';
7
-
8
- import write from './writer.js';
9
-
10
- vi.mock('node:fs');
11
- vi.mock('ini');
12
-
13
- describe('npm config writer', () => {
14
- it('should write the .npmrc file', async () => {
15
- const projectRoot = any.string();
16
- const config = any.simpleObject();
17
- const stringifiedIniConfig = any.string();
18
- when(stringify).calledWith(config).thenReturn(stringifiedIniConfig);
19
-
20
- await write({projectRoot, config});
21
-
22
- expect(fs.writeFile).toHaveBeenCalledWith(`${projectRoot}/.npmrc`, stringifiedIniConfig);
23
- });
24
- });