avro-config-cli 1.0.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/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # avro-config-cli
2
+
3
+ CLI tool for working with Avro schemas
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g avro-config-cli
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Initialize configuration
14
+
15
+ ```bash
16
+ avro-config init
17
+ avro-config init --template advanced
18
+ avro-config init --output custom-config.json
19
+ ```
20
+
21
+ ### Validate configuration
22
+
23
+ ```bash
24
+ avro-config validate
25
+ avro-config validate path/to/config.json
26
+ ```
27
+
28
+ ### View configuration
29
+
30
+ ```bash
31
+ avro-config show
32
+ avro-config show --env production
33
+ avro-config show --json
34
+ ```
35
+
36
+ ### Modify configuration
37
+
38
+ ```bash
39
+ avro-config set settings.debug true
40
+ avro-config set settings.logLevel \"warn\"
41
+ ```
42
+
43
+ ### Compare configurations
44
+
45
+ ```bash
46
+ avro-config diff config-dev.json config-prod.json
47
+ ```
48
+
49
+ ### List templates
50
+
51
+ ```bash
52
+ avro-config templates
53
+ ```
54
+
55
+ ## Templates
56
+
57
+ | Template | Description |
58
+ |----------|-------------|
59
+ | `minimal` | Bare minimum configuration |
60
+ | `standard` | Recommended defaults for most projects |
61
+ | `advanced` | Full-featured with security, caching, and multi-environment support |
62
+
63
+ ## Why avro-config-cli?
64
+
65
+ - **Zero dependencies at runtime** — just `commander` and `chalk`
66
+ - **Template-based** — start with minimal, standard, or advanced presets
67
+ - **Validation built-in** — catch config errors before deployment
68
+ - **Environment-aware** — manage dev/staging/production configs in one file
69
+ - **Diff support** — compare configs across environments
70
+
71
+ ## License
72
+
73
+ MIT
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,203 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { Command } from "commander";
5
+ import chalk from "chalk";
6
+ import { readFileSync, writeFileSync, existsSync } from "fs";
7
+ import { resolve } from "path";
8
+ var SCHEMA_FILE = "schema.avsc";
9
+ var AVRO_PRIMITIVES = /* @__PURE__ */ new Set([
10
+ "null",
11
+ "boolean",
12
+ "int",
13
+ "long",
14
+ "float",
15
+ "double",
16
+ "bytes",
17
+ "string"
18
+ ]);
19
+ function readSchema() {
20
+ const path = resolve(SCHEMA_FILE);
21
+ if (!existsSync(path)) {
22
+ console.error(chalk.red(`Schema file not found. Run ${chalk.bold("avro-config init")} first.`));
23
+ process.exit(1);
24
+ }
25
+ return JSON.parse(readFileSync(path, "utf-8"));
26
+ }
27
+ function writeSchema(schema) {
28
+ writeFileSync(resolve(SCHEMA_FILE), JSON.stringify(schema, null, 2) + "\n");
29
+ }
30
+ function parseAvroType(raw) {
31
+ const trimmed = raw.trim();
32
+ if (AVRO_PRIMITIVES.has(trimmed)) {
33
+ return trimmed;
34
+ }
35
+ if (trimmed.startsWith("array<") && trimmed.endsWith(">")) {
36
+ const inner = trimmed.slice(6, -1);
37
+ return { type: "array", items: parseAvroType(inner) };
38
+ }
39
+ if (trimmed.startsWith("map<") && trimmed.endsWith(">")) {
40
+ const inner = trimmed.slice(4, -1);
41
+ return { type: "map", values: parseAvroType(inner) };
42
+ }
43
+ if (trimmed.startsWith("union<") && trimmed.endsWith(">")) {
44
+ const inner = trimmed.slice(6, -1);
45
+ const parts = inner.split(",").map((p) => parseAvroType(p.trim()));
46
+ return parts;
47
+ }
48
+ console.error(
49
+ chalk.red(`Unknown Avro type: ${chalk.bold(raw)}`),
50
+ chalk.dim(
51
+ "\nValid primitives: null, boolean, int, long, float, double, bytes, string"
52
+ ),
53
+ chalk.dim("\nComplex syntax: array<type>, map<type>, union<type1,type2>")
54
+ );
55
+ process.exit(1);
56
+ return "null";
57
+ }
58
+ function avroTypeToTypeScript(type) {
59
+ if (typeof type === "string") {
60
+ const map = {
61
+ null: "null",
62
+ boolean: "boolean",
63
+ int: "number",
64
+ long: "number",
65
+ float: "number",
66
+ double: "number",
67
+ bytes: "Buffer",
68
+ string: "string"
69
+ };
70
+ return map[type] ?? "unknown";
71
+ }
72
+ if (Array.isArray(type)) {
73
+ return type.map(avroTypeToTypeScript).join(" | ");
74
+ }
75
+ if (type.type === "array") {
76
+ return `${avroTypeToTypeScript(type.items)}[]`;
77
+ }
78
+ if (type.type === "map") {
79
+ return `Record<string, ${avroTypeToTypeScript(type.values)}>`;
80
+ }
81
+ return "unknown";
82
+ }
83
+ function avroTypeToJsonSchema(type) {
84
+ if (typeof type === "string") {
85
+ const map = {
86
+ null: { type: "null" },
87
+ boolean: { type: "boolean" },
88
+ int: { type: "integer" },
89
+ long: { type: "integer" },
90
+ float: { type: "number" },
91
+ double: { type: "number" },
92
+ bytes: { type: "string", contentEncoding: "base64" },
93
+ string: { type: "string" }
94
+ };
95
+ return map[type] ?? {};
96
+ }
97
+ if (Array.isArray(type)) {
98
+ const schemas = type.map(avroTypeToJsonSchema);
99
+ return { oneOf: schemas };
100
+ }
101
+ if (type.type === "array") {
102
+ return { type: "array", items: avroTypeToJsonSchema(type.items) };
103
+ }
104
+ if (type.type === "map") {
105
+ return {
106
+ type: "object",
107
+ additionalProperties: avroTypeToJsonSchema(type.values)
108
+ };
109
+ }
110
+ return {};
111
+ }
112
+ var program = new Command();
113
+ program.name("avro-config").description("CLI tool for working with Apache Avro schemas").version("1.0.0");
114
+ program.command("init").description("Create a new Avro schema template").option("-n, --name <name>", "Record name", "MyRecord").option("--namespace <namespace>", "Namespace", "com.example").option("-d, --doc <doc>", "Documentation string", "An Avro record schema").action((opts) => {
115
+ if (existsSync(resolve(SCHEMA_FILE))) {
116
+ console.error(
117
+ chalk.yellow(`Schema file ${chalk.bold(SCHEMA_FILE)} already exists.`)
118
+ );
119
+ process.exit(1);
120
+ }
121
+ const schema = {
122
+ type: "record",
123
+ name: opts.name,
124
+ namespace: opts.namespace,
125
+ doc: opts.doc,
126
+ fields: []
127
+ };
128
+ writeSchema(schema);
129
+ console.log(chalk.green(`Created ${chalk.bold(SCHEMA_FILE)}`));
130
+ console.log(
131
+ chalk.dim(` name: ${schema.name}`)
132
+ );
133
+ console.log(chalk.dim(` namespace: ${schema.namespace}`));
134
+ console.log(chalk.dim(` doc: ${schema.doc}`));
135
+ });
136
+ program.command("field <name> <type>").description(
137
+ "Add a field to the schema. Types: null, boolean, int, long, float, double, bytes, string, array<type>, map<type>, union<t1,t2>"
138
+ ).option("-d, --doc <doc>", "Field documentation").option("--default <default>", "Default value (JSON)").action(
139
+ (name, type, opts) => {
140
+ const schema = readSchema();
141
+ if (schema.fields.some((f) => f.name === name)) {
142
+ console.error(
143
+ chalk.red(`Field ${chalk.bold(name)} already exists in schema.`)
144
+ );
145
+ process.exit(1);
146
+ }
147
+ const avroType = parseAvroType(type);
148
+ const field = { name, type: avroType };
149
+ if (opts.doc) field.doc = opts.doc;
150
+ if (opts.default !== void 0) {
151
+ try {
152
+ field.default = JSON.parse(opts.default);
153
+ } catch {
154
+ field.default = opts.default;
155
+ }
156
+ }
157
+ schema.fields.push(field);
158
+ writeSchema(schema);
159
+ console.log(
160
+ chalk.green(`Added field ${chalk.bold(name)} (${chalk.cyan(type)}) to ${SCHEMA_FILE}`)
161
+ );
162
+ }
163
+ );
164
+ program.command("convert").description("Show TypeScript and JSON Schema conversions for the Avro schema").action(() => {
165
+ const schema = readSchema();
166
+ console.log(chalk.bold("\nAvro Schema"));
167
+ console.log(chalk.dim("\u2500".repeat(50)));
168
+ console.log(chalk.cyan(JSON.stringify(schema, null, 2)));
169
+ console.log(chalk.bold("\nTypeScript Interface"));
170
+ console.log(chalk.dim("\u2500".repeat(50)));
171
+ const tsFields = schema.fields.map((f) => {
172
+ const tsType = avroTypeToTypeScript(f.type);
173
+ const comment = f.doc ? ` /** ${f.doc} */
174
+ ` : "";
175
+ return `${comment} ${f.name}: ${tsType};`;
176
+ }).join("\n");
177
+ console.log(
178
+ chalk.yellow(`export interface ${schema.name} {
179
+ ${tsFields}
180
+ }`)
181
+ );
182
+ console.log(chalk.bold("\nJSON Schema"));
183
+ console.log(chalk.dim("\u2500".repeat(50)));
184
+ const jsonSchemaProps = {};
185
+ const required = [];
186
+ for (const field of schema.fields) {
187
+ jsonSchemaProps[field.name] = avroTypeToJsonSchema(field.type);
188
+ const isNullable = Array.isArray(field.type) && field.type.some((t) => t === "null");
189
+ if (!isNullable && field.default === void 0) {
190
+ required.push(field.name);
191
+ }
192
+ }
193
+ const jsonSchema = {
194
+ $schema: "http://json-schema.org/draft-07/schema#",
195
+ title: schema.name,
196
+ description: schema.doc,
197
+ type: "object",
198
+ properties: jsonSchemaProps,
199
+ ...required.length > 0 ? { required } : {}
200
+ };
201
+ console.log(chalk.green(JSON.stringify(jsonSchema, null, 2)));
202
+ });
203
+ program.parse(process.argv);
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "avro-config-cli",
3
+ "version": "1.0.0",
4
+ "description": "CLI tool for working with Avro schemas",
5
+ "type": "module",
6
+ "bin": {
7
+ "avro-config": "./dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsup",
11
+ "dev": "tsup --watch"
12
+ },
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "dependencies": {
17
+ "chalk": "^5.3.0",
18
+ "commander": "^12.1.0"
19
+ },
20
+ "devDependencies": {
21
+ "@types/node": "^25.5.2",
22
+ "tsup": "^8.1.0",
23
+ "typescript": "^5.4.5"
24
+ },
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "https://github.com/okirmio-create/cli-forge.git",
28
+ "directory": "avro-config-cli"
29
+ },
30
+ "homepage": "https://github.com/okirmio-create/cli-forge/tree/main/avro-config-cli",
31
+ "bugs": {
32
+ "url": "https://github.com/okirmio-create/cli-forge/issues"
33
+ }
34
+ }