@vercel/build-utils 4.2.1 → 5.0.1

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.
@@ -1,34 +0,0 @@
1
- import type { Builder, BuilderFunctions, PackageJson, ProjectSettings } from './types';
2
- interface Metadata {
3
- plugins: string[];
4
- hasDotOutput: boolean;
5
- hasMiddleware: boolean;
6
- }
7
- /**
8
- * If the Deployment can be built with the new File System API,
9
- * return the new Builder. Otherwise an "Exclusion Condition"
10
- * was hit so return `null` builder with a `reason` for exclusion.
11
- */
12
- export declare function detectFileSystemAPI({ files, projectSettings, builders, vercelConfig, pkg, tag, enableFlag, }: {
13
- files: {
14
- [relPath: string]: any;
15
- };
16
- projectSettings: ProjectSettings;
17
- builders: Builder[];
18
- vercelConfig: {
19
- builds?: Builder[];
20
- functions?: BuilderFunctions;
21
- } | null | undefined;
22
- pkg: PackageJson | null | undefined;
23
- tag: string | undefined;
24
- enableFlag: boolean | undefined;
25
- }): Promise<{
26
- metadata: Metadata;
27
- fsApiBuilder: Builder;
28
- reason: null;
29
- } | {
30
- metadata: Metadata;
31
- fsApiBuilder: null;
32
- reason: string;
33
- }>;
34
- export {};
@@ -1,173 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.detectFileSystemAPI = void 0;
7
- const semver_1 = __importDefault(require("semver"));
8
- const _1 = require("./");
9
- const enableFileSystemApiFrameworks = new Set(['solidstart']);
10
- /**
11
- * If the Deployment can be built with the new File System API,
12
- * return the new Builder. Otherwise an "Exclusion Condition"
13
- * was hit so return `null` builder with a `reason` for exclusion.
14
- */
15
- async function detectFileSystemAPI({ files, projectSettings, builders, vercelConfig, pkg, tag, enableFlag = false, }) {
16
- const framework = projectSettings.framework || '';
17
- const deps = Object.assign({}, pkg?.dependencies, pkg?.devDependencies);
18
- const plugins = Object.keys(deps).filter(dep => dep.startsWith('vercel-plugin-'));
19
- const hasDotOutput = Object.keys(files).some(file => file.startsWith('.output/'));
20
- const hasMiddleware = Boolean(files['_middleware.js'] || files['_middleware.ts']);
21
- const metadata = {
22
- plugins,
23
- hasDotOutput,
24
- hasMiddleware,
25
- };
26
- const isEnabled = enableFlag ||
27
- hasMiddleware ||
28
- hasDotOutput ||
29
- enableFileSystemApiFrameworks.has(framework);
30
- if (!isEnabled) {
31
- return { metadata, fsApiBuilder: null, reason: 'Flag not enabled.' };
32
- }
33
- if (vercelConfig?.builds && vercelConfig.builds.length > 0) {
34
- return {
35
- metadata,
36
- fsApiBuilder: null,
37
- reason: 'Detected `builds` in vercel.json. Please remove it in favor of CLI plugins.',
38
- };
39
- }
40
- if (Object.values(vercelConfig?.functions || {}).some(fn => !!fn.runtime)) {
41
- return {
42
- metadata,
43
- fsApiBuilder: null,
44
- reason: 'Detected `functions.runtime` in vercel.json. Please remove it in favor of CLI plugins.',
45
- };
46
- }
47
- if (process.env.HUGO_VERSION) {
48
- return {
49
- metadata,
50
- fsApiBuilder: null,
51
- reason: 'Detected `HUGO_VERSION` environment variable. Please remove it.',
52
- };
53
- }
54
- if (process.env.ZOLA_VERSION) {
55
- return {
56
- metadata,
57
- fsApiBuilder: null,
58
- reason: 'Detected `ZOLA_VERSION` environment variable. Please remove it.',
59
- };
60
- }
61
- if (process.env.GUTENBERG_VERSION) {
62
- return {
63
- metadata,
64
- fsApiBuilder: null,
65
- reason: 'Detected `GUTENBERG_VERSION` environment variable. Please remove it.',
66
- };
67
- }
68
- const invalidBuilder = builders.find(({ use }) => {
69
- const valid = _1.isOfficialRuntime('go', use) ||
70
- _1.isOfficialRuntime('python', use) ||
71
- _1.isOfficialRuntime('ruby', use) ||
72
- _1.isOfficialRuntime('node', use) ||
73
- _1.isOfficialRuntime('next', use) ||
74
- _1.isOfficialRuntime('static', use) ||
75
- _1.isOfficialRuntime('static-build', use);
76
- return !valid;
77
- });
78
- if (invalidBuilder) {
79
- return {
80
- metadata,
81
- fsApiBuilder: null,
82
- reason: `Detected \`${invalidBuilder.use}\` in vercel.json. Please remove it in favor of CLI plugins.`,
83
- };
84
- }
85
- for (const lang of ['go', 'python', 'ruby']) {
86
- for (const { use } of builders) {
87
- const plugin = 'vercel-plugin-' + lang;
88
- if (_1.isOfficialRuntime(lang, use) && !deps[plugin]) {
89
- return {
90
- metadata,
91
- fsApiBuilder: null,
92
- reason: `Detected \`${lang}\` Serverless Function usage without plugin \`${plugin}\`. Please run \`npm i ${plugin}\`.`,
93
- };
94
- }
95
- }
96
- }
97
- if (framework === 'nuxtjs' ||
98
- framework === 'sveltekit' ||
99
- framework === 'redwoodjs') {
100
- return {
101
- metadata,
102
- fsApiBuilder: null,
103
- reason: `Detected framework \`${framework}\` that only supports legacy File System API. Please contact the framework author.`,
104
- };
105
- }
106
- if (framework === 'nextjs' && !hasDotOutput) {
107
- // Use the old pipeline if a custom output directory was specified for Next.js
108
- // because `vercel build` cannot ensure that the directory will be in the same
109
- // location as `.output`, which can break imports (not just nft.json files).
110
- if (projectSettings?.outputDirectory) {
111
- return {
112
- metadata,
113
- fsApiBuilder: null,
114
- reason: `Detected Next.js with Output Directory \`${projectSettings.outputDirectory}\` override. Please change it back to the default.`,
115
- };
116
- }
117
- const nextVersion = deps['next'];
118
- if (!nextVersion) {
119
- return {
120
- metadata,
121
- fsApiBuilder: null,
122
- reason: `Detected Next.js in Project Settings but missing \`next\` package.json dependencies. Please run \`npm i next\`.`,
123
- };
124
- }
125
- // TODO: Read version from lockfile instead of package.json
126
- if (nextVersion !== 'latest' && nextVersion !== 'canary') {
127
- const fixedVersion = semver_1.default.valid(semver_1.default.coerce(nextVersion) || '');
128
- if (!fixedVersion || !semver_1.default.gte(fixedVersion, '12.0.0')) {
129
- return {
130
- metadata,
131
- fsApiBuilder: null,
132
- reason: `Detected legacy Next.js version "${nextVersion}" in package.json. Please run \`npm i next@latest\` to upgrade.`,
133
- };
134
- }
135
- }
136
- }
137
- if (!hasDotOutput) {
138
- // TODO: Read version from lockfile instead of package.json
139
- const vercelCliVersion = deps['vercel'];
140
- if (vercelCliVersion &&
141
- vercelCliVersion !== 'latest' &&
142
- vercelCliVersion !== 'canary') {
143
- const fixedVersion = semver_1.default.valid(semver_1.default.coerce(vercelCliVersion) || '');
144
- // TODO: we might want to use '24.0.0' once its released
145
- if (!fixedVersion || !semver_1.default.gte(fixedVersion, '23.1.3-canary.68')) {
146
- return {
147
- metadata,
148
- fsApiBuilder: null,
149
- reason: `Detected legacy Vercel CLI version "${vercelCliVersion}" in package.json. Please run \`npm i vercel@latest\` to upgrade.`,
150
- };
151
- }
152
- }
153
- }
154
- const frontendBuilder = builders.find(({ use }) => _1.isOfficialRuntime('next', use) ||
155
- _1.isOfficialRuntime('static', use) ||
156
- _1.isOfficialRuntime('static-build', use));
157
- const config = frontendBuilder?.config || {};
158
- const withTag = tag ? `@${tag}` : '';
159
- const fsApiBuilder = {
160
- use: `@vercelruntimes/file-system-api${withTag}`,
161
- src: '**',
162
- config: {
163
- ...config,
164
- fileSystemAPI: true,
165
- framework: config.framework || framework || null,
166
- projectSettings,
167
- hasMiddleware,
168
- hasDotOutput,
169
- },
170
- };
171
- return { metadata, fsApiBuilder, reason: null };
172
- }
173
- exports.detectFileSystemAPI = detectFileSystemAPI;
@@ -1,12 +0,0 @@
1
- import { Framework } from '@vercel/frameworks';
2
- import { DetectorFilesystem } from './detectors/filesystem';
3
- interface BaseFramework {
4
- slug: Framework['slug'];
5
- detectors?: Framework['detectors'];
6
- }
7
- export interface DetectFrameworkOptions {
8
- fs: DetectorFilesystem;
9
- frameworkList: readonly BaseFramework[];
10
- }
11
- export declare function detectFramework({ fs, frameworkList, }: DetectFrameworkOptions): Promise<string | null>;
12
- export {};
@@ -1,60 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.detectFramework = void 0;
4
- async function matches(fs, framework) {
5
- const { detectors } = framework;
6
- if (!detectors) {
7
- return false;
8
- }
9
- const { every, some } = detectors;
10
- if (every !== undefined && !Array.isArray(every)) {
11
- return false;
12
- }
13
- if (some !== undefined && !Array.isArray(some)) {
14
- return false;
15
- }
16
- const check = async ({ path, matchContent }) => {
17
- if (!path) {
18
- return false;
19
- }
20
- if ((await fs.hasPath(path)) === false) {
21
- return false;
22
- }
23
- if (matchContent) {
24
- if ((await fs.isFile(path)) === false) {
25
- return false;
26
- }
27
- const regex = new RegExp(matchContent, 'gm');
28
- const content = await fs.readFile(path);
29
- if (!regex.test(content.toString())) {
30
- return false;
31
- }
32
- }
33
- return true;
34
- };
35
- const result = [];
36
- if (every) {
37
- const everyResult = await Promise.all(every.map(item => check(item)));
38
- result.push(...everyResult);
39
- }
40
- if (some) {
41
- let someResult = false;
42
- for (const item of some) {
43
- if (await check(item)) {
44
- someResult = true;
45
- break;
46
- }
47
- }
48
- result.push(someResult);
49
- }
50
- return result.every(res => res === true);
51
- }
52
- async function detectFramework({ fs, frameworkList, }) {
53
- for (const framework of frameworkList) {
54
- if (await matches(fs, framework)) {
55
- return framework.slug;
56
- }
57
- }
58
- return null;
59
- }
60
- exports.detectFramework = detectFramework;
@@ -1,54 +0,0 @@
1
- /// <reference types="node" />
2
- export interface Stat {
3
- name: string;
4
- path: string;
5
- type: 'file' | 'dir';
6
- }
7
- /**
8
- * `DetectorFilesystem` is an abstract class that represents a virtual filesystem
9
- * to perform read-only operations on in order to detect which framework is being
10
- * used.
11
- *
12
- * Its abstract methods must be implemented by a subclass that perform the actual
13
- * FS operations. Example subclasses could be implemented as:
14
- *
15
- * - Local filesystem, which proxies the FS operations to the equivalent `fs`
16
- * module functions.
17
- * - HTTP filesystem, which implements the FS operations over an HTTP server
18
- * and does not require a local copy of the files.
19
- * - `Files` filesystem, which operates on a virtual `Files` object (i.e. from
20
- * the `glob()` function) which could include `FileFsRef`, `FileBlob`, etc.
21
- *
22
- * This base class implements various helper functions for common tasks (i.e.
23
- * read and parse a JSON file). It also includes caching for all FS operations
24
- * so that multiple detector functions de-dup read operations on the same file
25
- * to reduce network/filesystem overhead.
26
- *
27
- * **NOTE:** It's important that all instance methods in this base class are
28
- * bound to `this` so that the `fs` object may be destructured in the detector
29
- * functions. The easiest way to do this is to use the `=` syntax when defining
30
- * methods in this class definition.
31
- */
32
- export declare abstract class DetectorFilesystem {
33
- protected abstract _hasPath(name: string): Promise<boolean>;
34
- protected abstract _readFile(name: string): Promise<Buffer>;
35
- protected abstract _isFile(name: string): Promise<boolean>;
36
- protected abstract _readdir(name: string): Promise<Stat[]>;
37
- protected abstract _chdir(name: string): DetectorFilesystem;
38
- private pathCache;
39
- private fileCache;
40
- private readFileCache;
41
- private readdirCache;
42
- constructor();
43
- hasPath: (path: string) => Promise<boolean>;
44
- isFile: (name: string) => Promise<boolean>;
45
- readFile: (name: string) => Promise<Buffer>;
46
- /**
47
- * Returns a list of Stat objects from the current working directory.
48
- */
49
- readdir: (name: string) => Promise<Stat[]>;
50
- /**
51
- * Changes the current directory to the specified path and returns a new instance of DetectorFilesystem.
52
- */
53
- chdir: (name: string) => DetectorFilesystem;
54
- }
@@ -1,78 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DetectorFilesystem = void 0;
4
- /**
5
- * `DetectorFilesystem` is an abstract class that represents a virtual filesystem
6
- * to perform read-only operations on in order to detect which framework is being
7
- * used.
8
- *
9
- * Its abstract methods must be implemented by a subclass that perform the actual
10
- * FS operations. Example subclasses could be implemented as:
11
- *
12
- * - Local filesystem, which proxies the FS operations to the equivalent `fs`
13
- * module functions.
14
- * - HTTP filesystem, which implements the FS operations over an HTTP server
15
- * and does not require a local copy of the files.
16
- * - `Files` filesystem, which operates on a virtual `Files` object (i.e. from
17
- * the `glob()` function) which could include `FileFsRef`, `FileBlob`, etc.
18
- *
19
- * This base class implements various helper functions for common tasks (i.e.
20
- * read and parse a JSON file). It also includes caching for all FS operations
21
- * so that multiple detector functions de-dup read operations on the same file
22
- * to reduce network/filesystem overhead.
23
- *
24
- * **NOTE:** It's important that all instance methods in this base class are
25
- * bound to `this` so that the `fs` object may be destructured in the detector
26
- * functions. The easiest way to do this is to use the `=` syntax when defining
27
- * methods in this class definition.
28
- */
29
- class DetectorFilesystem {
30
- constructor() {
31
- this.hasPath = async (path) => {
32
- let p = this.pathCache.get(path);
33
- if (!p) {
34
- p = this._hasPath(path);
35
- this.pathCache.set(path, p);
36
- }
37
- return p;
38
- };
39
- this.isFile = async (name) => {
40
- let p = this.fileCache.get(name);
41
- if (!p) {
42
- p = this._isFile(name);
43
- this.fileCache.set(name, p);
44
- }
45
- return p;
46
- };
47
- this.readFile = async (name) => {
48
- let p = this.readFileCache.get(name);
49
- if (!p) {
50
- p = this._readFile(name);
51
- this.readFileCache.set(name, p);
52
- }
53
- return p;
54
- };
55
- /**
56
- * Returns a list of Stat objects from the current working directory.
57
- */
58
- this.readdir = async (name) => {
59
- let p = this.readdirCache.get(name);
60
- if (!p) {
61
- p = this._readdir(name);
62
- this.readdirCache.set(name, p);
63
- }
64
- return p;
65
- };
66
- /**
67
- * Changes the current directory to the specified path and returns a new instance of DetectorFilesystem.
68
- */
69
- this.chdir = (name) => {
70
- return this._chdir(name);
71
- };
72
- this.pathCache = new Map();
73
- this.fileCache = new Map();
74
- this.readFileCache = new Map();
75
- this.readdirCache = new Map();
76
- }
77
- }
78
- exports.DetectorFilesystem = DetectorFilesystem;
@@ -1,6 +0,0 @@
1
- /// <reference types="node" />
2
- import fs from 'fs';
3
- import { DetectorFilesystem } from '../detectors/filesystem';
4
- declare type GlobFs = typeof fs;
5
- export declare function getGlobFs(_fs: DetectorFilesystem): GlobFs;
6
- export {};
@@ -1,71 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getGlobFs = void 0;
7
- const fs_1 = __importDefault(require("fs"));
8
- function normalizePath(path) {
9
- // on windows, this will return a path like
10
- // D:/c/package.json
11
- // since we abstract the filesystem, we need to remove windows specific info from the path
12
- // and let the FS decide how to process the path
13
- // D:/c/package.json => /c/package.json
14
- return path.replace(/^[a-zA-Z]:/, '');
15
- }
16
- function getGlobFs(_fs) {
17
- const readdir = (path, callback) => {
18
- _fs
19
- .readdir(normalizePath(String(path)))
20
- .then(stats => callback(null, stats.map(stat => stat.name)))
21
- .catch(err => callback(err, []));
22
- };
23
- const stat = (path, callback) => {
24
- _fs
25
- .isFile(normalizePath(String(path)))
26
- .then(isPathAFile => {
27
- callback(null, {
28
- ino: 0,
29
- mode: 0,
30
- nlink: 0,
31
- uid: 0,
32
- gid: 0,
33
- rdev: 0,
34
- size: 0,
35
- blksize: 0,
36
- blocks: 0,
37
- atimeMs: 0,
38
- mtimeMs: 0,
39
- ctimeMs: 0,
40
- birthtimeMs: 0,
41
- atime: new Date(),
42
- mtime: new Date(),
43
- ctime: new Date(),
44
- birthtime: new Date(),
45
- dev: 0,
46
- isBlockDevice: () => false,
47
- isCharacterDevice: () => false,
48
- isDirectory: () => !isPathAFile,
49
- isFIFO: () => false,
50
- isFile: () => isPathAFile,
51
- isSocket: () => false,
52
- isSymbolicLink: () => false,
53
- });
54
- })
55
- .catch(err => callback(err, null));
56
- };
57
- return new Proxy(fs_1.default, {
58
- get(_target, prop) {
59
- switch (prop) {
60
- case 'readdir':
61
- return readdir;
62
- case 'lstat':
63
- case 'stat':
64
- return stat;
65
- default:
66
- throw new Error('Not Implemented');
67
- }
68
- },
69
- });
70
- }
71
- exports.getGlobFs = getGlobFs;
@@ -1,9 +0,0 @@
1
- import { DetectorFilesystem } from './detectors/filesystem';
2
- export interface GetProjectPathsOptions {
3
- fs: DetectorFilesystem;
4
- path?: string;
5
- skipPaths?: string[];
6
- depth?: number;
7
- }
8
- export declare type ProjectPath = string;
9
- export declare const getProjectPaths: ({ fs, path, skipPaths, depth, }: GetProjectPathsOptions) => Promise<ProjectPath[]>;
@@ -1,39 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getProjectPaths = void 0;
7
- const detect_framework_1 = require("./detect-framework");
8
- const frameworks_1 = __importDefault(require("@vercel/frameworks"));
9
- const MAX_DEPTH_TRAVERSE = 3;
10
- const getProjectPaths = async ({ fs, path, skipPaths, depth = MAX_DEPTH_TRAVERSE, }) => {
11
- if (depth === 0)
12
- return [];
13
- const allPaths = [];
14
- const topPath = path ?? './';
15
- if (path && skipPaths?.includes(path)) {
16
- return allPaths;
17
- }
18
- const framework = await detect_framework_1.detectFramework({
19
- fs: fs.chdir(topPath),
20
- frameworkList: frameworks_1.default,
21
- });
22
- if (framework !== null)
23
- allPaths.push(topPath);
24
- if (depth > 1) {
25
- const directoryContents = await fs.readdir(topPath);
26
- const childDirectories = directoryContents.filter(stat => stat.type === 'dir' && !skipPaths?.includes(stat.path));
27
- const paths = (await Promise.all(childDirectories.map(({ path }) => {
28
- return exports.getProjectPaths({
29
- fs,
30
- path,
31
- depth: depth - 1,
32
- skipPaths,
33
- });
34
- }))).flat();
35
- return [...paths, ...allPaths];
36
- }
37
- return allPaths;
38
- };
39
- exports.getProjectPaths = getProjectPaths;
@@ -1,16 +0,0 @@
1
- import type { Framework } from '@vercel/frameworks';
2
- /**
3
- * The supported list of monorepo managers.
4
- *
5
- * This list is designed to work with the @see {@link detectFramework} function.
6
- *
7
- * @example
8
- * import { monorepoManagers as frameworkList } from '@vercel/build-utils'
9
- * import { detectFramework } from '@vercel/build-utils'
10
- *
11
- * const fs = new GitDetectorFilesystem(...)
12
- * detectFramwork({ fs, frameworkList }) // returns the 'slug' field if detected, otherwise null
13
- *
14
- */
15
- export declare const monorepoManagers: Array<Omit<Framework, 'description' | 'logo' | 'settings' | 'getOutputDirName'>>;
16
- export default monorepoManagers;
@@ -1,34 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.monorepoManagers = void 0;
4
- /**
5
- * The supported list of monorepo managers.
6
- *
7
- * This list is designed to work with the @see {@link detectFramework} function.
8
- *
9
- * @example
10
- * import { monorepoManagers as frameworkList } from '@vercel/build-utils'
11
- * import { detectFramework } from '@vercel/build-utils'
12
- *
13
- * const fs = new GitDetectorFilesystem(...)
14
- * detectFramwork({ fs, frameworkList }) // returns the 'slug' field if detected, otherwise null
15
- *
16
- */
17
- exports.monorepoManagers = [
18
- {
19
- name: 'Turborepo',
20
- slug: 'turbo',
21
- detectors: {
22
- some: [
23
- {
24
- path: 'turbo.json',
25
- },
26
- {
27
- path: 'package.json',
28
- matchContent: '"turbo":\\s*{[^}]*.+[^}]*}',
29
- },
30
- ],
31
- },
32
- },
33
- ];
34
- exports.default = exports.monorepoManagers;
@@ -1,11 +0,0 @@
1
- import { DetectorFilesystem } from '../detectors/filesystem';
2
- import { Workspace } from './get-workspaces';
3
- interface GetPackagePathOptions {
4
- fs: DetectorFilesystem;
5
- }
6
- export interface GetWorkspacePackagePathsOptions extends GetPackagePathOptions {
7
- fs: DetectorFilesystem;
8
- workspace: Workspace;
9
- }
10
- export declare function getWorkspacePackagePaths({ fs, workspace, }: GetWorkspacePackagePathsOptions): Promise<string[]>;
11
- export {};
@@ -1,62 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getWorkspacePackagePaths = void 0;
7
- const path_1 = __importDefault(require("path"));
8
- const js_yaml_1 = __importDefault(require("js-yaml"));
9
- const glob_1 = __importDefault(require("glob"));
10
- const get_glob_fs_1 = require("../fs/get-glob-fs");
11
- const normalize_path_1 = require("../fs/normalize-path");
12
- const posixPath = path_1.default.posix;
13
- async function getWorkspacePackagePaths({ fs, workspace, }) {
14
- const { type, rootPath } = workspace;
15
- const workspaceFs = fs.chdir(rootPath);
16
- let results = [];
17
- switch (type) {
18
- case 'yarn':
19
- case 'npm':
20
- results = await getPackageJsonWorkspacePackagePaths({ fs: workspaceFs });
21
- break;
22
- case 'pnpm':
23
- results = await getPnpmWorkspacePackagePaths({ fs: workspaceFs });
24
- break;
25
- default:
26
- throw new Error(`Unknown workspace implementation: ${type}`);
27
- }
28
- return results.map(packagePath => {
29
- return posixPath.join(rootPath, posixPath.dirname(packagePath));
30
- });
31
- }
32
- exports.getWorkspacePackagePaths = getWorkspacePackagePaths;
33
- async function getPackagePaths(packages, fs) {
34
- return (await Promise.all(packages.map(packageGlob => new Promise((resolve, reject) => {
35
- glob_1.default(normalize_path_1.normalizePath(posixPath.join(packageGlob, 'package.json')), {
36
- cwd: '/',
37
- fs: get_glob_fs_1.getGlobFs(fs),
38
- }, (err, matches) => {
39
- if (err)
40
- reject(err);
41
- else
42
- resolve(matches);
43
- });
44
- })))).flat();
45
- }
46
- async function getPackageJsonWorkspacePackagePaths({ fs, }) {
47
- const packageJsonAsBuffer = await fs.readFile('package.json');
48
- const { workspaces } = JSON.parse(packageJsonAsBuffer.toString());
49
- let packages = [];
50
- if (Array.isArray(workspaces)) {
51
- packages = workspaces;
52
- }
53
- else {
54
- packages = workspaces?.packages ?? [];
55
- }
56
- return getPackagePaths(packages, fs);
57
- }
58
- async function getPnpmWorkspacePackagePaths({ fs, }) {
59
- const pnpmWorkspaceAsBuffer = await fs.readFile('pnpm-workspace.yaml');
60
- const { packages = [] } = js_yaml_1.default.load(pnpmWorkspaceAsBuffer.toString());
61
- return getPackagePaths(packages, fs);
62
- }