@ebay-dt/bonfire-cli 0.1.0-alpha.0
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 +21 -0
- package/README.md +52 -0
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +5 -0
- package/dist/bin.js.map +1 -0
- package/dist/branch-prepare.d.ts +14 -0
- package/dist/branch-prepare.d.ts.map +1 -0
- package/dist/branch-prepare.js +51 -0
- package/dist/branch-prepare.js.map +1 -0
- package/dist/command.d.ts +16 -0
- package/dist/command.d.ts.map +1 -0
- package/dist/command.js +113 -0
- package/dist/command.js.map +1 -0
- package/dist/env-file.d.ts +25 -0
- package/dist/env-file.d.ts.map +1 -0
- package/dist/env-file.js +257 -0
- package/dist/env-file.js.map +1 -0
- package/dist/gitignore.d.ts +5 -0
- package/dist/gitignore.d.ts.map +1 -0
- package/dist/gitignore.js +95 -0
- package/dist/gitignore.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/prepare.d.ts +17 -0
- package/dist/prepare.d.ts.map +1 -0
- package/dist/prepare.js +95 -0
- package/dist/prepare.js.map +1 -0
- package/package.json +52 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Bonfire contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# `@ebay-dt/bonfire-cli`
|
|
2
|
+
|
|
3
|
+
The Bonfire preparation command for local development.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
Add the package to an application and run this before Next.js development:
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"scripts": {
|
|
12
|
+
"dev": "bonfire prepare && next dev"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
bonfire prepare [--root <application-root>]
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`prepare` validates `BF_SESSION_SECRET` from the process environment when it
|
|
22
|
+
is supplied. Otherwise it safely creates or updates `<root>/.env.local` with
|
|
23
|
+
32 random bytes encoded as hexadecimal, without rotating an existing valid
|
|
24
|
+
secret. It also ensures `.env.local` is ignored by `<root>/.gitignore`.
|
|
25
|
+
|
|
26
|
+
For values already in `.env.local`, the command accepts only literal values:
|
|
27
|
+
unquoted `#`, `$` variable expansion, and malformed or multiline quotes are
|
|
28
|
+
rejected. This keeps the value validated by Bonfire identical to the value
|
|
29
|
+
loaded by Next.js. Put secrets requiring other dotenv syntax in the process
|
|
30
|
+
environment instead.
|
|
31
|
+
|
|
32
|
+
The command never invokes GitHub CLI, loads application configuration, or
|
|
33
|
+
prints the secret. It exits with `0` on success, `1` on validation or
|
|
34
|
+
filesystem failure, and `2` for invalid command syntax.
|
|
35
|
+
|
|
36
|
+
## Branch preparation
|
|
37
|
+
|
|
38
|
+
Before starting Next.js in development, run:
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
bonfire branch prepare --root <application-root> --hostname <hostname>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The command loads environment values with Next-compatible precedence and
|
|
45
|
+
honors `BF_DISABLE_AUTO_BRANCH_SWITCH=true`. Disabled mode performs no GitHub
|
|
46
|
+
CLI or Git operation. When switching is enabled, `BF_PROTOTYPE_BASE_BRANCH`
|
|
47
|
+
overrides the default `main` base branch and must name an existing local or
|
|
48
|
+
fetched branch; preparation fails rather than silently using another branch. When enabled, an already-authenticated GitHub CLI user
|
|
49
|
+
is prepared on their login branch through `@ebay-dt/bonfire-node`. Missing or
|
|
50
|
+
unauthenticated GitHub CLI is a successful deferred result; other failures
|
|
51
|
+
return exit code `1`. The command never starts interactive authentication or
|
|
52
|
+
prints identity, credentials, paths, or Git output.
|
package/dist/bin.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":""}
|
package/dist/bin.js
ADDED
package/dist/bin.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,MAAM,QAAQ,GAAG,MAAM,GAAG,EAAE,CAAC;AAC7B,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type GitHubCliClientLike, type PrototypeLifecycle } from "@ebay-dt/bonfire-node";
|
|
2
|
+
import type { BranchPrepareCommandOptions } from "./command.js";
|
|
3
|
+
export type CliEnvironmentLoader = (root: string) => Readonly<Record<string, string | undefined>>;
|
|
4
|
+
export type BranchPrepareDependencies = {
|
|
5
|
+
environment?: Readonly<Record<string, string | undefined>>;
|
|
6
|
+
loadEnvironment?: CliEnvironmentLoader;
|
|
7
|
+
githubCli?: GitHubCliClientLike;
|
|
8
|
+
lifecycle?: Pick<PrototypeLifecycle, "prepareBranch">;
|
|
9
|
+
};
|
|
10
|
+
export declare class BranchPrepareError extends Error {
|
|
11
|
+
constructor(message: string);
|
|
12
|
+
}
|
|
13
|
+
export declare function runBranchPrepare(options: BranchPrepareCommandOptions, dependencies: BranchPrepareDependencies): Promise<number>;
|
|
14
|
+
//# sourceMappingURL=branch-prepare.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branch-prepare.d.ts","sourceRoot":"","sources":["../src/branch-prepare.ts"],"names":[],"mappings":"AAKA,OAAO,EAIL,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACxB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC;AAEhE,MAAM,MAAM,oBAAoB,GAAG,CACjC,IAAI,EAAE,MAAM,KACT,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;AAElD,MAAM,MAAM,yBAAyB,GAAG;IACtC,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IAC3D,eAAe,CAAC,EAAE,oBAAoB,CAAC;IACvC,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,SAAS,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC;CACvD,CAAC;AAEF,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAMD,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,2BAA2B,EACpC,YAAY,EAAE,yBAAyB,GACtC,OAAO,CAAC,MAAM,CAAC,CAiDjB"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import nextEnv from "@next/env";
|
|
2
|
+
import { parseAutomaticBranchSwitchSetting, parseHostname, } from "@ebay-dt/bonfire-core";
|
|
3
|
+
import { GitHubCliClient, GitHubCliError, LocalPrototypeLifecycle, } from "@ebay-dt/bonfire-node";
|
|
4
|
+
import { resolve } from "node:path";
|
|
5
|
+
export class BranchPrepareError extends Error {
|
|
6
|
+
constructor(message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "BranchPrepareError";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function loadEnvironment(root) {
|
|
12
|
+
return nextEnv.loadEnvConfig(root, true, undefined, false).combinedEnv;
|
|
13
|
+
}
|
|
14
|
+
export async function runBranchPrepare(options, dependencies) {
|
|
15
|
+
const root = resolve(options.root);
|
|
16
|
+
const environment = dependencies.environment ??
|
|
17
|
+
dependencies.loadEnvironment?.(root) ??
|
|
18
|
+
loadEnvironment(root);
|
|
19
|
+
const mode = parseAutomaticBranchSwitchSetting(environment.BF_DISABLE_AUTO_BRANCH_SWITCH);
|
|
20
|
+
const hostname = parseHostname(options.hostname);
|
|
21
|
+
if (mode === "disabled") {
|
|
22
|
+
console.log("Automatic branch switching is disabled.");
|
|
23
|
+
return 0;
|
|
24
|
+
}
|
|
25
|
+
const githubCli = dependencies.githubCli ?? new GitHubCliClient({ hostname });
|
|
26
|
+
let identity;
|
|
27
|
+
try {
|
|
28
|
+
identity = await githubCli.getUser();
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
if (error instanceof GitHubCliError &&
|
|
32
|
+
(error.reason === "missing" || error.reason === "unauthenticated")) {
|
|
33
|
+
console.log("Branch preparation deferred; GitHub CLI authentication is not available.");
|
|
34
|
+
return 0;
|
|
35
|
+
}
|
|
36
|
+
throw new BranchPrepareError("Unable to resolve GitHub CLI identity.");
|
|
37
|
+
}
|
|
38
|
+
const lifecycle = dependencies.lifecycle ??
|
|
39
|
+
new LocalPrototypeLifecycle({
|
|
40
|
+
repositoryRoot: root,
|
|
41
|
+
primaryBranch: environment.BF_PROTOTYPE_BASE_BRANCH,
|
|
42
|
+
automaticBranchSwitch: mode,
|
|
43
|
+
});
|
|
44
|
+
const result = await lifecycle.prepareBranch(identity);
|
|
45
|
+
if (!result.ok) {
|
|
46
|
+
throw new BranchPrepareError(`Branch preparation failed with ${result.error.code}.`);
|
|
47
|
+
}
|
|
48
|
+
console.log("Branch preparation complete.");
|
|
49
|
+
return 0;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=branch-prepare.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branch-prepare.js","sourceRoot":"","sources":["../src/branch-prepare.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,WAAW,CAAC;AAChC,OAAO,EACL,iCAAiC,EACjC,aAAa,GACd,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,eAAe,EACf,cAAc,EACd,uBAAuB,GAGxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,SAAS,eAAe,CAAC,IAAY;IACnC,OAAO,OAAO,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,WAAW,CAAC;AACzE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAoC,EACpC,YAAuC;IAEvC,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,WAAW,GACf,YAAY,CAAC,WAAW;QACxB,YAAY,CAAC,eAAe,EAAE,CAAC,IAAI,CAAC;QACpC,eAAe,CAAC,IAAI,CAAC,CAAC;IACxB,MAAM,IAAI,GAAG,iCAAiC,CAC5C,WAAW,CAAC,6BAA6B,CAC1C,CAAC;IACF,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAEjD,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;QACvD,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,SAAS,GAAG,YAAY,CAAC,SAAS,IAAI,IAAI,eAAe,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC9E,IAAI,QAAQ,CAAC;IACb,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE,CAAC;IACvC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IACE,KAAK,YAAY,cAAc;YAC/B,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,KAAK,iBAAiB,CAAC,EAClE,CAAC;YACD,OAAO,CAAC,GAAG,CACT,0EAA0E,CAC3E,CAAC;YACF,OAAO,CAAC,CAAC;QACX,CAAC;QACD,MAAM,IAAI,kBAAkB,CAAC,wCAAwC,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,SAAS,GACb,YAAY,CAAC,SAAS;QACtB,IAAI,uBAAuB,CAAC;YAC1B,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,WAAW,CAAC,wBAAwB;YACnD,qBAAqB,EAAE,IAAI;SAC5B,CAAC,CAAC;IACL,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IACvD,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,MAAM,IAAI,kBAAkB,CAC1B,kCAAkC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,CACvD,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;IAC5C,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type BranchPrepareDependencies } from "./branch-prepare.js";
|
|
2
|
+
export declare class CliSyntaxError extends Error {
|
|
3
|
+
constructor(message: string);
|
|
4
|
+
}
|
|
5
|
+
export type PrepareCommandOptions = {
|
|
6
|
+
root: string;
|
|
7
|
+
};
|
|
8
|
+
export type BranchPrepareCommandOptions = {
|
|
9
|
+
root: string;
|
|
10
|
+
hostname: string;
|
|
11
|
+
};
|
|
12
|
+
type CliCommandOptions = PrepareCommandOptions | BranchPrepareCommandOptions;
|
|
13
|
+
export declare function parseArgs(argv: readonly string[]): CliCommandOptions;
|
|
14
|
+
export declare function run(argv?: readonly string[], dependencies?: BranchPrepareDependencies): Promise<number>;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,yBAAyB,EAC/B,MAAM,qBAAqB,CAAC;AAE7B,qBAAa,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,KAAK,iBAAiB,GAAG,qBAAqB,GAAG,2BAA2B,CAAC;AA6E7E,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,iBAAiB,CAQpE;AAED,wBAAsB,GAAG,CACvB,IAAI,GAAE,SAAS,MAAM,EAA0B,EAC/C,YAAY,GAAE,yBAA8B,GAC3C,OAAO,CAAC,MAAM,CAAC,CAuCjB"}
|
package/dist/command.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { prepare, PrepareError } from "./prepare.js";
|
|
2
|
+
import { BranchPrepareError, runBranchPrepare, } from "./branch-prepare.js";
|
|
3
|
+
export class CliSyntaxError extends Error {
|
|
4
|
+
constructor(message) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = "CliSyntaxError";
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
function parseRootOption(argv, start) {
|
|
10
|
+
const value = argv[start + 1];
|
|
11
|
+
if (!value || value.startsWith("--")) {
|
|
12
|
+
throw new CliSyntaxError("The --root option requires a value");
|
|
13
|
+
}
|
|
14
|
+
return { root: value, nextIndex: start + 2 };
|
|
15
|
+
}
|
|
16
|
+
function parsePrepareArgs(argv) {
|
|
17
|
+
let root = process.cwd();
|
|
18
|
+
let rootProvided = false;
|
|
19
|
+
for (let index = 1; index < argv.length;) {
|
|
20
|
+
if (argv[index] !== "--root") {
|
|
21
|
+
throw new CliSyntaxError(`Unknown option: ${argv[index]}`);
|
|
22
|
+
}
|
|
23
|
+
if (rootProvided) {
|
|
24
|
+
throw new CliSyntaxError("The --root option may only be provided once");
|
|
25
|
+
}
|
|
26
|
+
const parsed = parseRootOption(argv, index);
|
|
27
|
+
root = parsed.root;
|
|
28
|
+
rootProvided = true;
|
|
29
|
+
index = parsed.nextIndex;
|
|
30
|
+
}
|
|
31
|
+
return { root };
|
|
32
|
+
}
|
|
33
|
+
function parseBranchPrepareArgs(argv) {
|
|
34
|
+
let root = process.cwd();
|
|
35
|
+
let hostname;
|
|
36
|
+
let rootProvided = false;
|
|
37
|
+
let hostnameProvided = false;
|
|
38
|
+
for (let index = 2; index < argv.length;) {
|
|
39
|
+
const option = argv[index];
|
|
40
|
+
if (option === "--root") {
|
|
41
|
+
if (rootProvided) {
|
|
42
|
+
throw new CliSyntaxError("The --root option may only be provided once");
|
|
43
|
+
}
|
|
44
|
+
const parsed = parseRootOption(argv, index);
|
|
45
|
+
root = parsed.root;
|
|
46
|
+
rootProvided = true;
|
|
47
|
+
index = parsed.nextIndex;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (option === "--hostname") {
|
|
51
|
+
if (hostnameProvided) {
|
|
52
|
+
throw new CliSyntaxError("The --hostname option may only be provided once");
|
|
53
|
+
}
|
|
54
|
+
const value = argv[index + 1];
|
|
55
|
+
if (!value || value.startsWith("--")) {
|
|
56
|
+
throw new CliSyntaxError("The --hostname option requires a value");
|
|
57
|
+
}
|
|
58
|
+
hostname = value;
|
|
59
|
+
hostnameProvided = true;
|
|
60
|
+
index += 2;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
throw new CliSyntaxError(`Unknown option: ${option}`);
|
|
64
|
+
}
|
|
65
|
+
if (hostname === undefined) {
|
|
66
|
+
throw new CliSyntaxError("Usage: bonfire branch prepare --root <application-root> --hostname <hostname>");
|
|
67
|
+
}
|
|
68
|
+
return { root, hostname };
|
|
69
|
+
}
|
|
70
|
+
export function parseArgs(argv) {
|
|
71
|
+
if (argv[0] === "prepare")
|
|
72
|
+
return parsePrepareArgs(argv);
|
|
73
|
+
if (argv[0] === "branch" && argv[1] === "prepare") {
|
|
74
|
+
return parseBranchPrepareArgs(argv);
|
|
75
|
+
}
|
|
76
|
+
throw new CliSyntaxError("Usage: bonfire prepare [--root <application-root>] | bonfire branch prepare --root <application-root> --hostname <hostname>");
|
|
77
|
+
}
|
|
78
|
+
export async function run(argv = process.argv.slice(2), dependencies = {}) {
|
|
79
|
+
const isBranchPrepare = argv[0] === "branch";
|
|
80
|
+
try {
|
|
81
|
+
const options = parseArgs(argv);
|
|
82
|
+
if ("hostname" in options) {
|
|
83
|
+
return await runBranchPrepare(options, dependencies);
|
|
84
|
+
}
|
|
85
|
+
const result = await prepare(options);
|
|
86
|
+
const descriptions = {
|
|
87
|
+
environment: "the process environment",
|
|
88
|
+
existing: ".env.local",
|
|
89
|
+
generated: "a newly generated value in .env.local",
|
|
90
|
+
};
|
|
91
|
+
console.log(`Bonfire preparation complete; BF_SESSION_SECRET came from ${descriptions[result.source]}.`);
|
|
92
|
+
return 0;
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
if (error instanceof CliSyntaxError) {
|
|
96
|
+
console.error(`bonfire: ${error.message}`);
|
|
97
|
+
return 2;
|
|
98
|
+
}
|
|
99
|
+
if (isBranchPrepare) {
|
|
100
|
+
const message = error instanceof BranchPrepareError
|
|
101
|
+
? error.message
|
|
102
|
+
: "Unable to load branch preparation configuration.";
|
|
103
|
+
console.error(`bonfire branch prepare failed: ${message}`);
|
|
104
|
+
return 1;
|
|
105
|
+
}
|
|
106
|
+
const message = error instanceof PrepareError || error instanceof Error
|
|
107
|
+
? error.message
|
|
108
|
+
: "an unknown error occurred";
|
|
109
|
+
console.error(`bonfire prepare failed: ${message}`);
|
|
110
|
+
return 1;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.js","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export declare const BONFIRE_SESSION_SECRET = "BF_SESSION_SECRET";
|
|
2
|
+
export declare const SESSION_SECRET_BYTES = 32;
|
|
3
|
+
export type SecretGenerator = () => string;
|
|
4
|
+
export type ParsedEnvEntry = {
|
|
5
|
+
key: string;
|
|
6
|
+
value: string;
|
|
7
|
+
line: number;
|
|
8
|
+
valueStart: number;
|
|
9
|
+
valueEnd: number;
|
|
10
|
+
quote: '"' | "'" | null;
|
|
11
|
+
};
|
|
12
|
+
export declare class SessionSecretError extends Error {
|
|
13
|
+
constructor(message?: string);
|
|
14
|
+
}
|
|
15
|
+
export declare class SessionSecretSyntaxError extends Error {
|
|
16
|
+
constructor(message?: string);
|
|
17
|
+
}
|
|
18
|
+
export declare function validateSessionSecret(value: unknown): asserts value is string;
|
|
19
|
+
export declare function generateSessionSecret(): string;
|
|
20
|
+
export declare function parseEnvEntries(content: string): ParsedEnvEntry[];
|
|
21
|
+
export declare function validateLiteralSessionSecretEntry(content: string, entry: ParsedEnvEntry): void;
|
|
22
|
+
export declare function replaceOrAppendSecret(content: string, secret: string): string;
|
|
23
|
+
export declare function readEnvFile(path: string): Promise<string | null>;
|
|
24
|
+
export declare function writeFileAtomically(path: string, content: string, mode?: number): Promise<void>;
|
|
25
|
+
//# sourceMappingURL=env-file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-file.d.ts","sourceRoot":"","sources":["../src/env-file.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,sBAAsB,sBAAsB,CAAC;AAC1D,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAEvC,MAAM,MAAM,eAAe,GAAG,MAAM,MAAM,CAAC;AAE3C,MAAM,MAAM,cAAc,GAAG;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,GAAG,GAAG,GAAG,GAAG,IAAI,CAAC;CACzB,CAAC;AAOF,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,YACE,OAAO,SAA2D,EAInE;CACF;AAED,qBAAa,wBAAyB,SAAQ,KAAK;IACjD,YAAY,OAAO,SAA+C,EAGjE;CACF;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,MAAM,CAO7E;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AA4GD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,EAAE,CAgBjE;AAED,wBAAgB,iCAAiC,CAC/C,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,cAAc,GACpB,IAAI,CA6CN;AAQD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAsC7E;AAoBD,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAItE;AAED,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,SAAQ,GACX,OAAO,CAAC,IAAI,CAAC,CAoBf"}
|
package/dist/env-file.js
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { chmod, lstat, open, readFile, rename, unlink } from "node:fs/promises";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
export const BONFIRE_SESSION_SECRET = "BF_SESSION_SECRET";
|
|
5
|
+
export const SESSION_SECRET_BYTES = 32;
|
|
6
|
+
export class SessionSecretError extends Error {
|
|
7
|
+
constructor(message = "BF_SESSION_SECRET must contain at least 32 UTF-8 bytes") {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "SessionSecretError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export class SessionSecretSyntaxError extends Error {
|
|
13
|
+
constructor(message = "BF_SESSION_SECRET must use a literal value") {
|
|
14
|
+
super(message);
|
|
15
|
+
this.name = "SessionSecretSyntaxError";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function validateSessionSecret(value) {
|
|
19
|
+
if (typeof value !== "string" ||
|
|
20
|
+
Buffer.byteLength(value, "utf8") < SESSION_SECRET_BYTES) {
|
|
21
|
+
throw new SessionSecretError();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export function generateSessionSecret() {
|
|
25
|
+
return randomBytes(SESSION_SECRET_BYTES).toString("hex");
|
|
26
|
+
}
|
|
27
|
+
function syntaxError(message) {
|
|
28
|
+
throw new SessionSecretSyntaxError(`BF_SESSION_SECRET ${message}`);
|
|
29
|
+
}
|
|
30
|
+
function splitLines(content) {
|
|
31
|
+
const lines = [];
|
|
32
|
+
let start = 0;
|
|
33
|
+
for (let index = 0; index < content.length; index += 1) {
|
|
34
|
+
if (content[index] !== "\n" && content[index] !== "\r")
|
|
35
|
+
continue;
|
|
36
|
+
const ending = content[index] === "\r" && content[index + 1] === "\n"
|
|
37
|
+
? "\r\n"
|
|
38
|
+
: (content[index] ?? "");
|
|
39
|
+
lines.push({ text: content.slice(start, index), ending });
|
|
40
|
+
start = index + ending.length;
|
|
41
|
+
if (ending.length === 2)
|
|
42
|
+
index += 1;
|
|
43
|
+
}
|
|
44
|
+
if (start < content.length)
|
|
45
|
+
lines.push({ text: content.slice(start), ending: "" });
|
|
46
|
+
return lines;
|
|
47
|
+
}
|
|
48
|
+
function firstUnescapedQuote(text, quote) {
|
|
49
|
+
for (let index = 1; index < text.length; index += 1) {
|
|
50
|
+
if (text[index] !== quote || text[index - 1] === "\\")
|
|
51
|
+
continue;
|
|
52
|
+
let slashes = 0;
|
|
53
|
+
for (let previous = index - 1; previous >= 0 && text[previous] === "\\"; previous -= 1) {
|
|
54
|
+
slashes += 1;
|
|
55
|
+
}
|
|
56
|
+
if (slashes % 2 === 0)
|
|
57
|
+
return index;
|
|
58
|
+
}
|
|
59
|
+
return -1;
|
|
60
|
+
}
|
|
61
|
+
function decodeQuotedValue(value, quote) {
|
|
62
|
+
if (quote === "'")
|
|
63
|
+
return value;
|
|
64
|
+
return value.replace(/\\([\\"nrt])/g, (_match, escaped) => {
|
|
65
|
+
switch (escaped) {
|
|
66
|
+
case "n":
|
|
67
|
+
return "\n";
|
|
68
|
+
case "r":
|
|
69
|
+
return "\r";
|
|
70
|
+
case "t":
|
|
71
|
+
return "\t";
|
|
72
|
+
default:
|
|
73
|
+
return escaped;
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
function parseValue(line, afterEquals) {
|
|
78
|
+
let start = afterEquals;
|
|
79
|
+
while (/\s/.test(line[start] ?? ""))
|
|
80
|
+
start += 1;
|
|
81
|
+
if (start >= line.length || line[start] === "#") {
|
|
82
|
+
return {
|
|
83
|
+
value: "",
|
|
84
|
+
valueStart: afterEquals,
|
|
85
|
+
valueEnd: afterEquals,
|
|
86
|
+
quote: null,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
const firstCharacter = line[start];
|
|
90
|
+
const quote = firstCharacter === '"' ? '"' : firstCharacter === "'" ? "'" : null;
|
|
91
|
+
if (quote) {
|
|
92
|
+
const close = firstUnescapedQuote(line.slice(start), quote);
|
|
93
|
+
if (close >= 0) {
|
|
94
|
+
const end = start + close + 1;
|
|
95
|
+
const rest = line.slice(end).trimStart();
|
|
96
|
+
if (rest.length === 0 || rest.startsWith("#")) {
|
|
97
|
+
return {
|
|
98
|
+
value: decodeQuotedValue(line.slice(start + 1, end - 1), quote),
|
|
99
|
+
valueStart: start,
|
|
100
|
+
valueEnd: end,
|
|
101
|
+
quote,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
let end = line.length;
|
|
107
|
+
for (let index = start; index < line.length; index += 1) {
|
|
108
|
+
if (line[index] === "#") {
|
|
109
|
+
end = index;
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
while (end > start && /\s/.test(line[end - 1] ?? ""))
|
|
114
|
+
end -= 1;
|
|
115
|
+
return {
|
|
116
|
+
value: line.slice(start, end),
|
|
117
|
+
valueStart: start,
|
|
118
|
+
valueEnd: end,
|
|
119
|
+
quote: null,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
export function parseEnvEntries(content) {
|
|
123
|
+
const entries = [];
|
|
124
|
+
for (const [index, line] of splitLines(content).entries()) {
|
|
125
|
+
const match = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/.exec(line.text);
|
|
126
|
+
if (!match)
|
|
127
|
+
continue;
|
|
128
|
+
const fullMatch = match[0];
|
|
129
|
+
const key = match[1];
|
|
130
|
+
if (!fullMatch || !key)
|
|
131
|
+
continue;
|
|
132
|
+
const afterEquals = fullMatch.length;
|
|
133
|
+
const parsed = parseValue(line.text, afterEquals);
|
|
134
|
+
entries.push({ key, line: index, ...parsed });
|
|
135
|
+
}
|
|
136
|
+
return entries;
|
|
137
|
+
}
|
|
138
|
+
export function validateLiteralSessionSecretEntry(content, entry) {
|
|
139
|
+
const line = splitLines(content)[entry.line]?.text;
|
|
140
|
+
if (line === undefined)
|
|
141
|
+
syntaxError("has an invalid assignment");
|
|
142
|
+
const match = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/.exec(line);
|
|
143
|
+
if (!match || match[1] !== BONFIRE_SESSION_SECRET) {
|
|
144
|
+
syntaxError("has an invalid assignment");
|
|
145
|
+
}
|
|
146
|
+
const rawValue = line.slice(match[0].length).trim();
|
|
147
|
+
if (rawValue.length === 0 || rawValue.startsWith("#"))
|
|
148
|
+
return;
|
|
149
|
+
if (rawValue.startsWith('"') ||
|
|
150
|
+
rawValue.startsWith("'") ||
|
|
151
|
+
rawValue.startsWith("`")) {
|
|
152
|
+
if (rawValue.startsWith("`")) {
|
|
153
|
+
syntaxError("must not use unsupported backtick quoting");
|
|
154
|
+
}
|
|
155
|
+
const quote = rawValue[0] === '"' ? '"' : "'";
|
|
156
|
+
const close = firstUnescapedQuote(rawValue, quote);
|
|
157
|
+
if (close < 0)
|
|
158
|
+
syntaxError("must not contain an unterminated or multiline quote");
|
|
159
|
+
const quotedValue = rawValue.slice(1, close);
|
|
160
|
+
const remainder = rawValue.slice(close + 1).trimStart();
|
|
161
|
+
if (remainder.length > 0 && !remainder.startsWith("#")) {
|
|
162
|
+
syntaxError("must use a complete quoted value");
|
|
163
|
+
}
|
|
164
|
+
if (quotedValue.includes("$")) {
|
|
165
|
+
syntaxError("must not use variable expansion");
|
|
166
|
+
}
|
|
167
|
+
if (quotedValue.includes("\\")) {
|
|
168
|
+
syntaxError("must not use escape sequences");
|
|
169
|
+
}
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
if (rawValue.includes("#")) {
|
|
173
|
+
syntaxError("must not contain # in an unquoted value");
|
|
174
|
+
}
|
|
175
|
+
if (rawValue.includes("$")) {
|
|
176
|
+
syntaxError("must not use variable expansion");
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function newlineFor(content) {
|
|
180
|
+
if (content.includes("\r\n"))
|
|
181
|
+
return "\r\n";
|
|
182
|
+
if (content.includes("\r"))
|
|
183
|
+
return "\r";
|
|
184
|
+
return "\n";
|
|
185
|
+
}
|
|
186
|
+
export function replaceOrAppendSecret(content, secret) {
|
|
187
|
+
validateSessionSecret(secret);
|
|
188
|
+
const lines = splitLines(content);
|
|
189
|
+
const entries = parseEnvEntries(content).filter((entry) => entry.key === BONFIRE_SESSION_SECRET);
|
|
190
|
+
if (entries.length > 1) {
|
|
191
|
+
throw new SessionSecretError("Multiple BF_SESSION_SECRET assignments were found");
|
|
192
|
+
}
|
|
193
|
+
if (entries.length === 1) {
|
|
194
|
+
const entry = entries[0];
|
|
195
|
+
if (!entry)
|
|
196
|
+
throw new SessionSecretError("BF_SESSION_SECRET assignment was not found");
|
|
197
|
+
const line = lines[entry.line];
|
|
198
|
+
if (!line)
|
|
199
|
+
throw new SessionSecretError("BF_SESSION_SECRET line was not found");
|
|
200
|
+
const replacement = entry.quote
|
|
201
|
+
? `${entry.quote}${secret}${entry.quote}`
|
|
202
|
+
: secret;
|
|
203
|
+
line.text = `${line.text.slice(0, entry.valueStart)}${replacement}${line.text.slice(entry.valueEnd)}`;
|
|
204
|
+
const result = lines.map(({ text, ending }) => text + ending).join("");
|
|
205
|
+
return result.endsWith("\n") || result.endsWith("\r")
|
|
206
|
+
? result
|
|
207
|
+
: `${result}${newlineFor(content)}`;
|
|
208
|
+
}
|
|
209
|
+
const newline = newlineFor(content);
|
|
210
|
+
const suffix = content.length === 0 || content.endsWith("\n") || content.endsWith("\r")
|
|
211
|
+
? ""
|
|
212
|
+
: newline;
|
|
213
|
+
return `${content}${suffix}${BONFIRE_SESSION_SECRET}=${secret}${newline}`;
|
|
214
|
+
}
|
|
215
|
+
async function existingMode(path) {
|
|
216
|
+
try {
|
|
217
|
+
const stats = await lstat(path);
|
|
218
|
+
if (stats.isSymbolicLink())
|
|
219
|
+
throw new Error(`Refusing to follow symlink: ${path}`);
|
|
220
|
+
return stats.mode & 0o7777;
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
if (error &&
|
|
224
|
+
typeof error === "object" &&
|
|
225
|
+
"code" in error &&
|
|
226
|
+
error.code === "ENOENT")
|
|
227
|
+
return undefined;
|
|
228
|
+
throw error;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
export async function readEnvFile(path) {
|
|
232
|
+
const mode = await existingMode(path);
|
|
233
|
+
if (mode === undefined)
|
|
234
|
+
return null;
|
|
235
|
+
return readFile(path, "utf8");
|
|
236
|
+
}
|
|
237
|
+
export async function writeFileAtomically(path, content, mode = 0o600) {
|
|
238
|
+
const currentMode = await existingMode(path);
|
|
239
|
+
const fileMode = currentMode ?? mode;
|
|
240
|
+
const temporaryPath = join(dirname(path), `.${path.split(/[\\/]/).pop() ?? "bonfire"}.tmp-${process.pid}-${randomBytes(8).toString("hex")}`);
|
|
241
|
+
let handle;
|
|
242
|
+
try {
|
|
243
|
+
handle = await open(temporaryPath, "wx", fileMode);
|
|
244
|
+
await handle.writeFile(content, "utf8");
|
|
245
|
+
await handle.close();
|
|
246
|
+
handle = undefined;
|
|
247
|
+
await rename(temporaryPath, path);
|
|
248
|
+
if (currentMode !== undefined)
|
|
249
|
+
await chmod(path, currentMode);
|
|
250
|
+
}
|
|
251
|
+
finally {
|
|
252
|
+
if (handle)
|
|
253
|
+
await handle.close().catch(() => undefined);
|
|
254
|
+
await unlink(temporaryPath).catch(() => undefined);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
//# sourceMappingURL=env-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-file.js","sourceRoot":"","sources":["../src/env-file.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const BONFIRE_GITIGNORE_BLOCK = "# Bonfire local secrets\n.env.local";
|
|
2
|
+
export declare function isEnvLocalIgnored(content: string): boolean;
|
|
3
|
+
export declare function addManagedGitignoreBlock(content: string): string;
|
|
4
|
+
export declare function ensureEnvLocalIgnored(root: string): Promise<boolean>;
|
|
5
|
+
//# sourceMappingURL=gitignore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitignore.d.ts","sourceRoot":"","sources":["../src/gitignore.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,uBAAuB,wCAAwC,CAAC;AAmC7E,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAY1D;AAQD,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAQhE;AAiBD,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAU1E"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { lstat } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { readEnvFile, writeFileAtomically } from "./env-file.js";
|
|
4
|
+
export const BONFIRE_GITIGNORE_BLOCK = "# Bonfire local secrets\n.env.local";
|
|
5
|
+
function globRegex(pattern) {
|
|
6
|
+
let expression = "";
|
|
7
|
+
for (let index = 0; index < pattern.length; index += 1) {
|
|
8
|
+
const character = pattern[index];
|
|
9
|
+
if (!character)
|
|
10
|
+
continue;
|
|
11
|
+
if (character === "*" && pattern[index + 1] === "*") {
|
|
12
|
+
expression += ".*";
|
|
13
|
+
index += 1;
|
|
14
|
+
}
|
|
15
|
+
else if (character === "*") {
|
|
16
|
+
expression += "[^/]*";
|
|
17
|
+
}
|
|
18
|
+
else if (character === "?") {
|
|
19
|
+
expression += "[^/]";
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
expression += character.replace(/[\\^$+?.()|[\]{}]/g, "\\$&");
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return new RegExp(`^${expression}$`);
|
|
26
|
+
}
|
|
27
|
+
function patternMatchesTarget(pattern, target) {
|
|
28
|
+
let normalized = pattern.trimEnd();
|
|
29
|
+
if (normalized.startsWith("/"))
|
|
30
|
+
normalized = normalized.slice(1);
|
|
31
|
+
if (normalized.length === 0)
|
|
32
|
+
return false;
|
|
33
|
+
if (normalized.startsWith("**/")) {
|
|
34
|
+
normalized = normalized.slice(3);
|
|
35
|
+
return globRegex(normalized).test(target);
|
|
36
|
+
}
|
|
37
|
+
if (!normalized.includes("/"))
|
|
38
|
+
return globRegex(normalized).test(target);
|
|
39
|
+
return globRegex(normalized).test(target);
|
|
40
|
+
}
|
|
41
|
+
export function isEnvLocalIgnored(content) {
|
|
42
|
+
let ignored = false;
|
|
43
|
+
for (const line of content.split(/\r\n|\n|\r/)) {
|
|
44
|
+
const trimmed = line.trim();
|
|
45
|
+
if (!trimmed || trimmed.startsWith("#"))
|
|
46
|
+
continue;
|
|
47
|
+
const negated = trimmed.startsWith("!") && !trimmed.startsWith("\\!");
|
|
48
|
+
const pattern = negated ? trimmed.slice(1) : trimmed;
|
|
49
|
+
if (!patternMatchesTarget(pattern, ".env.local"))
|
|
50
|
+
continue;
|
|
51
|
+
ignored = !negated;
|
|
52
|
+
}
|
|
53
|
+
return ignored;
|
|
54
|
+
}
|
|
55
|
+
function newlineFor(content) {
|
|
56
|
+
if (content.includes("\r\n"))
|
|
57
|
+
return "\r\n";
|
|
58
|
+
if (content.includes("\r"))
|
|
59
|
+
return "\r";
|
|
60
|
+
return "\n";
|
|
61
|
+
}
|
|
62
|
+
export function addManagedGitignoreBlock(content) {
|
|
63
|
+
if (isEnvLocalIgnored(content))
|
|
64
|
+
return content;
|
|
65
|
+
const newline = newlineFor(content);
|
|
66
|
+
const separator = content.length === 0 || content.endsWith("\n") || content.endsWith("\r")
|
|
67
|
+
? ""
|
|
68
|
+
: newline;
|
|
69
|
+
return `${content}${separator}${BONFIRE_GITIGNORE_BLOCK.replaceAll("\n", newline)}${newline}`;
|
|
70
|
+
}
|
|
71
|
+
async function isSymlink(path) {
|
|
72
|
+
try {
|
|
73
|
+
return (await lstat(path)).isSymbolicLink();
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
if (error &&
|
|
77
|
+
typeof error === "object" &&
|
|
78
|
+
"code" in error &&
|
|
79
|
+
error.code === "ENOENT")
|
|
80
|
+
return false;
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
export async function ensureEnvLocalIgnored(root) {
|
|
85
|
+
const path = join(root, ".gitignore");
|
|
86
|
+
const content = await readEnvFile(path);
|
|
87
|
+
if (content !== null && isEnvLocalIgnored(content))
|
|
88
|
+
return false;
|
|
89
|
+
if (await isSymlink(path))
|
|
90
|
+
throw new Error("Refusing to modify symlinked .gitignore");
|
|
91
|
+
const nextContent = addManagedGitignoreBlock(content ?? "");
|
|
92
|
+
await writeFileAtomically(path, nextContent, 0o644);
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=gitignore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitignore.js","sourceRoot":"","sources":["../src/gitignore.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type SecretGenerator } from "./env-file.js";
|
|
2
|
+
export type PrepareSecretSource = "environment" | "existing" | "generated";
|
|
3
|
+
export type PrepareOptions = {
|
|
4
|
+
root: string;
|
|
5
|
+
environment?: Readonly<Record<string, string | undefined>>;
|
|
6
|
+
generateSecret?: SecretGenerator;
|
|
7
|
+
};
|
|
8
|
+
export type PrepareResult = {
|
|
9
|
+
source: PrepareSecretSource;
|
|
10
|
+
envFilePath: string | null;
|
|
11
|
+
gitignoreChanged: boolean;
|
|
12
|
+
};
|
|
13
|
+
export declare class PrepareError extends Error {
|
|
14
|
+
constructor(message: string);
|
|
15
|
+
}
|
|
16
|
+
export declare function prepare(options: PrepareOptions): Promise<PrepareResult>;
|
|
17
|
+
//# sourceMappingURL=prepare.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prepare.d.ts","sourceRoot":"","sources":["../src/prepare.ts"],"names":[],"mappings":"AACA,OAAO,EASL,KAAK,eAAe,EACrB,MAAM,eAAe,CAAC;AAGvB,MAAM,MAAM,mBAAmB,GAAG,aAAa,GAAG,UAAU,GAAG,WAAW,CAAC;AAE3E,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IAC3D,cAAc,CAAC,EAAE,eAAe,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,mBAAmB,CAAC;IAC5B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,gBAAgB,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,qBAAa,YAAa,SAAQ,KAAK;IACrC,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAQD,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CA8E7E"}
|
package/dist/prepare.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { join, resolve } from "node:path";
|
|
2
|
+
import { generateSessionSecret, parseEnvEntries, BONFIRE_SESSION_SECRET, readEnvFile, replaceOrAppendSecret, validateLiteralSessionSecretEntry, validateSessionSecret, writeFileAtomically, } from "./env-file.js";
|
|
3
|
+
import { ensureEnvLocalIgnored } from "./gitignore.js";
|
|
4
|
+
export class PrepareError extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "PrepareError";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
function hasEnvironmentEntry(environment) {
|
|
11
|
+
return Object.hasOwn(environment, BONFIRE_SESSION_SECRET);
|
|
12
|
+
}
|
|
13
|
+
export async function prepare(options) {
|
|
14
|
+
const root = resolve(options.root);
|
|
15
|
+
const environment = options.environment ?? process.env;
|
|
16
|
+
if (hasEnvironmentEntry(environment)) {
|
|
17
|
+
try {
|
|
18
|
+
validateSessionSecret(environment[BONFIRE_SESSION_SECRET]);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
throw new PrepareError("BF_SESSION_SECRET from the process environment is invalid");
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
source: "environment",
|
|
25
|
+
envFilePath: null,
|
|
26
|
+
gitignoreChanged: false,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
const envFilePath = join(root, ".env.local");
|
|
30
|
+
let content;
|
|
31
|
+
try {
|
|
32
|
+
content = await readEnvFile(envFilePath);
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
throw operationalError("Unable to read .env.local", error);
|
|
36
|
+
}
|
|
37
|
+
const entries = parseEnvEntries(content ?? "").filter((entry) => entry.key === BONFIRE_SESSION_SECRET);
|
|
38
|
+
if (entries.length > 1) {
|
|
39
|
+
throw new PrepareError(".env.local contains duplicate BF_SESSION_SECRET assignments");
|
|
40
|
+
}
|
|
41
|
+
const entry = entries[0];
|
|
42
|
+
if (entry) {
|
|
43
|
+
try {
|
|
44
|
+
validateLiteralSessionSecretEntry(content ?? "", entry);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
if (error instanceof Error)
|
|
48
|
+
throw new PrepareError(error.message);
|
|
49
|
+
throw new PrepareError("BF_SESSION_SECRET assignment is invalid");
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (entry && entry.value.length > 0) {
|
|
53
|
+
try {
|
|
54
|
+
validateSessionSecret(entry.value);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
throw new PrepareError("BF_SESSION_SECRET in .env.local is invalid");
|
|
58
|
+
}
|
|
59
|
+
const gitignoreChanged = await protectEnvFile(root);
|
|
60
|
+
return { source: "existing", envFilePath, gitignoreChanged };
|
|
61
|
+
}
|
|
62
|
+
const gitignoreChanged = await protectEnvFile(root);
|
|
63
|
+
const generate = options.generateSecret ?? generateSessionSecret;
|
|
64
|
+
let secret;
|
|
65
|
+
try {
|
|
66
|
+
secret = generate();
|
|
67
|
+
validateSessionSecret(secret);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
if (error instanceof PrepareError)
|
|
71
|
+
throw error;
|
|
72
|
+
throw new PrepareError("Unable to generate a valid BF_SESSION_SECRET");
|
|
73
|
+
}
|
|
74
|
+
const nextContent = replaceOrAppendSecret(content ?? "", secret);
|
|
75
|
+
try {
|
|
76
|
+
await writeFileAtomically(envFilePath, nextContent, 0o600);
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
throw operationalError("Unable to write .env.local", error);
|
|
80
|
+
}
|
|
81
|
+
return { source: "generated", envFilePath, gitignoreChanged };
|
|
82
|
+
}
|
|
83
|
+
async function protectEnvFile(root) {
|
|
84
|
+
try {
|
|
85
|
+
return await ensureEnvLocalIgnored(root);
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
throw operationalError("Unable to protect .env.local with .gitignore", error);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function operationalError(context, error) {
|
|
92
|
+
const detail = error instanceof Error ? error.message : "an unknown filesystem error";
|
|
93
|
+
return new PrepareError(`${context}: ${detail}`);
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=prepare.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prepare.js","sourceRoot":"","sources":["../src/prepare.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ebay-dt/bonfire-cli",
|
|
3
|
+
"version": "0.1.0-alpha.0",
|
|
4
|
+
"description": "The Bonfire command-line tool.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=24"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE"
|
|
14
|
+
],
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"import": "./dist/index.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"bin": {
|
|
22
|
+
"bonfire": "./dist/bin.js"
|
|
23
|
+
},
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://github.corp.ebay.com/Design-Technology/bonfire",
|
|
27
|
+
"directory": "packages/cli"
|
|
28
|
+
},
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@next/env": "16.3.4",
|
|
34
|
+
"@ebay-dt/bonfire-core": "0.1.0-alpha.0",
|
|
35
|
+
"@ebay-dt/bonfire-node": "0.1.0-alpha.0"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@repo/eslint-config": "0.0.0",
|
|
39
|
+
"@repo/typescript-config": "0.0.0",
|
|
40
|
+
"@types/node": "20.19.43",
|
|
41
|
+
"eslint": "10.9.1",
|
|
42
|
+
"typescript": "7.0.2",
|
|
43
|
+
"vitest": "^5.0.0"
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"build": "tsc -p tsconfig.build.json && node scripts/set-bin-mode.mjs",
|
|
47
|
+
"check": "tsc -p tsconfig.json --noEmit",
|
|
48
|
+
"lint": "eslint .",
|
|
49
|
+
"pretest": "pnpm build",
|
|
50
|
+
"test": "vitest run --passWithNoTests --exclude 'dist/**'"
|
|
51
|
+
}
|
|
52
|
+
}
|