crossplane-provider-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.
Files changed (3) hide show
  1. package/README.md +73 -0
  2. package/dist/index.js +505 -0
  3. package/package.json +55 -0
package/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # crossplane-provider-cli
2
+
3
+ Crossplane provider and composition configuration generator CLI
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g crossplane-provider-cli
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Initialize configuration
14
+
15
+ ```bash
16
+ crossplane-provider init
17
+ crossplane-provider init --template advanced
18
+ crossplane-provider init --output custom-config.json
19
+ ```
20
+
21
+ ### Validate configuration
22
+
23
+ ```bash
24
+ crossplane-provider validate
25
+ crossplane-provider validate path/to/config.json
26
+ ```
27
+
28
+ ### View configuration
29
+
30
+ ```bash
31
+ crossplane-provider show
32
+ crossplane-provider show --env production
33
+ crossplane-provider show --json
34
+ ```
35
+
36
+ ### Modify configuration
37
+
38
+ ```bash
39
+ crossplane-provider set settings.debug true
40
+ crossplane-provider set settings.logLevel \"warn\"
41
+ ```
42
+
43
+ ### Compare configurations
44
+
45
+ ```bash
46
+ crossplane-provider diff config-dev.json config-prod.json
47
+ ```
48
+
49
+ ### List templates
50
+
51
+ ```bash
52
+ crossplane-provider 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 crossplane-provider-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
package/dist/index.js ADDED
@@ -0,0 +1,505 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { Command } from "commander";
5
+ import chalk from "chalk";
6
+ import * as fs from "fs";
7
+ import * as path from "path";
8
+ import * as yaml from "js-yaml";
9
+ function writeYaml(outDir, filename, obj) {
10
+ fs.mkdirSync(outDir, { recursive: true });
11
+ const outPath = path.join(outDir, filename);
12
+ const docs = Array.isArray(obj) ? obj : [obj];
13
+ const content = docs.map((d) => yaml.dump(d, { noRefs: true, lineWidth: 120 })).join("---\n");
14
+ fs.writeFileSync(outPath, content, "utf8");
15
+ console.log(chalk.green(" wrote ") + chalk.cyan(outPath));
16
+ }
17
+ function log(msg) {
18
+ console.log(chalk.bold(msg));
19
+ }
20
+ function buildProvider(cloud, version) {
21
+ const pkgMap = {
22
+ aws: `xpkg.upbound.io/upbound/provider-aws:${version}`,
23
+ gcp: `xpkg.upbound.io/upbound/provider-gcp:${version}`,
24
+ azure: `xpkg.upbound.io/upbound/provider-azure:${version}`
25
+ };
26
+ return {
27
+ apiVersion: "pkg.crossplane.io/v1",
28
+ kind: "Provider",
29
+ metadata: {
30
+ name: `provider-${cloud}`,
31
+ annotations: {
32
+ "crossplane.io/external-name": `provider-${cloud}`
33
+ }
34
+ },
35
+ spec: {
36
+ package: pkgMap[cloud],
37
+ controllerConfigRef: { name: `provider-${cloud}-controller-config` },
38
+ installationPolicy: "Automatic",
39
+ revisionActivationPolicy: "Automatic"
40
+ }
41
+ };
42
+ }
43
+ function buildControllerConfig(cloud) {
44
+ return {
45
+ apiVersion: "pkg.crossplane.io/v1alpha1",
46
+ kind: "ControllerConfig",
47
+ metadata: {
48
+ name: `provider-${cloud}-controller-config`,
49
+ annotations: {
50
+ "eks.amazonaws.com/role-arn": cloud === "aws" ? "arn:aws:iam::ACCOUNT_ID:role/crossplane-provider-aws" : ""
51
+ }
52
+ },
53
+ spec: {
54
+ podSecurityContext: { fsGroup: 2e3 },
55
+ resources: {
56
+ limits: { cpu: "500m", memory: "128Mi" },
57
+ requests: { cpu: "100m", memory: "64Mi" }
58
+ }
59
+ }
60
+ };
61
+ }
62
+ function buildProviderConfig(cloud) {
63
+ const credSources = {
64
+ aws: {
65
+ source: "InjectedIdentity"
66
+ },
67
+ gcp: {
68
+ source: "Secret",
69
+ secretRef: {
70
+ namespace: "crossplane-system",
71
+ name: "gcp-credentials",
72
+ key: "credentials.json"
73
+ }
74
+ },
75
+ azure: {
76
+ source: "Secret",
77
+ secretRef: {
78
+ namespace: "crossplane-system",
79
+ name: "azure-credentials",
80
+ key: "credentials"
81
+ }
82
+ }
83
+ };
84
+ return {
85
+ apiVersion: `${cloud}.upbound.io/v1beta1`,
86
+ kind: "ProviderConfig",
87
+ metadata: {
88
+ name: `${cloud}-provider-config`
89
+ },
90
+ spec: {
91
+ credentials: credSources[cloud]
92
+ }
93
+ };
94
+ }
95
+ function initCommand() {
96
+ return new Command("init").description("Generate Provider and ProviderConfig manifests for AWS, GCP, or Azure").requiredOption("-c, --cloud <cloud>", "Cloud provider: aws | gcp | azure").option("-v, --version <version>", "Provider package version", "v0.43.1").option("-o, --out <dir>", "Output directory", "./crossplane").action((opts) => {
97
+ const cloud = opts.cloud.toLowerCase();
98
+ if (!["aws", "gcp", "azure"].includes(cloud)) {
99
+ console.error(chalk.red(`Unknown cloud provider: ${opts.cloud}`));
100
+ process.exit(1);
101
+ }
102
+ log(`
103
+ Initialising Crossplane provider manifests for ${chalk.bold(cloud.toUpperCase())}...
104
+ `);
105
+ const outDir = path.resolve(opts.out, cloud);
106
+ writeYaml(outDir, "provider.yaml", buildProvider(cloud, opts.version));
107
+ writeYaml(outDir, "controller-config.yaml", buildControllerConfig(cloud));
108
+ writeYaml(outDir, "provider-config.yaml", buildProviderConfig(cloud));
109
+ console.log(chalk.green("\nDone. Edit credentials refs before applying.\n"));
110
+ });
111
+ }
112
+ function buildXRD(group, kind, claimKind, version) {
113
+ const plural = kind.toLowerCase() + "s";
114
+ const claimPlural = claimKind.toLowerCase() + "s";
115
+ return {
116
+ apiVersion: "apiextensions.crossplane.io/v1",
117
+ kind: "CompositeResourceDefinition",
118
+ metadata: {
119
+ name: `${plural}.${group}`
120
+ },
121
+ spec: {
122
+ group,
123
+ names: { kind, plural },
124
+ claimNames: { kind: claimKind, plural: claimPlural },
125
+ versions: [
126
+ {
127
+ name: version,
128
+ served: true,
129
+ referenceable: true,
130
+ schema: {
131
+ openAPIV3Schema: {
132
+ type: "object",
133
+ properties: {
134
+ spec: {
135
+ type: "object",
136
+ properties: {
137
+ parameters: {
138
+ type: "object",
139
+ description: "Parameters for the composite resource",
140
+ properties: {
141
+ region: { type: "string", description: "Cloud region", default: "us-east-1" },
142
+ environment: {
143
+ type: "string",
144
+ description: "Deployment environment",
145
+ enum: ["dev", "staging", "prod"]
146
+ },
147
+ size: {
148
+ type: "string",
149
+ description: "T-shirt size for resource allocation",
150
+ enum: ["small", "medium", "large"],
151
+ default: "small"
152
+ }
153
+ },
154
+ required: ["region", "environment"]
155
+ }
156
+ },
157
+ required: ["parameters"]
158
+ }
159
+ }
160
+ }
161
+ }
162
+ }
163
+ ]
164
+ }
165
+ };
166
+ }
167
+ function buildComposition(group, kind, cloud, version) {
168
+ const plural = kind.toLowerCase() + "s";
169
+ const apiVersionMap = {
170
+ aws: "s3.aws.upbound.io/v1beta1",
171
+ gcp: "storage.gcp.upbound.io/v1beta1",
172
+ azure: "storage.azure.upbound.io/v1beta1"
173
+ };
174
+ const kindMap = {
175
+ aws: "Bucket",
176
+ gcp: "Bucket",
177
+ azure: "Account"
178
+ };
179
+ const providerConfigRefMap = {
180
+ aws: "aws-provider-config",
181
+ gcp: "gcp-provider-config",
182
+ azure: "azure-provider-config"
183
+ };
184
+ return {
185
+ apiVersion: "apiextensions.crossplane.io/v1",
186
+ kind: "Composition",
187
+ metadata: {
188
+ name: `${plural}-${cloud}`,
189
+ labels: {
190
+ "crossplane.io/xrd": `${plural}.${group}`,
191
+ provider: cloud
192
+ }
193
+ },
194
+ spec: {
195
+ compositeTypeRef: { apiVersion: `${group}/${version}`, kind },
196
+ mode: "Pipeline",
197
+ pipeline: [
198
+ {
199
+ step: "patch-and-transform",
200
+ functionRef: { name: "function-patch-and-transform" },
201
+ input: {
202
+ apiVersion: "pt.fn.crossplane.io/v1beta1",
203
+ kind: "Resources",
204
+ resources: [
205
+ {
206
+ name: `${cloud}-resource`,
207
+ base: {
208
+ apiVersion: apiVersionMap[cloud],
209
+ kind: kindMap[cloud],
210
+ spec: {
211
+ forProvider: {
212
+ region: "us-east-1"
213
+ },
214
+ providerConfigRef: { name: providerConfigRefMap[cloud] }
215
+ }
216
+ },
217
+ patches: [
218
+ {
219
+ type: "FromCompositeFieldPath",
220
+ fromFieldPath: "spec.parameters.region",
221
+ toFieldPath: "spec.forProvider.region"
222
+ },
223
+ {
224
+ type: "FromCompositeFieldPath",
225
+ fromFieldPath: "metadata.name",
226
+ toFieldPath: "metadata.name",
227
+ transforms: [
228
+ {
229
+ type: "string",
230
+ string: { type: "Format", fmt: "%s-resource" }
231
+ }
232
+ ]
233
+ }
234
+ ]
235
+ }
236
+ ]
237
+ }
238
+ }
239
+ ]
240
+ }
241
+ };
242
+ }
243
+ function compositionCommand() {
244
+ return new Command("composition").description("Generate a Composition and CompositeResourceDefinition (XRD)").requiredOption("-g, --group <group>", "API group, e.g. platform.example.com").requiredOption("-k, --kind <kind>", "Composite resource kind, e.g. XDatabase").option("--claim-kind <claimKind>", "Claim kind (defaults to Kind without X prefix)").option("-c, --cloud <cloud>", "Target cloud provider: aws | gcp | azure", "aws").option("--version <version>", "CRD version", "v1alpha1").option("-o, --out <dir>", "Output directory", "./crossplane/compositions").action(
245
+ (opts) => {
246
+ const cloud = opts.cloud.toLowerCase();
247
+ const claimKind = opts.claimKind ?? opts.kind.replace(/^X/, "");
248
+ log(`
249
+ Generating Composition for ${chalk.bold(opts.kind)} (${cloud.toUpperCase()})...
250
+ `);
251
+ const outDir = path.resolve(opts.out);
252
+ writeYaml(outDir, `xrd-${opts.kind.toLowerCase()}.yaml`, buildXRD(opts.group, opts.kind, claimKind, opts.version));
253
+ writeYaml(outDir, `composition-${opts.kind.toLowerCase()}-${cloud}.yaml`, buildComposition(opts.group, opts.kind, cloud, opts.version));
254
+ console.log(chalk.green("\nDone. Register the Composition Functions before applying.\n"));
255
+ }
256
+ );
257
+ }
258
+ function buildClaim(group, claimKind, name, namespace, region, env, size, version) {
259
+ return {
260
+ apiVersion: `${group}/${version}`,
261
+ kind: claimKind,
262
+ metadata: {
263
+ name,
264
+ namespace,
265
+ labels: {
266
+ environment: env,
267
+ "managed-by": "crossplane"
268
+ }
269
+ },
270
+ spec: {
271
+ parameters: {
272
+ region,
273
+ environment: env,
274
+ size
275
+ },
276
+ compositionSelector: {
277
+ matchLabels: {
278
+ "crossplane.io/xrd": `${claimKind.toLowerCase()}s.${group}`
279
+ }
280
+ },
281
+ writeConnectionSecretToRef: {
282
+ name: `${name}-connection`
283
+ }
284
+ }
285
+ };
286
+ }
287
+ function claimCommand() {
288
+ return new Command("claim").description("Generate a Claim manifest for an infrastructure request").requiredOption("-g, --group <group>", "API group, e.g. platform.example.com").requiredOption("-k, --kind <kind>", "Claim kind, e.g. Database").option("-n, --name <name>", "Resource name", "my-resource").option("--namespace <ns>", "Kubernetes namespace", "default").option("-r, --region <region>", "Cloud region", "us-east-1").option("-e, --env <env>", "Environment: dev | staging | prod", "dev").option("-s, --size <size>", "Size: small | medium | large", "small").option("--version <version>", "API version", "v1alpha1").option("-o, --out <dir>", "Output directory", "./crossplane/claims").action(
289
+ (opts) => {
290
+ log(`
291
+ Generating Claim: ${chalk.bold(opts.name)} (${opts.kind})...
292
+ `);
293
+ const outDir = path.resolve(opts.out);
294
+ const claim = buildClaim(
295
+ opts.group,
296
+ opts.kind,
297
+ opts.name,
298
+ opts.namespace,
299
+ opts.region,
300
+ opts.env,
301
+ opts.size,
302
+ opts.version
303
+ );
304
+ writeYaml(outDir, `claim-${opts.name}.yaml`, claim);
305
+ console.log(chalk.green("\nDone.\n"));
306
+ }
307
+ );
308
+ }
309
+ function buildFunctionPAT() {
310
+ return {
311
+ apiVersion: "pkg.crossplane.io/v1beta1",
312
+ kind: "Function",
313
+ metadata: {
314
+ name: "function-patch-and-transform",
315
+ annotations: {
316
+ "pkg.crossplane.io/revision-history-limit": "3"
317
+ }
318
+ },
319
+ spec: {
320
+ package: "xpkg.upbound.io/crossplane-contrib/function-patch-and-transform:v0.5.0",
321
+ installationPolicy: "Automatic",
322
+ revisionActivationPolicy: "Automatic"
323
+ }
324
+ };
325
+ }
326
+ function buildFunctionGoTemplate() {
327
+ return {
328
+ apiVersion: "pkg.crossplane.io/v1beta1",
329
+ kind: "Function",
330
+ metadata: {
331
+ name: "function-go-templating"
332
+ },
333
+ spec: {
334
+ package: "xpkg.upbound.io/crossplane-contrib/function-go-templating:v0.4.1",
335
+ installationPolicy: "Automatic",
336
+ revisionActivationPolicy: "Automatic"
337
+ }
338
+ };
339
+ }
340
+ function buildFunctionAutoReady() {
341
+ return {
342
+ apiVersion: "pkg.crossplane.io/v1beta1",
343
+ kind: "Function",
344
+ metadata: {
345
+ name: "function-auto-ready"
346
+ },
347
+ spec: {
348
+ package: "xpkg.upbound.io/crossplane-contrib/function-auto-ready:v0.2.1",
349
+ installationPolicy: "Automatic",
350
+ revisionActivationPolicy: "Automatic"
351
+ }
352
+ };
353
+ }
354
+ function buildFunctionKCL() {
355
+ return {
356
+ apiVersion: "pkg.crossplane.io/v1beta1",
357
+ kind: "Function",
358
+ metadata: {
359
+ name: "function-kcl"
360
+ },
361
+ spec: {
362
+ package: "xpkg.upbound.io/crossplane-contrib/function-kcl:v0.9.4",
363
+ installationPolicy: "Automatic",
364
+ revisionActivationPolicy: "Automatic"
365
+ }
366
+ };
367
+ }
368
+ function buildFunctionExtraResources() {
369
+ return {
370
+ apiVersion: "pkg.crossplane.io/v1beta1",
371
+ kind: "Function",
372
+ metadata: {
373
+ name: "function-extra-resources"
374
+ },
375
+ spec: {
376
+ package: "xpkg.upbound.io/crossplane-contrib/function-extra-resources:v0.1.0",
377
+ installationPolicy: "Automatic",
378
+ revisionActivationPolicy: "Automatic"
379
+ }
380
+ };
381
+ }
382
+ function functionCommand() {
383
+ return new Command("function").description("Generate composition Function pipeline configuration manifests").option(
384
+ "-f, --fn <name>",
385
+ "Function name: patch-and-transform | go-templating | auto-ready | kcl | extra-resources | all",
386
+ "all"
387
+ ).option("-o, --out <dir>", "Output directory", "./crossplane/functions").action((opts) => {
388
+ const fnName = opts.fn;
389
+ const outDir = path.resolve(opts.out);
390
+ log(`
391
+ Generating Function manifests (${chalk.bold(fnName)})...
392
+ `);
393
+ const fnMap = {
394
+ "patch-and-transform": buildFunctionPAT,
395
+ "go-templating": buildFunctionGoTemplate,
396
+ "auto-ready": buildFunctionAutoReady,
397
+ kcl: buildFunctionKCL,
398
+ "extra-resources": buildFunctionExtraResources
399
+ };
400
+ if (fnName === "all") {
401
+ for (const [name, builder] of Object.entries(fnMap)) {
402
+ writeYaml(outDir, `function-${name}.yaml`, builder());
403
+ }
404
+ } else if (fnMap[fnName]) {
405
+ writeYaml(outDir, `function-${fnName}.yaml`, fnMap[fnName]());
406
+ } else {
407
+ console.error(chalk.red(`Unknown function: ${fnName}`));
408
+ process.exit(1);
409
+ }
410
+ console.log(chalk.green("\nDone.\n"));
411
+ });
412
+ }
413
+ function buildEnvironmentConfig(env, cloud, region, accountId) {
414
+ const regionMap = {
415
+ aws: { dev: "us-east-1", staging: "us-east-2", prod: "us-west-2" },
416
+ gcp: { dev: "us-central1", staging: "us-east1", prod: "us-east4" },
417
+ azure: { dev: "eastus", staging: "eastus2", prod: "westus2" }
418
+ };
419
+ const defaultRegion = region || regionMap[cloud][env];
420
+ const policyMap = {
421
+ dev: {
422
+ deletionPolicy: "Delete",
423
+ managementPolicies: ["*"]
424
+ },
425
+ staging: {
426
+ deletionPolicy: "Delete",
427
+ managementPolicies: ["Observe", "Create", "Update", "Delete"]
428
+ },
429
+ prod: {
430
+ deletionPolicy: "Orphan",
431
+ managementPolicies: ["Observe", "Create", "Update"]
432
+ }
433
+ };
434
+ const cloudSpecific = {
435
+ aws: {
436
+ accountId: accountId || "REPLACE_WITH_ACCOUNT_ID",
437
+ iamRolePrefix: `arn:aws:iam::${accountId || "ACCOUNT_ID"}:role/crossplane`,
438
+ kmsKeyArn: `arn:aws:kms:${defaultRegion}:${accountId || "ACCOUNT_ID"}:key/REPLACE_KEY_ID`
439
+ },
440
+ gcp: {
441
+ projectId: accountId || "REPLACE_WITH_PROJECT_ID",
442
+ serviceAccountEmail: `crossplane@${accountId || "PROJECT_ID"}.iam.gserviceaccount.com`
443
+ },
444
+ azure: {
445
+ subscriptionId: accountId || "REPLACE_WITH_SUBSCRIPTION_ID",
446
+ tenantId: "REPLACE_WITH_TENANT_ID",
447
+ resourceGroupPrefix: `rg-crossplane-${env}`
448
+ }
449
+ };
450
+ return {
451
+ apiVersion: "apiextensions.crossplane.io/v1alpha1",
452
+ kind: "EnvironmentConfig",
453
+ metadata: {
454
+ name: `${cloud}-${env}`,
455
+ labels: {
456
+ environment: env,
457
+ cloud,
458
+ "managed-by": "crossplane"
459
+ }
460
+ },
461
+ data: {
462
+ environment: env,
463
+ cloud,
464
+ region: defaultRegion,
465
+ policy: policyMap[env],
466
+ ...cloudSpecific[cloud],
467
+ tags: {
468
+ Environment: env,
469
+ ManagedBy: "crossplane",
470
+ Cloud: cloud
471
+ }
472
+ }
473
+ };
474
+ }
475
+ function environmentCommand() {
476
+ return new Command("environment").description("Generate EnvironmentConfig manifests for multi-environment setups").option("-c, --cloud <cloud>", "Cloud provider: aws | gcp | azure", "aws").option("-e, --env <env>", "Single env: dev | staging | prod (omit to generate all)", "").option("-r, --region <region>", "Override default region", "").option("-a, --account <accountId>", "Cloud account/project/subscription ID", "").option("-o, --out <dir>", "Output directory", "./crossplane/environments").action((opts) => {
477
+ const cloud = opts.cloud.toLowerCase();
478
+ if (!["aws", "gcp", "azure"].includes(cloud)) {
479
+ console.error(chalk.red(`Unknown cloud provider: ${opts.cloud}`));
480
+ process.exit(1);
481
+ }
482
+ const envs = opts.env ? [opts.env] : ["dev", "staging", "prod"];
483
+ log(`
484
+ Generating EnvironmentConfig manifests for ${chalk.bold(cloud.toUpperCase())} (${envs.join(", ")})...
485
+ `);
486
+ const outDir = path.resolve(opts.out);
487
+ for (const env of envs) {
488
+ if (!["dev", "staging", "prod"].includes(env)) {
489
+ console.error(chalk.red(`Unknown env: ${env}`));
490
+ process.exit(1);
491
+ }
492
+ const cfg = buildEnvironmentConfig(env, cloud, opts.region, opts.account);
493
+ writeYaml(outDir, `environment-config-${cloud}-${env}.yaml`, cfg);
494
+ }
495
+ console.log(chalk.green("\nDone. Replace placeholder values before applying.\n"));
496
+ });
497
+ }
498
+ var program = new Command();
499
+ program.name("crossplane-provider").description(chalk.cyan("Crossplane provider and composition configuration generator")).version("1.0.0");
500
+ program.addCommand(initCommand());
501
+ program.addCommand(compositionCommand());
502
+ program.addCommand(claimCommand());
503
+ program.addCommand(functionCommand());
504
+ program.addCommand(environmentCommand());
505
+ program.parse(process.argv);
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "crossplane-provider-cli",
3
+ "version": "1.0.0",
4
+ "description": "Crossplane provider and composition configuration generator CLI",
5
+ "type": "module",
6
+ "files": [
7
+ "dist"
8
+ ],
9
+ "bin": {
10
+ "crossplane-provider": "./dist/index.js"
11
+ },
12
+ "scripts": {
13
+ "build": "node node_modules/tsup/dist/cli-default.js",
14
+ "dev": "node node_modules/tsup/dist/cli-default.js --watch",
15
+ "prepublishOnly": "node node_modules/tsup/dist/cli-default.js"
16
+ },
17
+ "keywords": [
18
+ "crossplane",
19
+ "kubernetes",
20
+ "infrastructure",
21
+ "cloud",
22
+ "cli",
23
+ "composition",
24
+ "xrd",
25
+ "provider",
26
+ "aws",
27
+ "gcp",
28
+ "azure"
29
+ ],
30
+ "author": "crossplane-provider-cli",
31
+ "license": "MIT",
32
+ "engines": {
33
+ "node": ">=18.0.0"
34
+ },
35
+ "dependencies": {
36
+ "chalk": "^5.6.2",
37
+ "commander": "^14.0.3",
38
+ "js-yaml": "^4.1.1"
39
+ },
40
+ "devDependencies": {
41
+ "@types/js-yaml": "^4.0.9",
42
+ "@types/node": "^25.5.2",
43
+ "tsup": "^8.5.1",
44
+ "typescript": "^6.0.2"
45
+ },
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "https://github.com/okirmio-create/cli-forge.git",
49
+ "directory": "crossplane-provider-cli"
50
+ },
51
+ "homepage": "https://github.com/okirmio-create/cli-forge/tree/main/crossplane-provider-cli",
52
+ "bugs": {
53
+ "url": "https://github.com/okirmio-create/cli-forge/issues"
54
+ }
55
+ }