@entur/function-tools 0.0.7 → 0.0.9
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 +109 -20
- package/lib/bundle/index.js +6 -9
- package/lib/bundle/utils.js +12 -6
- package/lib/commands/build.js +21 -18
- package/lib/commands/deploy.js +20 -16
- package/lib/commands/start.js +15 -14
- package/lib/firebase/index.js +4 -2
- package/lib/{utils/firebase.js → firebase/utils.js} +1 -1
- package/lib/{utils/packageJSON.js → packageJSON/index.js} +1 -1
- package/lib/utils/fs.js +10 -2
- package/lib/utils/workspace.js +1 -1
- package/package.json +1 -1
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.9").option("-v, --verbose", "Enable verbose output");
|
|
9
9
|
registerBuild(program);
|
|
10
10
|
registerDeploy(program);
|
|
11
11
|
registerStart(program);
|
|
@@ -1,34 +1,121 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { copyFile } from 'node:fs/promises';
|
|
2
2
|
import { builtinModules } from 'node:module';
|
|
3
|
-
import { dirname } from 'node:path';
|
|
4
|
-
import {
|
|
3
|
+
import { dirname, relative } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { writePackageJSON, readPackageJSON, packageUp } from '../packageJSON/index.js';
|
|
6
|
+
import { filterMap } from '../utils/array.js';
|
|
5
7
|
import { groupByAsync, asyncMap } from '../utils/async.js';
|
|
6
8
|
import { spawnAsync } from '../utils/exec.js';
|
|
7
|
-
import {
|
|
9
|
+
import { readYAML, writeYAML } from '../utils/fs.js';
|
|
8
10
|
|
|
9
11
|
const alwaysIncludePackageNames = [
|
|
10
12
|
"@google-cloud/functions-framework",
|
|
11
13
|
"firebase-functions",
|
|
12
14
|
"firebase-admin"
|
|
13
15
|
];
|
|
14
|
-
async function writeDependencies(outputs, getOutputFilePath, outputDir) {
|
|
15
|
-
const
|
|
16
|
-
|
|
16
|
+
async function writeDependencies(outputs, getOutputFilePath, projectRoot, outputDir) {
|
|
17
|
+
const pnpmLockSourceURL = new URL("./pnpm-lock.yaml", projectRoot);
|
|
18
|
+
const pnpmLockOutputURL = new URL("./pnpm-lock.yaml", outputDir);
|
|
19
|
+
const pnpmWorkspaceSourceURL = new URL("./pnpm-workspace.yaml", projectRoot);
|
|
20
|
+
const pnpmWorkspaceOutputURL = new URL("./pnpm-workspace.yaml", outputDir);
|
|
21
|
+
await Promise.all([
|
|
22
|
+
copyFile(pnpmLockSourceURL, pnpmLockOutputURL),
|
|
23
|
+
copyFile(pnpmWorkspaceSourceURL, pnpmWorkspaceOutputURL)
|
|
24
|
+
]);
|
|
25
|
+
const dependencies = await calculateDependencies(outputs);
|
|
26
|
+
await Promise.all([
|
|
27
|
+
writePackageJSONs(dependencies, getOutputFilePath, outputDir),
|
|
28
|
+
updateWorkspace(dependencies, getOutputFilePath, pnpmWorkspaceOutputURL),
|
|
29
|
+
updatePNPMLock(dependencies, getOutputFilePath, pnpmLockOutputURL, projectRoot)
|
|
30
|
+
]);
|
|
31
|
+
}
|
|
32
|
+
async function writePackageJSONs(packageJSONMap, getOutputFilePath, outputDir) {
|
|
33
|
+
for (const [packageJSONPath, packageJSON] of packageJSONMap){
|
|
17
34
|
const newPackageJSONPath = getOutputFilePath(packageJSONPath);
|
|
18
|
-
|
|
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
|
-
}
|
|
35
|
+
await writePackageJSON(new URL(`./${newPackageJSONPath}`, outputDir), packageJSON);
|
|
28
36
|
}
|
|
29
|
-
|
|
37
|
+
}
|
|
38
|
+
async function updateWorkspace(packageJSONMap, getOutputFilePath, pnpmWorkspaceURL) {
|
|
39
|
+
const packages = filterMap([
|
|
40
|
+
...packageJSONMap.keys()
|
|
41
|
+
], (filePath)=>{
|
|
42
|
+
const outputFileName = dirname(getOutputFilePath(filePath));
|
|
43
|
+
return outputFileName !== "." ? outputFileName : undefined;
|
|
44
|
+
});
|
|
45
|
+
const workspace = await readYAML(pnpmWorkspaceURL);
|
|
46
|
+
await writeYAML(pnpmWorkspaceURL, {
|
|
47
|
+
...workspace,
|
|
30
48
|
packages
|
|
31
|
-
})
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
async function updatePNPMLock(packageJSONMap, getOutputFilePath, pnpmLockURL, projectRoot) {
|
|
52
|
+
const projectRootPath = fileURLToPath(projectRoot);
|
|
53
|
+
const lockfile = await readYAML(pnpmLockURL);
|
|
54
|
+
const updateDependencies = (dependencies, packageJSONDependencies)=>{
|
|
55
|
+
if (!dependencies || !packageJSONDependencies) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const entries = filterMap(Object.entries(dependencies), ([packageName, versionOrDependency])=>{
|
|
59
|
+
const specifier = packageJSONDependencies[packageName];
|
|
60
|
+
if (!specifier) return;
|
|
61
|
+
return typeof versionOrDependency === "string" ? [
|
|
62
|
+
packageName,
|
|
63
|
+
{
|
|
64
|
+
specifier,
|
|
65
|
+
version: versionOrDependency
|
|
66
|
+
}
|
|
67
|
+
] : [
|
|
68
|
+
packageName,
|
|
69
|
+
versionOrDependency
|
|
70
|
+
];
|
|
71
|
+
});
|
|
72
|
+
if (entries.length === 0) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
return Object.fromEntries(entries);
|
|
76
|
+
};
|
|
77
|
+
const findSnapshot = (packageName)=>{
|
|
78
|
+
for (const { dependencies, devDependencies } of Object.values(lockfile.importers)){
|
|
79
|
+
const found = dependencies?.[packageName] || devDependencies?.[packageName];
|
|
80
|
+
if (found) {
|
|
81
|
+
const key = `${packageName}@${found.version}`;
|
|
82
|
+
const snapshot = lockfile.snapshots[key];
|
|
83
|
+
if (snapshot) return snapshot;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
const entries = [
|
|
88
|
+
...packageJSONMap
|
|
89
|
+
].map(([packageJSONPath, packageJSON])=>{
|
|
90
|
+
const packageRootPath = dirname(packageJSONPath);
|
|
91
|
+
const key = relative(projectRootPath, packageRootPath);
|
|
92
|
+
const importer = lockfile.importers[key];
|
|
93
|
+
const updatedKey = getOutputFilePath(packageRootPath) || ".";
|
|
94
|
+
if (importer) {
|
|
95
|
+
return [
|
|
96
|
+
updatedKey,
|
|
97
|
+
{
|
|
98
|
+
dependencies: updateDependencies(importer.dependencies, packageJSON.dependencies),
|
|
99
|
+
devDependencies: updateDependencies(importer.devDependencies, packageJSON.devDependencies)
|
|
100
|
+
}
|
|
101
|
+
];
|
|
102
|
+
}
|
|
103
|
+
const snapshot = findSnapshot(packageJSON.name);
|
|
104
|
+
if (snapshot) {
|
|
105
|
+
return [
|
|
106
|
+
updatedKey,
|
|
107
|
+
{
|
|
108
|
+
dependencies: updateDependencies(snapshot.dependencies, packageJSON.dependencies),
|
|
109
|
+
devDependencies: updateDependencies(snapshot.devDependencies, packageJSON.devDependencies)
|
|
110
|
+
}
|
|
111
|
+
];
|
|
112
|
+
}
|
|
113
|
+
throw new Error(`Unable to create importer for ${packageJSON.name}`);
|
|
114
|
+
});
|
|
115
|
+
await writeYAML(pnpmLockURL, {
|
|
116
|
+
...lockfile,
|
|
117
|
+
importers: Object.fromEntries(entries)
|
|
118
|
+
});
|
|
32
119
|
}
|
|
33
120
|
async function calculateDependencies(outputs) {
|
|
34
121
|
const outputGroupedByPackage = await groupByAsync(outputs.filter((it)=>Boolean(it.type === "chunk" && it.facadeModuleId && it.imports.length > 0)), async (output)=>{
|
|
@@ -45,6 +132,7 @@ async function calculateDependencies(outputs) {
|
|
|
45
132
|
const entries = Object.entries(dependencies).filter(([key])=>lookup.has(key));
|
|
46
133
|
return entries.length > 0 ? Object.fromEntries(entries) : undefined;
|
|
47
134
|
};
|
|
135
|
+
const entryFile = outputs[0];
|
|
48
136
|
const entries = await asyncMap([
|
|
49
137
|
...outputGroupedByPackage
|
|
50
138
|
], async ([packageJSONPath, outputs])=>{
|
|
@@ -59,6 +147,7 @@ async function calculateDependencies(outputs) {
|
|
|
59
147
|
name,
|
|
60
148
|
type,
|
|
61
149
|
version,
|
|
150
|
+
main: outputs.includes(entryFile) ? `./${entryFile.fileName}` : undefined,
|
|
62
151
|
dependencies: filterDependencies(importedPackageNames, packageJSON.dependencies),
|
|
63
152
|
devDependencies: filterDependencies(importedPackageNames, packageJSON.devDependencies),
|
|
64
153
|
optionalDependencies: filterDependencies(importedPackageNames, packageJSON.optionalDependencies)
|
|
@@ -79,7 +168,7 @@ function isBuiltinImport(specifier) {
|
|
|
79
168
|
async function linkDependencies(workingDir) {
|
|
80
169
|
await spawnAsync("pnpm", [
|
|
81
170
|
"install",
|
|
82
|
-
"--
|
|
171
|
+
"--fix-lockfile"
|
|
83
172
|
], {
|
|
84
173
|
cwd: workingDir
|
|
85
174
|
});
|
package/lib/bundle/index.js
CHANGED
|
@@ -2,15 +2,13 @@ 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';
|
|
6
5
|
|
|
7
|
-
async function bundle(entryFile, { outputDir,
|
|
6
|
+
async function bundle(entryFile, { outputDir, outputFileName, shouldInlinePackage }) {
|
|
8
7
|
const bundle = await rollup({
|
|
9
8
|
input: fileURLToPath(entryFile),
|
|
10
|
-
plugins: plugins(
|
|
9
|
+
plugins: plugins(shouldInlinePackage),
|
|
11
10
|
treeshake: "smallest"
|
|
12
11
|
});
|
|
13
|
-
const outputFileName = createOutputFileName(packageRoot, projectRoot);
|
|
14
12
|
return bundle.write({
|
|
15
13
|
preserveModules: true,
|
|
16
14
|
format: "esm",
|
|
@@ -18,8 +16,7 @@ async function bundle(entryFile, { outputDir, packageRoot, projectRoot, packages
|
|
|
18
16
|
entryFileNames: ({ facadeModuleId })=>outputFileName(facadeModuleId)
|
|
19
17
|
});
|
|
20
18
|
}
|
|
21
|
-
async function bundleAndWatch(entryFile, { outputDir,
|
|
22
|
-
const outputFileName = createOutputFileName(packageRoot, projectRoot);
|
|
19
|
+
async function bundleAndWatch(entryFile, { outputDir, outputFileName, shouldInlinePackage, onBundleEnd }) {
|
|
23
20
|
const output = {
|
|
24
21
|
preserveModules: true,
|
|
25
22
|
format: "esm",
|
|
@@ -27,7 +24,7 @@ async function bundleAndWatch(entryFile, { outputDir, packageRoot, projectRoot,
|
|
|
27
24
|
entryFileNames: ({ facadeModuleId })=>outputFileName(facadeModuleId)
|
|
28
25
|
};
|
|
29
26
|
const watchOptions = {
|
|
30
|
-
plugins: plugins(
|
|
27
|
+
plugins: plugins(shouldInlinePackage),
|
|
31
28
|
input: fileURLToPath(entryFile),
|
|
32
29
|
treeshake: "smallest",
|
|
33
30
|
output,
|
|
@@ -61,7 +58,7 @@ async function bundleAndWatch(entryFile, { outputDir, packageRoot, projectRoot,
|
|
|
61
58
|
}
|
|
62
59
|
});
|
|
63
60
|
}
|
|
64
|
-
const plugins = (
|
|
61
|
+
const plugins = (resolveOnly)=>[
|
|
65
62
|
swc({
|
|
66
63
|
swc: {
|
|
67
64
|
jsc: {
|
|
@@ -70,7 +67,7 @@ const plugins = (workspacePackages)=>[
|
|
|
70
67
|
}
|
|
71
68
|
}),
|
|
72
69
|
nodeResolve({
|
|
73
|
-
resolveOnly
|
|
70
|
+
resolveOnly
|
|
74
71
|
})
|
|
75
72
|
];
|
|
76
73
|
|
package/lib/bundle/utils.js
CHANGED
|
@@ -5,19 +5,25 @@ function createOutputFileName(packageRootURL, projectRootURL) {
|
|
|
5
5
|
const projectRoot = fileURLToPath(projectRootURL);
|
|
6
6
|
const packageRoot = fileURLToPath(packageRootURL);
|
|
7
7
|
return (facadeModuleId)=>{
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
if (!facadeModuleId) {
|
|
9
|
+
throw new Error(`file path is null`);
|
|
10
|
+
}
|
|
11
|
+
const index = facadeModuleId.lastIndexOf(nodeModulesPartPath);
|
|
12
|
+
if (facadeModuleId && index > -1) {
|
|
10
13
|
return `bundled_modules/${facadeModuleId.slice(index + nodeModulesPartPath.length)}`;
|
|
11
14
|
}
|
|
12
|
-
const filePath = facadeModuleId
|
|
13
|
-
if (filePath
|
|
15
|
+
const filePath = facadeModuleId.replace(".ts", ".js").replaceAll("/src/", "/lib/");
|
|
16
|
+
if (filePath.startsWith(packageRoot) || packageRoot.slice(0, -1) === filePath) {
|
|
14
17
|
return filePath.slice(packageRoot.length);
|
|
15
18
|
}
|
|
16
|
-
if (filePath
|
|
19
|
+
if (filePath.startsWith(projectRoot)) {
|
|
17
20
|
return `local_modules/${filePath.slice(projectRoot.length)}`;
|
|
18
21
|
}
|
|
19
22
|
throw new Error(`Unable to determine correct placement for file ${facadeModuleId}`);
|
|
20
23
|
};
|
|
21
24
|
}
|
|
25
|
+
function createShouldInlinePackage(packagesToInline) {
|
|
26
|
+
return (moduleId)=>moduleId.startsWith(".") || packagesToInline?.some((it)=>moduleId.startsWith(it)) || moduleId.startsWith("@entur-private/") || false;
|
|
27
|
+
}
|
|
22
28
|
|
|
23
|
-
export { createOutputFileName };
|
|
29
|
+
export { createOutputFileName, createShouldInlinePackage };
|
package/lib/commands/build.js
CHANGED
|
@@ -1,37 +1,40 @@
|
|
|
1
|
-
import { writeDependencies } from '../bundle/dependencies.js';
|
|
1
|
+
import { writeDependencies, linkDependencies } from '../bundle/dependencies.js';
|
|
2
2
|
import { bundle } from '../bundle/index.js';
|
|
3
|
-
import { createOutputFileName } from '../bundle/utils.js';
|
|
3
|
+
import { createOutputFileName, createShouldInlinePackage } from '../bundle/utils.js';
|
|
4
|
+
import { readPackageJSON } from '../packageJSON/index.js';
|
|
4
5
|
import { cleanDir } from '../utils/fs.js';
|
|
5
|
-
import { readPackageJSON } from '../utils/packageJSON.js';
|
|
6
6
|
import { getWorkspacePackageNames } from '../utils/workspace.js';
|
|
7
7
|
import { resolveProjectConfig } from './utils.js';
|
|
8
8
|
|
|
9
9
|
function registerBuild(program) {
|
|
10
|
-
program.command("build").description("Build the project").option("-o, --output-dir <dir>", "Output directory").action(async (
|
|
10
|
+
program.command("build").description("Build the project").option("-o, --output-dir <dir>", "Output directory").action(async ({ outputDir })=>{
|
|
11
11
|
try {
|
|
12
|
-
const projectConfig = await resolveProjectConfig(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
await cleanDir(outputDir);
|
|
17
|
-
console.log(`🔨 Building ${name}`);
|
|
18
|
-
const workspacePackages = await getWorkspacePackageNames(pnpmWorkspaceYAML);
|
|
19
|
-
const entryFile = new URL(exports$1?.["."] ?? "./index.js", packageRoot);
|
|
20
|
-
await build(entryFile, workspacePackages, projectConfig);
|
|
12
|
+
const projectConfig = await resolveProjectConfig({
|
|
13
|
+
outputDir
|
|
14
|
+
});
|
|
15
|
+
await build(projectConfig);
|
|
21
16
|
} catch (error) {
|
|
22
17
|
console.error(error);
|
|
23
18
|
process.exit(1);
|
|
24
19
|
}
|
|
25
20
|
});
|
|
26
21
|
}
|
|
27
|
-
async function build(
|
|
22
|
+
async function build(projectConfig) {
|
|
23
|
+
const { packageRoot, projectRoot, packageJSON, outputDir, pnpmWorkspaceYAML } = projectConfig;
|
|
24
|
+
const { name, exports: exports$1 } = await readPackageJSON(packageJSON);
|
|
25
|
+
console.log("🧹 Cleaning dist folder");
|
|
26
|
+
await cleanDir(outputDir);
|
|
27
|
+
console.log(`🔨 Building ${name}`);
|
|
28
|
+
const entryFile = new URL(exports$1?.["."] ?? "./index.js", packageRoot);
|
|
29
|
+
const outputFileName = createOutputFileName(packageRoot, projectRoot);
|
|
30
|
+
const shouldInlinePackage = createShouldInlinePackage(await getWorkspacePackageNames(pnpmWorkspaceYAML));
|
|
28
31
|
const { output } = await bundle(entryFile, {
|
|
29
32
|
outputDir,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
packagesToInline
|
|
33
|
+
outputFileName,
|
|
34
|
+
shouldInlinePackage
|
|
33
35
|
});
|
|
34
|
-
await writeDependencies(output,
|
|
36
|
+
await writeDependencies(output, outputFileName, projectRoot, outputDir);
|
|
37
|
+
await linkDependencies(outputDir);
|
|
35
38
|
}
|
|
36
39
|
|
|
37
40
|
export { registerBuild };
|
package/lib/commands/deploy.js
CHANGED
|
@@ -1,33 +1,35 @@
|
|
|
1
1
|
import { writeDependencies, linkDependencies } from '../bundle/dependencies.js';
|
|
2
2
|
import { bundle } from '../bundle/index.js';
|
|
3
|
-
import { createOutputFileName } from '../bundle/utils.js';
|
|
3
|
+
import { createOutputFileName, createShouldInlinePackage } from '../bundle/utils.js';
|
|
4
4
|
import { deploy as deploy$1 } from '../firebase/index.js';
|
|
5
|
-
import { getFirebaseJSON, writeFirebaseJSON } from '../utils
|
|
5
|
+
import { getFirebaseJSON, writeFirebaseJSON } from '../firebase/utils.js';
|
|
6
|
+
import { readPackageJSON, getPackageName } from '../packageJSON/index.js';
|
|
6
7
|
import { cleanDir, writeJSON } from '../utils/fs.js';
|
|
7
|
-
import { readPackageJSON, getPackageName } from '../utils/packageJSON.js';
|
|
8
8
|
import { getWorkspacePackageNames } from '../utils/workspace.js';
|
|
9
9
|
import { resolveProjectConfig, copyEnvFiles } from './utils.js';
|
|
10
10
|
|
|
11
11
|
function registerDeploy(program) {
|
|
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").option("--debug", "print verbose debug output and keep a debug log file", false).action(async (options)=>{
|
|
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").option("--debug", "print verbose debug output and keep a debug log file", false).option("--force", "delete missing Cloud Functions and bypass interactive prompts", false).action(async ({ outputDir, project, ...options })=>{
|
|
13
13
|
try {
|
|
14
|
-
const projectConfig = await resolveProjectConfig(
|
|
15
|
-
|
|
14
|
+
const projectConfig = await resolveProjectConfig({
|
|
15
|
+
outputDir,
|
|
16
|
+
project
|
|
17
|
+
});
|
|
18
|
+
await deploy(options, projectConfig);
|
|
16
19
|
} catch (error) {
|
|
17
20
|
console.error(error);
|
|
18
21
|
process.exit(1);
|
|
19
22
|
}
|
|
20
23
|
});
|
|
21
24
|
}
|
|
22
|
-
async function deploy(
|
|
23
|
-
const { projectAlias, projectId, packageJSON, packageRoot,
|
|
25
|
+
async function deploy(options, projectConfig) {
|
|
26
|
+
const { projectAlias, projectId, packageJSON, packageRoot, projectRoot, outputDir } = projectConfig;
|
|
24
27
|
const { name, exports: exports$1 } = await readPackageJSON(packageJSON);
|
|
25
|
-
const workspacePackages = await getWorkspacePackageNames(pnpmWorkspaceYAML);
|
|
26
28
|
const entryFile = new URL(exports$1?.["."] ?? "./index.js", packageRoot);
|
|
27
29
|
console.log("🧹 Cleaning dist folder");
|
|
28
30
|
await cleanDir(outputDir);
|
|
29
31
|
console.log(`🔨 Building ${name}`);
|
|
30
|
-
await build(entryFile,
|
|
32
|
+
await build(entryFile, projectConfig);
|
|
31
33
|
console.log("⛷️ Prepare deploy");
|
|
32
34
|
const firebaseJSON = await getFirebaseJSON(new URL("firebase.json", projectRoot));
|
|
33
35
|
await prepareDeploy(getPackageName(name), firebaseJSON, projectConfig);
|
|
@@ -35,17 +37,19 @@ async function deploy(debug, projectConfig) {
|
|
|
35
37
|
await deploy$1({
|
|
36
38
|
projectId,
|
|
37
39
|
cwd: outputDir,
|
|
38
|
-
|
|
40
|
+
...options
|
|
39
41
|
});
|
|
40
42
|
}
|
|
41
|
-
async function build(entryFile,
|
|
43
|
+
async function build(entryFile, { outputDir, packageRoot, projectRoot, pnpmWorkspaceYAML }) {
|
|
44
|
+
const outputFileName = createOutputFileName(packageRoot, projectRoot);
|
|
45
|
+
const shouldInlinePackage = createShouldInlinePackage(await getWorkspacePackageNames(pnpmWorkspaceYAML));
|
|
42
46
|
const { output } = await bundle(entryFile, {
|
|
43
|
-
packageRoot,
|
|
44
|
-
projectRoot,
|
|
45
47
|
outputDir,
|
|
46
|
-
|
|
48
|
+
outputFileName,
|
|
49
|
+
shouldInlinePackage
|
|
47
50
|
});
|
|
48
|
-
await writeDependencies(output,
|
|
51
|
+
await writeDependencies(output, outputFileName, projectRoot, outputDir);
|
|
52
|
+
await linkDependencies(outputDir);
|
|
49
53
|
}
|
|
50
54
|
async function prepareDeploy(codebase, firebaseJSON, { projectAlias, projectId, outputDir, envFiles }) {
|
|
51
55
|
const envPrefix = `FUNCTION_CODEBASE='${codebase}'\nENTUR_PROJECT_ALIAS='${projectAlias}'`;
|
package/lib/commands/start.js
CHANGED
|
@@ -1,39 +1,42 @@
|
|
|
1
1
|
import { writeDependencies, linkDependencies } from '../bundle/dependencies.js';
|
|
2
2
|
import { bundleAndWatch } from '../bundle/index.js';
|
|
3
|
-
import { createOutputFileName } from '../bundle/utils.js';
|
|
3
|
+
import { createOutputFileName, createShouldInlinePackage } from '../bundle/utils.js';
|
|
4
4
|
import { startEmulator } from '../firebase/index.js';
|
|
5
|
-
import { getFirebaseJSON, writeFirebaseJSON } from '../utils
|
|
5
|
+
import { getFirebaseJSON, writeFirebaseJSON } from '../firebase/utils.js';
|
|
6
|
+
import { readPackageJSON, getPackageName } from '../packageJSON/index.js';
|
|
6
7
|
import { cleanDir, writeJSON } from '../utils/fs.js';
|
|
7
|
-
import { readPackageJSON, getPackageName } from '../utils/packageJSON.js';
|
|
8
8
|
import { getWorkspacePackageNames } from '../utils/workspace.js';
|
|
9
9
|
import { resolveProjectConfig, copyEnvFiles } from './utils.js';
|
|
10
10
|
|
|
11
11
|
function registerStart(program) {
|
|
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)", false).option("--debug", "print verbose debug output and keep a debug log file", false).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)", false).option("--debug", "print verbose debug output and keep a debug log file", false).action(async ({ outputDir, project, ...options })=>{
|
|
13
13
|
try {
|
|
14
14
|
const projectConfig = await resolveProjectConfig({
|
|
15
|
-
|
|
15
|
+
outputDir,
|
|
16
|
+
project,
|
|
16
17
|
isEmulator: true
|
|
17
18
|
});
|
|
18
|
-
await start(options
|
|
19
|
+
await start(options, projectConfig);
|
|
19
20
|
} catch (error) {
|
|
20
21
|
console.error(error);
|
|
21
22
|
process.exit(1);
|
|
22
23
|
}
|
|
23
24
|
});
|
|
24
25
|
}
|
|
25
|
-
async function start(
|
|
26
|
+
async function start(options, projectConfig) {
|
|
26
27
|
const { packageRoot, packageJSON, projectId, projectRoot, pnpmWorkspaceYAML, outputDir } = projectConfig;
|
|
27
28
|
const { name, exports: exports$1 } = await readPackageJSON(packageJSON);
|
|
28
29
|
const codebase = getPackageName(name);
|
|
29
|
-
const packagesToInline = await getWorkspacePackageNames(pnpmWorkspaceYAML);
|
|
30
30
|
const entryFile = new URL(exports$1?.["."] ?? "./index.js", packageRoot);
|
|
31
31
|
console.log("🧹 Cleaning dist folder");
|
|
32
32
|
await cleanDir(outputDir);
|
|
33
33
|
console.log(`🔨 Building ${name}`);
|
|
34
|
+
const outputFileName = createOutputFileName(packageRoot, projectRoot);
|
|
35
|
+
const shouldInlinePackage = createShouldInlinePackage(await getWorkspacePackageNames(pnpmWorkspaceYAML));
|
|
34
36
|
let firstRun = true;
|
|
35
37
|
const onBundleEnd = async ({ output })=>{
|
|
36
|
-
await writeDependencies(output,
|
|
38
|
+
await writeDependencies(output, outputFileName, projectRoot, outputDir);
|
|
39
|
+
await linkDependencies(outputDir);
|
|
37
40
|
const firebaseJSON = await getFirebaseJSON(new URL("firebase.json", projectRoot));
|
|
38
41
|
await prepareStart(codebase, firebaseJSON, projectConfig);
|
|
39
42
|
if (firstRun) {
|
|
@@ -41,8 +44,7 @@ async function start(debug, inspectFunctions, projectConfig) {
|
|
|
41
44
|
startEmulator({
|
|
42
45
|
projectId,
|
|
43
46
|
cwd: outputDir,
|
|
44
|
-
|
|
45
|
-
inspectFunctions
|
|
47
|
+
...options
|
|
46
48
|
}).catch((error)=>{
|
|
47
49
|
console.error(error);
|
|
48
50
|
});
|
|
@@ -50,9 +52,8 @@ async function start(debug, inspectFunctions, projectConfig) {
|
|
|
50
52
|
};
|
|
51
53
|
await bundleAndWatch(entryFile, {
|
|
52
54
|
outputDir,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
packagesToInline,
|
|
55
|
+
outputFileName,
|
|
56
|
+
shouldInlinePackage,
|
|
56
57
|
onBundleEnd
|
|
57
58
|
});
|
|
58
59
|
}
|
package/lib/firebase/index.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { spawnAsync } from '../utils/exec.js';
|
|
2
2
|
|
|
3
3
|
const FUNCTIONS_DISCOVERY_TIMEOUT = "30";
|
|
4
|
-
function deploy({ projectId, cwd, debug }) {
|
|
4
|
+
function deploy({ projectId, cwd, debug, force }) {
|
|
5
5
|
const extraArgs = [];
|
|
6
6
|
if (debug) {
|
|
7
|
-
console.log("Environment variables:", process.env);
|
|
8
7
|
extraArgs.push("--debug");
|
|
9
8
|
}
|
|
9
|
+
if (force) {
|
|
10
|
+
extraArgs.push("--force");
|
|
11
|
+
}
|
|
10
12
|
return spawnAsync("firebase", [
|
|
11
13
|
"deploy",
|
|
12
14
|
"--only",
|
package/lib/utils/fs.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { rm, mkdir,
|
|
1
|
+
import { readFile, rm, mkdir, writeFile, access } from 'node:fs/promises';
|
|
2
|
+
import { parse, stringify } from 'yaml';
|
|
2
3
|
|
|
3
4
|
async function cleanDir(dir) {
|
|
4
5
|
await rm(dir, {
|
|
@@ -24,5 +25,12 @@ async function readJSON(file) {
|
|
|
24
25
|
async function writeJSON(file, data) {
|
|
25
26
|
await writeFile(file, JSON.stringify(data, undefined, 4));
|
|
26
27
|
}
|
|
28
|
+
async function readYAML(file) {
|
|
29
|
+
const fileContent = await readFile(file, "utf-8");
|
|
30
|
+
return parse(fileContent);
|
|
31
|
+
}
|
|
32
|
+
async function writeYAML(file, data) {
|
|
33
|
+
await writeFile(file, stringify(data, undefined, 4));
|
|
34
|
+
}
|
|
27
35
|
|
|
28
|
-
export { cleanDir, exists, readJSON, writeJSON };
|
|
36
|
+
export { cleanDir, exists, readJSON, readYAML, writeJSON, writeYAML };
|
package/lib/utils/workspace.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFile, glob } from 'node:fs/promises';
|
|
2
2
|
import { parse } from 'yaml';
|
|
3
|
-
import { readPackageJSON } from '
|
|
3
|
+
import { readPackageJSON } from '../packageJSON/index.js';
|
|
4
4
|
|
|
5
5
|
async function getWorkspacePackageNames(pnpmWorkspaceYAML) {
|
|
6
6
|
const pnpmWorkspaceContent = await readFile(pnpmWorkspaceYAML, "utf-8");
|