@leyman/nx-plugin 0.0.0-stage → 0.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.
@@ -0,0 +1,208 @@
1
+ import Path from 'node:path';
2
+ import { getProjects, installPackagesTask, joinPathFragments, normalizePath, readJson, readNxJson, writeJson } from '@nx/devkit';
3
+ import { inferencePaths, inferTargets } from '../lib/infer.js';
4
+ import { resolveOptions } from '../lib/options.js';
5
+ import { name as pluginName } from '../lib/plugin.js';
6
+ import { assertOptions, defaultFloor } from '../lib/schema.js';
7
+ import { readWorkspaceVersions, resolveVersion } from '../lib/versions.js';
8
+ const readPluginOptions = (tree, config)=>{
9
+ if (config !== undefined) {
10
+ const options = readJson(tree, config);
11
+ assertOptions(options, config);
12
+ return options;
13
+ }
14
+ const plugin = readNxJson(tree)?.plugins?.find((entry)=>(typeof entry === 'string' ? entry : entry.plugin) === pluginName);
15
+ const options = typeof plugin === 'object' ? plugin.options ?? {} : {};
16
+ assertOptions(options, 'nx.json');
17
+ return options;
18
+ };
19
+ const projectSchema = (tree, directory)=>{
20
+ let schema;
21
+ for (const { root } of getProjects(tree).values()){
22
+ const path = joinPathFragments(root, 'project.json');
23
+ const $schema = tree.exists(path) ? readJson(tree, path).$schema : undefined;
24
+ if ($schema !== undefined && !/^[a-z]+:/v.test($schema)) {
25
+ schema = joinPathFragments(root, $schema);
26
+ break;
27
+ }
28
+ }
29
+ if (schema === undefined && tree.exists('node_modules/nx/package.json')) {
30
+ schema = 'node_modules/nx/schemas/project-schema.json';
31
+ }
32
+ return schema === undefined ? undefined : Path.posix.relative(directory, schema);
33
+ };
34
+ const repositoryFields = (url, directory)=>{
35
+ const base = url.replace(/^git\+/v, '').replace(/\.git$/v, '');
36
+ return {
37
+ repository: {
38
+ type: 'git',
39
+ url: `git+${base}.git`,
40
+ directory
41
+ },
42
+ homepage: `${base}/tree/main/${directory}#readme`,
43
+ bugs: {
44
+ url: `${base}/issues`
45
+ }
46
+ };
47
+ };
48
+ const sourceFile = (name)=>`/**
49
+ * A placeholder export, for the first test to import until the package has an API.
50
+ */
51
+ export const packageName = '${name}';
52
+ `;
53
+ const mochaSpec = (name)=>`import { expect } from '@leyman/expect';
54
+ import { suite, test } from 'mocha-chain';
55
+ import { packageName } from '${name}';
56
+
57
+ suite('${name}', () => {
58
+ test('Exports its name', () => {
59
+ expect(packageName).to.equal('${name}');
60
+ });
61
+ });
62
+ `;
63
+ const vitestSpec = (name)=>`import { expect, suite, test } from 'vitest';
64
+ import { packageName } from '${name}';
65
+
66
+ suite('${name}', () => {
67
+ test('Exports its name', () => {
68
+ expect(packageName).toBe('${name}');
69
+ });
70
+ });
71
+ `;
72
+ const eslintConfig = `import configGenerator from '@leyman/eslint-config';
73
+ import packageJson from './package.json' with { type: 'json' };
74
+
75
+ export default configGenerator({ configUrl: import.meta.url, node: true, packageJson });
76
+ `;
77
+ const testDependencies = {
78
+ mocha: [
79
+ '@leyman/expect',
80
+ '@types/mocha',
81
+ 'c8',
82
+ 'mocha',
83
+ 'mocha-chain'
84
+ ],
85
+ vitest: [
86
+ 'c8',
87
+ 'vitest'
88
+ ],
89
+ none: []
90
+ };
91
+ const packageGenerator = async (tree, options)=>{
92
+ const normalized = Path.posix.normalize(normalizePath(options.directory));
93
+ const directory = normalized.endsWith('/') ? normalized.slice(0, -1) : normalized;
94
+ if ([
95
+ 'package.json',
96
+ 'project.json'
97
+ ].some((file)=>tree.exists(joinPathFragments(directory, file)))) {
98
+ throw new Error(`${directory} already holds a project`);
99
+ }
100
+ const name = options.name ?? Path.posix.basename(directory);
101
+ const { published = false, floor = defaultFloor, test = 'mocha' } = options;
102
+ const resolved = resolveOptions(readPluginOptions(tree, options.config));
103
+ const versions = await readWorkspaceVersions(tree);
104
+ const devDependencies = [
105
+ ...new Set([
106
+ '@biomejs/biome',
107
+ '@leyman/configs',
108
+ '@leyman/eslint-config',
109
+ '@swc/cli',
110
+ '@swc/core',
111
+ '@types/node',
112
+ 'eslint',
113
+ "typescript",
114
+ ...testDependencies[test],
115
+ ...options.devDependencies ?? []
116
+ ])
117
+ ].toSorted((a, b)=>a.localeCompare(b));
118
+ const floorCatalog = `node-${floor}`;
119
+ const floorTypes = versions.catalogs[floorCatalog]?.['@types/node'] === undefined ? `^${floor}.0.0` : `catalog:${floorCatalog}`;
120
+ const packageJson = {
121
+ name,
122
+ version: '0.0.1',
123
+ description: options.description,
124
+ ...published ? {
125
+ engines: {
126
+ node: `>=${floor}`
127
+ }
128
+ } : {
129
+ private: true
130
+ },
131
+ type: 'module',
132
+ ...options.author !== undefined && {
133
+ author: options.author
134
+ },
135
+ ...options.license !== undefined && {
136
+ license: options.license
137
+ },
138
+ ...published && options.repository !== undefined && repositoryFields(options.repository, directory),
139
+ sideEffects: false,
140
+ types: './dist/index.js',
141
+ files: [
142
+ 'dist',
143
+ '!dist/**/*.map',
144
+ '!dist/tsconfig.tsbuildinfo'
145
+ ],
146
+ exports: {
147
+ '.': './dist/index.js'
148
+ },
149
+ devDependencies: Object.fromEntries(devDependencies.map((dependency)=>[
150
+ dependency,
151
+ published && dependency === '@types/node' ? floorTypes : resolveVersion(dependency, versions)
152
+ ]))
153
+ };
154
+ const { floorTsconfig } = resolved.checkPackage;
155
+ writeJson(tree, joinPathFragments(directory, 'package.json'), packageJson);
156
+ writeJson(tree, joinPathFragments(directory, 'tsconfig.json'), {
157
+ extends: published && floorTsconfig !== false ? floorTsconfig.replaceAll('{major}', ()=>String(floor)) : '@leyman/configs/tsconfig.build.json',
158
+ compilerOptions: {
159
+ outDir: 'dist',
160
+ rootDir: 'src',
161
+ tsBuildInfoFile: 'dist/tsconfig.tsbuildinfo'
162
+ },
163
+ include: [
164
+ 'src'
165
+ ]
166
+ });
167
+ tree.write(joinPathFragments(directory, 'src/index.ts'), sourceFile(name));
168
+ if (test !== 'none') {
169
+ writeJson(tree, joinPathFragments(directory, 'test/tsconfig.json'), {
170
+ extends: '@leyman/configs/tsconfig.test.json',
171
+ references: [
172
+ {
173
+ path: '..'
174
+ }
175
+ ]
176
+ });
177
+ tree.write(joinPathFragments(directory, 'test/unit/index.spec.ts'), test === 'mocha' ? mochaSpec(name) : vitestSpec(name));
178
+ }
179
+ tree.write(joinPathFragments(directory, 'eslint.config.js'), eslintConfig);
180
+ tree.write(joinPathFragments(directory, 'README.md'), `# ${name}\n\n${options.description}\n`);
181
+ const license = tree.read('LICENSE');
182
+ if (published && license !== null) {
183
+ tree.write(joinPathFragments(directory, 'LICENSE'), license);
184
+ }
185
+ const present = new Set(inferencePaths.filter((path)=>tree.exists(joinPathFragments(directory, path))));
186
+ const inferred = inferTargets({
187
+ packageJson,
188
+ root: directory,
189
+ isDependency: false,
190
+ has: (path)=>present.has(path)
191
+ }, resolved);
192
+ const targets = Object.fromEntries(inferred.map((target)=>[
193
+ resolved.targets[target].name,
194
+ {}
195
+ ]));
196
+ const $schema = projectSchema(tree, directory);
197
+ writeJson(tree, joinPathFragments(directory, 'project.json'), {
198
+ ...$schema !== undefined && {
199
+ $schema
200
+ },
201
+ name,
202
+ targets
203
+ });
204
+ return options.skipInstall === true ? undefined : installPackagesTask.bind(undefined, tree, true);
205
+ };
206
+ export default packageGenerator;
207
+
208
+ //# sourceMappingURL=package.js.map
@@ -0,0 +1,18 @@
1
+ export type { InferencePackageJson, ProjectFacts } from './lib/infer.js';
2
+ export { inferencePaths, inferTargets } from './lib/infer.js';
3
+ export type { Input, NamedInputName, NxPluginOptions, ResolvedOptions, TargetName, TargetOptions, } from './lib/options.js';
4
+ export { namedInputNames, resolveOptions, targetNames } from './lib/options.js';
5
+ export { namedInputs, targetConfigurations } from './lib/targets.js';
6
+ export type { WorkspaceProject } from './lib/sync.js';
7
+ export { syncTargets } from './lib/sync.js';
8
+ export { assertOptions, executorJsonSchema, initGeneratorJsonSchema, optionsJsonSchema, packageGeneratorJsonSchema, } from './lib/schema.js';
9
+ export { createNodes, name } from './lib/plugin.js';
10
+ export type { LoadedProject, WorkspacePackageJson } from './lib/projects.js';
11
+ export { loadProjects } from './lib/projects.js';
12
+ export type { InitGeneratorOptions } from './generators/init.js';
13
+ export { default as initGenerator, lifecycleBindings, lifecycleStages, } from './generators/init.js';
14
+ export type { PackageGeneratorOptions } from './generators/package.js';
15
+ export { default as packageGenerator } from './generators/package.js';
16
+ export type { WorkspaceVersions } from './lib/versions.js';
17
+ export { readWorkspaceVersions, resolveVersion } from './lib/versions.js';
18
+ //# sourceMappingURL=index.d.ts.map
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ export { inferencePaths, inferTargets } from './lib/infer.js';
2
+ export { namedInputNames, resolveOptions, targetNames } from './lib/options.js';
3
+ export { namedInputs, targetConfigurations } from './lib/targets.js';
4
+ export { syncTargets } from './lib/sync.js';
5
+ export { assertOptions, executorJsonSchema, initGeneratorJsonSchema, optionsJsonSchema, packageGeneratorJsonSchema } from './lib/schema.js';
6
+ export { createNodes, name } from './lib/plugin.js';
7
+ export { loadProjects } from './lib/projects.js';
8
+ export { default as initGenerator, lifecycleBindings, lifecycleStages } from './generators/init.js';
9
+ export { default as packageGenerator } from './generators/package.js';
10
+ export { readWorkspaceVersions, resolveVersion } from './lib/versions.js';
11
+
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,45 @@
1
+ import type { ResolvedOptions, TargetName } from './options.js';
2
+ /**
3
+ * The fields of a project's `package.json` inference reads.
4
+ */
5
+ export interface InferencePackageJson {
6
+ readonly private?: boolean;
7
+ readonly devDependencies?: Readonly<Record<string, string>>;
8
+ }
9
+ /**
10
+ * Every path, relative to a project, whose presence inference reads.
11
+ */
12
+ export declare const inferencePaths: readonly ['eslint.config.js', 'src', 'test/integration', 'test/tsconfig.json', 'test/unit', 'tsconfig.json'];
13
+ /**
14
+ * What inference knows of a project.
15
+ */
16
+ export interface ProjectFacts {
17
+ /**
18
+ * Root of the project, relative to the workspace, with `/` separators.
19
+ */
20
+ readonly root: string;
21
+ /**
22
+ * Its `package.json`, if it has one.
23
+ */
24
+ readonly packageJson: InferencePackageJson | undefined;
25
+ /**
26
+ * Whether another package of the workspace depends on it.
27
+ */
28
+ readonly isDependency: boolean;
29
+ /**
30
+ * Whether a file or directory exists in the project.
31
+ *
32
+ * @param path - one of {@link inferencePaths}
33
+ */
34
+ readonly has: (path: (typeof inferencePaths)[number]) => boolean;
35
+ }
36
+ /**
37
+ * Which of the plugin's targets a project gets: those its files call for, plus those it is included in, minus those it
38
+ * is excluded from or turned off.
39
+ *
40
+ * @param project - its root, files, `package.json` and dependents
41
+ * @param options - resolved options
42
+ * @returns each target's own name, in the order a `project.json` lists them
43
+ */
44
+ export declare const inferTargets: (project: ProjectFacts, options: ResolvedOptions) => TargetName[];
45
+ //# sourceMappingURL=infer.d.ts.map
@@ -0,0 +1,66 @@
1
+ import { targetNames } from './options.js';
2
+ export const inferencePaths = [
3
+ 'eslint.config.js',
4
+ 'src',
5
+ 'test/integration',
6
+ 'test/tsconfig.json',
7
+ 'test/unit',
8
+ 'tsconfig.json'
9
+ ];
10
+ const targetsFromFiles = ({ has, isDependency, packageJson })=>{
11
+ const targets = new Set([
12
+ 'biome'
13
+ ]);
14
+ if (packageJson === undefined) {
15
+ return targets;
16
+ }
17
+ if (isDependency) {
18
+ targets.add('sync-injected');
19
+ }
20
+ if (has('tsconfig.json')) {
21
+ targets.add('update-ts-references');
22
+ if (has('src')) {
23
+ targets.add('tsc');
24
+ }
25
+ }
26
+ if (has('test/tsconfig.json')) {
27
+ targets.add('tsc-test');
28
+ }
29
+ const devDependencies = packageJson.devDependencies ?? {};
30
+ if (Object.hasOwn(devDependencies, 'mocha')) {
31
+ if (has('test/unit')) {
32
+ targets.add('mocha-unit-test');
33
+ }
34
+ if (has('test/integration')) {
35
+ targets.add('mocha-integration-test');
36
+ }
37
+ } else if (Object.hasOwn(devDependencies, 'vitest') && has('test/unit')) {
38
+ targets.add('vitest-unit-test');
39
+ }
40
+ if (has('eslint.config.js')) {
41
+ targets.add('eslint');
42
+ }
43
+ if (targets.has('tsc')) {
44
+ const tested = [
45
+ 'mocha-unit-test',
46
+ 'mocha-integration-test',
47
+ 'vitest-unit-test'
48
+ ];
49
+ if (tested.some((target)=>targets.has(target))) {
50
+ targets.add('coverage-report');
51
+ }
52
+ if (packageJson.private !== true) {
53
+ targets.add('check-package');
54
+ }
55
+ }
56
+ return targets;
57
+ };
58
+ export const inferTargets = (project, options)=>{
59
+ const fromFiles = targetsFromFiles(project);
60
+ return targetNames.filter((target)=>{
61
+ const targetOptions = options.targets[target];
62
+ return targetOptions !== false && !targetOptions.exclude.includes(project.root) && (fromFiles.has(target) || targetOptions.include.includes(project.root));
63
+ });
64
+ };
65
+
66
+ //# sourceMappingURL=infer.js.map
@@ -0,0 +1,154 @@
1
+ import type { TargetConfiguration } from '@nx/devkit';
2
+ /**
3
+ * The targets the plugin infers, in the order a `project.json` lists them.
4
+ */
5
+ export declare const targetNames: readonly ['biome', 'eslint', 'check-package', 'update-ts-references', 'tsc', 'tsc-test', 'mocha-unit-test', 'mocha-integration-test', 'vitest-unit-test', 'coverage-report', 'sync-injected'];
6
+ export type TargetName = (typeof targetNames)[number];
7
+ /**
8
+ * The named inputs the plugin's targets use, and defines.
9
+ */
10
+ export declare const namedInputNames: readonly ['dependency-files', 'package-files', 'eslint-input', 'ts-source', 'dependency-builds', 'test-source'];
11
+ export type NamedInputName = (typeof namedInputNames)[number];
12
+ /**
13
+ * An entry of a target's `inputs` or of a named input.
14
+ */
15
+ export type Input = NonNullable<TargetConfiguration['inputs']>[number];
16
+ /**
17
+ * How one target is inferred.
18
+ */
19
+ export interface TargetOptions {
20
+ /**
21
+ * Name of the target in the project graph.
22
+ *
23
+ * @default the target's own name, e.g. `tsc`
24
+ */
25
+ readonly name?: string;
26
+ /**
27
+ * Roots of projects (`packages/a`) that get the target whatever their files.
28
+ */
29
+ readonly include?: readonly string[];
30
+ /**
31
+ * Roots of projects that never get the target.
32
+ */
33
+ readonly exclude?: readonly string[];
34
+ }
35
+ /**
36
+ * Options of the plugin, in `nx.json` (plugin mode) or in the file the `targets` executor reads.
37
+ */
38
+ export interface NxPluginOptions {
39
+ /**
40
+ * Each target's options, or `false` to infer it nowhere.
41
+ */
42
+ readonly targets?: Readonly<Partial<Record<TargetName, false | TargetOptions>>>;
43
+ /**
44
+ * Paths of the shared configs, relative to each project.
45
+ */
46
+ readonly configs?: {
47
+ /**
48
+ * @default 'node_modules/@leyman/configs/swcrc.jsonc'
49
+ */
50
+ readonly swc?: string;
51
+ /**
52
+ * @default 'node_modules/@leyman/configs/c8rc.json'
53
+ */
54
+ readonly c8?: string;
55
+ /**
56
+ * @default 'node_modules/@leyman/configs/vitest.config.js'
57
+ */
58
+ readonly vitest?: string;
59
+ };
60
+ /**
61
+ * Directory to run the plugin's scripts from, such as `$NX_WORKSPACE_ROOT/tools/nx-plugin/scripts` for a copy kept
62
+ * in the workspace. By default, they run as the package's bins (`leyman-swc-compile`...).
63
+ */
64
+ readonly scripts?: string;
65
+ /**
66
+ * Coverage thresholds `coverage-report` passes to c8, over the c8 config's.
67
+ */
68
+ readonly coverage?: {
69
+ readonly branches?: number;
70
+ readonly functions?: number;
71
+ readonly lines?: number;
72
+ readonly statements?: number;
73
+ };
74
+ /**
75
+ * Options of `check-package`.
76
+ */
77
+ readonly checkPackage?: {
78
+ /**
79
+ * The module resolutions every entry point must work under.
80
+ *
81
+ * @default check-package's own, `strict`
82
+ */
83
+ readonly profile?: 'esm-only' | 'node16' | 'strict';
84
+ /**
85
+ * The config a package's `tsconfig.json` must extend, with `{major}` for its support floor, or `false`
86
+ * not to check it.
87
+ *
88
+ * @default '@leyman/configs/tsconfig.node-{major}.json'
89
+ */
90
+ readonly floorTsconfig?: false | string;
91
+ /**
92
+ * What a change of check-package itself is hashed by.
93
+ *
94
+ * @default [{ externalDependencies: ['@leyman/check-package', 'typescript'] }]
95
+ */
96
+ readonly inputs?: readonly Input[];
97
+ };
98
+ /**
99
+ * What changes of the shared tools are hashed by.
100
+ */
101
+ readonly inputs?: {
102
+ /**
103
+ * The shared configs, for every target that reads one.
104
+ *
105
+ * @default [{ externalDependencies: ['@leyman/configs'] }]
106
+ */
107
+ readonly configs?: readonly Input[];
108
+ /**
109
+ * This plugin's scripts, for every target that runs one.
110
+ *
111
+ * @default [{ externalDependencies: ['@leyman/nx-plugin'] }]
112
+ */
113
+ readonly tools?: readonly Input[];
114
+ };
115
+ /**
116
+ * Inputs added to the end of each named input, such as a file the tests read.
117
+ */
118
+ readonly namedInputs?: Readonly<Partial<Record<NamedInputName, readonly Input[]>>>;
119
+ }
120
+ /**
121
+ * The options with every default filled in.
122
+ */
123
+ export interface ResolvedOptions {
124
+ readonly targets: Readonly<Record<TargetName, false | {
125
+ name: string;
126
+ include: readonly string[];
127
+ exclude: readonly string[];
128
+ }>>;
129
+ readonly configs: {
130
+ readonly swc: string;
131
+ readonly c8: string;
132
+ readonly vitest: string;
133
+ };
134
+ readonly scripts: string | undefined;
135
+ readonly coverage: NonNullable<NxPluginOptions['coverage']>;
136
+ readonly checkPackage: {
137
+ readonly profile: 'esm-only' | 'node16' | 'strict' | undefined;
138
+ readonly floorTsconfig: false | string;
139
+ readonly inputs: readonly Input[];
140
+ };
141
+ readonly inputs: {
142
+ readonly configs: readonly Input[];
143
+ readonly tools: readonly Input[];
144
+ };
145
+ readonly namedInputs: Readonly<Record<NamedInputName, readonly Input[]>>;
146
+ }
147
+ /**
148
+ * Fills in the default of every option.
149
+ *
150
+ * @param options - the plugin's options
151
+ * @returns every option
152
+ */
153
+ export declare const resolveOptions: (options?: NxPluginOptions) => ResolvedOptions;
154
+ //# sourceMappingURL=options.d.ts.map
@@ -0,0 +1,75 @@
1
+ export const targetNames = [
2
+ 'biome',
3
+ 'eslint',
4
+ 'check-package',
5
+ 'update-ts-references',
6
+ 'tsc',
7
+ 'tsc-test',
8
+ 'mocha-unit-test',
9
+ 'mocha-integration-test',
10
+ 'vitest-unit-test',
11
+ 'coverage-report',
12
+ 'sync-injected'
13
+ ];
14
+ export const namedInputNames = [
15
+ 'dependency-files',
16
+ 'package-files',
17
+ 'eslint-input',
18
+ 'ts-source',
19
+ 'dependency-builds',
20
+ 'test-source'
21
+ ];
22
+ export const resolveOptions = (options = {})=>({
23
+ targets: Object.fromEntries(targetNames.map((target)=>{
24
+ const targetOptions = options.targets?.[target] ?? {};
25
+ return [
26
+ target,
27
+ targetOptions === false ? false : {
28
+ name: targetOptions.name ?? target,
29
+ include: targetOptions.include ?? [],
30
+ exclude: targetOptions.exclude ?? []
31
+ }
32
+ ];
33
+ })),
34
+ configs: {
35
+ swc: options.configs?.swc ?? 'node_modules/@leyman/configs/swcrc.jsonc',
36
+ c8: options.configs?.c8 ?? 'node_modules/@leyman/configs/c8rc.json',
37
+ vitest: options.configs?.vitest ?? 'node_modules/@leyman/configs/vitest.config.js'
38
+ },
39
+ scripts: options.scripts,
40
+ coverage: options.coverage ?? {},
41
+ checkPackage: {
42
+ profile: options.checkPackage?.profile,
43
+ floorTsconfig: options.checkPackage?.floorTsconfig ?? '@leyman/configs/tsconfig.node-{major}.json',
44
+ inputs: options.checkPackage?.inputs ?? [
45
+ {
46
+ externalDependencies: [
47
+ '@leyman/check-package',
48
+ "typescript"
49
+ ]
50
+ }
51
+ ]
52
+ },
53
+ inputs: {
54
+ configs: options.inputs?.configs ?? [
55
+ {
56
+ externalDependencies: [
57
+ '@leyman/configs'
58
+ ]
59
+ }
60
+ ],
61
+ tools: options.inputs?.tools ?? [
62
+ {
63
+ externalDependencies: [
64
+ '@leyman/nx-plugin'
65
+ ]
66
+ }
67
+ ]
68
+ },
69
+ namedInputs: Object.fromEntries(namedInputNames.map((name)=>[
70
+ name,
71
+ options.namedInputs?.[name] ?? []
72
+ ]))
73
+ });
74
+
75
+ //# sourceMappingURL=options.js.map
@@ -0,0 +1,12 @@
1
+ import type { CreateNodes } from '@nx/devkit';
2
+ import type { NxPluginOptions } from './options.js';
3
+ /**
4
+ * Name of the plugin, as Nx reports it.
5
+ */
6
+ export declare const name = "@leyman/nx-plugin";
7
+ /**
8
+ * The Nx plugin: infers targets for each project with a `project.json`. A `project.json` overrides any part of a
9
+ * target, as Nx merges it over what plugins infer.
10
+ */
11
+ export declare const createNodes: CreateNodes<NxPluginOptions>;
12
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1,38 @@
1
+ import Path from 'node:path';
2
+ import { inferTargets } from './infer.js';
3
+ import { resolveOptions } from './options.js';
4
+ import { loadProjects } from './projects.js';
5
+ import { assertOptions } from './schema.js';
6
+ import { namedInputs, targetConfigurations } from './targets.js';
7
+ export const name = '@leyman/nx-plugin';
8
+ const createTypescriptNodes = async (projectJsonPaths, options, { workspaceRoot })=>{
9
+ assertOptions(options ?? {}, 'nx.json');
10
+ const resolved = resolveOptions(options);
11
+ const configurations = targetConfigurations(resolved);
12
+ const projectNamedInputs = namedInputs(resolved);
13
+ const projects = await loadProjects(workspaceRoot, projectJsonPaths.map((path)=>Path.dirname(path)));
14
+ return projects.map((project)=>{
15
+ const targets = {};
16
+ for (const target of inferTargets(project, resolved)){
17
+ const { name: targetName } = resolved.targets[target];
18
+ targets[targetName] = configurations[target];
19
+ }
20
+ return [
21
+ Path.join(project.root, 'project.json'),
22
+ {
23
+ projects: {
24
+ [project.root]: {
25
+ namedInputs: projectNamedInputs,
26
+ targets
27
+ }
28
+ }
29
+ }
30
+ ];
31
+ });
32
+ };
33
+ export const createNodes = [
34
+ '**/project.json',
35
+ createTypescriptNodes
36
+ ];
37
+
38
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1,27 @@
1
+ import type { InferencePackageJson, ProjectFacts } from './infer.js';
2
+ /**
3
+ * The fields of a workspace package's `package.json` the plugin reads.
4
+ */
5
+ export interface WorkspacePackageJson extends InferencePackageJson {
6
+ readonly name?: string;
7
+ readonly dependencies?: Readonly<Record<string, string>>;
8
+ readonly optionalDependencies?: Readonly<Record<string, string>>;
9
+ readonly peerDependencies?: Readonly<Record<string, string>>;
10
+ }
11
+ /**
12
+ * A project as inference sees it, with its `project.json` if it has one.
13
+ */
14
+ export interface LoadedProject extends ProjectFacts {
15
+ readonly projectJson: Record<string, unknown> | undefined;
16
+ }
17
+ export declare const readJson: (path: string) => Promise<unknown>;
18
+ /**
19
+ * Reads what inference needs of each project: its files, its `package.json`, and whether another of the projects
20
+ * depends on it.
21
+ *
22
+ * @param workspaceRoot - absolute path the roots are relative to
23
+ * @param roots - root of each project, relative to the workspace root
24
+ * @returns each project, in the order of `roots`
25
+ */
26
+ export declare const loadProjects: (workspaceRoot: string, roots: readonly string[]) => Promise<LoadedProject[]>;
27
+ //# sourceMappingURL=projects.d.ts.map