opencode-dotenv 0.1.0 → 0.3.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/README.md +27 -160
- package/dist/index.js +143 -43
- package/package.json +20 -2
package/README.md
CHANGED
|
@@ -2,28 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
OpenCode plugin to load `.env` files at startup.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Setup
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- Load `.env` from current working directory (optional)
|
|
9
|
-
- Override existing environment variables (later files override earlier ones)
|
|
10
|
-
- Configurable logging to `/tmp/opencode-dotenv.log` (enabled by default)
|
|
11
|
-
- Prevents double loading with load guard
|
|
12
|
-
- JSONC config file format (supports comments and trailing commas)
|
|
13
|
-
- **Requires Bun runtime**
|
|
14
|
-
|
|
15
|
-
## Installation
|
|
16
|
-
|
|
17
|
-
Add to your `opencode.jsonc`:
|
|
18
|
-
|
|
19
|
-
```jsonc
|
|
20
|
-
{
|
|
21
|
-
"$schema": "https://opencode.ai/config.json",
|
|
22
|
-
"plugin": ["file:./plugins/opencode-dotenv"]
|
|
23
|
-
}
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
After publishing to npm, you can use:
|
|
7
|
+
Add to `~/.config/opencode/opencode.jsonc`:
|
|
27
8
|
|
|
28
9
|
```jsonc
|
|
29
10
|
{
|
|
@@ -31,165 +12,51 @@ After publishing to npm, you can use:
|
|
|
31
12
|
}
|
|
32
13
|
```
|
|
33
14
|
|
|
34
|
-
##
|
|
35
|
-
|
|
36
|
-
Create `opencode-dotenv.jsonc` in one of these locations:
|
|
37
|
-
|
|
38
|
-
1. `~/.config/opencode/opencode-dotenv.jsonc` (recommended, global config)
|
|
39
|
-
2. `./opencode-dotenv.jsonc` in current working directory (project-specific)
|
|
40
|
-
|
|
41
|
-
**Note:** Config files are loaded in the order above; the first found file is used.
|
|
42
|
-
|
|
43
|
-
### Config Schema
|
|
44
|
-
|
|
45
|
-
Config file uses **JSONC format** (JSON with Comments), which supports:
|
|
46
|
-
- `//` single-line comments
|
|
47
|
-
- `/* */` multi-line comments
|
|
48
|
-
- Trailing commas
|
|
49
|
-
- Trailing spaces
|
|
50
|
-
|
|
51
|
-
```jsonc
|
|
52
|
-
{
|
|
53
|
-
"files": [
|
|
54
|
-
"~/.config/opencode/.env",
|
|
55
|
-
"~/a/.env"
|
|
56
|
-
],
|
|
57
|
-
"load_cwd_env": true,
|
|
58
|
-
"logging": {
|
|
59
|
-
"enabled": true
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
**Fields:**
|
|
65
|
-
- `files` (array, optional): List of `.env` file paths to load in order. Later files override earlier ones.
|
|
66
|
-
- `load_cwd_env` (boolean, optional): Whether to load `.env` from the directory where OpenCode is opened. Defaults to `true`.
|
|
67
|
-
- `logging.enabled` (boolean, optional): Enable/disable logging to `/tmp/opencode-dotenv.log`. Defaults to `true`.
|
|
68
|
-
|
|
69
|
-
**Notes:**
|
|
70
|
-
- Use `~` for home directory (automatically expanded)
|
|
71
|
-
- Paths are expanded before loading
|
|
72
|
-
- If no config file exists, only loads `./.env` from cwd (if present)
|
|
73
|
-
- Logging writes to `/tmp/opencode-dotenv.log` for debugging
|
|
74
|
-
|
|
75
|
-
### Load Order
|
|
76
|
-
|
|
77
|
-
1. Files listed in `config.files` array (in order, later files override earlier ones)
|
|
78
|
-
2. `.env` from current working directory (if `load_cwd_env: true`)
|
|
15
|
+
## Config
|
|
79
16
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
## Usage Examples
|
|
83
|
-
|
|
84
|
-
### Load global and project-specific .env files
|
|
85
|
-
|
|
86
|
-
Config (`~/.config/opencode/opencode-dotenv.jsonc`):
|
|
17
|
+
Create `~/.config/opencode/opencode-dotenv.jsonc`:
|
|
87
18
|
|
|
88
19
|
```jsonc
|
|
89
20
|
{
|
|
90
|
-
"files": [
|
|
91
|
-
"~/.config/opencode/.env"
|
|
92
|
-
],
|
|
21
|
+
"files": ["~/.config/opencode/.env"],
|
|
93
22
|
"load_cwd_env": true,
|
|
94
|
-
"
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
Result:
|
|
101
|
-
1. Loads `~/.config/opencode/.env`
|
|
102
|
-
2. Loads `./.env` from cwd (overrides any conflicts)
|
|
103
|
-
3. Logs all activity to `/tmp/opencode-dotenv.log`
|
|
104
|
-
|
|
105
|
-
### Load multiple global files without cwd .env
|
|
106
|
-
|
|
107
|
-
Config (`~/.config/opencode/opencode-dotenv.jsonc`):
|
|
108
|
-
|
|
109
|
-
```jsonc
|
|
110
|
-
{
|
|
111
|
-
"files": [
|
|
112
|
-
"~/.config/opencode/.env",
|
|
113
|
-
"~/a/.env"
|
|
114
|
-
],
|
|
115
|
-
"load_cwd_env": false,
|
|
116
|
-
"logging": {
|
|
117
|
-
"enabled": false
|
|
118
|
-
}
|
|
23
|
+
"prefix": "", // or "MYAPP_"
|
|
24
|
+
"logging": { "enabled": true }
|
|
119
25
|
}
|
|
120
26
|
```
|
|
121
27
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
### Example .env files
|
|
28
|
+
| Option | Default | Description |
|
|
29
|
+
|--------|---------|-------------|
|
|
30
|
+
| `files` | `[]` | `.env` files to load (later overrides earlier) |
|
|
31
|
+
| `load_cwd_env` | `true` | Load `.env` from cwd |
|
|
32
|
+
| `prefix` | `""` | Prefix for all variable names |
|
|
33
|
+
| `logging.enabled` | `true` | Log to `/tmp/opencode-dotenv.log` |
|
|
129
34
|
|
|
130
|
-
|
|
35
|
+
## .env Format
|
|
131
36
|
|
|
132
37
|
```bash
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
38
|
+
KEY=value
|
|
39
|
+
export EXPORTED=value
|
|
40
|
+
QUOTED="with spaces"
|
|
41
|
+
SINGLE='literal'
|
|
42
|
+
MULTILINE=first\
|
|
43
|
+
second
|
|
44
|
+
INLINE=value # comment stripped
|
|
45
|
+
ESCAPES="line1\nline2\ttab"
|
|
137
46
|
```
|
|
138
47
|
|
|
139
|
-
|
|
48
|
+
## Security
|
|
140
49
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
PROJECT_API_KEY=project_specific_key
|
|
145
|
-
```
|
|
50
|
+
- Paths restricted to `$HOME` or cwd
|
|
51
|
+
- Path traversal rejected
|
|
52
|
+
- Keys validated: `^[a-zA-Z_][a-zA-Z0-9_]*$`
|
|
146
53
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
### Logging
|
|
150
|
-
|
|
151
|
-
View plugin activity logs:
|
|
54
|
+
## Debug
|
|
152
55
|
|
|
153
56
|
```bash
|
|
154
57
|
tail -f /tmp/opencode-dotenv.log
|
|
155
58
|
```
|
|
156
59
|
|
|
157
|
-
Disable logging in config:
|
|
158
|
-
|
|
159
|
-
```jsonc
|
|
160
|
-
{
|
|
161
|
-
"files": ["~/.config/opencode/.env"],
|
|
162
|
-
"logging": {
|
|
163
|
-
"enabled": false
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
## Development
|
|
169
|
-
|
|
170
|
-
### Plugin structure
|
|
171
|
-
|
|
172
|
-
```
|
|
173
|
-
opencode-dotenv/
|
|
174
|
-
├── package.json
|
|
175
|
-
├── src/
|
|
176
|
-
│ └── index.ts
|
|
177
|
-
└── dist/
|
|
178
|
-
└── index.js (built)
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
### Build
|
|
182
|
-
|
|
183
|
-
```bash
|
|
184
|
-
bun run build
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
### Publish
|
|
188
|
-
|
|
189
|
-
```bash
|
|
190
|
-
npm publish
|
|
191
|
-
```
|
|
192
|
-
|
|
193
60
|
## License
|
|
194
61
|
|
|
195
62
|
MIT
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
// src/index.ts
|
|
3
|
-
import { homedir } from "os";
|
|
4
|
-
|
|
5
2
|
// node_modules/jsonc-parser/lib/esm/impl/scanner.js
|
|
6
3
|
function createScanner(text, ignoreTrivia = false) {
|
|
7
4
|
const len = text.length;
|
|
@@ -807,114 +804,217 @@ var ParseErrorCode;
|
|
|
807
804
|
})(ParseErrorCode || (ParseErrorCode = {}));
|
|
808
805
|
|
|
809
806
|
// src/index.ts
|
|
807
|
+
import { resolve, normalize } from "path";
|
|
808
|
+
import { homedir as osHomedir } from "os";
|
|
810
809
|
var LOG_FILE = "/tmp/opencode-dotenv.log";
|
|
811
810
|
var LOAD_GUARD = "__opencodeDotenvLoaded";
|
|
811
|
+
var VALID_ENV_KEY = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
812
|
+
function getHomeDir() {
|
|
813
|
+
return process.env.HOME ?? osHomedir();
|
|
814
|
+
}
|
|
812
815
|
function parseDotenv(content) {
|
|
813
816
|
const result = {};
|
|
814
|
-
|
|
815
|
-
`)
|
|
816
|
-
|
|
817
|
-
|
|
817
|
+
const lines = content.split(`
|
|
818
|
+
`);
|
|
819
|
+
let i = 0;
|
|
820
|
+
while (i < lines.length) {
|
|
821
|
+
let line = lines[i].trim();
|
|
822
|
+
i++;
|
|
823
|
+
if (!line || line.startsWith("#"))
|
|
818
824
|
continue;
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
825
|
+
while (line.endsWith("\\") && i < lines.length) {
|
|
826
|
+
line = line.slice(0, -1) + lines[i];
|
|
827
|
+
i++;
|
|
828
|
+
}
|
|
829
|
+
const exportMatch = line.match(/^export\s+(.*)$/);
|
|
830
|
+
if (exportMatch) {
|
|
831
|
+
line = exportMatch[1];
|
|
832
|
+
}
|
|
833
|
+
const eqIndex = line.indexOf("=");
|
|
834
|
+
if (eqIndex === -1)
|
|
835
|
+
continue;
|
|
836
|
+
const key = line.substring(0, eqIndex).trim();
|
|
837
|
+
const value = parseValue(line.substring(eqIndex + 1));
|
|
838
|
+
if (key && isValidEnvKey(key)) {
|
|
839
|
+
result[key] = value;
|
|
828
840
|
}
|
|
829
841
|
}
|
|
830
842
|
return result;
|
|
831
843
|
}
|
|
832
|
-
function
|
|
833
|
-
|
|
844
|
+
function parseValue(raw) {
|
|
845
|
+
let value = raw.trim();
|
|
846
|
+
if (value.startsWith('"')) {
|
|
847
|
+
const endQuote = findClosingQuote(value, '"');
|
|
848
|
+
if (endQuote !== -1) {
|
|
849
|
+
value = value.substring(1, endQuote);
|
|
850
|
+
return value.replace(/\\n/g, `
|
|
851
|
+
`).replace(/\\r/g, "\r").replace(/\\t/g, "\t").replace(/\\"/g, '"').replace(/\\\\/g, "\\");
|
|
852
|
+
}
|
|
853
|
+
return value;
|
|
854
|
+
}
|
|
855
|
+
if (value.startsWith("'")) {
|
|
856
|
+
const endQuote = findClosingQuote(value, "'");
|
|
857
|
+
if (endQuote !== -1) {
|
|
858
|
+
return value.substring(1, endQuote);
|
|
859
|
+
}
|
|
860
|
+
return value;
|
|
861
|
+
}
|
|
862
|
+
const inlineCommentIndex = value.indexOf(" #");
|
|
863
|
+
if (inlineCommentIndex !== -1) {
|
|
864
|
+
value = value.substring(0, inlineCommentIndex);
|
|
865
|
+
}
|
|
866
|
+
return value.trim();
|
|
867
|
+
}
|
|
868
|
+
function findClosingQuote(str, quote) {
|
|
869
|
+
let i = 1;
|
|
870
|
+
while (i < str.length) {
|
|
871
|
+
if (str[i] === "\\" && i + 1 < str.length) {
|
|
872
|
+
i += 2;
|
|
873
|
+
continue;
|
|
874
|
+
}
|
|
875
|
+
if (str[i] === quote) {
|
|
876
|
+
return i;
|
|
877
|
+
}
|
|
878
|
+
i++;
|
|
879
|
+
}
|
|
880
|
+
return -1;
|
|
881
|
+
}
|
|
882
|
+
function isValidEnvKey(key) {
|
|
883
|
+
return VALID_ENV_KEY.test(key);
|
|
884
|
+
}
|
|
885
|
+
function expandPath(rawPath) {
|
|
886
|
+
const home = getHomeDir();
|
|
887
|
+
const expanded = rawPath.replace(/^~/, home);
|
|
888
|
+
const resolved = resolve(expanded);
|
|
889
|
+
const normalized = normalize(resolved);
|
|
890
|
+
const cwd = process.cwd();
|
|
891
|
+
const isWithinAllowedDirectory = normalized.startsWith(home) || normalized.startsWith(cwd);
|
|
892
|
+
return isWithinAllowedDirectory ? normalized : null;
|
|
834
893
|
}
|
|
835
894
|
var loggingEnabled = true;
|
|
895
|
+
var logBuffer = [];
|
|
896
|
+
var flushScheduled = false;
|
|
836
897
|
function logToFile(message) {
|
|
837
898
|
if (!loggingEnabled)
|
|
838
899
|
return;
|
|
900
|
+
const timestamp = new Date().toISOString();
|
|
901
|
+
logBuffer.push(`[${timestamp}] ${message}`);
|
|
902
|
+
if (!flushScheduled) {
|
|
903
|
+
flushScheduled = true;
|
|
904
|
+
queueMicrotask(flushLogs);
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
async function flushLogs() {
|
|
908
|
+
if (logBuffer.length === 0) {
|
|
909
|
+
flushScheduled = false;
|
|
910
|
+
return;
|
|
911
|
+
}
|
|
912
|
+
const messages = logBuffer.join(`
|
|
913
|
+
`) + `
|
|
914
|
+
`;
|
|
915
|
+
logBuffer = [];
|
|
916
|
+
flushScheduled = false;
|
|
839
917
|
try {
|
|
840
|
-
const
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
} catch
|
|
918
|
+
const file = Bun.file(LOG_FILE);
|
|
919
|
+
const existing = await file.exists() ? await file.text() : "";
|
|
920
|
+
await Bun.write(LOG_FILE, existing + messages);
|
|
921
|
+
} catch {
|
|
922
|
+
loggingEnabled = false;
|
|
923
|
+
}
|
|
844
924
|
}
|
|
845
925
|
async function loadConfig() {
|
|
846
|
-
const
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
for (const configPath of configPaths) {
|
|
851
|
-
try {
|
|
852
|
-
const file = Bun.file(configPath);
|
|
853
|
-
if (!await file.exists())
|
|
854
|
-
continue;
|
|
926
|
+
const configPath = `${getHomeDir()}/.config/opencode/opencode-dotenv.jsonc`;
|
|
927
|
+
try {
|
|
928
|
+
const file = Bun.file(configPath);
|
|
929
|
+
if (await file.exists()) {
|
|
855
930
|
const content = await file.text();
|
|
856
|
-
const config = parse2(content, [], {
|
|
931
|
+
const config = parse2(content, [], {
|
|
932
|
+
allowTrailingComma: true
|
|
933
|
+
});
|
|
857
934
|
loggingEnabled = config.logging?.enabled !== false;
|
|
858
935
|
return config;
|
|
859
|
-
} catch (e) {
|
|
860
|
-
logToFile(`Failed to load config: ${e}`);
|
|
861
936
|
}
|
|
937
|
+
} catch (e) {
|
|
938
|
+
logToFile(`Failed to load config: ${e}`);
|
|
862
939
|
}
|
|
863
940
|
return { files: [], load_cwd_env: true };
|
|
864
941
|
}
|
|
865
|
-
async function loadDotenvFile(filePath) {
|
|
942
|
+
async function loadDotenvFile(filePath, prefix) {
|
|
943
|
+
const skipped = [];
|
|
866
944
|
try {
|
|
867
945
|
const file = Bun.file(filePath);
|
|
868
946
|
if (!await file.exists()) {
|
|
869
947
|
logToFile(`File not found: ${filePath}`);
|
|
870
|
-
return { count: 0, success: false };
|
|
948
|
+
return { count: 0, success: false, skipped };
|
|
871
949
|
}
|
|
872
950
|
const content = await file.text();
|
|
873
951
|
const envVars = parseDotenv(content);
|
|
952
|
+
let count = 0;
|
|
874
953
|
for (const [key, value] of Object.entries(envVars)) {
|
|
875
|
-
|
|
954
|
+
if (!isValidEnvKey(key)) {
|
|
955
|
+
skipped.push(key);
|
|
956
|
+
continue;
|
|
957
|
+
}
|
|
958
|
+
const envKey = prefix ? `${prefix}${key}` : key;
|
|
959
|
+
process.env[envKey] = value;
|
|
960
|
+
count++;
|
|
876
961
|
}
|
|
877
|
-
return { count
|
|
962
|
+
return { count, success: true, skipped };
|
|
878
963
|
} catch (error) {
|
|
879
964
|
logToFile(`Failed to load ${filePath}: ${error}`);
|
|
880
|
-
return { count: 0, success: false };
|
|
965
|
+
return { count: 0, success: false, skipped };
|
|
881
966
|
}
|
|
882
967
|
}
|
|
883
|
-
var DotEnvPlugin = async (
|
|
968
|
+
var DotEnvPlugin = async () => {
|
|
884
969
|
if (globalThis[LOAD_GUARD]) {
|
|
885
970
|
return {};
|
|
886
971
|
}
|
|
887
972
|
globalThis[LOAD_GUARD] = true;
|
|
888
973
|
logToFile("Plugin started");
|
|
889
974
|
const config = await loadConfig();
|
|
890
|
-
logToFile(`Config loaded: ${config.files.length} files, load_cwd_env=${config.load_cwd_env}, logging=${loggingEnabled}`);
|
|
975
|
+
logToFile(`Config loaded: ${config.files.length} files, load_cwd_env=${config.load_cwd_env}, prefix=${config.prefix ?? "(none)"}, logging=${loggingEnabled}`);
|
|
891
976
|
let totalFiles = 0;
|
|
892
977
|
let totalVars = 0;
|
|
893
978
|
for (const rawPath of config.files) {
|
|
894
979
|
const filePath = expandPath(rawPath);
|
|
980
|
+
if (!filePath) {
|
|
981
|
+
logToFile(`SECURITY: Rejected path outside allowed directories: ${rawPath}`);
|
|
982
|
+
continue;
|
|
983
|
+
}
|
|
895
984
|
logToFile(`Loading: ${filePath}`);
|
|
896
|
-
const result = await loadDotenvFile(filePath);
|
|
985
|
+
const result = await loadDotenvFile(filePath, config.prefix);
|
|
897
986
|
if (result.success) {
|
|
898
987
|
totalFiles++;
|
|
899
988
|
totalVars += result.count;
|
|
900
989
|
logToFile(`Loaded ${result.count} vars`);
|
|
990
|
+
if (result.skipped.length > 0) {
|
|
991
|
+
logToFile(`Skipped invalid keys: ${result.skipped.join(", ")}`);
|
|
992
|
+
}
|
|
901
993
|
}
|
|
902
994
|
}
|
|
903
995
|
if (config.load_cwd_env !== false) {
|
|
904
996
|
const cwdEnvPath = `${process.cwd()}/.env`;
|
|
905
997
|
logToFile(`Loading cwd: ${cwdEnvPath}`);
|
|
906
|
-
const result = await loadDotenvFile(cwdEnvPath);
|
|
998
|
+
const result = await loadDotenvFile(cwdEnvPath, config.prefix);
|
|
907
999
|
if (result.success) {
|
|
908
1000
|
totalFiles++;
|
|
909
1001
|
totalVars += result.count;
|
|
910
1002
|
logToFile(`Loaded ${result.count} vars from cwd`);
|
|
1003
|
+
if (result.skipped.length > 0) {
|
|
1004
|
+
logToFile(`Skipped invalid keys: ${result.skipped.join(", ")}`);
|
|
1005
|
+
}
|
|
911
1006
|
}
|
|
912
1007
|
}
|
|
913
1008
|
logToFile(`Plugin finished: ${totalFiles} files, ${totalVars} vars`);
|
|
1009
|
+
await flushLogs();
|
|
914
1010
|
return {};
|
|
915
1011
|
};
|
|
916
1012
|
var src_default = DotEnvPlugin;
|
|
917
1013
|
export {
|
|
1014
|
+
parseValue,
|
|
1015
|
+
parseDotenv,
|
|
1016
|
+
isValidEnvKey,
|
|
1017
|
+
expandPath,
|
|
918
1018
|
src_default as default,
|
|
919
1019
|
DotEnvPlugin
|
|
920
1020
|
};
|
package/package.json
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-dotenv",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "OpenCode plugin to load .env files at startup",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "MIT",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/assagman/opencode-dotenv.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/assagman/opencode-dotenv/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"opencode",
|
|
17
|
+
"plugin",
|
|
18
|
+
"dotenv",
|
|
19
|
+
"env",
|
|
20
|
+
"environment",
|
|
21
|
+
"variables"
|
|
22
|
+
],
|
|
8
23
|
"scripts": {
|
|
9
24
|
"build": "bun build src/index.ts --outdir dist --target bun",
|
|
25
|
+
"test": "bun test",
|
|
10
26
|
"prepublishOnly": "bun run build"
|
|
11
27
|
},
|
|
12
28
|
"files": [
|
|
@@ -20,5 +36,7 @@
|
|
|
20
36
|
"dependencies": {
|
|
21
37
|
"jsonc-parser": "^3.3.1"
|
|
22
38
|
},
|
|
23
|
-
"devDependencies": {
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/bun": "^1.2.4"
|
|
41
|
+
}
|
|
24
42
|
}
|