@ben-studios/envedit 0.0.0-stage → 1.0.1
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/.gitlab-ci.yml +133 -0
- package/@types/custom.d.ts +10 -0
- package/CHANGELOG.md +196 -0
- package/LICENSE +674 -0
- package/README.md +97 -2
- package/ci/npm.sh +4 -0
- package/cli/cmd/environment.ts +10 -0
- package/cli/cmd/environmentCmd/add.ts +115 -0
- package/cli/cmd/environmentCmd/edit.ts +74 -0
- package/cli/cmd/environmentCmd/index.ts +6 -0
- package/cli/cmd/environmentCmd/list.ts +16 -0
- package/cli/cmd/environmentCmd/remove.ts +47 -0
- package/cli/cmd/index.ts +7 -0
- package/cli/cmd/init.ts +60 -0
- package/cli/cmd/setup.ts +46 -0
- package/cli/cmd/use.ts +60 -0
- package/cli/cmd/variable.ts +10 -0
- package/cli/cmd/variableCmd/add.ts +92 -0
- package/cli/cmd/variableCmd/edit.ts +150 -0
- package/cli/cmd/variableCmd/index.ts +6 -0
- package/cli/cmd/variableCmd/list.ts +35 -0
- package/cli/cmd/variableCmd/remove.ts +39 -0
- package/cli/index.ts +28 -0
- package/lib/config.ts +133 -0
- package/lib/error.ts +6 -0
- package/lib/logger.ts +40 -0
- package/package.json +27 -3
- package/tsconfig.json +35 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { confirm, input, password, select, checkbox } from "@inquirer/prompts";
|
|
2
|
+
|
|
3
|
+
import { Configuration, EnvironmentFile, VariableType } from "#lib/config";
|
|
4
|
+
import { NotFoundError } from "#lib/error";
|
|
5
|
+
import { Logger } from "#lib/logger";
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
command: 'edit',
|
|
9
|
+
describe: 'Edit an environment variable',
|
|
10
|
+
builder: (yargs) => yargs,
|
|
11
|
+
handler: async (argv) => {
|
|
12
|
+
const config = new Configuration();
|
|
13
|
+
const logger = new Logger(argv.level);
|
|
14
|
+
|
|
15
|
+
const name = await select({
|
|
16
|
+
message: "Select the variable to edit:",
|
|
17
|
+
choices: Array.from(config.vars.keys()),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const variableConfiguration = config.vars.get(name);
|
|
21
|
+
|
|
22
|
+
if (!variableConfiguration) {
|
|
23
|
+
throw new NotFoundError(`Variable not found: ${name}`);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const isEditingConfig = await select({
|
|
27
|
+
message: "Are you editing the variable configuration (name/type) or the variable value?",
|
|
28
|
+
choices: [
|
|
29
|
+
{ name: "Configuration", value: true },
|
|
30
|
+
{ name: "Value", value: false },
|
|
31
|
+
],
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
if (isEditingConfig) {
|
|
35
|
+
logger.debug(`Editing variable configuration for: ${name}`);
|
|
36
|
+
|
|
37
|
+
const itemsToEdit = await checkbox({
|
|
38
|
+
message: "Select the items to edit:",
|
|
39
|
+
choices: [
|
|
40
|
+
{ name: "Name", value: "name" },
|
|
41
|
+
{ name: "Type", value: "type" },
|
|
42
|
+
],
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const updatedVariable = { ...variableConfiguration };
|
|
46
|
+
|
|
47
|
+
if (itemsToEdit.includes("name")) {
|
|
48
|
+
updatedVariable.name = await input({
|
|
49
|
+
message: "Enter the new variable name:",
|
|
50
|
+
default: variableConfiguration.name,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
for (const [_, env] of config.envs) {
|
|
54
|
+
const envFile = new EnvironmentFile(env.file);
|
|
55
|
+
|
|
56
|
+
logger.debug(`Editing variable "${name}" in environment file: ${env.file}`);
|
|
57
|
+
|
|
58
|
+
if (envFile.vars.has(name)) {
|
|
59
|
+
const value = envFile.vars.get(name) || '';
|
|
60
|
+
|
|
61
|
+
envFile.vars.delete(name);
|
|
62
|
+
envFile.vars.set(updatedVariable.name, value);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
envFile.save();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
config.vars.delete(name);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (itemsToEdit.includes("type")) {
|
|
72
|
+
updatedVariable.type = await select({
|
|
73
|
+
message: "Select the new variable type:",
|
|
74
|
+
choices: [
|
|
75
|
+
{ name: "Public", value: VariableType.Public },
|
|
76
|
+
{ name: "Private", value: VariableType.Private },
|
|
77
|
+
],
|
|
78
|
+
default: variableConfiguration.type,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
logger.debug(`Editing variable type for "${name}" to "${updatedVariable.type}"`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
config.vars.set(updatedVariable.name, updatedVariable);
|
|
85
|
+
config.save();
|
|
86
|
+
} else {
|
|
87
|
+
logger.debug(`Adding edited variable value for: ${name}`);
|
|
88
|
+
|
|
89
|
+
let valuesToSet = Array.from(config.envs.values()).map(env => ({
|
|
90
|
+
envName: env.name,
|
|
91
|
+
value: '',
|
|
92
|
+
}));
|
|
93
|
+
|
|
94
|
+
const shouldGloballySet = await confirm({
|
|
95
|
+
message: "Do you want to set this variable for all environments?",
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
if (shouldGloballySet) {
|
|
99
|
+
const request = {
|
|
100
|
+
message: `Enter the global value for ${variableConfiguration.name}:`,
|
|
101
|
+
mask: variableConfiguration.type === VariableType.Private ? "*" : undefined,
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const globalValue = variableConfiguration.type === VariableType.Private
|
|
105
|
+
? await password(request)
|
|
106
|
+
: await input(request);
|
|
107
|
+
|
|
108
|
+
logger.debug(`Setting variable "${variableConfiguration.name}" with global value "${globalValue}" for all environments`);
|
|
109
|
+
|
|
110
|
+
for (const [_, env] of config.envs) {
|
|
111
|
+
const envFile = new EnvironmentFile(env.file);
|
|
112
|
+
|
|
113
|
+
logger.debug(`Setting variable "${variableConfiguration.name}" with value "${globalValue}" in environment file: ${env.file}`);
|
|
114
|
+
|
|
115
|
+
envFile.vars.set(variableConfiguration.name, globalValue);
|
|
116
|
+
envFile.save();
|
|
117
|
+
}
|
|
118
|
+
} else {
|
|
119
|
+
const envsToEdit = await checkbox({
|
|
120
|
+
message: "Select the environments to edit the variable value for:",
|
|
121
|
+
choices: Array.from(config.envs.keys()),
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
logger.debug(`Selected environments for editing: ${envsToEdit.join(", ")}`);
|
|
125
|
+
|
|
126
|
+
for (const selectedEnv of envsToEdit) {
|
|
127
|
+
const env = config.envs.get(selectedEnv);
|
|
128
|
+
|
|
129
|
+
if (!env) {
|
|
130
|
+
throw new NotFoundError(`Environment not found: ${selectedEnv}`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const envFile = new EnvironmentFile(env.file);
|
|
134
|
+
|
|
135
|
+
const request = {
|
|
136
|
+
message: `Enter the value for ${variableConfiguration.name} in environment ${selectedEnv}:`,
|
|
137
|
+
mask: variableConfiguration.type === VariableType.Private ? "*" : undefined,
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const newValue = variableConfiguration.type === VariableType.Private
|
|
141
|
+
? await password(request)
|
|
142
|
+
: await input(request);
|
|
143
|
+
|
|
144
|
+
envFile.vars.set(variableConfiguration.name, newValue);
|
|
145
|
+
envFile.save();
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
} satisfies CommandModule;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Configuration, EnvironmentFile, VariableType } from "#lib/config";
|
|
2
|
+
import { NotFoundError } from "#lib/error";
|
|
3
|
+
import { Logger } from "#lib/logger";
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
command: 'list',
|
|
7
|
+
describe: 'List all environment variables',
|
|
8
|
+
builder: (yargs) => yargs,
|
|
9
|
+
handler: async (argv) => {
|
|
10
|
+
const config = new Configuration();
|
|
11
|
+
const logger = new Logger(argv.level);
|
|
12
|
+
|
|
13
|
+
const activeEnv = config.active ? config.envs.get(config.active)! : undefined;
|
|
14
|
+
|
|
15
|
+
if (!activeEnv) {
|
|
16
|
+
throw new NotFoundError(`No active environment found. Please set an active environment using the "use" command.`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const envFile = new EnvironmentFile(activeEnv.file);
|
|
20
|
+
|
|
21
|
+
for (const [key, value] of envFile.vars) {
|
|
22
|
+
const variableConfiguration = config.vars.get(key);
|
|
23
|
+
if (variableConfiguration) {
|
|
24
|
+
const type = Configuration.getTypeDetails(variableConfiguration.type);
|
|
25
|
+
|
|
26
|
+
const maskedValue = type.value === VariableType.Private ? value.replaceAll(/./gm, '*') : value;
|
|
27
|
+
|
|
28
|
+
logger
|
|
29
|
+
.info(`Name: ${key}`)
|
|
30
|
+
.info(`Value: ${maskedValue}`)
|
|
31
|
+
.info(`Type: ${type.name} (${type.value})`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
} satisfies CommandModule;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { select } from "@inquirer/prompts";
|
|
2
|
+
|
|
3
|
+
import { Configuration, EnvironmentFile } from "#lib/config";
|
|
4
|
+
import { NotFoundError } from "#lib/error";
|
|
5
|
+
import { Logger } from "#lib/logger";
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
command: 'remove',
|
|
9
|
+
describe: 'Remove an environment variable',
|
|
10
|
+
builder: (yargs) => yargs,
|
|
11
|
+
handler: async (argv) => {
|
|
12
|
+
const config = new Configuration();
|
|
13
|
+
const logger = new Logger(argv.level);
|
|
14
|
+
|
|
15
|
+
const name = await select({
|
|
16
|
+
message: "Select the variable to remove:",
|
|
17
|
+
choices: Array.from(config.vars.keys()),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
if (!config.vars.has(name)) {
|
|
21
|
+
throw new NotFoundError(`Variable not found: ${name}`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
logger.debug(`Removing variable "${name}" from configuration and all environment files`);
|
|
25
|
+
|
|
26
|
+
config.vars.delete(name);
|
|
27
|
+
config.save();
|
|
28
|
+
|
|
29
|
+
for (const [_, env] of config.envs) {
|
|
30
|
+
const envFile = new EnvironmentFile(env.file);
|
|
31
|
+
|
|
32
|
+
if (envFile.vars.has(name)) {
|
|
33
|
+
logger.debug(`Removing variable "${name}" from environment file: ${env.file}`);
|
|
34
|
+
envFile.vars.delete(name);
|
|
35
|
+
envFile.save();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
} satisfies CommandModule;
|
package/cli/index.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import yargs from "yargs";
|
|
3
|
+
import { hideBin } from "yargs/helpers";
|
|
4
|
+
|
|
5
|
+
if (!process.isBun) {
|
|
6
|
+
const [red, reset] = process.stdout.isTTY && process.env.TERM !== "dumb" ? ["\x1b[31m", "\x1b[0m"] : ["", ""];
|
|
7
|
+
console.error(`${red}This script is intended to be run with Bun.${reset}`);
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
await yargs(hideBin(process.argv))
|
|
12
|
+
.option("level", {
|
|
13
|
+
alias: "l",
|
|
14
|
+
type: "string",
|
|
15
|
+
description: "Set the log level",
|
|
16
|
+
default: process.env.LOG_LEVEL || "info",
|
|
17
|
+
})
|
|
18
|
+
.env('ENVEDIT')
|
|
19
|
+
.scriptName("envedit")
|
|
20
|
+
.usage("Usage: $0 <command>")
|
|
21
|
+
.command(await import("./cmd/index.ts").then((mod) => mod.default))
|
|
22
|
+
.showHelpOnFail(false)
|
|
23
|
+
.demandCommand()
|
|
24
|
+
.version()
|
|
25
|
+
.alias("h", "help")
|
|
26
|
+
.alias("v", "version")
|
|
27
|
+
.strict()
|
|
28
|
+
.parseAsync();
|
package/lib/config.ts
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import {
|
|
2
|
+
existsSync as exists,
|
|
3
|
+
readFileSync as read,
|
|
4
|
+
writeFileSync as write,
|
|
5
|
+
appendFileSync as append,
|
|
6
|
+
} from 'fs';
|
|
7
|
+
|
|
8
|
+
import { parse } from 'dotenv';
|
|
9
|
+
|
|
10
|
+
import { NotFoundError } from '#lib/error';
|
|
11
|
+
|
|
12
|
+
export enum VariableType {
|
|
13
|
+
Public,
|
|
14
|
+
Private,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface VariableConfiguration {
|
|
18
|
+
name: string;
|
|
19
|
+
type: VariableType;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface EnvironmentConfiguration {
|
|
23
|
+
name: string;
|
|
24
|
+
prefix: string;
|
|
25
|
+
file: string;
|
|
26
|
+
isActive: boolean;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface GeneralConfiguration {
|
|
30
|
+
version: number;
|
|
31
|
+
environments: EnvironmentConfiguration[];
|
|
32
|
+
variables: VariableConfiguration[];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export class Configuration {
|
|
36
|
+
public readonly vars: Map<string, VariableConfiguration> = new Map();
|
|
37
|
+
public readonly envs: Map<string, EnvironmentConfiguration> = new Map();
|
|
38
|
+
public readonly version: number = 1;
|
|
39
|
+
private readonly configFilePath: string = 'env.config.yaml';
|
|
40
|
+
|
|
41
|
+
constructor() {
|
|
42
|
+
if (!exists(this.configFilePath)) {
|
|
43
|
+
this
|
|
44
|
+
.importFromEnv(exists('.env') ? read('.env', "utf-8") : '')
|
|
45
|
+
.save();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const configContent = Bun.YAML.parse(read(this.configFilePath, "utf-8")) as GeneralConfiguration;
|
|
49
|
+
|
|
50
|
+
const setWrapper = <
|
|
51
|
+
K extends EnvironmentConfiguration | VariableConfiguration
|
|
52
|
+
>(map: Map<string, K>): ((item: K) => void) => (item: K) => void map.set(item.name, item);
|
|
53
|
+
|
|
54
|
+
configContent.environments.forEach(setWrapper(this.envs))
|
|
55
|
+
configContent.variables.forEach(setWrapper(this.vars))
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public save() {
|
|
59
|
+
write(
|
|
60
|
+
this.configFilePath,
|
|
61
|
+
Bun.YAML.stringify({
|
|
62
|
+
"$schema": "https://benshawmean.com/api/schema/envedit",
|
|
63
|
+
version: this.version,
|
|
64
|
+
environments: Array.from(this.envs.values()),
|
|
65
|
+
variables: Array.from(this.vars.values()),
|
|
66
|
+
}, null, 2),
|
|
67
|
+
{ mode: 0o600 },
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
return this;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
public get active() {
|
|
74
|
+
const activeEnv = Array.from(this.envs.values()).find(env => env.isActive);
|
|
75
|
+
|
|
76
|
+
return activeEnv ? activeEnv.name : undefined;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
public set active(env: string | undefined) {
|
|
80
|
+
if (env && !this.envs.has(env)) {
|
|
81
|
+
throw new NotFoundError(`Environment not found: ${env}`)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
for (const [name, environment] of this.envs.entries()) {
|
|
85
|
+
this.envs.set(name, { ...environment, isActive: name === env });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
this.save();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
public importFromEnv(content: string): Configuration {
|
|
92
|
+
for (const [key, _] of Object.entries(parse(content))) {
|
|
93
|
+
this.vars.set(key, { name: key, type: VariableType.Private });
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return this;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public static getTypeDetails(type: VariableType) {
|
|
100
|
+
const VariableTypeMap = new Map<number, keyof typeof VariableType>();
|
|
101
|
+
|
|
102
|
+
for (const [key, value] of Object.entries(VariableType)) {
|
|
103
|
+
if (typeof value !== "number") continue;
|
|
104
|
+
VariableTypeMap.set(value, key as keyof typeof VariableType);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
name: VariableTypeMap.get(type)!,
|
|
109
|
+
value: type
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export class EnvironmentFile {
|
|
115
|
+
public readonly vars: Map<string, string> = new Map();
|
|
116
|
+
constructor(public readonly path: string) {
|
|
117
|
+
if (exists(path)) {
|
|
118
|
+
const content = read(path, "utf-8");
|
|
119
|
+
const parsed = parse(content);
|
|
120
|
+
|
|
121
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
122
|
+
this.vars.set(key, value);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
public save() {
|
|
128
|
+
write(this.path, '')
|
|
129
|
+
for (const [key, value] of this.vars.entries()) {
|
|
130
|
+
append(this.path, `${key}='${value}'\n`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
package/lib/error.ts
ADDED
package/lib/logger.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import pino from 'pino';
|
|
2
|
+
import type { LevelWithSilentOrString, Logger as PinoLogger } from 'pino';
|
|
3
|
+
|
|
4
|
+
export class Logger {
|
|
5
|
+
private readonly logger: PinoLogger<never, boolean> = pino({
|
|
6
|
+
transport: {
|
|
7
|
+
target: 'pino-pretty',
|
|
8
|
+
options: {
|
|
9
|
+
colorize: true,
|
|
10
|
+
translateTime: 'SYS:standard',
|
|
11
|
+
ignore: 'pid,hostname',
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
constructor(public readonly level: LevelWithSilentOrString, private testMode: boolean = false) {
|
|
17
|
+
this.logger.level = level;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public readonly debug = (msg: string) => {
|
|
21
|
+
this.testMode ? '' : this.logger.debug(msg);
|
|
22
|
+
return this;
|
|
23
|
+
}
|
|
24
|
+
public readonly info = (msg: string) => {
|
|
25
|
+
this.testMode ? '' : this.logger.info(msg);
|
|
26
|
+
return this;
|
|
27
|
+
}
|
|
28
|
+
public readonly warn = (msg: string) => {
|
|
29
|
+
this.testMode ? '' : this.logger.warn(msg);
|
|
30
|
+
return this;
|
|
31
|
+
}
|
|
32
|
+
public readonly error = (msg: string) => {
|
|
33
|
+
this.testMode ? '' : this.logger.error(msg);
|
|
34
|
+
return this;
|
|
35
|
+
}
|
|
36
|
+
public readonly fatal = (msg: string) => {
|
|
37
|
+
this.testMode ? '' : this.logger.fatal(msg);
|
|
38
|
+
return this;
|
|
39
|
+
}
|
|
40
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ben-studios/envedit",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "1.0.1",
|
|
5
|
+
"license": "GPL-3.0-only",
|
|
6
|
+
"bin": {
|
|
7
|
+
"envedit": "cli/index.ts"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"url": "https://gitlab.com/ben-studios/envedit.git"
|
|
11
|
+
},
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public",
|
|
14
|
+
"provenance": true
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@types/bun": "^1.3.14",
|
|
18
|
+
"@types/yargs": "^17.0.35"
|
|
19
|
+
},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"typescript": "^5"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@inquirer/prompts": "^8.5.2",
|
|
25
|
+
"dotenv": "^17.4.2",
|
|
26
|
+
"pino": "^10.3.1",
|
|
27
|
+
"pino-pretty": "^13.1.3",
|
|
28
|
+
"yargs": "^18.1.0"
|
|
29
|
+
}
|
|
6
30
|
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
// Environment setup & latest features
|
|
4
|
+
"lib": ["ESNext"],
|
|
5
|
+
"target": "ESNext",
|
|
6
|
+
"module": "Preserve",
|
|
7
|
+
"moduleDetection": "force",
|
|
8
|
+
"jsx": "react-jsx",
|
|
9
|
+
"allowJs": true,
|
|
10
|
+
"types": ["bun", "./@types/custom.d.ts"],
|
|
11
|
+
|
|
12
|
+
// Bundler mode
|
|
13
|
+
"moduleResolution": "bundler",
|
|
14
|
+
"allowImportingTsExtensions": true,
|
|
15
|
+
"verbatimModuleSyntax": true,
|
|
16
|
+
"noEmit": true,
|
|
17
|
+
|
|
18
|
+
// Best practices
|
|
19
|
+
"strict": true,
|
|
20
|
+
"skipLibCheck": true,
|
|
21
|
+
"noFallthroughCasesInSwitch": true,
|
|
22
|
+
"noUncheckedIndexedAccess": true,
|
|
23
|
+
"noImplicitOverride": true,
|
|
24
|
+
|
|
25
|
+
// Some stricter flags (disabled by default)
|
|
26
|
+
"noUnusedLocals": false,
|
|
27
|
+
"noUnusedParameters": false,
|
|
28
|
+
"noPropertyAccessFromIndexSignature": false,
|
|
29
|
+
|
|
30
|
+
"paths": {
|
|
31
|
+
"@/*": ["./*"],
|
|
32
|
+
"#lib/*": ["./lib/*"]
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|