@arcgis/node-toolkit 5.2.0-next.100
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/LICENSE.md +19 -0
- package/README.md +12 -0
- package/dist/file.d.ts +37 -0
- package/dist/file.js +49 -0
- package/dist/glob.d.ts +28 -0
- package/dist/glob.js +28 -0
- package/dist/packageJson.d.ts +104 -0
- package/dist/packageJson.js +58 -0
- package/dist/path.d.ts +60 -0
- package/dist/path.js +48 -0
- package/dist/shell.d.ts +115 -0
- package/dist/shell.js +160 -0
- package/dist/vite/externalizeDependenciesPlugin.d.ts +96 -0
- package/dist/vite/externalizeDependenciesPlugin.js +104 -0
- package/dist/vite/installPlaywright.d.ts +3 -0
- package/dist/vite/installPlaywright.js +87 -0
- package/dist/vite/presetPlugin.d.ts +21 -0
- package/dist/vite/presetPlugin.js +76 -0
- package/dist/vite/simpleTypesEmit.d.ts +19 -0
- package/dist/vite/simpleTypesEmit.js +76 -0
- package/dist/vite/typeScript.d.ts +21 -0
- package/dist/vite/typeScript.js +40 -0
- package/dist/workspace.d.ts +62 -0
- package/dist/workspace.js +78 -0
- package/package.json +32 -0
package/dist/shell.js
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { exec, spawn, spawnSync, execSync } from "node:child_process";
|
|
2
|
+
import { styleText } from "node:util";
|
|
3
|
+
function sh(command, options = {}) {
|
|
4
|
+
try {
|
|
5
|
+
const normalizedOptions = { encoding: "utf8", ...options };
|
|
6
|
+
return execSync(command.trim(), normalizedOptions).trim();
|
|
7
|
+
} catch (error) {
|
|
8
|
+
makeExecErrorReadable(error);
|
|
9
|
+
throw error;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
async function asyncSh(command, options = {}) {
|
|
13
|
+
const normalizedOptions = { encoding: "utf8", ...options };
|
|
14
|
+
return await new Promise((resolve, reject) => {
|
|
15
|
+
exec(command.trim(), normalizedOptions, (error, stdout, stderr) => {
|
|
16
|
+
if (error) {
|
|
17
|
+
makeExecErrorReadable(error);
|
|
18
|
+
reject(error);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
resolve(stdout.trim() || stderr.trim());
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function makeExecErrorReadable(error) {
|
|
26
|
+
if (error instanceof Error && error.stack && "output" in error && Array.isArray(error.output) && "status" in error) {
|
|
27
|
+
const stackIndex = error.stack.indexOf("\n at ");
|
|
28
|
+
if (stackIndex !== -1) {
|
|
29
|
+
const output = error.output.filter(Boolean).join("\n").trim();
|
|
30
|
+
const newHeader = `${styleText("red", error.message)} (exit code: ${String(error.status)})
|
|
31
|
+
${output}`;
|
|
32
|
+
const oldStackFrames = error.stack.substring(stackIndex);
|
|
33
|
+
error.stack = `Error: ${newHeader}${oldStackFrames}`;
|
|
34
|
+
}
|
|
35
|
+
Object.defineProperties(error, {
|
|
36
|
+
output: { enumerable: false },
|
|
37
|
+
stdout: { enumerable: false },
|
|
38
|
+
stderr: { enumerable: false },
|
|
39
|
+
signal: { enumerable: false },
|
|
40
|
+
status: { enumerable: false },
|
|
41
|
+
pid: { enumerable: false },
|
|
42
|
+
stdio: { enumerable: false }
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function sp(command, args, options = {}) {
|
|
47
|
+
if (process.platform === "win32" && command === "pnpm" && // Allow explicit shell config including shell:false for environment-specific handling.
|
|
48
|
+
!("shell" in options)) {
|
|
49
|
+
throw Error(
|
|
50
|
+
'If invoking pnpm on Windows, provide { shell: true } or { shell: process.platform === "win32" } and handle shell escaping.'
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
const normalizedOptions = { encoding: "utf8", ...options };
|
|
54
|
+
const result = spawnSync(command, args, normalizedOptions);
|
|
55
|
+
if (result.error) {
|
|
56
|
+
throw result.error;
|
|
57
|
+
}
|
|
58
|
+
const sep = result.stdout && result.stderr ? "\n" : "";
|
|
59
|
+
const output = `${result.stdout ?? ""}${sep}${result.stderr ?? ""}`.trim();
|
|
60
|
+
const exitCode = result.status ?? 0;
|
|
61
|
+
if (exitCode !== 0) {
|
|
62
|
+
throw makeSpawnError(command, args, exitCode, result.signal, output);
|
|
63
|
+
}
|
|
64
|
+
return output;
|
|
65
|
+
}
|
|
66
|
+
function runCommandSync(command, args, options = {}) {
|
|
67
|
+
const fixedOptions = fixPnpmUsage(command, options);
|
|
68
|
+
const { input } = fixedOptions;
|
|
69
|
+
const stdio = input === void 0 ? "inherit" : ["pipe", "inherit", "inherit"];
|
|
70
|
+
const result = spawnSync(command, args, { stdio, ...fixedOptions });
|
|
71
|
+
assertSyncResultSuccess(command, args, result);
|
|
72
|
+
}
|
|
73
|
+
async function runCommand(command, args, options = {}) {
|
|
74
|
+
const fixedOptions = fixPnpmUsage(command, options);
|
|
75
|
+
const { input } = fixedOptions;
|
|
76
|
+
const stdio = input === void 0 ? "inherit" : ["pipe", "inherit", "inherit"];
|
|
77
|
+
const child = spawn(command, args, { stdio, ...fixedOptions });
|
|
78
|
+
if (input !== void 0) {
|
|
79
|
+
child.stdin?.end(input);
|
|
80
|
+
}
|
|
81
|
+
await new Promise((resolve, reject) => {
|
|
82
|
+
child.on("error", (error) => reject(error));
|
|
83
|
+
child.on("close", (code, signal) => {
|
|
84
|
+
if (code !== 0) {
|
|
85
|
+
reject(makeSpawnError(command, args, code, signal, ""));
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
resolve();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
function collectOutputSync(command, args, options = {}) {
|
|
93
|
+
const fixedOptions = fixPnpmUsage(command, options);
|
|
94
|
+
const { input, stderr = "inherit", ...spawnOptions } = fixedOptions;
|
|
95
|
+
const result = spawnSync(command, args, {
|
|
96
|
+
encoding: "utf8",
|
|
97
|
+
stdio: [input === void 0 ? "ignore" : "pipe", "pipe", stderr],
|
|
98
|
+
...spawnOptions,
|
|
99
|
+
...input === void 0 ? {} : { input }
|
|
100
|
+
});
|
|
101
|
+
assertSyncResultSuccess(command, args, result);
|
|
102
|
+
return (result.stdout ?? "").trim();
|
|
103
|
+
}
|
|
104
|
+
async function collectOutput(command, args, options = {}) {
|
|
105
|
+
const fixedOptions = fixPnpmUsage(command, options);
|
|
106
|
+
const { input } = fixedOptions;
|
|
107
|
+
const child = spawn(command, args, {
|
|
108
|
+
stdio: [input === void 0 ? "ignore" : "pipe", "pipe", "inherit"],
|
|
109
|
+
...fixedOptions
|
|
110
|
+
});
|
|
111
|
+
if (input !== void 0) {
|
|
112
|
+
child.stdin?.end(input);
|
|
113
|
+
}
|
|
114
|
+
const stdoutChunks = [];
|
|
115
|
+
child.stdout?.on(
|
|
116
|
+
"data",
|
|
117
|
+
(chunk) => stdoutChunks.push(Buffer.isBuffer(chunk) ? chunk.toString("utf8") : String(chunk))
|
|
118
|
+
);
|
|
119
|
+
await new Promise((resolve, reject) => {
|
|
120
|
+
child.on("error", (error) => reject(error));
|
|
121
|
+
child.on("close", (code, signal) => {
|
|
122
|
+
if (code !== 0) {
|
|
123
|
+
reject(makeSpawnError(command, args, code, signal, ""));
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
resolve();
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
return stdoutChunks.join("").trim();
|
|
130
|
+
}
|
|
131
|
+
function fixPnpmUsage(command, options) {
|
|
132
|
+
if (process.platform === "win32" && command === "pnpm") {
|
|
133
|
+
const fixedOptions = { shell: process.platform === "win32", ...options };
|
|
134
|
+
return fixedOptions;
|
|
135
|
+
}
|
|
136
|
+
return options;
|
|
137
|
+
}
|
|
138
|
+
function assertSyncResultSuccess(command, args, result) {
|
|
139
|
+
if (result.error) {
|
|
140
|
+
throw result.error;
|
|
141
|
+
}
|
|
142
|
+
if (result.status !== 0) {
|
|
143
|
+
throw makeSpawnError(command, args, result.status, result.signal, String(result.stderr ?? "").trim());
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function makeSpawnError(command, args, code, signal, output) {
|
|
147
|
+
const commandText = `${command} ${args.join(" ")}`.trim();
|
|
148
|
+
const statusText = code !== null ? `exit code ${String(code)}` : `signal ${signal ?? "unknown"}`;
|
|
149
|
+
return new Error(`Command failed with ${statusText}: ${commandText}
|
|
150
|
+
${output}`.trim());
|
|
151
|
+
}
|
|
152
|
+
export {
|
|
153
|
+
asyncSh,
|
|
154
|
+
collectOutput,
|
|
155
|
+
collectOutputSync,
|
|
156
|
+
runCommand,
|
|
157
|
+
runCommandSync,
|
|
158
|
+
sh,
|
|
159
|
+
sp
|
|
160
|
+
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { Plugin } from "vite";
|
|
2
|
+
import { type PackageJson } from "../packageJson.ts";
|
|
3
|
+
/**
|
|
4
|
+
* Options for managing dependencies in a Vite project.
|
|
5
|
+
*
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
export type DependencyManagementOptions = {
|
|
9
|
+
/**
|
|
10
|
+
* Force bundle in these dependencies even if they are declared as
|
|
11
|
+
* dependencies or peerDependencies.
|
|
12
|
+
*
|
|
13
|
+
* @public
|
|
14
|
+
* @example
|
|
15
|
+
* This is desirable if you wish to control the version of a dependency or
|
|
16
|
+
* need to post-process the dependency in some way. Usually, you will declare
|
|
17
|
+
* such as a devDependency, but there is a use case for declaring it as a
|
|
18
|
+
* dependency instead:
|
|
19
|
+
*
|
|
20
|
+
* - If TypeScript types from the bundled in dependencies are referenced in
|
|
21
|
+
* the `.d.ts` files of your library, you will need to declare the package
|
|
22
|
+
* as a `dependency`, so that it is still installed on the consumer's
|
|
23
|
+
* computer so that TypeScript can correctly resolve the types of that
|
|
24
|
+
* library.
|
|
25
|
+
*/
|
|
26
|
+
readonly bundleIn?: (RegExp | string)[];
|
|
27
|
+
/**
|
|
28
|
+
* Force externalize these dependencies, even if they are declared as
|
|
29
|
+
* devDependencies.
|
|
30
|
+
*
|
|
31
|
+
* @public
|
|
32
|
+
* @example
|
|
33
|
+
* This is desirable if you are sure the end user will have these dependencies
|
|
34
|
+
* available, yet do not wish to declare these as devDependencies for some
|
|
35
|
+
* technical reasons.
|
|
36
|
+
*/
|
|
37
|
+
readonly externalize?: (RegExp | string)[];
|
|
38
|
+
/**
|
|
39
|
+
* By default, this plugin errors if any devDependency is used in runtime code
|
|
40
|
+
* to avoid bundling in dependencies in a library. In application packages,
|
|
41
|
+
* bundling in everything is desirable, so enable this option.
|
|
42
|
+
*
|
|
43
|
+
* @public
|
|
44
|
+
* @default false
|
|
45
|
+
*/
|
|
46
|
+
readonly isApplication?: boolean;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* By default, Rollup will bundle-in all dependencies.
|
|
50
|
+
*
|
|
51
|
+
* We change it as follows:
|
|
52
|
+
* Externalize all packages that are defined as
|
|
53
|
+
* "dependency" or "peerDependency" in the package.json.
|
|
54
|
+
* If you wish to bundle-in some package, define it as a "devDependency".
|
|
55
|
+
*
|
|
56
|
+
* Bundling-in packages is not recommended because:
|
|
57
|
+
* - it makes our build take longer
|
|
58
|
+
* - it pushes larger packages to NPM
|
|
59
|
+
* - user of our library is locked into the version of the package we bundled in
|
|
60
|
+
* - if user has two packages using the same library, there will be two copies
|
|
61
|
+
* served on the page
|
|
62
|
+
* - It may break some libraries/prevent them from optimizing correctly
|
|
63
|
+
* depending on the production/development mode, or prevent them from loading
|
|
64
|
+
* correct code depending on browser/node.js environment.
|
|
65
|
+
*
|
|
66
|
+
* For example, see this statement from Lit:
|
|
67
|
+
* https://lit.dev/docs/ssr/authoring/#:~:text=Don%27t%20bundle%20Lit,based%20on%20environment.
|
|
68
|
+
*
|
|
69
|
+
* > If a dependency is both a peerDependency and a devDependency, it will still
|
|
70
|
+
* > be externalized (because all peerDependencies are externalized).
|
|
71
|
+
*
|
|
72
|
+
* @public
|
|
73
|
+
* @param options
|
|
74
|
+
*/
|
|
75
|
+
export declare function externalizeDependencies(options: DependencyManagementOptions): Plugin;
|
|
76
|
+
interface PluginShape extends Plugin {
|
|
77
|
+
resolveId: {
|
|
78
|
+
filter: {
|
|
79
|
+
id: {
|
|
80
|
+
include: RegExp[];
|
|
81
|
+
exclude: RegExp[] | undefined;
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
handler: (id: string, importer: string | undefined, options: {
|
|
85
|
+
isEntry: boolean;
|
|
86
|
+
}) => false | undefined;
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
declare function externalizeDependenciesImplementation(options: DependencyManagementOptions, packageJson: PackageJson): PluginShape;
|
|
90
|
+
declare function matchesAny(id: string, patterns: readonly RegExp[]): boolean;
|
|
91
|
+
export declare const exportsForTests: {
|
|
92
|
+
stringToStartsWithGlob: (option: RegExp | string) => RegExp;
|
|
93
|
+
externalizeDependenciesImplementation: typeof externalizeDependenciesImplementation;
|
|
94
|
+
matchesAny: typeof matchesAny;
|
|
95
|
+
};
|
|
96
|
+
export {};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { builtinModules } from "node:module";
|
|
2
|
+
import { styleText } from "node:util";
|
|
3
|
+
import { toPosixPathSeparators } from "../path.js";
|
|
4
|
+
import { retrievePackageJson } from "../packageJson.js";
|
|
5
|
+
function externalizeDependencies(options) {
|
|
6
|
+
return externalizeDependenciesImplementation(options, retrievePackageJson());
|
|
7
|
+
}
|
|
8
|
+
function externalizeDependenciesImplementation(options, packageJson) {
|
|
9
|
+
const externalDependencies = Object.keys({
|
|
10
|
+
...packageJson.dependencies,
|
|
11
|
+
...packageJson.peerDependencies,
|
|
12
|
+
...packageJson.optionalDependencies
|
|
13
|
+
});
|
|
14
|
+
const isStrictBundling = toPosixPathSeparators(import.meta.dirname).includes("support-packages/node-toolkit");
|
|
15
|
+
const bundleIn = options.bundleIn?.map(stringToStartsWithGlob);
|
|
16
|
+
const explicitExternalize = options.externalize?.map(stringToStartsWithGlob) ?? [];
|
|
17
|
+
const externalize = [
|
|
18
|
+
...explicitExternalize,
|
|
19
|
+
// BUG: we shouldn't silently externalize node in browser packages.
|
|
20
|
+
// Consider erroring instead
|
|
21
|
+
/^node:/u,
|
|
22
|
+
new RegExp(
|
|
23
|
+
`^(?:${externalDependencies.join("|")}${externalDependencies.length === 0 ? "" : "|"}${builtinModules.join("|")})(?:/|$)`,
|
|
24
|
+
"u"
|
|
25
|
+
)
|
|
26
|
+
];
|
|
27
|
+
const plugin = {
|
|
28
|
+
name: pluginName,
|
|
29
|
+
apply: "build",
|
|
30
|
+
// Externalize before Vite's default resolution runs
|
|
31
|
+
enforce: "pre",
|
|
32
|
+
// Rolldown also has "external" option, which can be provided regexes.
|
|
33
|
+
// Theoretically that would be more efficient due to less communication
|
|
34
|
+
// overhead, but in practice they always evaluate it on the JS side:
|
|
35
|
+
// https://github.com/rolldown/rolldown/blob/4f996e637732a26ca04972975884abad5183292b/packages/rolldown/src/utils/bindingify-input-options.ts#L167
|
|
36
|
+
// https://github.com/rolldown/rolldown/blob/4f996e637732a26ca04972975884abad5183292b/crates/rolldown_binding/src/utils/normalize_binding_options.rs#L130
|
|
37
|
+
resolveId: {
|
|
38
|
+
filter: {
|
|
39
|
+
id: {
|
|
40
|
+
include: [
|
|
41
|
+
// In most cases, we want all dependencies in library packages to be
|
|
42
|
+
// externalized. Thus, this regex matches all non-relative imports.
|
|
43
|
+
nonRelativeSpecifierPattern,
|
|
44
|
+
// Also include explicitExternalize because those may target relative
|
|
45
|
+
// paths (e.g. ./draconvert.js in mock-services).
|
|
46
|
+
...explicitExternalize
|
|
47
|
+
],
|
|
48
|
+
exclude: bundleIn
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
handler(id, importer, resolveOptions) {
|
|
52
|
+
if (matchesAny(id, externalize)) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
if (
|
|
56
|
+
// Entrypoints look like src/components/button/button.tsx, so are
|
|
57
|
+
// matched by the nonRelativeSpecifierPattern
|
|
58
|
+
resolveOptions.isEntry || // Virtual specifiers are handled by plugins
|
|
59
|
+
id.startsWith("\0") || // data: node: virtual:
|
|
60
|
+
id.includes(":") || // ?raw ?url ?worker - resolved by other plugins
|
|
61
|
+
id.includes("?") || // Applications can bundle in anything
|
|
62
|
+
options.isApplication === true
|
|
63
|
+
) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const error = `[${pluginName}] Vite tried to bundle in "${id}" (imported by ${importer}).
|
|
67
|
+
This is likely undesirable. To externalize it, declare this dependency as a "dependency", "peerDependency" or "optionalDependency" in package.json.
|
|
68
|
+
If this is intentional, add it to the build.dependencies.bundleIn option in useLumina() or bundleIn option in the vitePresetPlugin().
|
|
69
|
+
If this is an application rather than a library, pass isApplication:true in vitePresetPlugin().`;
|
|
70
|
+
if (isStrictBundling) {
|
|
71
|
+
throw Error(error);
|
|
72
|
+
} else {
|
|
73
|
+
console.error(styleText("red", `${error}
|
|
74
|
+
This will be an error in future version.`));
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
return plugin;
|
|
81
|
+
}
|
|
82
|
+
const pluginName = "@arcgis/node-toolkit:externalize-dependencies";
|
|
83
|
+
const stringToStartsWithGlob = (option) => typeof option === "string" ? new RegExp(
|
|
84
|
+
`^${option.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&")}${option.endsWith("/") ? "(?:.+)?" : "(?:/.+)?"}$`,
|
|
85
|
+
"u"
|
|
86
|
+
) : option;
|
|
87
|
+
const nonRelativeSpecifierPattern = /^[^\.\/]/u;
|
|
88
|
+
function matchesAny(id, patterns) {
|
|
89
|
+
for (let index = 0; index < patterns.length; ++index) {
|
|
90
|
+
if (patterns[index].test(id)) {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
const exportsForTests = {
|
|
97
|
+
stringToStartsWithGlob,
|
|
98
|
+
externalizeDependenciesImplementation,
|
|
99
|
+
matchesAny
|
|
100
|
+
};
|
|
101
|
+
export {
|
|
102
|
+
exportsForTests,
|
|
103
|
+
externalizeDependencies
|
|
104
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { mkdir, rm, stat } from "node:fs/promises";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { findPath, existsAsync } from "../file.js";
|
|
5
|
+
import { runCommand } from "../shell.js";
|
|
6
|
+
import { pathToFileURL } from "node:url";
|
|
7
|
+
let installPromise;
|
|
8
|
+
function installPlaywright() {
|
|
9
|
+
return {
|
|
10
|
+
name: "install-playwright",
|
|
11
|
+
apply() {
|
|
12
|
+
if (process.env.VITEST === "true") {
|
|
13
|
+
installPromise ??= ensureInstalled();
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
return false;
|
|
17
|
+
},
|
|
18
|
+
async configResolved() {
|
|
19
|
+
await installPromise;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
async function ensureInstalled() {
|
|
24
|
+
const playwrightCwd = findPath("node_modules/playwright");
|
|
25
|
+
if (playwrightCwd === void 0) {
|
|
26
|
+
throw new Error("Playwright not found in node_modules. Please install it first.");
|
|
27
|
+
}
|
|
28
|
+
const { chromium } = await import(pathToFileURL(join(playwrightCwd, "index.mjs")).href);
|
|
29
|
+
if (await existsAsync(chromium.executablePath())) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const home = homedir();
|
|
33
|
+
const { env, platform } = process;
|
|
34
|
+
const stateDir = env.XDG_STATE_HOME ?? env.XDG_CACHE_HOME ?? (platform === "win32" ? env.LOCALAPPDATA ?? join(home, "AppData", "Local", "webgis-sdk") : platform === "darwin" ? join(home, "Library", "Caches", "webgis-sdk") : join(home, ".local", "state", "webgis-sdk"));
|
|
35
|
+
const lockPath = join(stateDir, "playwright-install.lock");
|
|
36
|
+
await mkdir(stateDir, { recursive: true });
|
|
37
|
+
const releaseLock = await acquireLock(lockPath);
|
|
38
|
+
try {
|
|
39
|
+
if (await existsAsync(chromium.executablePath())) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const installArgs = [
|
|
43
|
+
join(playwrightCwd, "cli.js"),
|
|
44
|
+
"install",
|
|
45
|
+
...process.platform === "linux" ? ["--with-deps"] : [],
|
|
46
|
+
"chromium",
|
|
47
|
+
"chromium-headless-shell"
|
|
48
|
+
];
|
|
49
|
+
await runCommand(process.execPath, installArgs, { stdio: ["ignore", "ignore", "inherit"] });
|
|
50
|
+
} finally {
|
|
51
|
+
await releaseLock();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const lockPoll = 500;
|
|
55
|
+
async function acquireLock(lockDir) {
|
|
56
|
+
const startTime = Date.now();
|
|
57
|
+
while (true) {
|
|
58
|
+
try {
|
|
59
|
+
await mkdir(lockDir);
|
|
60
|
+
return async () => {
|
|
61
|
+
await rm(lockDir, { recursive: true, force: true }).catch(() => {
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
} catch (err) {
|
|
65
|
+
if (err?.code !== "EEXIST") {
|
|
66
|
+
throw err;
|
|
67
|
+
}
|
|
68
|
+
const lockTimeout = 10 * 60 * 1e3;
|
|
69
|
+
try {
|
|
70
|
+
const stats = await stat(lockDir);
|
|
71
|
+
if (Date.now() - stats.mtimeMs > lockTimeout) {
|
|
72
|
+
await rm(lockDir, { recursive: true, force: true }).catch(() => {
|
|
73
|
+
});
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
} catch {
|
|
77
|
+
}
|
|
78
|
+
if (Date.now() - startTime > lockTimeout) {
|
|
79
|
+
throw new Error(`Timed out waiting for Playwright install lock: ${lockDir}`);
|
|
80
|
+
}
|
|
81
|
+
await new Promise((resolve) => setTimeout(resolve, lockPoll));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
export {
|
|
86
|
+
installPlaywright
|
|
87
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Plugin } from "vite";
|
|
2
|
+
import type dts from "vite-plugin-dts";
|
|
3
|
+
import { type DependencyManagementOptions } from "./externalizeDependenciesPlugin.ts";
|
|
4
|
+
/** @public */
|
|
5
|
+
export type VitePresetOptions = DependencyManagementOptions & {
|
|
6
|
+
/**
|
|
7
|
+
* Options for `vite-plugin-dts`
|
|
8
|
+
*
|
|
9
|
+
* @public
|
|
10
|
+
* @deprecated Use https://webgis.esri.com/references/api-extractor/integrations instead
|
|
11
|
+
*/
|
|
12
|
+
dtsOptions?: Parameters<typeof dts>[0] | false;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Vite preset for all our support packages:
|
|
16
|
+
* - externalizes all non-dev-dependencies
|
|
17
|
+
*
|
|
18
|
+
* @public
|
|
19
|
+
* @param options
|
|
20
|
+
*/
|
|
21
|
+
export declare function vitePresetPlugin({ dtsOptions, externalize, bundleIn, isApplication }?: VitePresetOptions): [Plugin, Plugin, Promise<Plugin> | undefined];
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { path } from "../path.js";
|
|
2
|
+
import { externalizeDependencies } from "./externalizeDependenciesPlugin.js";
|
|
3
|
+
function shouldSkip(id) {
|
|
4
|
+
return id.includes("__test") || id.includes(".e2e.") || id.includes(".spec.") || id.includes(".test.") || id.includes(".stories.");
|
|
5
|
+
}
|
|
6
|
+
function vitePresetPlugin({ dtsOptions = {}, externalize, bundleIn, isApplication } = {
|
|
7
|
+
externalize: [],
|
|
8
|
+
dtsOptions: {}
|
|
9
|
+
}) {
|
|
10
|
+
const dist = `${path.resolve("dist")}/`;
|
|
11
|
+
const distSrc = `${dist}src/`;
|
|
12
|
+
let command = void 0;
|
|
13
|
+
return [
|
|
14
|
+
{
|
|
15
|
+
name: "vite-preset-config",
|
|
16
|
+
config({ build: { target } = {} }, env) {
|
|
17
|
+
command = env.command;
|
|
18
|
+
return {
|
|
19
|
+
build: {
|
|
20
|
+
// REFACTOR: get this from tsconfig
|
|
21
|
+
// It's a best practice to let the final bundler down-level as needed.
|
|
22
|
+
target: target ?? "es2024"
|
|
23
|
+
},
|
|
24
|
+
define: env.mode === "test" ? {
|
|
25
|
+
"process.env.ESRI_INTERNAL": true
|
|
26
|
+
} : void 0
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
externalizeDependencies({
|
|
31
|
+
externalize,
|
|
32
|
+
bundleIn,
|
|
33
|
+
isApplication
|
|
34
|
+
}),
|
|
35
|
+
// This dependency pulls in many others. Since components-build-utils has a
|
|
36
|
+
// single entry point, we load a large module tree needlessly. To avoid,
|
|
37
|
+
// load the plugin on demand.
|
|
38
|
+
dtsOptions === false ? void 0 : import("vite-plugin-dts").then(
|
|
39
|
+
({ default: dts }) => dts({
|
|
40
|
+
logLevel: "warn",
|
|
41
|
+
...dtsOptions,
|
|
42
|
+
compilerOptions: {
|
|
43
|
+
rootDir: ".",
|
|
44
|
+
...dtsOptions.compilerOptions
|
|
45
|
+
},
|
|
46
|
+
/**
|
|
47
|
+
* Do not emit any .d.ts files for files outside the dist directory
|
|
48
|
+
* (i.e vite.config.ts, storybook stories and etc)
|
|
49
|
+
* This also applies for references to node_modules/.../components.d.ts files in
|
|
50
|
+
* tsconfig.json - these must be included in TypeScript program to provide
|
|
51
|
+
* types, but should not be re-emitted during build.
|
|
52
|
+
*/
|
|
53
|
+
beforeWriteFile: async (filePath, content) => {
|
|
54
|
+
if (filePath.startsWith(distSrc) && !shouldSkip(filePath)) {
|
|
55
|
+
const filePathRelativeToDist = `${dist}${filePath.slice(distSrc.length)}`;
|
|
56
|
+
return dtsOptions?.beforeWriteFile ? await dtsOptions.beforeWriteFile(filePathRelativeToDist, content) : { filePath: filePathRelativeToDist, content };
|
|
57
|
+
} else {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
afterDiagnostic(diagnostics) {
|
|
62
|
+
const hasErrors = diagnostics.length > 0;
|
|
63
|
+
const isBuilding = command === "build";
|
|
64
|
+
const stopBuild = hasErrors && isBuilding;
|
|
65
|
+
if (stopBuild) {
|
|
66
|
+
throw new Error("TypeScript errors reported. See error messages above");
|
|
67
|
+
}
|
|
68
|
+
return dtsOptions?.afterDiagnostic?.(diagnostics);
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
)
|
|
72
|
+
];
|
|
73
|
+
}
|
|
74
|
+
export {
|
|
75
|
+
vitePresetPlugin
|
|
76
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Plugin } from "vite";
|
|
2
|
+
/**
|
|
3
|
+
* A barebones tsc integration for Vite.
|
|
4
|
+
* This emits types for all .ts and .tsx files in src/ using tsconfig.json.
|
|
5
|
+
*
|
|
6
|
+
* Do not use this plugin for new code.
|
|
7
|
+
* Use https://webgis.esri.com/references/api-extractor/integrations instead.
|
|
8
|
+
*
|
|
9
|
+
* This exists only for usage by `@arcgis/toolkit` and
|
|
10
|
+
* `@arcgis/node-toolkit` as they cannot use API Extractor to avoid a
|
|
11
|
+
* cyclical dependency.
|
|
12
|
+
*
|
|
13
|
+
* This serves as a minimal replacement for vite-plugin-dts. For comparison,
|
|
14
|
+
* node-toolkit build using this package in 1s compared to 1.3s for
|
|
15
|
+
* vite-plugin-dts.
|
|
16
|
+
*
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
19
|
+
export declare function simpleTypesEmit(): Plugin;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import { loadTypeScriptConfig } from "./typeScript.js";
|
|
3
|
+
import { path } from "../path.js";
|
|
4
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
5
|
+
function simpleTypesEmit() {
|
|
6
|
+
let oldProgram;
|
|
7
|
+
let isWatchMode = false;
|
|
8
|
+
const sourcePrefix = path.join(process.cwd(), "src/");
|
|
9
|
+
const distPrefix = path.join(process.cwd(), "dist/");
|
|
10
|
+
const distSrcPrefix = path.join(distPrefix, "src/");
|
|
11
|
+
return {
|
|
12
|
+
name: "simple-types-emit",
|
|
13
|
+
apply: "build",
|
|
14
|
+
configResolved(viteConfig) {
|
|
15
|
+
const isBuildMode = viteConfig.command === "build";
|
|
16
|
+
isWatchMode = (isBuildMode ? viteConfig.build.watch : viteConfig.server.watch) != null;
|
|
17
|
+
},
|
|
18
|
+
writeBundle: {
|
|
19
|
+
sequential: true,
|
|
20
|
+
async handler() {
|
|
21
|
+
const { config } = loadTypeScriptConfig(void 0, void 0, true);
|
|
22
|
+
const compilerHost = ts.createCompilerHost(config.options);
|
|
23
|
+
const program = ts.createProgram(
|
|
24
|
+
config.fileNames,
|
|
25
|
+
{ ...config.options, noEmit: false, declaration: true, emitDeclarationOnly: true },
|
|
26
|
+
compilerHost,
|
|
27
|
+
oldProgram
|
|
28
|
+
);
|
|
29
|
+
oldProgram = program;
|
|
30
|
+
const allDiagnostics = [...ts.getPreEmitDiagnostics(program)];
|
|
31
|
+
const writeQueue = [];
|
|
32
|
+
for (const sourceFile of program.getSourceFiles()) {
|
|
33
|
+
if (!isIncludedFile(sourceFile.fileName, sourcePrefix)) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const diagnostics = program.emit(
|
|
37
|
+
sourceFile,
|
|
38
|
+
(name, text) => {
|
|
39
|
+
const filePath = distPrefix + name.slice(distSrcPrefix.length);
|
|
40
|
+
writeQueue.push(
|
|
41
|
+
mkdir(path.dirname(filePath), { recursive: true }).then(async () => await writeFile(filePath, text))
|
|
42
|
+
);
|
|
43
|
+
},
|
|
44
|
+
void 0,
|
|
45
|
+
true
|
|
46
|
+
);
|
|
47
|
+
allDiagnostics.push(...diagnostics.diagnostics);
|
|
48
|
+
}
|
|
49
|
+
await Promise.all(writeQueue);
|
|
50
|
+
const deduplicatedDiagnostics = ts.sortAndDeduplicateDiagnostics(allDiagnostics);
|
|
51
|
+
const hasErrors = deduplicatedDiagnostics.length > 0;
|
|
52
|
+
const stopBuild = hasErrors && !isWatchMode;
|
|
53
|
+
if (stopBuild) {
|
|
54
|
+
console.error(
|
|
55
|
+
ts.formatDiagnosticsWithColorAndContext(deduplicatedDiagnostics, {
|
|
56
|
+
getCurrentDirectory: ts.sys.getCurrentDirectory,
|
|
57
|
+
getCanonicalFileName: (fileName) => fileName,
|
|
58
|
+
getNewLine: () => ts.sys.newLine
|
|
59
|
+
})
|
|
60
|
+
);
|
|
61
|
+
const error = new Error("TypeScript errors reported. See error messages above");
|
|
62
|
+
error.stack = "";
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
const isIncludedFile = (filePath, prefix) => isPermittedFile(filePath) && isInIncludedFolder(filePath, prefix);
|
|
70
|
+
const isPermittedFile = (filePath) => (filePath.endsWith(".ts") || filePath.endsWith(".tsx")) && !isTestFile(filePath) && !isStoryFile(filePath);
|
|
71
|
+
const isTestFile = (filePath) => filePath.includes("__test") || filePath.includes(".e2e.") || filePath.includes(".spec.") || filePath.includes(".test.");
|
|
72
|
+
const isStoryFile = (filePath) => filePath.includes(".stories.");
|
|
73
|
+
const isInIncludedFolder = (fileOrFolderPath, prefix) => fileOrFolderPath.startsWith(prefix) && !fileOrFolderPath.includes("node_modules");
|
|
74
|
+
export {
|
|
75
|
+
simpleTypesEmit
|
|
76
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
/** @public */
|
|
3
|
+
export interface TypeScriptConfigResult {
|
|
4
|
+
/**
|
|
5
|
+
* Absolute path to the resolved tsconfig.json file.
|
|
6
|
+
*
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
configPath: string;
|
|
10
|
+
/** @public */
|
|
11
|
+
config: ts.ParsedCommandLine;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* @public
|
|
15
|
+
* @param cwd Defaults to process.cwd()
|
|
16
|
+
* @param configPath Optional absolute or relative path to a tsconfig.json file.
|
|
17
|
+
* @param resolveIncludedFiles If true, will resolve tsconfig's include, exclude,
|
|
18
|
+
* and files globs. Resolved files can be accessed via
|
|
19
|
+
* TypeScriptConfigResult.config.fileNames.
|
|
20
|
+
*/
|
|
21
|
+
export declare function loadTypeScriptConfig(cwd: string | undefined, configPath: string | undefined, resolveIncludedFiles: boolean): TypeScriptConfigResult;
|