@take-out/scripts 0.2.6 ā 0.2.7
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/package.json +3 -3
- package/src/env-update.ts +60 -3
- package/src/up.ts +8 -4
- package/src/generate-env.ts +0 -145
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@take-out/scripts",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./src/cmd.ts",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@clack/prompts": "^0.8.2",
|
|
32
|
-
"@take-out/helpers": "0.2.
|
|
33
|
-
"@take-out/run": "0.2.
|
|
32
|
+
"@take-out/helpers": "0.2.7",
|
|
33
|
+
"@take-out/run": "0.2.7",
|
|
34
34
|
"picocolors": "^1.1.1"
|
|
35
35
|
}
|
|
36
36
|
}
|
package/src/env-update.ts
CHANGED
|
@@ -146,6 +146,11 @@ await cmd`sync environment variables from package.json to matching files`
|
|
|
146
146
|
files.push(...expandPattern(p))
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
+
// ensure .env is always processed (may not exist yet for fresh projects)
|
|
150
|
+
if (!files.includes('.env')) {
|
|
151
|
+
files.push('.env')
|
|
152
|
+
}
|
|
153
|
+
|
|
149
154
|
// markers
|
|
150
155
|
const markerStart = 'š start - this is generated by "bun env:update"'
|
|
151
156
|
const markerEnd = 'š end - this is generated by "bun env:update"'
|
|
@@ -154,7 +159,16 @@ await cmd`sync environment variables from package.json to matching files`
|
|
|
154
159
|
const jsStart = `// ${markerStart}`
|
|
155
160
|
const jsEnd = `// ${markerEnd}`
|
|
156
161
|
|
|
157
|
-
|
|
162
|
+
// .env auto-generated section markers
|
|
163
|
+
const dotenvSectionStart = '# ---- BEGIN AUTO-GENERATED (DO NOT EDIT) ----'
|
|
164
|
+
const dotenvSectionEnd = '# ---- END AUTO-GENERATED ----'
|
|
165
|
+
|
|
166
|
+
type Strategy =
|
|
167
|
+
| 'yaml-markers'
|
|
168
|
+
| 'js-markers'
|
|
169
|
+
| 'dotenv-section'
|
|
170
|
+
| 'dotenv-inline'
|
|
171
|
+
| 'ts-inline'
|
|
158
172
|
|
|
159
173
|
function detectStrategy(filePath: string, content: string): Strategy | null {
|
|
160
174
|
if (content.includes(yamlStart) && content.includes(yamlEnd)) {
|
|
@@ -163,7 +177,11 @@ await cmd`sync environment variables from package.json to matching files`
|
|
|
163
177
|
if (content.includes(jsStart) && content.includes(jsEnd)) {
|
|
164
178
|
return 'js-markers'
|
|
165
179
|
}
|
|
166
|
-
|
|
180
|
+
const basename = path.basename(filePath)
|
|
181
|
+
if (basename === '.env') {
|
|
182
|
+
return 'dotenv-section'
|
|
183
|
+
}
|
|
184
|
+
if (/^\.env/.test(basename)) {
|
|
167
185
|
return 'dotenv-inline'
|
|
168
186
|
}
|
|
169
187
|
if (filePath.endsWith('.ts') && Object.keys(depResolved).length > 0) {
|
|
@@ -234,6 +252,39 @@ await cmd`sync environment variables from package.json to matching files`
|
|
|
234
252
|
return replaceMarkerSection(content, jsStart, jsEnd, envExports)
|
|
235
253
|
}
|
|
236
254
|
|
|
255
|
+
function applyDotenvSection(_filePath: string, content: string): string {
|
|
256
|
+
const lines: string[] = [dotenvSectionStart]
|
|
257
|
+
|
|
258
|
+
for (const [key, value] of Object.entries(envVars)) {
|
|
259
|
+
const dep = resolveDepVersion(value, packageJson.dependencies)
|
|
260
|
+
if (dep) {
|
|
261
|
+
lines.push(`${key}=${dep}`)
|
|
262
|
+
} else if (typeof value === 'string' && value.startsWith('$dep:')) {
|
|
263
|
+
console.warn(
|
|
264
|
+
`could not resolve dependency version for ${value.slice('$dep:'.length)}`
|
|
265
|
+
)
|
|
266
|
+
} else if (typeof value === 'string' && value !== '') {
|
|
267
|
+
lines.push(`${key}=${value}`)
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
lines.push(dotenvSectionEnd)
|
|
272
|
+
const section = lines.join('\n')
|
|
273
|
+
|
|
274
|
+
const beginIndex = content.indexOf(dotenvSectionStart)
|
|
275
|
+
const endIndex = content.indexOf(dotenvSectionEnd)
|
|
276
|
+
|
|
277
|
+
if (beginIndex !== -1 && endIndex !== -1 && endIndex > beginIndex) {
|
|
278
|
+
const before = content.substring(0, beginIndex).trimEnd()
|
|
279
|
+
const after = content.substring(endIndex + dotenvSectionEnd.length).trimStart()
|
|
280
|
+
return [before, section, after].filter(Boolean).join('\n\n')
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// no existing section ā append
|
|
284
|
+
const trimmed = content.trimEnd()
|
|
285
|
+
return trimmed ? `${trimmed}\n\n${section}` : section
|
|
286
|
+
}
|
|
287
|
+
|
|
237
288
|
function applyDotenvInline(_filePath: string, content: string): string {
|
|
238
289
|
let result = content
|
|
239
290
|
for (const [key, value] of Object.entries(depResolved)) {
|
|
@@ -261,6 +312,7 @@ await cmd`sync environment variables from package.json to matching files`
|
|
|
261
312
|
const strategies: Record<Strategy, (filePath: string, content: string) => string> = {
|
|
262
313
|
'yaml-markers': applyYamlMarkers,
|
|
263
314
|
'js-markers': applyJsMarkers,
|
|
315
|
+
'dotenv-section': applyDotenvSection,
|
|
264
316
|
'dotenv-inline': applyDotenvInline,
|
|
265
317
|
'ts-inline': applyTsInline,
|
|
266
318
|
}
|
|
@@ -272,7 +324,12 @@ await cmd`sync environment variables from package.json to matching files`
|
|
|
272
324
|
try {
|
|
273
325
|
content = fs.readFileSync(filePath, 'utf-8')
|
|
274
326
|
} catch {
|
|
275
|
-
|
|
327
|
+
// allow .env to be created from scratch
|
|
328
|
+
if (path.basename(filePath) === '.env') {
|
|
329
|
+
content = ''
|
|
330
|
+
} else {
|
|
331
|
+
continue
|
|
332
|
+
}
|
|
276
333
|
}
|
|
277
334
|
|
|
278
335
|
const strategy = detectStrategy(filePath, content)
|
package/src/up.ts
CHANGED
|
@@ -426,10 +426,14 @@ await cmd`upgrade packages by name or pattern`
|
|
|
426
426
|
|
|
427
427
|
await updatePackages(packagesByWorkspace, rootDir, packageJsonFiles)
|
|
428
428
|
|
|
429
|
-
//
|
|
430
|
-
if (
|
|
431
|
-
|
|
432
|
-
|
|
429
|
+
// sync resolved $dep: values (like ZERO_VERSION) to all env targets
|
|
430
|
+
if (
|
|
431
|
+
Object.values(packageJson.env || {}).some(
|
|
432
|
+
(v: any) => typeof v === 'string' && v.startsWith('$dep:')
|
|
433
|
+
)
|
|
434
|
+
) {
|
|
435
|
+
console.info('\nš Syncing env variables...')
|
|
436
|
+
await $`bun tko run env-update`
|
|
433
437
|
}
|
|
434
438
|
|
|
435
439
|
console.info('\nš Dependency update complete!')
|
package/src/generate-env.ts
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
|
|
3
|
-
import fs from 'node:fs'
|
|
4
|
-
|
|
5
|
-
import { cmd } from './cmd'
|
|
6
|
-
import { resolveDepVersion } from './helpers/resolve-dep-version'
|
|
7
|
-
|
|
8
|
-
await cmd`sync auto-generated env vars to local .env file`.run(async ({ path }) => {
|
|
9
|
-
const ENV_PATH = path.join(process.cwd(), '.env')
|
|
10
|
-
const ENV_BACKUP_PATH = path.join(process.cwd(), '.env.backup')
|
|
11
|
-
const ENV_TEMP_PATH = path.join(process.cwd(), '.env.tmp')
|
|
12
|
-
|
|
13
|
-
// auto-generated section markers
|
|
14
|
-
const BEGIN_MARKER = '# ---- BEGIN AUTO-GENERATED (DO NOT EDIT) ----'
|
|
15
|
-
const END_MARKER = '# ---- END AUTO-GENERATED ----'
|
|
16
|
-
|
|
17
|
-
function getAutoGeneratedContent(): string {
|
|
18
|
-
const packageJsonPath = path.join(process.cwd(), 'package.json')
|
|
19
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'))
|
|
20
|
-
const envVars = packageJson.env as Record<string, boolean | string>
|
|
21
|
-
|
|
22
|
-
if (!envVars || typeof envVars !== 'object') {
|
|
23
|
-
console.warn('No env section found in package.json')
|
|
24
|
-
return ''
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const lines: string[] = [BEGIN_MARKER, `# Generated at: ${new Date().toISOString()}`]
|
|
28
|
-
|
|
29
|
-
for (const [key, value] of Object.entries(envVars)) {
|
|
30
|
-
const depVersion = resolveDepVersion(value, packageJson.dependencies)
|
|
31
|
-
if (depVersion) {
|
|
32
|
-
lines.push(`${key}=${depVersion}`)
|
|
33
|
-
} else if (typeof value === 'string' && value.startsWith('$dep:')) {
|
|
34
|
-
console.warn(
|
|
35
|
-
`Could not resolve dependency version for ${value.slice('$dep:'.length)}`
|
|
36
|
-
)
|
|
37
|
-
} else if (typeof value === 'string' && value !== '') {
|
|
38
|
-
// non-empty string default
|
|
39
|
-
lines.push(`${key}=${value}`)
|
|
40
|
-
}
|
|
41
|
-
// skip true (required, no default) and "" (no meaningful default)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
lines.push(END_MARKER)
|
|
45
|
-
return lines.join('\n')
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function updateEnvFile(): void {
|
|
49
|
-
// ensure .env exists
|
|
50
|
-
if (!fs.existsSync(ENV_PATH)) {
|
|
51
|
-
fs.writeFileSync(ENV_PATH, '')
|
|
52
|
-
console.info('Created empty .env file')
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
try {
|
|
56
|
-
// create backup
|
|
57
|
-
if (fs.existsSync(ENV_PATH)) {
|
|
58
|
-
fs.copyFileSync(ENV_PATH, ENV_BACKUP_PATH)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const currentContent = fs.readFileSync(ENV_PATH, 'utf-8')
|
|
62
|
-
|
|
63
|
-
const beginIndex = currentContent.indexOf(BEGIN_MARKER)
|
|
64
|
-
const endIndex = currentContent.indexOf(END_MARKER)
|
|
65
|
-
|
|
66
|
-
let newContent: string
|
|
67
|
-
|
|
68
|
-
if (beginIndex !== -1 && endIndex !== -1 && endIndex > beginIndex) {
|
|
69
|
-
// replace existing auto-generated section
|
|
70
|
-
const beforeSection = currentContent.substring(0, beginIndex).trimEnd()
|
|
71
|
-
const afterSection = currentContent
|
|
72
|
-
.substring(endIndex + END_MARKER.length)
|
|
73
|
-
.trimStart()
|
|
74
|
-
|
|
75
|
-
newContent = [beforeSection, getAutoGeneratedContent(), afterSection]
|
|
76
|
-
.filter(Boolean)
|
|
77
|
-
.join('\n\n')
|
|
78
|
-
} else if (beginIndex !== -1 || endIndex !== -1) {
|
|
79
|
-
// malformed markers - preserve content and append new section
|
|
80
|
-
console.warn('Found malformed auto-generated section, appending new section')
|
|
81
|
-
newContent = currentContent.trimEnd() + '\n\n' + getAutoGeneratedContent()
|
|
82
|
-
} else {
|
|
83
|
-
// no existing section - append to end
|
|
84
|
-
const trimmedContent = currentContent.trimEnd()
|
|
85
|
-
newContent = trimmedContent
|
|
86
|
-
? trimmedContent + '\n\n' + getAutoGeneratedContent()
|
|
87
|
-
: getAutoGeneratedContent()
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// write to temp file first (atomic operation)
|
|
91
|
-
fs.writeFileSync(ENV_TEMP_PATH, newContent)
|
|
92
|
-
|
|
93
|
-
// validate temp file
|
|
94
|
-
const tempContent = fs.readFileSync(ENV_TEMP_PATH, 'utf-8')
|
|
95
|
-
if (!tempContent.includes(BEGIN_MARKER) || !tempContent.includes(END_MARKER)) {
|
|
96
|
-
throw new Error('Generated content validation failed')
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// atomic replace
|
|
100
|
-
fs.renameSync(ENV_TEMP_PATH, ENV_PATH)
|
|
101
|
-
|
|
102
|
-
if (fs.existsSync(ENV_BACKUP_PATH)) {
|
|
103
|
-
try {
|
|
104
|
-
fs.unlinkSync(ENV_BACKUP_PATH)
|
|
105
|
-
} catch {
|
|
106
|
-
// ignore cleanup errors
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
console.info('Updated .env auto-generated section')
|
|
111
|
-
} catch (error) {
|
|
112
|
-
console.error('Failed to update .env file:', error)
|
|
113
|
-
|
|
114
|
-
// attempt to restore backup
|
|
115
|
-
if (fs.existsSync(ENV_BACKUP_PATH)) {
|
|
116
|
-
try {
|
|
117
|
-
fs.copyFileSync(ENV_BACKUP_PATH, ENV_PATH)
|
|
118
|
-
console.info('Restored .env from backup')
|
|
119
|
-
} catch (restoreError) {
|
|
120
|
-
console.error('Failed to restore backup:', restoreError)
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// clean up temp file
|
|
125
|
-
if (fs.existsSync(ENV_TEMP_PATH)) {
|
|
126
|
-
try {
|
|
127
|
-
fs.unlinkSync(ENV_TEMP_PATH)
|
|
128
|
-
} catch {
|
|
129
|
-
// ignore cleanup errors
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// don't fail the install process
|
|
134
|
-
process.exit(0)
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
try {
|
|
139
|
-
updateEnvFile()
|
|
140
|
-
} catch (error) {
|
|
141
|
-
// catch any unexpected errors and exit gracefully
|
|
142
|
-
console.error('Bootstrap script error:', error)
|
|
143
|
-
process.exit(0)
|
|
144
|
-
}
|
|
145
|
-
})
|