@entur/function-tools 0.0.4 → 0.0.6
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/bin/enturFunctions.js +1 -1
- package/lib/bundle/dependencies.js +88 -0
- package/lib/{utils/bundle.js → bundle/index.js} +20 -20
- package/lib/bundle/utils.js +23 -0
- package/lib/commands/build.js +12 -13
- package/lib/commands/deploy.js +24 -49
- package/lib/commands/start.js +29 -44
- package/lib/commands/utils.d.ts +5 -2
- package/lib/commands/utils.js +44 -7
- package/lib/firebase/index.js +47 -0
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/utils/array.js +1 -15
- package/lib/utils/fs.js +10 -2
- package/package.json +1 -2
- package/lib/utils/dependencies.js +0 -159
package/bin/enturFunctions.js
CHANGED
|
@@ -5,7 +5,7 @@ import { registerStart } from '../lib/commands/start.js';
|
|
|
5
5
|
import { registerUnusedExports } from '../lib/commands/unusedExports.js';
|
|
6
6
|
|
|
7
7
|
const program = new Command();
|
|
8
|
-
program.name("entur-functions").description("A multi-tool for Firebase functions at Entur").version("0.0.
|
|
8
|
+
program.name("entur-functions").description("A multi-tool for Firebase functions at Entur").version("0.0.6").option("-v, --verbose", "Enable verbose output");
|
|
9
9
|
registerBuild(program);
|
|
10
10
|
registerDeploy(program);
|
|
11
11
|
registerStart(program);
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { writeFile } from 'node:fs/promises';
|
|
2
|
+
import { builtinModules } from 'node:module';
|
|
3
|
+
import { dirname } from 'node:path';
|
|
4
|
+
import { stringify } from 'yaml';
|
|
5
|
+
import { groupByAsync, asyncMap } from '../utils/async.js';
|
|
6
|
+
import { spawnAsync } from '../utils/exec.js';
|
|
7
|
+
import { writePackageJSON, readPackageJSON, packageUp } from '../utils/packageJSON.js';
|
|
8
|
+
|
|
9
|
+
const alwaysIncludePackageNames = [
|
|
10
|
+
"@google-cloud/functions-framework",
|
|
11
|
+
"firebase-functions",
|
|
12
|
+
"firebase-admin"
|
|
13
|
+
];
|
|
14
|
+
async function writeDependencies(outputs, getOutputFilePath, outputDir) {
|
|
15
|
+
const packages = [];
|
|
16
|
+
for (const [packageJSONPath, packageJSON] of (await calculateDependencies(outputs))){
|
|
17
|
+
const newPackageJSONPath = getOutputFilePath(packageJSONPath);
|
|
18
|
+
const directory = dirname(newPackageJSONPath);
|
|
19
|
+
if (directory === ".") {
|
|
20
|
+
await writePackageJSON(new URL(`./${newPackageJSONPath}`, outputDir), {
|
|
21
|
+
...packageJSON,
|
|
22
|
+
main: `./${outputs[0].fileName}`
|
|
23
|
+
});
|
|
24
|
+
} else {
|
|
25
|
+
await writePackageJSON(new URL(`./${newPackageJSONPath}`, outputDir), packageJSON);
|
|
26
|
+
packages.push(directory);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
await writeFile(new URL("./pnpm-workspace.yaml", outputDir), stringify({
|
|
30
|
+
packages
|
|
31
|
+
}));
|
|
32
|
+
}
|
|
33
|
+
async function calculateDependencies(outputs) {
|
|
34
|
+
const outputGroupedByPackage = await groupByAsync(outputs.filter((it)=>Boolean(it.type === "chunk" && it.facadeModuleId && it.imports.length > 0)), async (output)=>{
|
|
35
|
+
const key = output.facadeModuleId && await packageUp({
|
|
36
|
+
cwd: output.facadeModuleId
|
|
37
|
+
});
|
|
38
|
+
if (!key) {
|
|
39
|
+
throw new Error(`No package.json found for ${output.facadeModuleId}`);
|
|
40
|
+
}
|
|
41
|
+
return key;
|
|
42
|
+
});
|
|
43
|
+
const filterDependencies = (lookup, dependencies)=>{
|
|
44
|
+
if (!dependencies) return;
|
|
45
|
+
const entries = Object.entries(dependencies).filter(([key])=>lookup.has(key));
|
|
46
|
+
return entries.length > 0 ? Object.fromEntries(entries) : undefined;
|
|
47
|
+
};
|
|
48
|
+
const entries = await asyncMap([
|
|
49
|
+
...outputGroupedByPackage
|
|
50
|
+
], async ([packageJSONPath, outputs])=>{
|
|
51
|
+
const { name, type, version, ...packageJSON } = await readPackageJSON(packageJSONPath);
|
|
52
|
+
const importedPackageNames = new Set(outputs.flatMap((it)=>it.imports).filter((it)=>!isBuiltinImport(it)).map(specifierToPackageName));
|
|
53
|
+
alwaysIncludePackageNames?.forEach((it)=>{
|
|
54
|
+
importedPackageNames.add(it);
|
|
55
|
+
});
|
|
56
|
+
return [
|
|
57
|
+
packageJSONPath,
|
|
58
|
+
{
|
|
59
|
+
name,
|
|
60
|
+
type,
|
|
61
|
+
version,
|
|
62
|
+
dependencies: filterDependencies(importedPackageNames, packageJSON.dependencies),
|
|
63
|
+
devDependencies: filterDependencies(importedPackageNames, packageJSON.devDependencies),
|
|
64
|
+
optionalDependencies: filterDependencies(importedPackageNames, packageJSON.optionalDependencies)
|
|
65
|
+
}
|
|
66
|
+
];
|
|
67
|
+
});
|
|
68
|
+
return new Map(entries);
|
|
69
|
+
}
|
|
70
|
+
function specifierToPackageName(specifier) {
|
|
71
|
+
if (specifier.startsWith("@")) {
|
|
72
|
+
return specifier.split("/", 2).join("/");
|
|
73
|
+
}
|
|
74
|
+
return specifier.split("/", 1).join("/");
|
|
75
|
+
}
|
|
76
|
+
function isBuiltinImport(specifier) {
|
|
77
|
+
return specifier.startsWith("node:") || builtinModules.includes(specifier);
|
|
78
|
+
}
|
|
79
|
+
async function linkDependencies(workingDir) {
|
|
80
|
+
await spawnAsync("pnpm", [
|
|
81
|
+
"install",
|
|
82
|
+
"--prefer-offline"
|
|
83
|
+
], {
|
|
84
|
+
cwd: workingDir
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export { linkDependencies, writeDependencies };
|
|
@@ -2,29 +2,35 @@ import { fileURLToPath } from 'node:url';
|
|
|
2
2
|
import { nodeResolve } from '@rollup/plugin-node-resolve';
|
|
3
3
|
import swc from '@rollup/plugin-swc';
|
|
4
4
|
import { rollup, watch } from 'rollup';
|
|
5
|
+
import { createOutputFileName } from './utils.js';
|
|
5
6
|
|
|
6
|
-
async function bundle(entryFile, outputDir,
|
|
7
|
-
const
|
|
7
|
+
async function bundle(entryFile, { outputDir, packageRoot, projectRoot, packagesToInline }) {
|
|
8
|
+
const bundle = await rollup({
|
|
8
9
|
input: fileURLToPath(entryFile),
|
|
9
10
|
plugins: plugins(packagesToInline),
|
|
10
11
|
treeshake: "smallest"
|
|
11
12
|
});
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
const outputFileName = createOutputFileName(packageRoot, projectRoot);
|
|
14
|
+
return bundle.write({
|
|
15
|
+
preserveModules: true,
|
|
16
|
+
format: "esm",
|
|
17
|
+
dir: fileURLToPath(outputDir),
|
|
18
|
+
entryFileNames: ({ facadeModuleId })=>outputFileName(facadeModuleId)
|
|
16
19
|
});
|
|
17
20
|
}
|
|
18
|
-
async function bundleAndWatch(entryFile, outputDir,
|
|
21
|
+
async function bundleAndWatch(entryFile, { outputDir, packageRoot, projectRoot, packagesToInline, onBundleEnd }) {
|
|
22
|
+
const outputFileName = createOutputFileName(packageRoot, projectRoot);
|
|
23
|
+
const output = {
|
|
24
|
+
preserveModules: true,
|
|
25
|
+
format: "esm",
|
|
26
|
+
dir: fileURLToPath(outputDir),
|
|
27
|
+
entryFileNames: ({ facadeModuleId })=>outputFileName(facadeModuleId)
|
|
28
|
+
};
|
|
19
29
|
const watchOptions = {
|
|
20
30
|
plugins: plugins(packagesToInline),
|
|
21
31
|
input: fileURLToPath(entryFile),
|
|
22
32
|
treeshake: "smallest",
|
|
23
|
-
output
|
|
24
|
-
...outputOptions(),
|
|
25
|
-
sourcemap: true,
|
|
26
|
-
dir: fileURLToPath(outputDir)
|
|
27
|
-
},
|
|
33
|
+
output,
|
|
28
34
|
watch: {
|
|
29
35
|
exclude: [
|
|
30
36
|
fileURLToPath(outputDir)
|
|
@@ -41,9 +47,9 @@ async function bundleAndWatch(entryFile, outputDir, { packagesToInline, onBundle
|
|
|
41
47
|
}
|
|
42
48
|
case "BUNDLE_END":
|
|
43
49
|
{
|
|
44
|
-
const
|
|
50
|
+
const bundledOutput = await event.result.generate(output);
|
|
45
51
|
console.log(`🏠 Finished build in ${event.duration}ms`);
|
|
46
|
-
await onBundleEnd?.(
|
|
52
|
+
await onBundleEnd?.(bundledOutput);
|
|
47
53
|
return event.result.close();
|
|
48
54
|
}
|
|
49
55
|
case "ERROR":
|
|
@@ -67,11 +73,5 @@ const plugins = (workspacePackages)=>[
|
|
|
67
73
|
resolveOnly: (moduleId)=>moduleId.startsWith(".") || workspacePackages?.some((it)=>moduleId.startsWith(it)) || moduleId.startsWith("@entur-private/") || false
|
|
68
74
|
})
|
|
69
75
|
];
|
|
70
|
-
const outputOptions = ()=>({
|
|
71
|
-
preserveModules: true,
|
|
72
|
-
dir: "lib",
|
|
73
|
-
format: "esm",
|
|
74
|
-
entryFileNames: ({ isEntry })=>isEntry ? "index.js" : "[hash].js"
|
|
75
|
-
});
|
|
76
76
|
|
|
77
77
|
export { bundle, bundleAndWatch };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { fileURLToPath } from 'node:url';
|
|
2
|
+
|
|
3
|
+
const nodeModulesPartPath = "/node_modules/";
|
|
4
|
+
function createOutputFileName(packageRootURL, projectRootURL) {
|
|
5
|
+
const projectRoot = fileURLToPath(projectRootURL);
|
|
6
|
+
const packageRoot = fileURLToPath(packageRootURL);
|
|
7
|
+
return (facadeModuleId)=>{
|
|
8
|
+
const index = facadeModuleId?.lastIndexOf(nodeModulesPartPath);
|
|
9
|
+
if (facadeModuleId && index && index > -1) {
|
|
10
|
+
return `bundled_modules/${facadeModuleId.slice(index + nodeModulesPartPath.length)}`;
|
|
11
|
+
}
|
|
12
|
+
const filePath = facadeModuleId?.replace(".ts", ".js").replaceAll("/src/", "/lib/");
|
|
13
|
+
if (filePath?.startsWith(packageRoot)) {
|
|
14
|
+
return filePath.slice(packageRoot.length);
|
|
15
|
+
}
|
|
16
|
+
if (filePath?.startsWith(projectRoot)) {
|
|
17
|
+
return `local_modules/${filePath.slice(projectRoot.length)}`;
|
|
18
|
+
}
|
|
19
|
+
throw new Error(`Unable to determine correct placement for file ${facadeModuleId}`);
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { createOutputFileName };
|
package/lib/commands/build.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { writeDependencies } from '../bundle/dependencies.js';
|
|
2
|
+
import { bundle } from '../bundle/index.js';
|
|
3
|
+
import { createOutputFileName } from '../bundle/utils.js';
|
|
3
4
|
import { cleanDir } from '../utils/fs.js';
|
|
4
5
|
import { readPackageJSON } from '../utils/packageJSON.js';
|
|
5
6
|
import { getWorkspacePackageNames } from '../utils/workspace.js';
|
|
@@ -8,31 +9,29 @@ import { resolveProjectConfig } from './utils.js';
|
|
|
8
9
|
function registerBuild(program) {
|
|
9
10
|
program.command("build").description("Build the project").option("-o, --output-dir <dir>", "Output directory").action(async (options)=>{
|
|
10
11
|
try {
|
|
11
|
-
const
|
|
12
|
+
const projectConfig = await resolveProjectConfig(options);
|
|
13
|
+
const { packageRoot, packageJSON, outputDir, pnpmWorkspaceYAML } = projectConfig;
|
|
12
14
|
const { name, exports: exports$1 } = await readPackageJSON(packageJSON);
|
|
13
15
|
console.log("🧹 Cleaning dist folder");
|
|
14
16
|
await cleanDir(outputDir);
|
|
15
17
|
console.log(`🔨 Building ${name}`);
|
|
16
18
|
const workspacePackages = await getWorkspacePackageNames(pnpmWorkspaceYAML);
|
|
17
19
|
const entryFile = new URL(exports$1?.["."] ?? "./index.js", packageRoot);
|
|
18
|
-
await build(entryFile,
|
|
20
|
+
await build(entryFile, workspacePackages, projectConfig);
|
|
19
21
|
} catch (error) {
|
|
20
22
|
console.error(error);
|
|
21
23
|
process.exit(1);
|
|
22
24
|
}
|
|
23
25
|
});
|
|
24
26
|
}
|
|
25
|
-
async function build(entryFile, outputDir,
|
|
26
|
-
const
|
|
27
|
-
|
|
27
|
+
async function build(entryFile, packagesToInline, { outputDir, packageRoot, projectRoot }) {
|
|
28
|
+
const { output } = await bundle(entryFile, {
|
|
29
|
+
outputDir,
|
|
30
|
+
packageRoot,
|
|
31
|
+
projectRoot,
|
|
28
32
|
packagesToInline
|
|
29
33
|
});
|
|
30
|
-
|
|
31
|
-
// const { contentHash } = await pack(functionGroupDir, distDir)
|
|
32
|
-
return {
|
|
33
|
-
main: `./lib/${output[0].fileName}`,
|
|
34
|
-
dependencies
|
|
35
|
-
};
|
|
34
|
+
await writeDependencies(output, createOutputFileName(packageRoot, projectRoot), outputDir);
|
|
36
35
|
}
|
|
37
36
|
|
|
38
37
|
export { registerBuild };
|
package/lib/commands/deploy.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { bundle } from '../
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { writeDependencies, linkDependencies } from '../bundle/dependencies.js';
|
|
2
|
+
import { bundle } from '../bundle/index.js';
|
|
3
|
+
import { createOutputFileName } from '../bundle/utils.js';
|
|
4
|
+
import { deploy as deploy$1 } from '../firebase/index.js';
|
|
5
5
|
import { getFirebaseJSON, writeFirebaseJSON } from '../utils/firebase.js';
|
|
6
6
|
import { cleanDir, writeJSON } from '../utils/fs.js';
|
|
7
|
-
import { readPackageJSON, getPackageName
|
|
7
|
+
import { readPackageJSON, getPackageName } from '../utils/packageJSON.js';
|
|
8
8
|
import { getWorkspacePackageNames } from '../utils/workspace.js';
|
|
9
|
-
import { resolveProjectConfig } from './utils.js';
|
|
9
|
+
import { resolveProjectConfig, copyEnvFiles } from './utils.js';
|
|
10
10
|
|
|
11
11
|
function registerDeploy(program) {
|
|
12
12
|
program.command("deploy").description("Deploy the project").option("-o, --output-dir <dir>", "Output directory").option("-P, --project <project id or alias>", "Project id or alias").action(async (options)=>{
|
|
@@ -19,45 +19,39 @@ function registerDeploy(program) {
|
|
|
19
19
|
}
|
|
20
20
|
});
|
|
21
21
|
}
|
|
22
|
-
async function deploy(
|
|
23
|
-
const {
|
|
22
|
+
async function deploy(projectConfig) {
|
|
23
|
+
const { projectAlias, projectId, packageJSON, packageRoot, pnpmWorkspaceYAML, projectRoot, outputDir } = projectConfig;
|
|
24
|
+
const { name, exports: exports$1 } = await readPackageJSON(packageJSON);
|
|
24
25
|
const workspacePackages = await getWorkspacePackageNames(pnpmWorkspaceYAML);
|
|
25
26
|
const entryFile = new URL(exports$1?.["."] ?? "./index.js", packageRoot);
|
|
26
27
|
console.log("🧹 Cleaning dist folder");
|
|
27
28
|
await cleanDir(outputDir);
|
|
28
29
|
console.log(`🔨 Building ${name}`);
|
|
29
|
-
|
|
30
|
+
await build(entryFile, workspacePackages, projectConfig);
|
|
30
31
|
console.log("⛷️ Prepare deploy");
|
|
31
32
|
const firebaseJSON = await getFirebaseJSON(new URL("firebase.json", projectRoot));
|
|
32
|
-
await prepareDeploy(getPackageName(name),
|
|
33
|
-
name,
|
|
34
|
-
type: "module",
|
|
35
|
-
version,
|
|
36
|
-
main,
|
|
37
|
-
...dependencies
|
|
38
|
-
}, firebaseJSON, outputDir);
|
|
39
|
-
// contentHash,
|
|
33
|
+
await prepareDeploy(getPackageName(name), firebaseJSON, projectConfig);
|
|
40
34
|
console.log(`🚢 Deploying to ${projectAlias} (${projectId})`);
|
|
41
|
-
await
|
|
35
|
+
await deploy$1({
|
|
36
|
+
projectId,
|
|
37
|
+
cwd: outputDir
|
|
38
|
+
});
|
|
42
39
|
}
|
|
43
|
-
async function build(entryFile, outputDir,
|
|
44
|
-
const
|
|
45
|
-
|
|
40
|
+
async function build(entryFile, packagesToInline, { outputDir, packageRoot, projectRoot }) {
|
|
41
|
+
const { output } = await bundle(entryFile, {
|
|
42
|
+
packageRoot,
|
|
43
|
+
projectRoot,
|
|
44
|
+
outputDir,
|
|
46
45
|
packagesToInline
|
|
47
46
|
});
|
|
48
|
-
|
|
49
|
-
// const { contentHash } = await pack(functionGroupDir, distDir)
|
|
50
|
-
return {
|
|
51
|
-
main: `./lib/${output[0].fileName}`,
|
|
52
|
-
dependencies
|
|
53
|
-
};
|
|
47
|
+
await writeDependencies(output, createOutputFileName(packageRoot, projectRoot), outputDir);
|
|
54
48
|
}
|
|
55
|
-
async function prepareDeploy(codebase, projectAlias, projectId,
|
|
49
|
+
async function prepareDeploy(codebase, firebaseJSON, { projectAlias, projectId, outputDir, envFiles }) {
|
|
50
|
+
const envPrefix = `FUNCTION_CODEBASE='${codebase}'\nENTUR_PROJECT_ALIAS='${projectAlias}'`;
|
|
56
51
|
await Promise.all([
|
|
57
52
|
writeFirebaseJSON(codebase, firebaseJSON, outputDir),
|
|
58
53
|
createFirebaseRC(projectAlias, projectId, outputDir),
|
|
59
|
-
|
|
60
|
-
createDotenv(codebase, projectAlias, outputDir)
|
|
54
|
+
copyEnvFiles(envFiles, envPrefix, outputDir)
|
|
61
55
|
]);
|
|
62
56
|
await linkDependencies(outputDir);
|
|
63
57
|
}
|
|
@@ -68,24 +62,5 @@ async function createFirebaseRC(projectAlias, projectId, outputDir) {
|
|
|
68
62
|
}
|
|
69
63
|
});
|
|
70
64
|
}
|
|
71
|
-
function deployToFirebase(workingDir, projectId, extraArgs = []) {
|
|
72
|
-
return spawnAsync("firebase", [
|
|
73
|
-
"deploy",
|
|
74
|
-
"--only",
|
|
75
|
-
"functions,firestore",
|
|
76
|
-
"-P",
|
|
77
|
-
projectId,
|
|
78
|
-
...extraArgs
|
|
79
|
-
], {
|
|
80
|
-
cwd: workingDir
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
async function createDotenv(codebase, projectAlias, outputDir) {
|
|
84
|
-
const envFile = `
|
|
85
|
-
NODE_OPTIONS='--enable-source-maps'
|
|
86
|
-
FUNCTION_CODEBASE='${codebase}'
|
|
87
|
-
ENTUR_PROJECT_ALIAS='${projectAlias}'`;
|
|
88
|
-
await writeFile(new URL("./.env", outputDir), envFile.trim());
|
|
89
|
-
}
|
|
90
65
|
|
|
91
66
|
export { registerDeploy };
|
package/lib/commands/start.js
CHANGED
|
@@ -1,63 +1,66 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { writeDependencies, linkDependencies } from '../bundle/dependencies.js';
|
|
2
|
+
import { bundleAndWatch } from '../bundle/index.js';
|
|
3
|
+
import { createOutputFileName } from '../bundle/utils.js';
|
|
4
|
+
import { startEmulator } from '../firebase/index.js';
|
|
4
5
|
import { getFirebaseJSON, writeFirebaseJSON } from '../utils/firebase.js';
|
|
5
6
|
import { cleanDir, writeJSON } from '../utils/fs.js';
|
|
6
|
-
import { readPackageJSON, getPackageName
|
|
7
|
+
import { readPackageJSON, getPackageName } from '../utils/packageJSON.js';
|
|
7
8
|
import { getWorkspacePackageNames } from '../utils/workspace.js';
|
|
8
|
-
import { resolveProjectConfig } from './utils.js';
|
|
9
|
+
import { resolveProjectConfig, copyEnvFiles } from './utils.js';
|
|
9
10
|
|
|
10
11
|
function registerStart(program) {
|
|
11
|
-
program.command("start").description("Start function emulator").option("-o, --output-dir <dir>", "Output directory").option("-P, --project <project id or alias>", "Project id or alias").action(async (options)=>{
|
|
12
|
+
program.command("start").description("Start function emulator").option("-o, --output-dir <dir>", "Output directory").option("-P, --project <project id or alias>", "Project id or alias").option("--inspect-functions [port]", "emulate Cloud Functions in debug mode with the node inspector on the given port (9229 if not specified)").action(async (options)=>{
|
|
12
13
|
try {
|
|
13
|
-
const projectConfig = await resolveProjectConfig(
|
|
14
|
-
|
|
14
|
+
const projectConfig = await resolveProjectConfig({
|
|
15
|
+
...options,
|
|
16
|
+
isEmulator: true
|
|
17
|
+
});
|
|
18
|
+
await start(options.inspectFunctions ?? false, projectConfig);
|
|
15
19
|
} catch (error) {
|
|
16
20
|
console.error(error);
|
|
17
21
|
process.exit(1);
|
|
18
22
|
}
|
|
19
23
|
});
|
|
20
24
|
}
|
|
21
|
-
async function start(
|
|
22
|
-
const {
|
|
25
|
+
async function start(inspectFunctions, projectConfig) {
|
|
26
|
+
const { packageRoot, packageJSON, projectId, projectRoot, pnpmWorkspaceYAML, outputDir } = projectConfig;
|
|
27
|
+
const { name, exports: exports$1 } = await readPackageJSON(packageJSON);
|
|
23
28
|
const codebase = getPackageName(name);
|
|
24
29
|
const packagesToInline = await getWorkspacePackageNames(pnpmWorkspaceYAML);
|
|
25
30
|
const entryFile = new URL(exports$1?.["."] ?? "./index.js", packageRoot);
|
|
26
31
|
console.log("🧹 Cleaning dist folder");
|
|
27
32
|
await cleanDir(outputDir);
|
|
28
33
|
console.log(`🔨 Building ${name}`);
|
|
29
|
-
const bundleOutputDir = new URL("lib", outputDir);
|
|
30
34
|
let firstRun = true;
|
|
31
35
|
const onBundleEnd = async ({ output })=>{
|
|
32
|
-
|
|
33
|
-
const dependencies = await flattenDependencies(harmonizeDependencies(await calculateDependencies(output)));
|
|
34
|
-
// const { contentHash } = await pack(functionGroupDir, distDir)
|
|
36
|
+
await writeDependencies(output, createOutputFileName(packageRoot, projectRoot), outputDir);
|
|
35
37
|
const firebaseJSON = await getFirebaseJSON(new URL("firebase.json", projectRoot));
|
|
36
|
-
await prepareStart(codebase,
|
|
37
|
-
name,
|
|
38
|
-
type: "module",
|
|
39
|
-
version,
|
|
40
|
-
main,
|
|
41
|
-
...dependencies
|
|
42
|
-
}, firebaseJSON, outputDir);
|
|
38
|
+
await prepareStart(codebase, firebaseJSON, projectConfig);
|
|
43
39
|
if (firstRun) {
|
|
44
40
|
firstRun = false;
|
|
45
|
-
|
|
41
|
+
startEmulator({
|
|
42
|
+
projectId,
|
|
43
|
+
cwd: outputDir,
|
|
44
|
+
inspectFunctions
|
|
45
|
+
}).catch((error)=>{
|
|
46
46
|
console.error(error);
|
|
47
|
-
process.exit(1);
|
|
48
47
|
});
|
|
49
48
|
}
|
|
50
49
|
};
|
|
51
|
-
await bundleAndWatch(entryFile,
|
|
50
|
+
await bundleAndWatch(entryFile, {
|
|
51
|
+
outputDir,
|
|
52
|
+
projectRoot,
|
|
53
|
+
packageRoot,
|
|
52
54
|
packagesToInline,
|
|
53
55
|
onBundleEnd
|
|
54
56
|
});
|
|
55
57
|
}
|
|
56
|
-
async function prepareStart(codebase, projectAlias, projectId,
|
|
58
|
+
async function prepareStart(codebase, firebaseJSON, { projectAlias, projectId, outputDir, envFiles }) {
|
|
59
|
+
const envPrefix = `FUNCTION_CODEBASE='${codebase}'\nENTUR_PROJECT_ALIAS='${projectAlias}'`;
|
|
57
60
|
await Promise.all([
|
|
58
61
|
writeFirebaseJSON(codebase, firebaseJSON, outputDir),
|
|
59
62
|
createFirebaseRC(projectAlias, projectId, outputDir),
|
|
60
|
-
|
|
63
|
+
copyEnvFiles(envFiles, envPrefix, outputDir)
|
|
61
64
|
]);
|
|
62
65
|
await linkDependencies(outputDir);
|
|
63
66
|
}
|
|
@@ -68,23 +71,5 @@ async function createFirebaseRC(projectAlias, projectId, outputDir) {
|
|
|
68
71
|
}
|
|
69
72
|
});
|
|
70
73
|
}
|
|
71
|
-
function runEmulator(codebase, projectAlias, projectId, workingDir, extraArgs) {
|
|
72
|
-
return spawnAsync("firebase", [
|
|
73
|
-
"emulators:start",
|
|
74
|
-
"--only",
|
|
75
|
-
"functions",
|
|
76
|
-
"-P",
|
|
77
|
-
projectId,
|
|
78
|
-
...extraArgs
|
|
79
|
-
], {
|
|
80
|
-
cwd: workingDir,
|
|
81
|
-
env: {
|
|
82
|
-
...process.env,
|
|
83
|
-
FUNCTION_CODEBASE: codebase,
|
|
84
|
-
ENTUR_PROJECT_ALIAS: projectAlias,
|
|
85
|
-
NODE_OPTIONS: process.env.NODE_OPTIONS ? `${process.env.NODE_OPTIONS} --enable-source-maps` : "--enable-source-maps"
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
74
|
|
|
90
75
|
export { registerStart };
|
package/lib/commands/utils.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ type Options = {
|
|
|
2
2
|
outputDir?: string;
|
|
3
3
|
project?: string;
|
|
4
4
|
cwd?: string;
|
|
5
|
+
isEmulator?: boolean;
|
|
5
6
|
};
|
|
6
7
|
type ProjectConfig = {
|
|
7
8
|
pnpmWorkspaceYAML: URL;
|
|
@@ -11,8 +12,10 @@ type ProjectConfig = {
|
|
|
11
12
|
projectRoot: URL;
|
|
12
13
|
projectAlias: string;
|
|
13
14
|
projectId: string;
|
|
15
|
+
envFiles: URL[];
|
|
14
16
|
};
|
|
15
|
-
declare function resolveProjectConfig({ outputDir, project, cwd, }?: Options): Promise<ProjectConfig>;
|
|
17
|
+
declare function resolveProjectConfig({ outputDir, project, isEmulator, cwd, }?: Options): Promise<ProjectConfig>;
|
|
18
|
+
declare function copyEnvFiles([envFile, ...envFiles]: URL[], prefix: string, outputDir: URL): Promise<void>;
|
|
16
19
|
|
|
17
|
-
export { resolveProjectConfig };
|
|
20
|
+
export { copyEnvFiles, resolveProjectConfig };
|
|
18
21
|
export type { ProjectConfig };
|
package/lib/commands/utils.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readFile, writeFile, cp } from 'node:fs/promises';
|
|
2
|
+
import { basename } from 'node:path';
|
|
3
|
+
import { pathToFileURL, fileURLToPath } from 'node:url';
|
|
2
4
|
import { findUp } from 'find-up-simple';
|
|
3
|
-
import {
|
|
5
|
+
import { asyncFilterMap } from '../utils/async.js';
|
|
6
|
+
import { readJSON, exists } from '../utils/fs.js';
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
const FUNCTIONS_EMULATOR_DOTENV = ".env.local";
|
|
9
|
+
async function resolveProjectConfig({ outputDir = "dist", project, isEmulator, cwd = process.cwd() } = {}) {
|
|
6
10
|
const [pnpmWorkspacePath, packageJSONPath, firebaseRCPath] = await Promise.all([
|
|
7
11
|
findUp("pnpm-workspace.yaml", {
|
|
8
12
|
cwd
|
|
@@ -28,14 +32,18 @@ async function resolveProjectConfig({ outputDir = "dist", project, cwd = process
|
|
|
28
32
|
const outputDirUrl = new URL(`./${outputDir}/`, `${pathToFileURL(cwd)}/`);
|
|
29
33
|
const pnpmWorkspaceYAML = pathToFileURL(pnpmWorkspacePath);
|
|
30
34
|
const packageJSONUrl = pathToFileURL(packageJSONPath);
|
|
35
|
+
const packageRoot = new URL("./", packageJSONUrl);
|
|
36
|
+
const projectRoot = new URL("./", pnpmWorkspaceYAML);
|
|
37
|
+
const envFiles = await findEnvFiles(packageRoot, projectId, projectAlias, isEmulator);
|
|
31
38
|
return {
|
|
32
39
|
pnpmWorkspaceYAML,
|
|
33
40
|
packageJSON: packageJSONUrl,
|
|
34
41
|
outputDir: outputDirUrl,
|
|
35
|
-
packageRoot
|
|
36
|
-
projectRoot
|
|
42
|
+
packageRoot,
|
|
43
|
+
projectRoot,
|
|
37
44
|
projectAlias,
|
|
38
|
-
projectId
|
|
45
|
+
projectId,
|
|
46
|
+
envFiles
|
|
39
47
|
};
|
|
40
48
|
}
|
|
41
49
|
function getProjectAliasAndId({ default: defaultProjectId, ...projects }, project) {
|
|
@@ -67,5 +75,34 @@ function getProjectAliasAndId({ default: defaultProjectId, ...projects }, projec
|
|
|
67
75
|
}
|
|
68
76
|
throw new Error(`No project with alias or id ${project} found in .firebaserc`);
|
|
69
77
|
}
|
|
78
|
+
function findEnvFiles(packageRoot, projectId, projectAlias, isEmulator) {
|
|
79
|
+
const files = [
|
|
80
|
+
".env"
|
|
81
|
+
];
|
|
82
|
+
files.push(`.env.${projectId}`);
|
|
83
|
+
if (projectAlias) {
|
|
84
|
+
files.push(`.env.${projectAlias}`);
|
|
85
|
+
}
|
|
86
|
+
if (isEmulator) {
|
|
87
|
+
files.push(FUNCTIONS_EMULATOR_DOTENV);
|
|
88
|
+
}
|
|
89
|
+
return asyncFilterMap(files, async (fileName)=>{
|
|
90
|
+
const fileUrl = new URL(`./${fileName}`, packageRoot);
|
|
91
|
+
return await exists(fileUrl) ? fileUrl : undefined;
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
async function copyEnvFiles([envFile, ...envFiles], prefix, outputDir) {
|
|
95
|
+
if (envFile) {
|
|
96
|
+
const fileContent = await readFile(envFile, "utf8");
|
|
97
|
+
const fileName = basename(fileURLToPath(envFile));
|
|
98
|
+
await writeFile(new URL(`./${fileName}`, outputDir), `${prefix}\n${fileContent}`);
|
|
99
|
+
} else {
|
|
100
|
+
await writeFile(new URL("./.env", outputDir), prefix);
|
|
101
|
+
}
|
|
102
|
+
for (const envFile of envFiles){
|
|
103
|
+
const fileName = basename(fileURLToPath(envFile));
|
|
104
|
+
await cp(envFile, new URL(`./${fileName}`, outputDir));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
70
107
|
|
|
71
|
-
export { resolveProjectConfig };
|
|
108
|
+
export { copyEnvFiles, resolveProjectConfig };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { spawnAsync } from '../utils/exec.js';
|
|
2
|
+
|
|
3
|
+
const FUNCTIONS_DISCOVERY_TIMEOUT = "30";
|
|
4
|
+
function deploy({ projectId, cwd }) {
|
|
5
|
+
return spawnAsync("firebase", [
|
|
6
|
+
"deploy",
|
|
7
|
+
"--only",
|
|
8
|
+
"functions,firestore",
|
|
9
|
+
"-P",
|
|
10
|
+
projectId
|
|
11
|
+
], {
|
|
12
|
+
cwd,
|
|
13
|
+
env: {
|
|
14
|
+
...process.env,
|
|
15
|
+
FUNCTIONS_DISCOVERY_TIMEOUT
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
function startEmulator({ projectId, cwd, inspectFunctions }) {
|
|
20
|
+
let extraArgs = [];
|
|
21
|
+
if (typeof inspectFunctions === "string") {
|
|
22
|
+
extraArgs = [
|
|
23
|
+
"--inspect-functions",
|
|
24
|
+
inspectFunctions
|
|
25
|
+
];
|
|
26
|
+
} else if (inspectFunctions) {
|
|
27
|
+
extraArgs = [
|
|
28
|
+
"--inspect-functions"
|
|
29
|
+
];
|
|
30
|
+
}
|
|
31
|
+
return spawnAsync("firebase", [
|
|
32
|
+
"emulators:start",
|
|
33
|
+
"--only",
|
|
34
|
+
"functions",
|
|
35
|
+
"-P",
|
|
36
|
+
projectId,
|
|
37
|
+
...extraArgs
|
|
38
|
+
], {
|
|
39
|
+
cwd,
|
|
40
|
+
env: {
|
|
41
|
+
...process.env,
|
|
42
|
+
FUNCTIONS_DISCOVERY_TIMEOUT
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export { deploy, startEmulator };
|
package/lib/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { ProjectConfig, resolveProjectConfig } from './commands/utils.js';
|
|
1
|
+
export { ProjectConfig, copyEnvFiles, resolveProjectConfig } from './commands/utils.js';
|
|
2
2
|
export { Export, getExports } from './importExports/exports.js';
|
|
3
3
|
export { Import, getImports } from './importExports/imports.js';
|
package/lib/index.js
CHANGED
package/lib/utils/array.js
CHANGED
|
@@ -12,20 +12,6 @@ function filterMap(arr, mapper) {
|
|
|
12
12
|
return acc;
|
|
13
13
|
}, []);
|
|
14
14
|
}
|
|
15
|
-
function groupBy(array, iteratee) {
|
|
16
|
-
return array.reduce((map, item, index, array_)=>{
|
|
17
|
-
const key = iteratee(item, index, array_);
|
|
18
|
-
const existingGroup = map.get(key);
|
|
19
|
-
if (existingGroup) {
|
|
20
|
-
existingGroup.push(item);
|
|
21
|
-
} else {
|
|
22
|
-
map.set(key, [
|
|
23
|
-
item
|
|
24
|
-
]);
|
|
25
|
-
}
|
|
26
|
-
return map;
|
|
27
|
-
}, new Map());
|
|
28
|
-
}
|
|
29
15
|
function partition(array, predicate) {
|
|
30
16
|
return array.reduce((result, value, index, arr)=>{
|
|
31
17
|
const [include, exclude] = result;
|
|
@@ -41,4 +27,4 @@ function partition(array, predicate) {
|
|
|
41
27
|
]);
|
|
42
28
|
}
|
|
43
29
|
|
|
44
|
-
export { filterMap,
|
|
30
|
+
export { filterMap, partition, uniq };
|
package/lib/utils/fs.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { rm, mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
1
|
+
import { rm, mkdir, readFile, writeFile, access } from 'node:fs/promises';
|
|
2
2
|
|
|
3
3
|
async function cleanDir(dir) {
|
|
4
4
|
await rm(dir, {
|
|
@@ -9,6 +9,14 @@ async function cleanDir(dir) {
|
|
|
9
9
|
recursive: true
|
|
10
10
|
});
|
|
11
11
|
}
|
|
12
|
+
async function exists(fileOrDirectory) {
|
|
13
|
+
try {
|
|
14
|
+
await access(fileOrDirectory);
|
|
15
|
+
return true;
|
|
16
|
+
} catch {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
12
20
|
async function readJSON(file) {
|
|
13
21
|
const fileContent = await readFile(file, "utf-8");
|
|
14
22
|
return JSON.parse(fileContent);
|
|
@@ -17,4 +25,4 @@ async function writeJSON(file, data) {
|
|
|
17
25
|
await writeFile(file, JSON.stringify(data, undefined, 4));
|
|
18
26
|
}
|
|
19
27
|
|
|
20
|
-
export { cleanDir, readJSON, writeJSON };
|
|
28
|
+
export { cleanDir, exists, readJSON, writeJSON };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@entur/function-tools",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.6",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
"oxc-resolver": "^11.16.2",
|
|
22
22
|
"rollup": "^4.54.0",
|
|
23
23
|
"rollup-plugin-dts": "^6.3.0",
|
|
24
|
-
"semver": "^7.7.3",
|
|
25
24
|
"yaml": "^2.8.2"
|
|
26
25
|
},
|
|
27
26
|
"peerDependencies": {
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
import { builtinModules } from 'node:module';
|
|
2
|
-
import { dirname } from 'node:path';
|
|
3
|
-
import { coerce, satisfies } from 'semver';
|
|
4
|
-
import { groupBy } from './array.js';
|
|
5
|
-
import { groupByAsync, asyncMap } from './async.js';
|
|
6
|
-
import { spawnAsync } from './exec.js';
|
|
7
|
-
import { readPackageJSON, packageUp } from './packageJSON.js';
|
|
8
|
-
|
|
9
|
-
const alwaysIncludePackageNames = [
|
|
10
|
-
"@google-cloud/functions-framework"
|
|
11
|
-
];
|
|
12
|
-
async function calculateDependencies(outputs) {
|
|
13
|
-
const outputGroupedByPackage = await groupByAsync(outputs.filter((it)=>Boolean(it.type === "chunk" && it.facadeModuleId && it.imports.length > 0)), async (output)=>{
|
|
14
|
-
const key = output.facadeModuleId && await packageUp({
|
|
15
|
-
cwd: output.facadeModuleId
|
|
16
|
-
});
|
|
17
|
-
if (!key) {
|
|
18
|
-
throw new Error(`No package.json found for ${output.facadeModuleId}`);
|
|
19
|
-
}
|
|
20
|
-
return key;
|
|
21
|
-
});
|
|
22
|
-
const filterDependencies = (lookup, dependencies)=>{
|
|
23
|
-
if (!dependencies) return;
|
|
24
|
-
const entries = Object.entries(dependencies).filter(([key])=>lookup.has(key));
|
|
25
|
-
return Object.fromEntries(entries);
|
|
26
|
-
};
|
|
27
|
-
const entries = await asyncMap([
|
|
28
|
-
...outputGroupedByPackage
|
|
29
|
-
], async ([packageJSONPath, outputs])=>{
|
|
30
|
-
const packageJSON = await readPackageJSON(packageJSONPath);
|
|
31
|
-
const importedPackageNames = new Set(outputs.flatMap((it)=>it.imports).filter((it)=>!isBuiltinImport(it)).map(specifierToPackageName));
|
|
32
|
-
if (alwaysIncludePackageNames?.length) {
|
|
33
|
-
alwaysIncludePackageNames.forEach((it)=>{
|
|
34
|
-
importedPackageNames.add(it);
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
return [
|
|
38
|
-
dirname(packageJSONPath),
|
|
39
|
-
{
|
|
40
|
-
...packageJSON,
|
|
41
|
-
dependencies: filterDependencies(importedPackageNames, packageJSON.dependencies),
|
|
42
|
-
devDependencies: filterDependencies(importedPackageNames, packageJSON.devDependencies),
|
|
43
|
-
optionalDependencies: filterDependencies(importedPackageNames, packageJSON.optionalDependencies)
|
|
44
|
-
}
|
|
45
|
-
];
|
|
46
|
-
});
|
|
47
|
-
return new Map(entries);
|
|
48
|
-
}
|
|
49
|
-
function specifierToPackageName(specifier) {
|
|
50
|
-
if (specifier.startsWith("@")) {
|
|
51
|
-
return specifier.split("/", 2).join("/");
|
|
52
|
-
}
|
|
53
|
-
return specifier.split("/", 1).join("/");
|
|
54
|
-
}
|
|
55
|
-
function isBuiltinImport(specifier) {
|
|
56
|
-
return builtinModules.includes(specifier) || specifier.startsWith("node:");
|
|
57
|
-
}
|
|
58
|
-
function harmonizeDependencies(initialDependecies) {
|
|
59
|
-
const entries = [
|
|
60
|
-
...initialDependecies.values()
|
|
61
|
-
].flatMap((it)=>[
|
|
62
|
-
...Object.entries(it.dependencies ?? {}),
|
|
63
|
-
...Object.entries(it.devDependencies ?? {}),
|
|
64
|
-
...Object.entries(it.peerDependencies ?? {}),
|
|
65
|
-
...Object.entries(it.optionalDependencies ?? {})
|
|
66
|
-
]);
|
|
67
|
-
const harmonizedSemvers = new Map([
|
|
68
|
-
...groupBy(entries, ([packageName])=>packageName)
|
|
69
|
-
].map(([packageName, entriesForPackageName])=>{
|
|
70
|
-
const firstVersion = entriesForPackageName[0][1];
|
|
71
|
-
if (entriesForPackageName.length === 1) {
|
|
72
|
-
return [
|
|
73
|
-
packageName,
|
|
74
|
-
firstVersion
|
|
75
|
-
];
|
|
76
|
-
}
|
|
77
|
-
if (entriesForPackageName.every(([, semver])=>semver === firstVersion)) {
|
|
78
|
-
return [
|
|
79
|
-
packageName,
|
|
80
|
-
firstVersion
|
|
81
|
-
];
|
|
82
|
-
}
|
|
83
|
-
const satisfiedVersion = entriesForPackageName.reduce((acc, [, semver])=>{
|
|
84
|
-
if (acc === semver) {
|
|
85
|
-
return acc;
|
|
86
|
-
}
|
|
87
|
-
const semVerOrNull = coerce(semver);
|
|
88
|
-
if (semVerOrNull !== null && satisfies(semVerOrNull, acc)) {
|
|
89
|
-
console.log(`${packageName} ${semver} over ${acc}`);
|
|
90
|
-
return semver;
|
|
91
|
-
}
|
|
92
|
-
if (semVerOrNull !== null && satisfies(semVerOrNull, semver)) {
|
|
93
|
-
console.log(`${packageName} ${acc} over ${semver}`);
|
|
94
|
-
return acc;
|
|
95
|
-
}
|
|
96
|
-
throw new Error(`Unable to find determine correct version of ${packageName} between ${semver} and ${acc}`);
|
|
97
|
-
}, firstVersion);
|
|
98
|
-
return [
|
|
99
|
-
packageName,
|
|
100
|
-
satisfiedVersion
|
|
101
|
-
];
|
|
102
|
-
}));
|
|
103
|
-
const harmonizeSemver = (dependencies)=>{
|
|
104
|
-
if (!dependencies) return;
|
|
105
|
-
const entries = Object.entries(dependencies).map(([packageName, initialSemver])=>{
|
|
106
|
-
const semver = harmonizedSemvers.get(packageName);
|
|
107
|
-
return [
|
|
108
|
-
packageName,
|
|
109
|
-
semver ?? initialSemver
|
|
110
|
-
];
|
|
111
|
-
});
|
|
112
|
-
return Object.fromEntries(entries);
|
|
113
|
-
};
|
|
114
|
-
return new Map([
|
|
115
|
-
...initialDependecies
|
|
116
|
-
].map(([packageName, packageJSON])=>{
|
|
117
|
-
return [
|
|
118
|
-
packageName,
|
|
119
|
-
{
|
|
120
|
-
...packageJSON,
|
|
121
|
-
dependencies: harmonizeSemver(packageJSON.dependencies),
|
|
122
|
-
devDependencies: harmonizeSemver(packageJSON.devDependencies),
|
|
123
|
-
peerDependencies: harmonizeSemver(packageJSON.peerDependencies)
|
|
124
|
-
}
|
|
125
|
-
];
|
|
126
|
-
}));
|
|
127
|
-
}
|
|
128
|
-
// optionalDependencies: harmonizeSemver(packageJSON.optionalDependencies),
|
|
129
|
-
async function flattenDependencies(dependencies) {
|
|
130
|
-
const listOfDependencies = [
|
|
131
|
-
...dependencies.values()
|
|
132
|
-
].map((it)=>it.dependencies);
|
|
133
|
-
const listOfDevDependencies = [
|
|
134
|
-
...dependencies.values()
|
|
135
|
-
].map((it)=>it.devDependencies);
|
|
136
|
-
const listOfPeerDependencies = [
|
|
137
|
-
...dependencies.values()
|
|
138
|
-
].map((it)=>it.peerDependencies);
|
|
139
|
-
const listOfOptionalDependencies = [
|
|
140
|
-
...dependencies.values()
|
|
141
|
-
].map((it)=>it.optionalDependencies);
|
|
142
|
-
return {
|
|
143
|
-
dependencies: Object.assign({}, ...listOfDependencies),
|
|
144
|
-
devDependencies: Object.assign({}, ...listOfDevDependencies),
|
|
145
|
-
peerDependencies: Object.assign({}, ...listOfPeerDependencies),
|
|
146
|
-
optionalDependencies: Object.assign({}, ...listOfOptionalDependencies)
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
async function linkDependencies(workingDir) {
|
|
150
|
-
await spawnAsync("pnpm", [
|
|
151
|
-
"install",
|
|
152
|
-
"--ignore-workspace",
|
|
153
|
-
"--prefer-offline"
|
|
154
|
-
], {
|
|
155
|
-
cwd: workingDir
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
export { calculateDependencies, flattenDependencies, harmonizeDependencies, linkDependencies };
|