@entur/function-tools 0.0.3 → 0.0.5

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.
@@ -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-firebase").description("A multi-command CLI built with commander").version("0.0.3").option("-v, --verbose", "Enable verbose output");
8
+ program.name("entur-functions").description("A multi-tool for Firebase functions at Entur").version("0.0.5").option("-v, --verbose", "Enable verbose output");
9
9
  registerBuild(program);
10
10
  registerDeploy(program);
11
11
  registerStart(program);
@@ -1,4 +1,3 @@
1
- import { writeFile } from 'node:fs/promises';
2
1
  import { bundle } from '../utils/bundle.js';
3
2
  import { flattenDependencies, harmonizeDependencies, calculateDependencies, linkDependencies } from '../utils/dependencies.js';
4
3
  import { spawnAsync } from '../utils/exec.js';
@@ -6,7 +5,7 @@ import { getFirebaseJSON, writeFirebaseJSON } from '../utils/firebase.js';
6
5
  import { cleanDir, writeJSON } from '../utils/fs.js';
7
6
  import { readPackageJSON, getPackageName, writePackageJSON } from '../utils/packageJSON.js';
8
7
  import { getWorkspacePackageNames } from '../utils/workspace.js';
9
- import { resolveProjectConfig } from './utils.js';
8
+ import { resolveProjectConfig, copyEnvFiles } from './utils.js';
10
9
 
11
10
  function registerDeploy(program) {
12
11
  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,7 +18,8 @@ function registerDeploy(program) {
19
18
  }
20
19
  });
21
20
  }
22
- async function deploy({ projectAlias, projectId, packageJSON, packageRoot, pnpmWorkspaceYAML, projectRoot, outputDir }) {
21
+ async function deploy(projectConfig) {
22
+ const { projectAlias, projectId, packageJSON, packageRoot, pnpmWorkspaceYAML, projectRoot, outputDir } = projectConfig;
23
23
  const { name, version, exports: exports$1 } = await readPackageJSON(packageJSON);
24
24
  const workspacePackages = await getWorkspacePackageNames(pnpmWorkspaceYAML);
25
25
  const entryFile = new URL(exports$1?.["."] ?? "./index.js", packageRoot);
@@ -29,14 +29,13 @@ async function deploy({ projectAlias, projectId, packageJSON, packageRoot, pnpmW
29
29
  const { main, dependencies } = await build(entryFile, outputDir, workspacePackages);
30
30
  console.log("⛷️ Prepare deploy");
31
31
  const firebaseJSON = await getFirebaseJSON(new URL("firebase.json", projectRoot));
32
- await prepareDeploy(getPackageName(name), projectAlias, projectId, {
32
+ await prepareDeploy(getPackageName(name), {
33
33
  name,
34
34
  type: "module",
35
35
  version,
36
36
  main,
37
37
  ...dependencies
38
- }, firebaseJSON, outputDir);
39
- // contentHash,
38
+ }, firebaseJSON, projectConfig);
40
39
  console.log(`🚢 Deploying to ${projectAlias} (${projectId})`);
41
40
  await deployToFirebase(outputDir, projectId);
42
41
  }
@@ -52,12 +51,17 @@ async function build(entryFile, outputDir, packagesToInline) {
52
51
  dependencies
53
52
  };
54
53
  }
55
- async function prepareDeploy(codebase, projectAlias, projectId, packageJSON, firebaseJSON, outputDir) {
54
+ async function prepareDeploy(codebase, packageJSON, firebaseJSON, { projectAlias, projectId, outputDir, envFiles }) {
55
+ const envPrefix = `
56
+ NODE_OPTIONS='--enable-source-maps'
57
+ FUNCTION_CODEBASE='${codebase}'
58
+ ENTUR_PROJECT_ALIAS='${projectAlias}'
59
+ `.trimStart();
56
60
  await Promise.all([
57
61
  writeFirebaseJSON(codebase, firebaseJSON, outputDir),
58
62
  createFirebaseRC(projectAlias, projectId, outputDir),
59
63
  writePackageJSON(new URL("./package.json", outputDir), packageJSON),
60
- createDotenv(codebase, projectAlias, outputDir)
64
+ copyEnvFiles(envFiles, envPrefix, outputDir)
61
65
  ]);
62
66
  await linkDependencies(outputDir);
63
67
  }
@@ -80,12 +84,5 @@ function deployToFirebase(workingDir, projectId, extraArgs = []) {
80
84
  cwd: workingDir
81
85
  });
82
86
  }
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
87
 
91
88
  export { registerDeploy };
@@ -5,12 +5,15 @@ import { getFirebaseJSON, writeFirebaseJSON } from '../utils/firebase.js';
5
5
  import { cleanDir, writeJSON } from '../utils/fs.js';
6
6
  import { readPackageJSON, getPackageName, writePackageJSON } from '../utils/packageJSON.js';
7
7
  import { getWorkspacePackageNames } from '../utils/workspace.js';
8
- import { resolveProjectConfig } from './utils.js';
8
+ import { resolveProjectConfig, copyEnvFiles } from './utils.js';
9
9
 
10
10
  function registerStart(program) {
11
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
12
  try {
13
- const projectConfig = await resolveProjectConfig(options);
13
+ const projectConfig = await resolveProjectConfig({
14
+ ...options,
15
+ isEmulator: true
16
+ });
14
17
  await start(projectConfig);
15
18
  } catch (error) {
16
19
  console.error(error);
@@ -18,7 +21,8 @@ function registerStart(program) {
18
21
  }
19
22
  });
20
23
  }
21
- async function start({ packageRoot, packageJSON, projectAlias, projectId, projectRoot, pnpmWorkspaceYAML, outputDir }) {
24
+ async function start(projectConfig) {
25
+ const { packageRoot, packageJSON, projectAlias, projectId, projectRoot, pnpmWorkspaceYAML, outputDir } = projectConfig;
22
26
  const { name, version, exports: exports$1 } = await readPackageJSON(packageJSON);
23
27
  const codebase = getPackageName(name);
24
28
  const packagesToInline = await getWorkspacePackageNames(pnpmWorkspaceYAML);
@@ -33,13 +37,13 @@ async function start({ packageRoot, packageJSON, projectAlias, projectId, projec
33
37
  const dependencies = await flattenDependencies(harmonizeDependencies(await calculateDependencies(output)));
34
38
  // const { contentHash } = await pack(functionGroupDir, distDir)
35
39
  const firebaseJSON = await getFirebaseJSON(new URL("firebase.json", projectRoot));
36
- await prepareStart(codebase, projectAlias, projectId, {
40
+ await prepareStart(codebase, {
37
41
  name,
38
42
  type: "module",
39
43
  version,
40
44
  main,
41
45
  ...dependencies
42
- }, firebaseJSON, outputDir);
46
+ }, firebaseJSON, projectConfig);
43
47
  if (firstRun) {
44
48
  firstRun = false;
45
49
  runEmulator(codebase, projectAlias, projectId, outputDir, []).catch((error)=>{
@@ -53,11 +57,17 @@ async function start({ packageRoot, packageJSON, projectAlias, projectId, projec
53
57
  onBundleEnd
54
58
  });
55
59
  }
56
- async function prepareStart(codebase, projectAlias, projectId, packageJSON, firebaseJSON, outputDir) {
60
+ async function prepareStart(codebase, packageJSON, firebaseJSON, { projectAlias, projectId, outputDir, envFiles }) {
61
+ const envPrefix = `
62
+ NODE_OPTIONS='--enable-source-maps'
63
+ FUNCTION_CODEBASE='${codebase}'
64
+ ENTUR_PROJECT_ALIAS='${projectAlias}'
65
+ `.trimStart();
57
66
  await Promise.all([
58
67
  writeFirebaseJSON(codebase, firebaseJSON, outputDir),
59
68
  createFirebaseRC(projectAlias, projectId, outputDir),
60
- writePackageJSON(new URL("./package.json", outputDir), packageJSON)
69
+ writePackageJSON(new URL("./package.json", outputDir), packageJSON),
70
+ copyEnvFiles(envFiles, envPrefix, outputDir)
61
71
  ]);
62
72
  await linkDependencies(outputDir);
63
73
  }
@@ -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 };
@@ -1,8 +1,12 @@
1
- import { pathToFileURL } from 'node:url';
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 { readJSON } from '../utils/fs.js';
5
+ import { asyncFilterMap } from '../utils/async.js';
6
+ import { readJSON, exists } from '../utils/fs.js';
4
7
 
5
- async function resolveProjectConfig({ outputDir = "dist", project, cwd = process.cwd() } = {}) {
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: new URL("./", packageJSONUrl),
36
- projectRoot: new URL("./", pnpmWorkspaceYAML),
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.trimStart() + 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 };
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
@@ -1,3 +1,3 @@
1
- export { resolveProjectConfig } from './commands/utils.js';
1
+ export { copyEnvFiles, resolveProjectConfig } from './commands/utils.js';
2
2
  export { getExports } from './importExports/exports.js';
3
3
  export { getImports } from './importExports/imports.js';
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,13 +1,16 @@
1
1
  {
2
2
  "name": "@entur/function-tools",
3
3
  "type": "module",
4
- "version": "0.0.3",
4
+ "version": "0.0.5",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
8
8
  "bin": {
9
9
  "entur-functions": "./bin/enturFunctions.js"
10
10
  },
11
+ "exports": {
12
+ ".": "./lib/index.js"
13
+ },
11
14
  "dependencies": {
12
15
  "@rollup/plugin-swc": "^0.4.0",
13
16
  "@rollup/plugin-node-resolve": "^16.0.3",