@ant.sh/colony 0.1.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 +172 -0
- package/dist/cjs/cli.js +281 -0
- package/dist/cjs/cli.js.map +7 -0
- package/dist/cjs/index.js +383 -0
- package/dist/cjs/index.js.map +7 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/parser.js +319 -0
- package/dist/cjs/parser.js.map +7 -0
- package/dist/cjs/providers/aws.js +115 -0
- package/dist/cjs/providers/aws.js.map +7 -0
- package/dist/cjs/providers/openbao.js +49 -0
- package/dist/cjs/providers/openbao.js.map +7 -0
- package/dist/cjs/providers/vault-base.js +98 -0
- package/dist/cjs/providers/vault-base.js.map +7 -0
- package/dist/cjs/providers/vault.js +49 -0
- package/dist/cjs/providers/vault.js.map +7 -0
- package/dist/cjs/resolver.js +247 -0
- package/dist/cjs/resolver.js.map +7 -0
- package/dist/cjs/secrets.js +238 -0
- package/dist/cjs/secrets.js.map +7 -0
- package/dist/cjs/strings.js +99 -0
- package/dist/cjs/strings.js.map +7 -0
- package/dist/cjs/util.js +74 -0
- package/dist/cjs/util.js.map +7 -0
- package/dist/esm/cli.js +281 -0
- package/dist/esm/cli.js.map +7 -0
- package/dist/esm/index.d.ts +342 -0
- package/dist/esm/index.js +347 -0
- package/dist/esm/index.js.map +7 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/parser.js +286 -0
- package/dist/esm/parser.js.map +7 -0
- package/dist/esm/providers/aws.js +82 -0
- package/dist/esm/providers/aws.js.map +7 -0
- package/dist/esm/providers/openbao.js +26 -0
- package/dist/esm/providers/openbao.js.map +7 -0
- package/dist/esm/providers/vault-base.js +75 -0
- package/dist/esm/providers/vault-base.js.map +7 -0
- package/dist/esm/providers/vault.js +26 -0
- package/dist/esm/providers/vault.js.map +7 -0
- package/dist/esm/resolver.js +224 -0
- package/dist/esm/resolver.js.map +7 -0
- package/dist/esm/secrets.js +209 -0
- package/dist/esm/secrets.js.map +7 -0
- package/dist/esm/strings.js +75 -0
- package/dist/esm/strings.js.map +7 -0
- package/dist/esm/util.js +47 -0
- package/dist/esm/util.js.map +7 -0
- package/package.json +66 -0
- package/src/cli.js +353 -0
- package/src/index.d.ts +342 -0
- package/src/index.js +473 -0
- package/src/parser.js +381 -0
- package/src/providers/aws.js +112 -0
- package/src/providers/openbao.js +32 -0
- package/src/providers/vault-base.js +92 -0
- package/src/providers/vault.js +31 -0
- package/src/resolver.js +286 -0
- package/src/secrets.js +313 -0
- package/src/strings.js +84 -0
- package/src/util.js +49 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 rune-config 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,172 @@
|
|
|
1
|
+
# Colony
|
|
2
|
+
|
|
3
|
+
**Environment-aware config for Node.js. One file, multiple environments.**
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@ant.sh/colony)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
# config/app.colony
|
|
10
|
+
*.database.host = "localhost";
|
|
11
|
+
prod.database.host = "prod-db.example.com";
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
```js
|
|
15
|
+
import { loadColony } from "@ant.sh/colony";
|
|
16
|
+
|
|
17
|
+
const config = await loadColony({
|
|
18
|
+
entry: "./config/app.colony",
|
|
19
|
+
ctx: { env: "prod" }
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
config.database.host // => "prod-db.example.com"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Features
|
|
26
|
+
|
|
27
|
+
- **Single config file** for all environments (dev, staging, prod)
|
|
28
|
+
- **Wildcard matching** - `*` sets defaults, specific rules override
|
|
29
|
+
- **Multiple dimensions** - env, region, feature flags, anything
|
|
30
|
+
- **Secret management** - AWS Secrets Manager, Vault, OpenBao
|
|
31
|
+
- **Interpolation** - `${ENV:VAR}`, `${ctx.region}`, `${VAR:custom}`
|
|
32
|
+
- **CLI tools** - validate, diff, lint, print
|
|
33
|
+
- **TypeScript** - Full type definitions included
|
|
34
|
+
- **Zero runtime deps** - Only `fast-glob` and `json5`
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm install @ant.sh/colony
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Quick Start
|
|
43
|
+
|
|
44
|
+
**1. Create `config/app.colony`**
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
@dims env;
|
|
48
|
+
|
|
49
|
+
# Defaults
|
|
50
|
+
*.app.name = "MyApp";
|
|
51
|
+
*.database.host = "localhost";
|
|
52
|
+
*.database.port = 5432;
|
|
53
|
+
|
|
54
|
+
# Production overrides
|
|
55
|
+
prod.database.host = "prod-db.example.com";
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**2. Load in your app**
|
|
59
|
+
|
|
60
|
+
```js
|
|
61
|
+
import { loadColony } from "@ant.sh/colony";
|
|
62
|
+
|
|
63
|
+
const config = await loadColony({
|
|
64
|
+
entry: "./config/app.colony",
|
|
65
|
+
ctx: { env: process.env.NODE_ENV || "dev" }
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
console.log(config.database.host);
|
|
69
|
+
// dev: "localhost"
|
|
70
|
+
// prod: "prod-db.example.com"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Multiple Dimensions
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
@dims env, region;
|
|
77
|
+
|
|
78
|
+
*.*.database.host = "localhost";
|
|
79
|
+
prod.*.database.host = "prod-db.example.com";
|
|
80
|
+
prod.eu.database.host = "prod-db-eu.example.com";
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
```js
|
|
84
|
+
const config = await loadColony({
|
|
85
|
+
entry: "./config/app.colony",
|
|
86
|
+
ctx: { env: "prod", region: "eu" }
|
|
87
|
+
});
|
|
88
|
+
// => "prod-db-eu.example.com"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Secrets Integration
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
*.db.password = "${AWS:myapp/db#password}";
|
|
95
|
+
*.api.key = "${OPENBAO:secret/data/app#api_key}";
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
```js
|
|
99
|
+
import { loadColony, AwsSecretsProvider, OpenBaoProvider } from "@ant.sh/colony";
|
|
100
|
+
|
|
101
|
+
const config = await loadColony({
|
|
102
|
+
entry: "./config/app.colony",
|
|
103
|
+
secrets: {
|
|
104
|
+
providers: [
|
|
105
|
+
new AwsSecretsProvider({ region: "us-east-1" }),
|
|
106
|
+
new OpenBaoProvider(),
|
|
107
|
+
],
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Built-in providers:** AWS Secrets Manager, HashiCorp Vault, OpenBao
|
|
113
|
+
|
|
114
|
+
## CLI
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
colony print --entry ./config/app.colony --ctx "env=prod"
|
|
118
|
+
colony diff --entry ./config/app.colony --ctx1 "env=dev" --ctx2 "env=prod"
|
|
119
|
+
colony validate --entry ./config/app.colony
|
|
120
|
+
colony lint --entry ./config/app.colony
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## package.json Setup
|
|
124
|
+
|
|
125
|
+
```json
|
|
126
|
+
{
|
|
127
|
+
"scripts": {
|
|
128
|
+
"dev": "NODE_ENV=dev node src/index.js",
|
|
129
|
+
"prod": "NODE_ENV=prod node src/index.js",
|
|
130
|
+
"start": "node src/index.js",
|
|
131
|
+
"config:validate": "colony validate --entry ./config/app.colony",
|
|
132
|
+
"config:lint": "colony lint --entry ./config/app.colony",
|
|
133
|
+
"config:diff": "colony diff --entry ./config/app.colony --ctx1 \"env=dev\" --ctx2 \"env=prod\""
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
npm run dev # Run with dev config
|
|
140
|
+
npm run prod # Run with prod config
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Your app picks up the environment automatically:
|
|
144
|
+
|
|
145
|
+
```js
|
|
146
|
+
// src/index.js
|
|
147
|
+
import { loadColony } from "@ant.sh/colony";
|
|
148
|
+
|
|
149
|
+
const config = await loadColony({
|
|
150
|
+
entry: "./config/app.colony",
|
|
151
|
+
ctx: { env: process.env.NODE_ENV || "dev" }
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
console.log(`Running in ${process.env.NODE_ENV} mode`);
|
|
155
|
+
console.log(`Database: ${config.database.host}`);
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Documentation
|
|
159
|
+
|
|
160
|
+
See [DOCS.md](./DOCS.md) for complete documentation including:
|
|
161
|
+
|
|
162
|
+
- Config syntax reference
|
|
163
|
+
- All operators (`=`, `:=`, `+=`, `-=`, `|=`)
|
|
164
|
+
- Interpolation patterns
|
|
165
|
+
- Secret providers
|
|
166
|
+
- Security sandbox options
|
|
167
|
+
- API reference
|
|
168
|
+
- TypeScript types
|
|
169
|
+
|
|
170
|
+
## License
|
|
171
|
+
|
|
172
|
+
MIT
|
package/dist/cjs/cli.js
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var import_index = require("./index.js");
|
|
3
|
+
var import_util = require("./util.js");
|
|
4
|
+
function parseArgs(argv) {
|
|
5
|
+
const args = { _: [] };
|
|
6
|
+
for (let i = 2; i < argv.length; i++) {
|
|
7
|
+
const a = argv[i];
|
|
8
|
+
if (a.startsWith("--")) {
|
|
9
|
+
const k = a.slice(2);
|
|
10
|
+
const v = i + 1 < argv.length && !argv[i + 1].startsWith("--") ? argv[++i] : true;
|
|
11
|
+
args[k] = v;
|
|
12
|
+
} else {
|
|
13
|
+
args._.push(a);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return args;
|
|
17
|
+
}
|
|
18
|
+
function parseCtx(s) {
|
|
19
|
+
const out = {};
|
|
20
|
+
if (!s || s === true) return out;
|
|
21
|
+
const parts = String(s).split(/\s+/).filter(Boolean);
|
|
22
|
+
for (const p of parts) {
|
|
23
|
+
const idx = p.indexOf("=");
|
|
24
|
+
if (idx === -1) continue;
|
|
25
|
+
out[p.slice(0, idx)] = p.slice(idx + 1);
|
|
26
|
+
}
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
29
|
+
function printUsage() {
|
|
30
|
+
console.error(`Usage:
|
|
31
|
+
colony print --entry ./config/app.colony [options]
|
|
32
|
+
colony validate --entry ./config/app.colony
|
|
33
|
+
colony dry-run --entry ./config/app.colony
|
|
34
|
+
colony diff --entry ./config/app.colony --ctx1 "env=dev" --ctx2 "env=prod"
|
|
35
|
+
colony keys --entry ./config/app.colony [--ctx "..."]
|
|
36
|
+
colony env --entry ./config/app.colony [--ctx "..."]
|
|
37
|
+
colony lint --entry ./config/app.colony
|
|
38
|
+
|
|
39
|
+
Commands:
|
|
40
|
+
print Resolve and print the configuration
|
|
41
|
+
validate Check syntax of all colony files without resolving
|
|
42
|
+
dry-run List all files that would be included
|
|
43
|
+
diff Compare configs between two contexts
|
|
44
|
+
keys List all config keys in dot notation
|
|
45
|
+
env Output config as KEY=value for shell sourcing
|
|
46
|
+
lint Check for potential issues (unused rules, shadows, etc.)
|
|
47
|
+
|
|
48
|
+
Options for 'print':
|
|
49
|
+
--entry <file> Entry colony file (required)
|
|
50
|
+
--dims <d1,d2,...> Dimension names (comma-separated)
|
|
51
|
+
--ctx "k1=v1 k2=v2" Context values (space-separated key=value pairs)
|
|
52
|
+
--format <json|env> Output format (default: json)
|
|
53
|
+
--query <key.path> Extract specific value (like jq)
|
|
54
|
+
--explain <key.path> Show which rule set a specific key
|
|
55
|
+
--base-path <dir> Restrict includes to this directory (security)
|
|
56
|
+
--allowed-env <v1,v2> Whitelist of allowed env vars (security)
|
|
57
|
+
--allowed-vars <v1,v2> Whitelist of allowed custom vars (security)
|
|
58
|
+
--max-file-size <bytes> Maximum file size for includes (security)
|
|
59
|
+
--warn-skipped Warn when skipping already-visited includes
|
|
60
|
+
--show-warnings Show all warnings after output
|
|
61
|
+
--strict Exit with error if there are any warnings
|
|
62
|
+
|
|
63
|
+
Options for 'diff':
|
|
64
|
+
--entry <file> Entry colony file (required)
|
|
65
|
+
--dims <d1,d2,...> Dimension names (comma-separated)
|
|
66
|
+
--ctx1 "k1=v1 ..." First context
|
|
67
|
+
--ctx2 "k1=v1 ..." Second context
|
|
68
|
+
--format <json|text> Output format (default: text)
|
|
69
|
+
`);
|
|
70
|
+
}
|
|
71
|
+
function formatDiff(diff, format = "text") {
|
|
72
|
+
if (format === "json") {
|
|
73
|
+
return JSON.stringify(diff, null, 2);
|
|
74
|
+
}
|
|
75
|
+
const lines = [];
|
|
76
|
+
if (diff.added.length > 0) {
|
|
77
|
+
lines.push("Added:");
|
|
78
|
+
for (const key of diff.added) {
|
|
79
|
+
lines.push(` + ${key}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (diff.removed.length > 0) {
|
|
83
|
+
if (lines.length > 0) lines.push("");
|
|
84
|
+
lines.push("Removed:");
|
|
85
|
+
for (const key of diff.removed) {
|
|
86
|
+
lines.push(` - ${key}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (diff.changed.length > 0) {
|
|
90
|
+
if (lines.length > 0) lines.push("");
|
|
91
|
+
lines.push("Changed:");
|
|
92
|
+
for (const { key, from, to } of diff.changed) {
|
|
93
|
+
lines.push(` ~ ${key}`);
|
|
94
|
+
lines.push(` from: ${JSON.stringify(from)}`);
|
|
95
|
+
lines.push(` to: ${JSON.stringify(to)}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (lines.length === 0) {
|
|
99
|
+
return "No differences found.";
|
|
100
|
+
}
|
|
101
|
+
return lines.join("\n");
|
|
102
|
+
}
|
|
103
|
+
function formatAsEnv(cfg, prefix = "") {
|
|
104
|
+
const lines = [];
|
|
105
|
+
function flatten(obj, currentPrefix) {
|
|
106
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
107
|
+
const envKey = currentPrefix ? `${currentPrefix}_${key}`.toUpperCase().replace(/[^A-Z0-9_]/g, "_") : key.toUpperCase().replace(/[^A-Z0-9_]/g, "_");
|
|
108
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
109
|
+
flatten(value, envKey);
|
|
110
|
+
} else {
|
|
111
|
+
const envValue = typeof value === "string" ? value : JSON.stringify(value);
|
|
112
|
+
const escaped = envValue.replace(/'/g, "'\\''");
|
|
113
|
+
lines.push(`${envKey}='${escaped}'`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
flatten(cfg, prefix);
|
|
118
|
+
return lines.sort().join("\n");
|
|
119
|
+
}
|
|
120
|
+
(async () => {
|
|
121
|
+
try {
|
|
122
|
+
const args = parseArgs(process.argv);
|
|
123
|
+
const cmd = args._[0];
|
|
124
|
+
if (!cmd || cmd === "help" || args.help) {
|
|
125
|
+
printUsage();
|
|
126
|
+
process.exit(cmd === "help" || args.help ? 0 : 1);
|
|
127
|
+
}
|
|
128
|
+
const entry = args.entry;
|
|
129
|
+
if (!entry) {
|
|
130
|
+
console.error("Error: Missing --entry\n");
|
|
131
|
+
printUsage();
|
|
132
|
+
process.exit(1);
|
|
133
|
+
}
|
|
134
|
+
if (cmd === "validate") {
|
|
135
|
+
const result = await (0, import_index.validateColony)(entry);
|
|
136
|
+
if (result.valid) {
|
|
137
|
+
console.log(`\u2713 All ${result.files.length} file(s) valid:`);
|
|
138
|
+
for (const f of result.files) {
|
|
139
|
+
console.log(` ${f}`);
|
|
140
|
+
}
|
|
141
|
+
process.exit(0);
|
|
142
|
+
} else {
|
|
143
|
+
console.error(`\u2717 Validation failed with ${result.errors.length} error(s):`);
|
|
144
|
+
for (const e of result.errors) {
|
|
145
|
+
console.error(`
|
|
146
|
+
${e.file}:`);
|
|
147
|
+
console.error(` ${e.error}`);
|
|
148
|
+
}
|
|
149
|
+
process.exit(1);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (cmd === "dry-run") {
|
|
153
|
+
const files = await (0, import_index.dryRunIncludes)(entry);
|
|
154
|
+
console.log(`Files that would be included (${files.length}):`);
|
|
155
|
+
for (const f of files) {
|
|
156
|
+
console.log(` ${f}`);
|
|
157
|
+
}
|
|
158
|
+
process.exit(0);
|
|
159
|
+
}
|
|
160
|
+
if (cmd === "diff") {
|
|
161
|
+
if (!args.ctx1 || !args.ctx2) {
|
|
162
|
+
console.error("Error: diff command requires both --ctx1 and --ctx2\n");
|
|
163
|
+
printUsage();
|
|
164
|
+
process.exit(1);
|
|
165
|
+
}
|
|
166
|
+
const dims2 = typeof args.dims === "string" ? args.dims.split(",").map((s) => s.trim()).filter(Boolean) : void 0;
|
|
167
|
+
const ctx1 = parseCtx(args.ctx1);
|
|
168
|
+
const ctx2 = parseCtx(args.ctx2);
|
|
169
|
+
const result = await (0, import_index.diffColony)({ entry, dims: dims2, ctx1, ctx2 });
|
|
170
|
+
const format = args.format || "text";
|
|
171
|
+
console.log(formatDiff(result.diff, format));
|
|
172
|
+
const hasDiffs = result.diff.added.length > 0 || result.diff.removed.length > 0 || result.diff.changed.length > 0;
|
|
173
|
+
process.exit(hasDiffs ? 1 : 0);
|
|
174
|
+
}
|
|
175
|
+
if (cmd === "lint") {
|
|
176
|
+
const dims2 = typeof args.dims === "string" ? args.dims.split(",").map((s) => s.trim()).filter(Boolean) : void 0;
|
|
177
|
+
const result = await (0, import_index.lintColony)({ entry, dims: dims2 });
|
|
178
|
+
if (result.issues.length === 0) {
|
|
179
|
+
console.log("\u2713 No issues found");
|
|
180
|
+
process.exit(0);
|
|
181
|
+
}
|
|
182
|
+
console.error(`Found ${result.issues.length} issue(s):
|
|
183
|
+
`);
|
|
184
|
+
for (const issue of result.issues) {
|
|
185
|
+
const icon = issue.severity === "error" ? "\u2717" : "\u26A0";
|
|
186
|
+
console.error(`${icon} [${issue.type}] ${issue.message}`);
|
|
187
|
+
if (issue.file) {
|
|
188
|
+
console.error(` at ${issue.file}:${issue.line || 0}`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
process.exit(result.issues.some((i) => i.severity === "error") ? 1 : 0);
|
|
192
|
+
}
|
|
193
|
+
if (cmd === "keys") {
|
|
194
|
+
const dims2 = typeof args.dims === "string" ? args.dims.split(",").map((s) => s.trim()).filter(Boolean) : void 0;
|
|
195
|
+
const ctx2 = parseCtx(args.ctx);
|
|
196
|
+
const cfg2 = await (0, import_index.loadColony)({ entry, dims: dims2, ctx: ctx2 });
|
|
197
|
+
const keys = cfg2.keys();
|
|
198
|
+
for (const key of keys) {
|
|
199
|
+
console.log(key);
|
|
200
|
+
}
|
|
201
|
+
process.exit(0);
|
|
202
|
+
}
|
|
203
|
+
if (cmd === "env") {
|
|
204
|
+
const dims2 = typeof args.dims === "string" ? args.dims.split(",").map((s) => s.trim()).filter(Boolean) : void 0;
|
|
205
|
+
const ctx2 = parseCtx(args.ctx);
|
|
206
|
+
const cfg2 = await (0, import_index.loadColony)({ entry, dims: dims2, ctx: ctx2 });
|
|
207
|
+
console.log(formatAsEnv(cfg2.toJSON(), args.prefix || ""));
|
|
208
|
+
process.exit(0);
|
|
209
|
+
}
|
|
210
|
+
if (cmd !== "print") {
|
|
211
|
+
console.error(`Error: Unknown command "${cmd}"
|
|
212
|
+
`);
|
|
213
|
+
printUsage();
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
216
|
+
const dims = typeof args.dims === "string" ? args.dims.split(",").map((s) => s.trim()).filter(Boolean) : void 0;
|
|
217
|
+
const ctx = parseCtx(args.ctx);
|
|
218
|
+
const sandbox = {};
|
|
219
|
+
if (args["base-path"]) {
|
|
220
|
+
sandbox.basePath = args["base-path"];
|
|
221
|
+
}
|
|
222
|
+
if (args["allowed-env"]) {
|
|
223
|
+
sandbox.allowedEnvVars = args["allowed-env"].split(",").map((s) => s.trim()).filter(Boolean);
|
|
224
|
+
}
|
|
225
|
+
if (args["allowed-vars"]) {
|
|
226
|
+
sandbox.allowedVars = args["allowed-vars"].split(",").map((s) => s.trim()).filter(Boolean);
|
|
227
|
+
}
|
|
228
|
+
if (args["max-file-size"]) {
|
|
229
|
+
sandbox.maxFileSize = parseInt(args["max-file-size"], 10);
|
|
230
|
+
}
|
|
231
|
+
const warnOnSkippedIncludes = !!args["warn-skipped"];
|
|
232
|
+
const cfg = await (0, import_index.loadColony)({ entry, dims, ctx, sandbox, warnOnSkippedIncludes });
|
|
233
|
+
if (args.query) {
|
|
234
|
+
const value = (0, import_util.getByPath)(cfg, args.query);
|
|
235
|
+
if (value === void 0) {
|
|
236
|
+
console.error(`Key not found: ${args.query}`);
|
|
237
|
+
process.exit(1);
|
|
238
|
+
}
|
|
239
|
+
if (typeof value === "object") {
|
|
240
|
+
console.log(JSON.stringify(value, null, 2));
|
|
241
|
+
} else {
|
|
242
|
+
console.log(value);
|
|
243
|
+
}
|
|
244
|
+
} else {
|
|
245
|
+
const format = args.format || "json";
|
|
246
|
+
if (format === "env") {
|
|
247
|
+
console.log(formatAsEnv(cfg.toJSON(), args.prefix || ""));
|
|
248
|
+
} else {
|
|
249
|
+
console.log(JSON.stringify(cfg, null, 2));
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
if (args.strict && cfg._warnings?.length > 0) {
|
|
253
|
+
console.error(`
|
|
254
|
+
\u2717 Strict mode: ${cfg._warnings.length} warning(s) found:`);
|
|
255
|
+
for (const w of cfg._warnings) {
|
|
256
|
+
console.error(` [${w.type}] ${w.message}`);
|
|
257
|
+
}
|
|
258
|
+
process.exit(1);
|
|
259
|
+
}
|
|
260
|
+
if (args["show-warnings"] && cfg._warnings?.length > 0) {
|
|
261
|
+
console.error(`
|
|
262
|
+
Warnings (${cfg._warnings.length}):`);
|
|
263
|
+
for (const w of cfg._warnings) {
|
|
264
|
+
console.error(` [${w.type}] ${w.message}`);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
if (typeof args.explain === "string") {
|
|
268
|
+
const info = cfg.explain(args.explain);
|
|
269
|
+
console.error(`
|
|
270
|
+
Explain ${args.explain}:`);
|
|
271
|
+
console.error(info ? JSON.stringify(info, null, 2) : "(no matching rule / unset)");
|
|
272
|
+
}
|
|
273
|
+
} catch (err) {
|
|
274
|
+
console.error(`Error: ${err.message}`);
|
|
275
|
+
if (process.env.DEBUG) {
|
|
276
|
+
console.error(err.stack);
|
|
277
|
+
}
|
|
278
|
+
process.exit(1);
|
|
279
|
+
}
|
|
280
|
+
})();
|
|
281
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/cli.js"],
|
|
4
|
+
"sourcesContent": ["#!/usr/bin/env node\nimport { loadColony, validateColony, dryRunIncludes, diffColony, lintColony } from \"./index.js\";\nimport { getByPath } from \"./util.js\";\n\nfunction parseArgs(argv) {\n const args = { _: [] };\n for (let i = 2; i < argv.length; i++) {\n const a = argv[i];\n if (a.startsWith(\"--\")) {\n const k = a.slice(2);\n const v = (i + 1 < argv.length && !argv[i + 1].startsWith(\"--\")) ? argv[++i] : true;\n args[k] = v;\n } else {\n args._.push(a);\n }\n }\n return args;\n}\n\nfunction parseCtx(s) {\n const out = {};\n if (!s || s === true) return out;\n const parts = String(s).split(/\\s+/).filter(Boolean);\n for (const p of parts) {\n const idx = p.indexOf(\"=\");\n if (idx === -1) continue;\n out[p.slice(0, idx)] = p.slice(idx + 1);\n }\n return out;\n}\n\nfunction printUsage() {\n console.error(`Usage:\n colony print --entry ./config/app.colony [options]\n colony validate --entry ./config/app.colony\n colony dry-run --entry ./config/app.colony\n colony diff --entry ./config/app.colony --ctx1 \"env=dev\" --ctx2 \"env=prod\"\n colony keys --entry ./config/app.colony [--ctx \"...\"]\n colony env --entry ./config/app.colony [--ctx \"...\"]\n colony lint --entry ./config/app.colony\n\nCommands:\n print Resolve and print the configuration\n validate Check syntax of all colony files without resolving\n dry-run List all files that would be included\n diff Compare configs between two contexts\n keys List all config keys in dot notation\n env Output config as KEY=value for shell sourcing\n lint Check for potential issues (unused rules, shadows, etc.)\n\nOptions for 'print':\n --entry <file> Entry colony file (required)\n --dims <d1,d2,...> Dimension names (comma-separated)\n --ctx \"k1=v1 k2=v2\" Context values (space-separated key=value pairs)\n --format <json|env> Output format (default: json)\n --query <key.path> Extract specific value (like jq)\n --explain <key.path> Show which rule set a specific key\n --base-path <dir> Restrict includes to this directory (security)\n --allowed-env <v1,v2> Whitelist of allowed env vars (security)\n --allowed-vars <v1,v2> Whitelist of allowed custom vars (security)\n --max-file-size <bytes> Maximum file size for includes (security)\n --warn-skipped Warn when skipping already-visited includes\n --show-warnings Show all warnings after output\n --strict Exit with error if there are any warnings\n\nOptions for 'diff':\n --entry <file> Entry colony file (required)\n --dims <d1,d2,...> Dimension names (comma-separated)\n --ctx1 \"k1=v1 ...\" First context\n --ctx2 \"k1=v1 ...\" Second context\n --format <json|text> Output format (default: text)\n`);\n}\n\nfunction formatDiff(diff, format = \"text\") {\n if (format === \"json\") {\n return JSON.stringify(diff, null, 2);\n }\n\n const lines = [];\n\n if (diff.added.length > 0) {\n lines.push(\"Added:\");\n for (const key of diff.added) {\n lines.push(` + ${key}`);\n }\n }\n\n if (diff.removed.length > 0) {\n if (lines.length > 0) lines.push(\"\");\n lines.push(\"Removed:\");\n for (const key of diff.removed) {\n lines.push(` - ${key}`);\n }\n }\n\n if (diff.changed.length > 0) {\n if (lines.length > 0) lines.push(\"\");\n lines.push(\"Changed:\");\n for (const { key, from, to } of diff.changed) {\n lines.push(` ~ ${key}`);\n lines.push(` from: ${JSON.stringify(from)}`);\n lines.push(` to: ${JSON.stringify(to)}`);\n }\n }\n\n if (lines.length === 0) {\n return \"No differences found.\";\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Format config as KEY=value for shell sourcing\n */\nfunction formatAsEnv(cfg, prefix = \"\") {\n const lines = [];\n\n function flatten(obj, currentPrefix) {\n for (const [key, value] of Object.entries(obj)) {\n const envKey = currentPrefix\n ? `${currentPrefix}_${key}`.toUpperCase().replace(/[^A-Z0-9_]/g, \"_\")\n : key.toUpperCase().replace(/[^A-Z0-9_]/g, \"_\");\n\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) {\n flatten(value, envKey);\n } else {\n const envValue = typeof value === \"string\"\n ? value\n : JSON.stringify(value);\n // Escape single quotes for shell\n const escaped = envValue.replace(/'/g, \"'\\\\''\");\n lines.push(`${envKey}='${escaped}'`);\n }\n }\n }\n\n flatten(cfg, prefix);\n return lines.sort().join(\"\\n\");\n}\n\n(async () => {\n try {\n const args = parseArgs(process.argv);\n const cmd = args._[0];\n\n if (!cmd || cmd === \"help\" || args.help) {\n printUsage();\n process.exit(cmd === \"help\" || args.help ? 0 : 1);\n }\n\n const entry = args.entry;\n if (!entry) {\n console.error(\"Error: Missing --entry\\n\");\n printUsage();\n process.exit(1);\n }\n\n // Handle validate command\n if (cmd === \"validate\") {\n const result = await validateColony(entry);\n if (result.valid) {\n console.log(`\u2713 All ${result.files.length} file(s) valid:`);\n for (const f of result.files) {\n console.log(` ${f}`);\n }\n process.exit(0);\n } else {\n console.error(`\u2717 Validation failed with ${result.errors.length} error(s):`);\n for (const e of result.errors) {\n console.error(`\\n ${e.file}:`);\n console.error(` ${e.error}`);\n }\n process.exit(1);\n }\n }\n\n // Handle dry-run command\n if (cmd === \"dry-run\") {\n const files = await dryRunIncludes(entry);\n console.log(`Files that would be included (${files.length}):`);\n for (const f of files) {\n console.log(` ${f}`);\n }\n process.exit(0);\n }\n\n // Handle diff command\n if (cmd === \"diff\") {\n if (!args.ctx1 || !args.ctx2) {\n console.error(\"Error: diff command requires both --ctx1 and --ctx2\\n\");\n printUsage();\n process.exit(1);\n }\n\n const dims = typeof args.dims === \"string\"\n ? args.dims.split(\",\").map((s) => s.trim()).filter(Boolean)\n : undefined;\n\n const ctx1 = parseCtx(args.ctx1);\n const ctx2 = parseCtx(args.ctx2);\n\n const result = await diffColony({ entry, dims, ctx1, ctx2 });\n\n const format = args.format || \"text\";\n console.log(formatDiff(result.diff, format));\n\n // Exit with code 1 if there are differences (useful for CI)\n const hasDiffs = result.diff.added.length > 0 ||\n result.diff.removed.length > 0 ||\n result.diff.changed.length > 0;\n process.exit(hasDiffs ? 1 : 0);\n }\n\n // Handle lint command\n if (cmd === \"lint\") {\n const dims = typeof args.dims === \"string\"\n ? args.dims.split(\",\").map((s) => s.trim()).filter(Boolean)\n : undefined;\n\n const result = await lintColony({ entry, dims });\n\n if (result.issues.length === 0) {\n console.log(\"\u2713 No issues found\");\n process.exit(0);\n }\n\n console.error(`Found ${result.issues.length} issue(s):\\n`);\n for (const issue of result.issues) {\n const icon = issue.severity === \"error\" ? \"\u2717\" : \"\u26A0\";\n console.error(`${icon} [${issue.type}] ${issue.message}`);\n if (issue.file) {\n console.error(` at ${issue.file}:${issue.line || 0}`);\n }\n }\n process.exit(result.issues.some((i) => i.severity === \"error\") ? 1 : 0);\n }\n\n // Handle keys command\n if (cmd === \"keys\") {\n const dims = typeof args.dims === \"string\"\n ? args.dims.split(\",\").map((s) => s.trim()).filter(Boolean)\n : undefined;\n\n const ctx = parseCtx(args.ctx);\n const cfg = await loadColony({ entry, dims, ctx });\n\n const keys = cfg.keys();\n for (const key of keys) {\n console.log(key);\n }\n process.exit(0);\n }\n\n // Handle env command\n if (cmd === \"env\") {\n const dims = typeof args.dims === \"string\"\n ? args.dims.split(\",\").map((s) => s.trim()).filter(Boolean)\n : undefined;\n\n const ctx = parseCtx(args.ctx);\n const cfg = await loadColony({ entry, dims, ctx });\n\n console.log(formatAsEnv(cfg.toJSON(), args.prefix || \"\"));\n process.exit(0);\n }\n\n // Handle print command\n if (cmd !== \"print\") {\n console.error(`Error: Unknown command \"${cmd}\"\\n`);\n printUsage();\n process.exit(1);\n }\n\n const dims = typeof args.dims === \"string\"\n ? args.dims.split(\",\").map((s) => s.trim()).filter(Boolean)\n : undefined;\n\n const ctx = parseCtx(args.ctx);\n\n // Build sandbox options\n const sandbox = {};\n if (args[\"base-path\"]) {\n sandbox.basePath = args[\"base-path\"];\n }\n if (args[\"allowed-env\"]) {\n sandbox.allowedEnvVars = args[\"allowed-env\"].split(\",\").map((s) => s.trim()).filter(Boolean);\n }\n if (args[\"allowed-vars\"]) {\n sandbox.allowedVars = args[\"allowed-vars\"].split(\",\").map((s) => s.trim()).filter(Boolean);\n }\n if (args[\"max-file-size\"]) {\n sandbox.maxFileSize = parseInt(args[\"max-file-size\"], 10);\n }\n\n const warnOnSkippedIncludes = !!args[\"warn-skipped\"];\n\n const cfg = await loadColony({ entry, dims, ctx, sandbox, warnOnSkippedIncludes });\n\n // Handle --query option\n if (args.query) {\n const value = getByPath(cfg, args.query);\n if (value === undefined) {\n console.error(`Key not found: ${args.query}`);\n process.exit(1);\n }\n if (typeof value === \"object\") {\n console.log(JSON.stringify(value, null, 2));\n } else {\n console.log(value);\n }\n } else {\n // Format output\n const format = args.format || \"json\";\n if (format === \"env\") {\n console.log(formatAsEnv(cfg.toJSON(), args.prefix || \"\"));\n } else {\n console.log(JSON.stringify(cfg, null, 2));\n }\n }\n\n // Handle --strict flag\n if (args.strict && cfg._warnings?.length > 0) {\n console.error(`\\n\u2717 Strict mode: ${cfg._warnings.length} warning(s) found:`);\n for (const w of cfg._warnings) {\n console.error(` [${w.type}] ${w.message}`);\n }\n process.exit(1);\n }\n\n // Show warnings if requested\n if (args[\"show-warnings\"] && cfg._warnings?.length > 0) {\n console.error(`\\nWarnings (${cfg._warnings.length}):`);\n for (const w of cfg._warnings) {\n console.error(` [${w.type}] ${w.message}`);\n }\n }\n\n if (typeof args.explain === \"string\") {\n const info = cfg.explain(args.explain);\n console.error(`\\nExplain ${args.explain}:`);\n console.error(info ? JSON.stringify(info, null, 2) : \"(no matching rule / unset)\");\n }\n\n } catch (err) {\n console.error(`Error: ${err.message}`);\n if (process.env.DEBUG) {\n console.error(err.stack);\n }\n process.exit(1);\n }\n})();\n"],
|
|
5
|
+
"mappings": ";AACA,mBAAmF;AACnF,kBAA0B;AAE1B,SAAS,UAAU,MAAM;AACvB,QAAM,OAAO,EAAE,GAAG,CAAC,EAAE;AACrB,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,IAAI,KAAK,CAAC;AAChB,QAAI,EAAE,WAAW,IAAI,GAAG;AACtB,YAAM,IAAI,EAAE,MAAM,CAAC;AACnB,YAAM,IAAK,IAAI,IAAI,KAAK,UAAU,CAAC,KAAK,IAAI,CAAC,EAAE,WAAW,IAAI,IAAK,KAAK,EAAE,CAAC,IAAI;AAC/E,WAAK,CAAC,IAAI;AAAA,IACZ,OAAO;AACL,WAAK,EAAE,KAAK,CAAC;AAAA,IACf;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,SAAS,GAAG;AACnB,QAAM,MAAM,CAAC;AACb,MAAI,CAAC,KAAK,MAAM,KAAM,QAAO;AAC7B,QAAM,QAAQ,OAAO,CAAC,EAAE,MAAM,KAAK,EAAE,OAAO,OAAO;AACnD,aAAW,KAAK,OAAO;AACrB,UAAM,MAAM,EAAE,QAAQ,GAAG;AACzB,QAAI,QAAQ,GAAI;AAChB,QAAI,EAAE,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,MAAM,MAAM,CAAC;AAAA,EACxC;AACA,SAAO;AACT;AAEA,SAAS,aAAa;AACpB,UAAQ,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAuCf;AACD;AAEA,SAAS,WAAW,MAAM,SAAS,QAAQ;AACzC,MAAI,WAAW,QAAQ;AACrB,WAAO,KAAK,UAAU,MAAM,MAAM,CAAC;AAAA,EACrC;AAEA,QAAM,QAAQ,CAAC;AAEf,MAAI,KAAK,MAAM,SAAS,GAAG;AACzB,UAAM,KAAK,QAAQ;AACnB,eAAW,OAAO,KAAK,OAAO;AAC5B,YAAM,KAAK,OAAO,GAAG,EAAE;AAAA,IACzB;AAAA,EACF;AAEA,MAAI,KAAK,QAAQ,SAAS,GAAG;AAC3B,QAAI,MAAM,SAAS,EAAG,OAAM,KAAK,EAAE;AACnC,UAAM,KAAK,UAAU;AACrB,eAAW,OAAO,KAAK,SAAS;AAC9B,YAAM,KAAK,OAAO,GAAG,EAAE;AAAA,IACzB;AAAA,EACF;AAEA,MAAI,KAAK,QAAQ,SAAS,GAAG;AAC3B,QAAI,MAAM,SAAS,EAAG,OAAM,KAAK,EAAE;AACnC,UAAM,KAAK,UAAU;AACrB,eAAW,EAAE,KAAK,MAAM,GAAG,KAAK,KAAK,SAAS;AAC5C,YAAM,KAAK,OAAO,GAAG,EAAE;AACvB,YAAM,KAAK,aAAa,KAAK,UAAU,IAAI,CAAC,EAAE;AAC9C,YAAM,KAAK,aAAa,KAAK,UAAU,EAAE,CAAC,EAAE;AAAA,IAC9C;AAAA,EACF;AAEA,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO;AAAA,EACT;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAKA,SAAS,YAAY,KAAK,SAAS,IAAI;AACrC,QAAM,QAAQ,CAAC;AAEf,WAAS,QAAQ,KAAK,eAAe;AACnC,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC9C,YAAM,SAAS,gBACX,GAAG,aAAa,IAAI,GAAG,GAAG,YAAY,EAAE,QAAQ,eAAe,GAAG,IAClE,IAAI,YAAY,EAAE,QAAQ,eAAe,GAAG;AAEhD,UAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,GAAG;AACxE,gBAAQ,OAAO,MAAM;AAAA,MACvB,OAAO;AACL,cAAM,WAAW,OAAO,UAAU,WAC9B,QACA,KAAK,UAAU,KAAK;AAExB,cAAM,UAAU,SAAS,QAAQ,MAAM,OAAO;AAC9C,cAAM,KAAK,GAAG,MAAM,KAAK,OAAO,GAAG;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAEA,UAAQ,KAAK,MAAM;AACnB,SAAO,MAAM,KAAK,EAAE,KAAK,IAAI;AAC/B;AAAA,CAEC,YAAY;AACX,MAAI;AACF,UAAM,OAAO,UAAU,QAAQ,IAAI;AACnC,UAAM,MAAM,KAAK,EAAE,CAAC;AAEpB,QAAI,CAAC,OAAO,QAAQ,UAAU,KAAK,MAAM;AACvC,iBAAW;AACX,cAAQ,KAAK,QAAQ,UAAU,KAAK,OAAO,IAAI,CAAC;AAAA,IAClD;AAEA,UAAM,QAAQ,KAAK;AACnB,QAAI,CAAC,OAAO;AACV,cAAQ,MAAM,0BAA0B;AACxC,iBAAW;AACX,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,QAAI,QAAQ,YAAY;AACtB,YAAM,SAAS,UAAM,6BAAe,KAAK;AACzC,UAAI,OAAO,OAAO;AAChB,gBAAQ,IAAI,cAAS,OAAO,MAAM,MAAM,iBAAiB;AACzD,mBAAW,KAAK,OAAO,OAAO;AAC5B,kBAAQ,IAAI,KAAK,CAAC,EAAE;AAAA,QACtB;AACA,gBAAQ,KAAK,CAAC;AAAA,MAChB,OAAO;AACL,gBAAQ,MAAM,iCAA4B,OAAO,OAAO,MAAM,YAAY;AAC1E,mBAAW,KAAK,OAAO,QAAQ;AAC7B,kBAAQ,MAAM;AAAA,IAAO,EAAE,IAAI,GAAG;AAC9B,kBAAQ,MAAM,OAAO,EAAE,KAAK,EAAE;AAAA,QAChC;AACA,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF;AAGA,QAAI,QAAQ,WAAW;AACrB,YAAM,QAAQ,UAAM,6BAAe,KAAK;AACxC,cAAQ,IAAI,iCAAiC,MAAM,MAAM,IAAI;AAC7D,iBAAW,KAAK,OAAO;AACrB,gBAAQ,IAAI,KAAK,CAAC,EAAE;AAAA,MACtB;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,QAAI,QAAQ,QAAQ;AAClB,UAAI,CAAC,KAAK,QAAQ,CAAC,KAAK,MAAM;AAC5B,gBAAQ,MAAM,uDAAuD;AACrE,mBAAW;AACX,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,YAAMA,QAAO,OAAO,KAAK,SAAS,WAC9B,KAAK,KAAK,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO,IACxD;AAEJ,YAAM,OAAO,SAAS,KAAK,IAAI;AAC/B,YAAM,OAAO,SAAS,KAAK,IAAI;AAE/B,YAAM,SAAS,UAAM,yBAAW,EAAE,OAAO,MAAAA,OAAM,MAAM,KAAK,CAAC;AAE3D,YAAM,SAAS,KAAK,UAAU;AAC9B,cAAQ,IAAI,WAAW,OAAO,MAAM,MAAM,CAAC;AAG3C,YAAM,WAAW,OAAO,KAAK,MAAM,SAAS,KAC3B,OAAO,KAAK,QAAQ,SAAS,KAC7B,OAAO,KAAK,QAAQ,SAAS;AAC9C,cAAQ,KAAK,WAAW,IAAI,CAAC;AAAA,IAC/B;AAGA,QAAI,QAAQ,QAAQ;AAClB,YAAMA,QAAO,OAAO,KAAK,SAAS,WAC9B,KAAK,KAAK,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO,IACxD;AAEJ,YAAM,SAAS,UAAM,yBAAW,EAAE,OAAO,MAAAA,MAAK,CAAC;AAE/C,UAAI,OAAO,OAAO,WAAW,GAAG;AAC9B,gBAAQ,IAAI,wBAAmB;AAC/B,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,cAAQ,MAAM,SAAS,OAAO,OAAO,MAAM;AAAA,CAAc;AACzD,iBAAW,SAAS,OAAO,QAAQ;AACjC,cAAM,OAAO,MAAM,aAAa,UAAU,WAAM;AAChD,gBAAQ,MAAM,GAAG,IAAI,KAAK,MAAM,IAAI,KAAK,MAAM,OAAO,EAAE;AACxD,YAAI,MAAM,MAAM;AACd,kBAAQ,MAAM,QAAQ,MAAM,IAAI,IAAI,MAAM,QAAQ,CAAC,EAAE;AAAA,QACvD;AAAA,MACF;AACA,cAAQ,KAAK,OAAO,OAAO,KAAK,CAAC,MAAM,EAAE,aAAa,OAAO,IAAI,IAAI,CAAC;AAAA,IACxE;AAGA,QAAI,QAAQ,QAAQ;AAClB,YAAMA,QAAO,OAAO,KAAK,SAAS,WAC9B,KAAK,KAAK,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO,IACxD;AAEJ,YAAMC,OAAM,SAAS,KAAK,GAAG;AAC7B,YAAMC,OAAM,UAAM,yBAAW,EAAE,OAAO,MAAAF,OAAM,KAAAC,KAAI,CAAC;AAEjD,YAAM,OAAOC,KAAI,KAAK;AACtB,iBAAW,OAAO,MAAM;AACtB,gBAAQ,IAAI,GAAG;AAAA,MACjB;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,QAAI,QAAQ,OAAO;AACjB,YAAMF,QAAO,OAAO,KAAK,SAAS,WAC9B,KAAK,KAAK,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO,IACxD;AAEJ,YAAMC,OAAM,SAAS,KAAK,GAAG;AAC7B,YAAMC,OAAM,UAAM,yBAAW,EAAE,OAAO,MAAAF,OAAM,KAAAC,KAAI,CAAC;AAEjD,cAAQ,IAAI,YAAYC,KAAI,OAAO,GAAG,KAAK,UAAU,EAAE,CAAC;AACxD,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,QAAI,QAAQ,SAAS;AACnB,cAAQ,MAAM,2BAA2B,GAAG;AAAA,CAAK;AACjD,iBAAW;AACX,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,UAAM,OAAO,OAAO,KAAK,SAAS,WAC9B,KAAK,KAAK,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO,IACxD;AAEJ,UAAM,MAAM,SAAS,KAAK,GAAG;AAG7B,UAAM,UAAU,CAAC;AACjB,QAAI,KAAK,WAAW,GAAG;AACrB,cAAQ,WAAW,KAAK,WAAW;AAAA,IACrC;AACA,QAAI,KAAK,aAAa,GAAG;AACvB,cAAQ,iBAAiB,KAAK,aAAa,EAAE,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO;AAAA,IAC7F;AACA,QAAI,KAAK,cAAc,GAAG;AACxB,cAAQ,cAAc,KAAK,cAAc,EAAE,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO;AAAA,IAC3F;AACA,QAAI,KAAK,eAAe,GAAG;AACzB,cAAQ,cAAc,SAAS,KAAK,eAAe,GAAG,EAAE;AAAA,IAC1D;AAEA,UAAM,wBAAwB,CAAC,CAAC,KAAK,cAAc;AAEnD,UAAM,MAAM,UAAM,yBAAW,EAAE,OAAO,MAAM,KAAK,SAAS,sBAAsB,CAAC;AAGjF,QAAI,KAAK,OAAO;AACd,YAAM,YAAQ,uBAAU,KAAK,KAAK,KAAK;AACvC,UAAI,UAAU,QAAW;AACvB,gBAAQ,MAAM,kBAAkB,KAAK,KAAK,EAAE;AAC5C,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA,UAAI,OAAO,UAAU,UAAU;AAC7B,gBAAQ,IAAI,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA,MAC5C,OAAO;AACL,gBAAQ,IAAI,KAAK;AAAA,MACnB;AAAA,IACF,OAAO;AAEL,YAAM,SAAS,KAAK,UAAU;AAC9B,UAAI,WAAW,OAAO;AACpB,gBAAQ,IAAI,YAAY,IAAI,OAAO,GAAG,KAAK,UAAU,EAAE,CAAC;AAAA,MAC1D,OAAO;AACL,gBAAQ,IAAI,KAAK,UAAU,KAAK,MAAM,CAAC,CAAC;AAAA,MAC1C;AAAA,IACF;AAGA,QAAI,KAAK,UAAU,IAAI,WAAW,SAAS,GAAG;AAC5C,cAAQ,MAAM;AAAA,sBAAoB,IAAI,UAAU,MAAM,oBAAoB;AAC1E,iBAAW,KAAK,IAAI,WAAW;AAC7B,gBAAQ,MAAM,MAAM,EAAE,IAAI,KAAK,EAAE,OAAO,EAAE;AAAA,MAC5C;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,QAAI,KAAK,eAAe,KAAK,IAAI,WAAW,SAAS,GAAG;AACtD,cAAQ,MAAM;AAAA,YAAe,IAAI,UAAU,MAAM,IAAI;AACrD,iBAAW,KAAK,IAAI,WAAW;AAC7B,gBAAQ,MAAM,MAAM,EAAE,IAAI,KAAK,EAAE,OAAO,EAAE;AAAA,MAC5C;AAAA,IACF;AAEA,QAAI,OAAO,KAAK,YAAY,UAAU;AACpC,YAAM,OAAO,IAAI,QAAQ,KAAK,OAAO;AACrC,cAAQ,MAAM;AAAA,UAAa,KAAK,OAAO,GAAG;AAC1C,cAAQ,MAAM,OAAO,KAAK,UAAU,MAAM,MAAM,CAAC,IAAI,4BAA4B;AAAA,IACnF;AAAA,EAEF,SAAS,KAAK;AACZ,YAAQ,MAAM,UAAU,IAAI,OAAO,EAAE;AACrC,QAAI,QAAQ,IAAI,OAAO;AACrB,cAAQ,MAAM,IAAI,KAAK;AAAA,IACzB;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,GAAG;",
|
|
6
|
+
"names": ["dims", "ctx", "cfg"]
|
|
7
|
+
}
|