@udondan/avanti 0.1.0 → 0.3.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/CHANGELOG.md +25 -0
- package/README.md +254 -14
- package/dist/cli.js +2 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/diff.d.ts.map +1 -1
- package/dist/commands/diff.js +9 -5
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/pull.d.ts.map +1 -1
- package/dist/commands/pull.js +9 -5
- package/dist/commands/pull.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +85 -55
- package/dist/config.js.map +1 -1
- package/dist/diff.d.ts +2 -1
- package/dist/diff.d.ts.map +1 -1
- package/dist/diff.js +42 -18
- package/dist/diff.js.map +1 -1
- package/dist/processors/post.d.ts +2 -1
- package/dist/processors/post.d.ts.map +1 -1
- package/dist/processors/post.js +7 -5
- package/dist/processors/post.js.map +1 -1
- package/dist/processors/replace.d.ts +2 -2
- package/dist/processors/replace.d.ts.map +1 -1
- package/dist/processors/replace.js +8 -5
- package/dist/processors/replace.js.map +1 -1
- package/dist/sources/exec.js +3 -3
- package/dist/sources/github.js +15 -15
- package/dist/sources/gitlab.js +11 -11
- package/dist/sources/http.js +5 -5
- package/dist/sources/index.d.ts +2 -2
- package/dist/sources/index.d.ts.map +1 -1
- package/dist/sources/index.js +47 -30
- package/dist/sources/index.js.map +1 -1
- package/dist/sources/local.d.ts +1 -1
- package/dist/sources/local.d.ts.map +1 -1
- package/dist/sources/local.js +12 -9
- package/dist/sources/local.js.map +1 -1
- package/dist/types.d.ts +7 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/variables.d.ts +5 -0
- package/dist/variables.d.ts.map +1 -0
- package/dist/variables.js +34 -0
- package/dist/variables.js.map +1 -0
- package/dist/writer.js +3 -3
- package/package.json +19 -7
- package/.claude/settings.local.json +0 -9
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.3.0](https://github.com/udondan/avanti/compare/v0.2.1...v0.3.0) (2026-05-07)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add inline raw source content ([#7](https://github.com/udondan/avanti/issues/7)) ([dd46cba](https://github.com/udondan/avanti/commit/dd46cba2a8a79f2882847a7da3beaf5ae002b799))
|
|
9
|
+
* add variables and env var support ([#10](https://github.com/udondan/avanti/issues/10)) ([c5eea93](https://github.com/udondan/avanti/commit/c5eea9374d3fb3aeeb6413e6bf6aecfe825465b4))
|
|
10
|
+
* add working directory constraint and -w/--working-dir flag ([#9](https://github.com/udondan/avanti/issues/9)) ([5cc731e](https://github.com/udondan/avanti/commit/5cc731e223e4dca893f26f64158f2377c077cbe8))
|
|
11
|
+
* resolve variables in target path ([#12](https://github.com/udondan/avanti/issues/12)) ([9aa64fb](https://github.com/udondan/avanti/commit/9aa64fb121ad5a9a052df5ac2afa096fcf1f728a))
|
|
12
|
+
|
|
13
|
+
## [0.2.1](https://github.com/udondan/avanti/compare/v0.2.0...v0.2.1) (2026-05-07)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Bug Fixes
|
|
17
|
+
|
|
18
|
+
* add repository url to package.json ([#5](https://github.com/udondan/avanti/issues/5)) ([842c843](https://github.com/udondan/avanti/commit/842c843f433243b1ef131f0e9192e10fb7816e98))
|
|
19
|
+
|
|
20
|
+
## [0.2.0](https://github.com/udondan/avanti/compare/v0.1.0...v0.2.0) (2026-05-07)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Features
|
|
24
|
+
|
|
25
|
+
* initial implementation ([#1](https://github.com/udondan/avanti/issues/1)) ([a97bbfa](https://github.com/udondan/avanti/commit/a97bbfa0fb07b9bb0dc6518bf8345aaf789bf09f))
|
package/README.md
CHANGED
|
@@ -4,12 +4,13 @@ Assemble local files from any source via a declarative YAML spec.
|
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- Fetch files from **HTTP/HTTPS**, **local paths**, **GitLab** (via `glab`), **GitHub** (via `gh`),
|
|
7
|
+
- Fetch files from **HTTP/HTTPS**, **local paths**, **GitLab** (via `glab`), **GitHub** (via `gh`), **shell commands**, or **inline raw content**
|
|
8
8
|
- **Multi-source entries** — combine multiple sources into a single file by providing `src` as a list
|
|
9
9
|
- **Atomic writes** — all files are staged to a temp dir first; targets are only written if everything succeeds
|
|
10
10
|
- **Diff preview** — see exactly what will change before applying
|
|
11
11
|
- **Post-processing** — apply text replacements (string or regex) and/or pipe content through a shell script
|
|
12
12
|
- **Directory sync** — recursively sync directories from GitLab/GitHub/local sources
|
|
13
|
+
- **Variables** — define reusable values in a `variables:` block and reference them anywhere with `$name`; use `$env:NAME` for environment variables
|
|
13
14
|
|
|
14
15
|
## Requirements
|
|
15
16
|
|
|
@@ -35,11 +36,12 @@ npx @udondan/avanti --help
|
|
|
35
36
|
avanti [options] [command]
|
|
36
37
|
|
|
37
38
|
Options:
|
|
38
|
-
-c, --config <path>
|
|
39
|
+
-c, --config <path> path to config file (default: auto-detected)
|
|
40
|
+
-w, --working-dir <path> working directory for resolving paths (default: current directory)
|
|
39
41
|
|
|
40
42
|
Commands:
|
|
41
|
-
diff
|
|
42
|
-
pull [--yes]
|
|
43
|
+
diff Show diff between remote sources and local files
|
|
44
|
+
pull [--yes] Pull remote sources and write to local files
|
|
43
45
|
```
|
|
44
46
|
|
|
45
47
|
### `avanti diff`
|
|
@@ -50,6 +52,28 @@ Shows a colored git-diff-like output of what would change. Exits `0` if no chang
|
|
|
50
52
|
|
|
51
53
|
Fetches all sources, shows the diff, and prompts for confirmation before writing. Use `--yes` to skip the prompt.
|
|
52
54
|
|
|
55
|
+
## Working Directory
|
|
56
|
+
|
|
57
|
+
All relative `src` and `target` paths are resolved relative to the **working directory** — the directory where you invoke `avanti`, or the path given with `-C`.
|
|
58
|
+
|
|
59
|
+
This is independent of where the config file lives. A config loaded from another directory with `-c /shared/avanti.yml` still resolves all paths from your working directory (or the one you specify with `-C`).
|
|
60
|
+
|
|
61
|
+
Use `-C` to deploy the same config to multiple locations without `cd`-ing there first:
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
avanti -c /shared/avanti.yml -C /project-a pull
|
|
65
|
+
avanti -c /shared/avanti.yml -C /project-b pull
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Path Constraints
|
|
69
|
+
|
|
70
|
+
Avanti enforces that target paths cannot escape the working directory:
|
|
71
|
+
|
|
72
|
+
- **Relative targets** are resolved under the working directory. A path like `../../etc/passwd` is rejected.
|
|
73
|
+
- **Absolute targets** (e.g. `/etc/hosts`) are only permitted when the working directory is `/`. If your working directory is any other path, absolute targets are an error.
|
|
74
|
+
|
|
75
|
+
These rules apply to `target` values in your config. Source (`src`) paths are reads-only and are not restricted.
|
|
76
|
+
|
|
53
77
|
## Configuration
|
|
54
78
|
|
|
55
79
|
Create one of the following files in your project root (searched in this order, case-insensitive):
|
|
@@ -62,12 +86,15 @@ Create one of the following files in your project root (searched in this order,
|
|
|
62
86
|
Example:
|
|
63
87
|
|
|
64
88
|
```yaml
|
|
89
|
+
variables:
|
|
90
|
+
email: you@example.com
|
|
91
|
+
|
|
65
92
|
files:
|
|
66
93
|
- src: http://www.example.com/example.yml
|
|
67
94
|
target: my-example.yml
|
|
68
95
|
replace:
|
|
69
96
|
- from: '{EMAIL}'
|
|
70
|
-
to:
|
|
97
|
+
to: $email
|
|
71
98
|
- from: /\d+/
|
|
72
99
|
to: number
|
|
73
100
|
|
|
@@ -97,14 +124,14 @@ files:
|
|
|
97
124
|
|
|
98
125
|
### File Entry Fields
|
|
99
126
|
|
|
100
|
-
| Field | Required | Description
|
|
101
|
-
| --------- | ----------- |
|
|
102
|
-
| `src` | Yes | Source (see below). May be a single source or a **list** of sources to concatenate.
|
|
103
|
-
| `target` | Conditional | Local path to write to. Required for `exec:` sources and when `src` is a list. May be omitted when filename is inferable. |
|
|
104
|
-
| `ref` | No | Branch, tag, or `$latest` (resolves to latest tag). GitLab/GitHub only.
|
|
105
|
-
| `mode` | No | File permission mode, e.g. `"0755"`
|
|
106
|
-
| `replace` | No | List of `{from, to}` replacement rules. `from` may be a plain string or `/pattern/flags` regex.
|
|
107
|
-
| `post` | No | Shell script. Content is piped via stdin; stdout is used as the result. Runs after `replace`.
|
|
127
|
+
| Field | Required | Description |
|
|
128
|
+
| --------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
129
|
+
| `src` | Yes | Source (see below). May be a single source or a **list** of sources to concatenate. |
|
|
130
|
+
| `target` | Conditional | Local path to write to. Required for `exec:` and `raw:` sources and when `src` is a list. May be omitted when filename is inferable. |
|
|
131
|
+
| `ref` | No | Branch, tag, or `$latest` (resolves to latest tag). GitLab/GitHub only. |
|
|
132
|
+
| `mode` | No | File permission mode, e.g. `"0755"` |
|
|
133
|
+
| `replace` | No | List of `{from, to}` replacement rules. `from` may be a plain string or `/pattern/flags` regex. |
|
|
134
|
+
| `post` | No | Shell script. Content is piped via stdin; stdout is used as the result. Runs after `replace`. |
|
|
108
135
|
|
|
109
136
|
### Source Types
|
|
110
137
|
|
|
@@ -116,12 +143,16 @@ src: ~/templates/file.txt
|
|
|
116
143
|
src: /absolute/path/file.txt
|
|
117
144
|
```
|
|
118
145
|
|
|
119
|
-
**Map** — for exec, gitlab, github:
|
|
146
|
+
**Map** — for exec, gitlab, github, raw:
|
|
120
147
|
|
|
121
148
|
```yaml
|
|
122
149
|
src:
|
|
123
150
|
exec: <shell command> # stdout becomes file content; target required
|
|
124
151
|
|
|
152
|
+
src:
|
|
153
|
+
raw: | # inline content; target required
|
|
154
|
+
your content here
|
|
155
|
+
|
|
125
156
|
src:
|
|
126
157
|
gitlab:
|
|
127
158
|
project: group/repo # GitLab project path
|
|
@@ -150,6 +181,215 @@ target: combined.txt
|
|
|
150
181
|
|
|
151
182
|
Sources are fetched in order and joined with a newline. Post-processing (`replace`, `post`) is applied to the combined result. If any source fails, the entire entry is aborted.
|
|
152
183
|
|
|
184
|
+
### Variables
|
|
185
|
+
|
|
186
|
+
Define reusable values at the top level under `variables:`:
|
|
187
|
+
|
|
188
|
+
```yaml
|
|
189
|
+
variables:
|
|
190
|
+
email: you@example.com
|
|
191
|
+
version: '1.2.3'
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Reference them anywhere in the config with `$name`:
|
|
195
|
+
|
|
196
|
+
```yaml
|
|
197
|
+
files:
|
|
198
|
+
- src:
|
|
199
|
+
gitlab:
|
|
200
|
+
project: group/project
|
|
201
|
+
file: renovate.json
|
|
202
|
+
ref: $version # resolved to "1.2.3"
|
|
203
|
+
replace:
|
|
204
|
+
- from: '{EMAIL}'
|
|
205
|
+
to: $email # resolved to "you@example.com"
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Variables are resolved in every string field: `target`, `ref`, `exec` commands, HTTP URLs, local paths, `raw` content, `replace` rules (`from` and `to`), and `post` scripts.
|
|
209
|
+
|
|
210
|
+
**Environment variables** use the `$env:NAME` form:
|
|
211
|
+
|
|
212
|
+
```yaml
|
|
213
|
+
replace:
|
|
214
|
+
- from: /secret-token/
|
|
215
|
+
to: $env:MY_SECRET # reads process.env.MY_SECRET at runtime
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Referencing an undefined variable or a missing environment variable is an error.
|
|
219
|
+
|
|
220
|
+
`$latest` is reserved for GitLab's "latest tag" resolution and cannot be used as a variable name.
|
|
221
|
+
|
|
222
|
+
## Use Cases
|
|
223
|
+
|
|
224
|
+
### Composable AI Agent Instructions (CLAUDE.md / AGENTS.md)
|
|
225
|
+
|
|
226
|
+
Assemble agent instruction files from multiple sources: a static header defined inline, team-specific rules from a shared GitLab repo, and company-wide standards from GitHub — all merged into one file. Every developer runs `avanti pull` and stays in sync without copy-paste drift across dozens of repos.
|
|
227
|
+
|
|
228
|
+
```yaml
|
|
229
|
+
# .avanti.yml
|
|
230
|
+
variables:
|
|
231
|
+
team: backend
|
|
232
|
+
jira_project: BE
|
|
233
|
+
oncall_channel: '#backend-oncall'
|
|
234
|
+
|
|
235
|
+
files:
|
|
236
|
+
- src:
|
|
237
|
+
- raw: |
|
|
238
|
+
# AI Assistant Guidelines
|
|
239
|
+
<!-- THIS FILE IS MANAGED — run `avanti pull` to update -->
|
|
240
|
+
- gitlab:
|
|
241
|
+
project: platform/ai-standards
|
|
242
|
+
file: teams/backend-rules.md
|
|
243
|
+
ref: main
|
|
244
|
+
- github:
|
|
245
|
+
repo: org/shared-prompts
|
|
246
|
+
file: company-standards.md
|
|
247
|
+
ref: main
|
|
248
|
+
- raw: |
|
|
249
|
+
## Team Context
|
|
250
|
+
Team: $team
|
|
251
|
+
Jira project: $jira_project
|
|
252
|
+
Oncall: $oncall_channel
|
|
253
|
+
target: CLAUDE.md
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Shared Tooling Config (Renovate, ESLint, Prettier, TSConfig)
|
|
257
|
+
|
|
258
|
+
A platform team owns canonical configs in a central repo. Projects pull them and stay current. Pin all files to the same version in one place — bump `standards_ref` and `avanti diff` shows every file that will change before you apply it.
|
|
259
|
+
|
|
260
|
+
```yaml
|
|
261
|
+
variables:
|
|
262
|
+
standards_ref: v2.4.1
|
|
263
|
+
|
|
264
|
+
files:
|
|
265
|
+
- src:
|
|
266
|
+
github:
|
|
267
|
+
repo: org/standards
|
|
268
|
+
file: renovate.json
|
|
269
|
+
ref: $standards_ref
|
|
270
|
+
|
|
271
|
+
- src:
|
|
272
|
+
github:
|
|
273
|
+
repo: org/standards
|
|
274
|
+
file: eslint.config.js
|
|
275
|
+
ref: $standards_ref
|
|
276
|
+
|
|
277
|
+
- src:
|
|
278
|
+
github:
|
|
279
|
+
repo: org/standards
|
|
280
|
+
file: tsconfig.base.json
|
|
281
|
+
ref: $standards_ref
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### CI/CD: Shared Workflow Fragments
|
|
285
|
+
|
|
286
|
+
Pull reusable CI steps from a central repo into each project. A managed header makes it obvious the file should not be edited by hand.
|
|
287
|
+
|
|
288
|
+
```yaml
|
|
289
|
+
files:
|
|
290
|
+
- src:
|
|
291
|
+
- raw: |
|
|
292
|
+
# THIS FILE IS MANAGED — run `avanti pull` to update
|
|
293
|
+
- github:
|
|
294
|
+
repo: org/ci-templates
|
|
295
|
+
file: workflows/security-scan.yml
|
|
296
|
+
ref: main
|
|
297
|
+
target: .github/workflows/security-scan.yml
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Use `avanti diff` in CI to detect drift — if a project's checked-in file no longer matches the source, the pipeline fails.
|
|
301
|
+
|
|
302
|
+
### Environment-Specific Config from a Single Spec
|
|
303
|
+
|
|
304
|
+
One config file adapts to any environment via variables and env vars. No duplicate specs, no templating hacks.
|
|
305
|
+
|
|
306
|
+
```yaml
|
|
307
|
+
variables:
|
|
308
|
+
region: eu-west-1
|
|
309
|
+
|
|
310
|
+
files:
|
|
311
|
+
- src:
|
|
312
|
+
github:
|
|
313
|
+
repo: org/infra
|
|
314
|
+
file: k8s/deployment-template.yaml
|
|
315
|
+
ref: $env:DEPLOY_VERSION
|
|
316
|
+
target: k8s/deployment.yaml
|
|
317
|
+
replace:
|
|
318
|
+
- from: '{ENV}'
|
|
319
|
+
to: $env:ENVIRONMENT
|
|
320
|
+
- from: '{REGION}'
|
|
321
|
+
to: $region
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
CI sets `DEPLOY_VERSION` and `ENVIRONMENT`; the config pins every file to exactly the version being deployed.
|
|
325
|
+
|
|
326
|
+
### Secrets from Vault or AWS SSM
|
|
327
|
+
|
|
328
|
+
Use `exec:` to pull secrets at runtime and write them to a local file. Config variables handle structure; env vars keep credentials out of git.
|
|
329
|
+
|
|
330
|
+
```yaml
|
|
331
|
+
variables:
|
|
332
|
+
org: acme
|
|
333
|
+
region: us-east-1
|
|
334
|
+
|
|
335
|
+
files:
|
|
336
|
+
- src:
|
|
337
|
+
exec: >
|
|
338
|
+
aws ssm get-parameter
|
|
339
|
+
--name /$org/$region/db-config
|
|
340
|
+
--profile $env:AWS_PROFILE
|
|
341
|
+
--with-decryption
|
|
342
|
+
--query Parameter.Value --output text
|
|
343
|
+
target: config/db.json
|
|
344
|
+
mode: '0600'
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Multi-Project Deployment
|
|
348
|
+
|
|
349
|
+
Pair a shared config with `-w` to stamp files across many service directories without duplicating the spec:
|
|
350
|
+
|
|
351
|
+
```sh
|
|
352
|
+
for dir in services/*/; do
|
|
353
|
+
avanti -c shared/avanti.yml -w "$dir" pull --yes
|
|
354
|
+
done
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Developer Onboarding Bootstrap
|
|
358
|
+
|
|
359
|
+
A single `avanti pull` populates a new project with everything it needs: editor config, CI workflows, linting rules, AI instructions — all from blessed central sources, all up to date.
|
|
360
|
+
|
|
361
|
+
```yaml
|
|
362
|
+
files:
|
|
363
|
+
- src:
|
|
364
|
+
github:
|
|
365
|
+
repo: org/standards
|
|
366
|
+
file: .editorconfig
|
|
367
|
+
ref: main
|
|
368
|
+
|
|
369
|
+
- src:
|
|
370
|
+
github:
|
|
371
|
+
repo: org/standards
|
|
372
|
+
file: .prettierrc
|
|
373
|
+
ref: main
|
|
374
|
+
|
|
375
|
+
- src:
|
|
376
|
+
- raw: |
|
|
377
|
+
# AI Assistant Guidelines
|
|
378
|
+
<!-- THIS FILE IS MANAGED — run `avanti pull` to update -->
|
|
379
|
+
- github:
|
|
380
|
+
repo: org/ai-standards
|
|
381
|
+
file: CLAUDE.md
|
|
382
|
+
ref: main
|
|
383
|
+
target: CLAUDE.md
|
|
384
|
+
|
|
385
|
+
- src:
|
|
386
|
+
github:
|
|
387
|
+
repo: org/ci-templates
|
|
388
|
+
file: workflows/
|
|
389
|
+
ref: main
|
|
390
|
+
target: .github/workflows/
|
|
391
|
+
```
|
|
392
|
+
|
|
153
393
|
## Exit Codes
|
|
154
394
|
|
|
155
395
|
| Code | Meaning |
|
package/dist/cli.js
CHANGED
|
@@ -9,7 +9,8 @@ program
|
|
|
9
9
|
.name('avanti')
|
|
10
10
|
.description('Assemble local files from any source via a declarative YAML spec')
|
|
11
11
|
.version('0.1.0')
|
|
12
|
-
.option('-c, --config <path>', 'path to config file')
|
|
12
|
+
.option('-c, --config <path>', 'path to config file')
|
|
13
|
+
.option('-w, --working-dir <path>', 'working directory for resolving relative paths (default: current directory)');
|
|
13
14
|
program.addCommand((0, diff_1.diffCommand)());
|
|
14
15
|
program.addCommand((0, pull_1.pullCommand)());
|
|
15
16
|
program.parse(process.argv);
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,0CAA8C;AAC9C,0CAA8C;AAE9C,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CACV,kEAAkE,CACnE;KACA,OAAO,CAAC,OAAO,CAAC;KAChB,MAAM,CAAC,qBAAqB,EAAE,qBAAqB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,0CAA8C;AAC9C,0CAA8C;AAE9C,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CACV,kEAAkE,CACnE;KACA,OAAO,CAAC,OAAO,CAAC;KAChB,MAAM,CAAC,qBAAqB,EAAE,qBAAqB,CAAC;KACpD,MAAM,CACL,0BAA0B,EAC1B,6EAA6E,CAC9E,CAAC;AAEJ,OAAO,CAAC,UAAU,CAAC,IAAA,kBAAW,GAAE,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,IAAA,kBAAW,GAAE,CAAC,CAAC;AAElC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,wBAAgB,WAAW,IAAI,OAAO,
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,wBAAgB,WAAW,IAAI,OAAO,CAsDrC"}
|
package/dist/commands/diff.js
CHANGED
|
@@ -36,6 +36,10 @@ function diffCommand() {
|
|
|
36
36
|
.description('Show diff between remote sources and local files')
|
|
37
37
|
.action(async (_options, cmd) => {
|
|
38
38
|
const configPath = (0, config_1.resolveConfigPath)(cmd.parent?.opts().config);
|
|
39
|
+
const rawWorkingDir = cmd.parent?.opts().workingDir;
|
|
40
|
+
const workingDir = rawWorkingDir
|
|
41
|
+
? path.resolve(rawWorkingDir)
|
|
42
|
+
: process.cwd();
|
|
39
43
|
let config;
|
|
40
44
|
try {
|
|
41
45
|
config = (0, config_1.loadConfig)(configPath);
|
|
@@ -44,19 +48,19 @@ function diffCommand() {
|
|
|
44
48
|
console.error(err.message);
|
|
45
49
|
process.exit(2);
|
|
46
50
|
}
|
|
47
|
-
const baseDir = path.dirname(configPath);
|
|
48
51
|
const allDiffs = [];
|
|
49
52
|
let hasError = false;
|
|
53
|
+
const vars = config.variables ?? {};
|
|
50
54
|
for (const entry of config.files) {
|
|
51
55
|
try {
|
|
52
|
-
const result = await (0, sources_1.fetchSource)(entry);
|
|
56
|
+
const result = await (0, sources_1.fetchSource)(entry, workingDir, vars);
|
|
53
57
|
for (const [relPath, rawContent] of result.files) {
|
|
54
58
|
let content = rawContent;
|
|
55
59
|
if (entry.replace?.length)
|
|
56
|
-
content = (0, replace_1.applyReplace)(content, entry.replace);
|
|
60
|
+
content = (0, replace_1.applyReplace)(content, entry.replace, vars);
|
|
57
61
|
if (entry.post)
|
|
58
|
-
content = (0, post_1.applyPost)(content, entry.post);
|
|
59
|
-
const targetPath = (0, diff_1.resolveTargetPath)(entry, relPath,
|
|
62
|
+
content = (0, post_1.applyPost)(content, entry.post, vars);
|
|
63
|
+
const targetPath = (0, diff_1.resolveTargetPath)(entry, relPath, workingDir, vars);
|
|
60
64
|
allDiffs.push((0, diff_1.computeDiff)(targetPath, content));
|
|
61
65
|
}
|
|
62
66
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yCAAoC;AACpC,2CAA6B;AAC7B,sCAA0D;AAC1D,wCAAyC;AACzC,mDAAqD;AACrD,6CAA+C;AAC/C,kCAAqE;AAGrE,SAAgB,WAAW;IACzB,OAAO,IAAI,mBAAO,CAAC,MAAM,CAAC;SACvB,WAAW,CAAC,kDAAkD,CAAC;SAC/D,MAAM,CAAC,KAAK,EAAE,QAAiB,EAAE,GAAY,EAAE,EAAE;QAChD,MAAM,UAAU,GAAG,IAAA,0BAAiB,EAClC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,MAA4B,CAChD,CAAC;QACF,IAAI,MAAM,CAAC;QACX,IAAI,CAAC;YACH,MAAM,GAAG,IAAA,mBAAU,EAAC,UAAU,CAAC,CAAC;QAClC,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,OAAO,CAAC,KAAK,CAAE,GAAa,CAAC,OAAO,CAAC,CAAC;YACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yCAAoC;AACpC,2CAA6B;AAC7B,sCAA0D;AAC1D,wCAAyC;AACzC,mDAAqD;AACrD,6CAA+C;AAC/C,kCAAqE;AAGrE,SAAgB,WAAW;IACzB,OAAO,IAAI,mBAAO,CAAC,MAAM,CAAC;SACvB,WAAW,CAAC,kDAAkD,CAAC;SAC/D,MAAM,CAAC,KAAK,EAAE,QAAiB,EAAE,GAAY,EAAE,EAAE;QAChD,MAAM,UAAU,GAAG,IAAA,0BAAiB,EAClC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,MAA4B,CAChD,CAAC;QACF,MAAM,aAAa,GAAG,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,UAAgC,CAAC;QAC1E,MAAM,UAAU,GAAG,aAAa;YAC9B,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC;YAC7B,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QAElB,IAAI,MAAM,CAAC;QACX,IAAI,CAAC;YACH,MAAM,GAAG,IAAA,mBAAU,EAAC,UAAU,CAAC,CAAC;QAClC,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,OAAO,CAAC,KAAK,CAAE,GAAa,CAAC,OAAO,CAAC,CAAC;YACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,QAAQ,GAAe,EAAE,CAAC;QAChC,IAAI,QAAQ,GAAG,KAAK,CAAC;QAErB,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC;QAEpC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjC,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAA,qBAAW,EAAC,KAAK,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;gBAC1D,KAAK,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;oBACjD,IAAI,OAAO,GAAG,UAAU,CAAC;oBACzB,IAAI,KAAK,CAAC,OAAO,EAAE,MAAM;wBACvB,OAAO,GAAG,IAAA,sBAAY,EAAC,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;oBACvD,IAAI,KAAK,CAAC,IAAI;wBAAE,OAAO,GAAG,IAAA,gBAAS,EAAC,OAAO,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;oBAC/D,MAAM,UAAU,GAAG,IAAA,wBAAiB,EAClC,KAAK,EACL,OAAO,EACP,UAAU,EACV,IAAI,CACL,CAAC;oBACF,QAAQ,CAAC,IAAI,CAAC,IAAA,kBAAW,EAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;gBAClD,CAAC;YACH,CAAC;YAAC,OAAO,GAAY,EAAE,CAAC;gBACtB,OAAO,CAAC,KAAK,CACX,oBAAoB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,KAAM,GAAa,CAAC,OAAO,EAAE,CAC3E,CAAC;gBACF,QAAQ,GAAG,IAAI,CAAC;YAClB,CAAC;QACH,CAAC;QAED,IAAA,iBAAU,EAAC,QAAQ,CAAC,CAAC;QAErB,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;QACtD,IAAI,QAAQ;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9B,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACP,CAAC;AAtDD,kCAsDC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2BpC,wBAAgB,WAAW,IAAI,OAAO,
|
|
1
|
+
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2BpC,wBAAgB,WAAW,IAAI,OAAO,CAkFrC"}
|
package/dist/commands/pull.js
CHANGED
|
@@ -52,6 +52,10 @@ function pullCommand() {
|
|
|
52
52
|
.option('-y, --yes', 'skip confirmation prompt')
|
|
53
53
|
.action(async (options, cmd) => {
|
|
54
54
|
const configPath = (0, config_1.resolveConfigPath)(cmd.parent?.opts().config);
|
|
55
|
+
const rawWorkingDir = cmd.parent?.opts().workingDir;
|
|
56
|
+
const workingDir = rawWorkingDir
|
|
57
|
+
? path.resolve(rawWorkingDir)
|
|
58
|
+
: process.cwd();
|
|
55
59
|
let config;
|
|
56
60
|
try {
|
|
57
61
|
config = (0, config_1.loadConfig)(configPath);
|
|
@@ -60,20 +64,20 @@ function pullCommand() {
|
|
|
60
64
|
console.error(err.message);
|
|
61
65
|
process.exit(2);
|
|
62
66
|
}
|
|
63
|
-
const baseDir = path.dirname(configPath);
|
|
64
67
|
const allDiffs = [];
|
|
65
68
|
const writeTargets = [];
|
|
66
69
|
let hasError = false;
|
|
70
|
+
const vars = config.variables ?? {};
|
|
67
71
|
for (const entry of config.files) {
|
|
68
72
|
try {
|
|
69
|
-
const result = await (0, sources_1.fetchSource)(entry);
|
|
73
|
+
const result = await (0, sources_1.fetchSource)(entry, workingDir, vars);
|
|
70
74
|
for (const [relPath, rawContent] of result.files) {
|
|
71
75
|
let content = rawContent;
|
|
72
76
|
if (entry.replace?.length)
|
|
73
|
-
content = (0, replace_1.applyReplace)(content, entry.replace);
|
|
77
|
+
content = (0, replace_1.applyReplace)(content, entry.replace, vars);
|
|
74
78
|
if (entry.post)
|
|
75
|
-
content = (0, post_1.applyPost)(content, entry.post);
|
|
76
|
-
const targetPath = (0, diff_1.resolveTargetPath)(entry, relPath,
|
|
79
|
+
content = (0, post_1.applyPost)(content, entry.post, vars);
|
|
80
|
+
const targetPath = (0, diff_1.resolveTargetPath)(entry, relPath, workingDir, vars);
|
|
77
81
|
allDiffs.push((0, diff_1.computeDiff)(targetPath, content));
|
|
78
82
|
writeTargets.push({ targetPath, content, mode: entry.mode });
|
|
79
83
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pull.js","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yCAAoC;AACpC,2CAA6B;AAC7B,mDAAqC;AACrC,sCAA0D;AAC1D,wCAAyC;AACzC,mDAAqD;AACrD,6CAA+C;AAC/C,kCAAqE;AACrE,sCAAqD;AAGrD,KAAK,UAAU,OAAO,CAAC,QAAgB;IACrC,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC;QAClC,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;IACH,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,EAAE;YAC/B,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CACL,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,GAAG;gBACjC,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,KAAK,CACxC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAgB,WAAW;IACzB,OAAO,IAAI,mBAAO,CAAC,MAAM,CAAC;SACvB,WAAW,CAAC,8CAA8C,CAAC;SAC3D,MAAM,CAAC,WAAW,EAAE,0BAA0B,CAAC;SAC/C,MAAM,CAAC,KAAK,EAAE,OAAgB,EAAE,GAAY,EAAE,EAAE;QAC/C,MAAM,UAAU,GAAG,IAAA,0BAAiB,EAClC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,MAA4B,CAChD,CAAC;QACF,IAAI,MAAM,CAAC;QACX,IAAI,CAAC;YACH,MAAM,GAAG,IAAA,mBAAU,EAAC,UAAU,CAAC,CAAC;QAClC,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,OAAO,CAAC,KAAK,CAAE,GAAa,CAAC,OAAO,CAAC,CAAC;YACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,
|
|
1
|
+
{"version":3,"file":"pull.js","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FileFerryConfig } from
|
|
1
|
+
import { FileFerryConfig } from './types';
|
|
2
2
|
export declare function resolveConfigPath(explicit?: string): string;
|
|
3
3
|
export declare function loadConfig(configPath: string): FileFerryConfig;
|
|
4
4
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,eAAe,EAKhB,MAAM,SAAS,CAAC;AAUjB,wBAAgB,iBAAiB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAa3D;AAED,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,CAyE9D"}
|