kubernetes-fluent-client 1.5.1 → 1.6.1

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/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ // SPDX-FileCopyrightText: 2023-Present The Kubernetes Fluent Client Authors
5
+ var __importDefault = (this && this.__importDefault) || function (mod) {
6
+ return (mod && mod.__esModule) ? mod : { "default": mod };
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ const helpers_1 = require("yargs/helpers");
10
+ const yargs_1 = __importDefault(require("yargs/yargs"));
11
+ const generate_1 = require("./generate");
12
+ void (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
13
+ .version(false)
14
+ .command("crd [source] [directory]", "generate usable types from a K8s CRD", yargs => {
15
+ return yargs
16
+ .positional("source", {
17
+ describe: "the yaml file path, remote url, or K8s CRD name",
18
+ type: "string",
19
+ })
20
+ .positional("directory", {
21
+ describe: "the directory to output the generated types to",
22
+ type: "string",
23
+ })
24
+ .option("plain", {
25
+ alias: "p",
26
+ type: "boolean",
27
+ description: "generate plain types without binding to the fluent client, automatically enabled when an alternate language is specified",
28
+ })
29
+ .option("language", {
30
+ alias: "l",
31
+ type: "string",
32
+ default: "ts",
33
+ description: "the language to generate types in, see https://github.com/glideapps/quicktype#target-languages for a list of supported languages",
34
+ })
35
+ .demandOption(["source", "directory"]);
36
+ }, async (argv) => {
37
+ const opts = argv;
38
+ opts.logFn = console.log;
39
+ try {
40
+ await (0, generate_1.generate)(opts);
41
+ }
42
+ catch (e) {
43
+ console.log(`\n❌ ${e.message}`);
44
+ }
45
+ })
46
+ .parse();
package/dist/fetch.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  // SPDX-License-Identifier: Apache-2.0
3
- // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
+ // SPDX-FileCopyrightText: 2023-Present The Kubernetes Fluent Client Authors
4
4
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5
5
  if (k2 === undefined) k2 = k;
6
6
  var desc = Object.getOwnPropertyDescriptor(m, k);
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  // SPDX-License-Identifier: Apache-2.0
3
- // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
+ // SPDX-FileCopyrightText: 2023-Present The Kubernetes Fluent Client Authors
4
4
  var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  return (mod && mod.__esModule) ? mod : { "default": mod };
6
6
  };
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  // SPDX-License-Identifier: Apache-2.0
3
- // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
+ // SPDX-FileCopyrightText: 2023-Present The Kubernetes Fluent Client Authors
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  // SPDX-License-Identifier: Apache-2.0
3
- // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
+ // SPDX-FileCopyrightText: 2023-Present The Kubernetes Fluent Client Authors
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.K8s = void 0;
6
6
  const http_status_codes_1 = require("http-status-codes");
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  // SPDX-License-Identifier: Apache-2.0
3
- // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
+ // SPDX-FileCopyrightText: 2023-Present The Kubernetes Fluent Client Authors
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.WatchPhase = void 0;
6
6
  /**
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  // SPDX-License-Identifier: Apache-2.0
3
- // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
+ // SPDX-FileCopyrightText: 2023-Present The Kubernetes Fluent Client Authors
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.k8sExec = exports.k8sCfg = exports.pathBuilder = void 0;
6
6
  const client_node_1 = require("@kubernetes/client-node");
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  // SPDX-License-Identifier: Apache-2.0
3
- // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
+ // SPDX-FileCopyrightText: 2023-Present The Kubernetes Fluent Client Authors
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
5
  const globals_1 = require("@jest/globals");
6
6
  const fetch_1 = require("../fetch");
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  // SPDX-License-Identifier: Apache-2.0
3
- // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
+ // SPDX-FileCopyrightText: 2023-Present The Kubernetes Fluent Client Authors
4
4
  var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  return (mod && mod.__esModule) ? mod : { "default": mod };
6
6
  };
@@ -0,0 +1,24 @@
1
+ import { TargetLanguage } from "quicktype-core";
2
+ import { LogFn } from "./types";
3
+ export interface GenerateOptions {
4
+ /** The source URL, yaml file path or K8s CRD name */
5
+ source: string;
6
+ /** The output directory path */
7
+ directory?: string;
8
+ /** Disable kubernetes-fluent-client wrapping */
9
+ plain?: boolean;
10
+ /** The language to generate types in */
11
+ language?: string | TargetLanguage;
12
+ /** Override the NPM package to import when generating formatted Typescript */
13
+ npmPackage?: string;
14
+ /** Log function callback */
15
+ logFn: LogFn;
16
+ }
17
+ /**
18
+ * Generate TypeScript types from a K8s CRD
19
+ *
20
+ * @param opts The options to use when generating
21
+ * @returns A promise that resolves when the TypeScript types have been generated
22
+ */
23
+ export declare function generate(opts: GenerateOptions): Promise<Record<string, string[]>>;
24
+ //# sourceMappingURL=generate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../src/generate.ts"],"names":[],"mappings":"AAMA,OAAO,EAIL,cAAc,EAEf,MAAM,gBAAgB,CAAC;AAKxB,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,MAAM,WAAW,eAAe;IAC9B,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,MAAM,GAAG,cAAc,CAAC;IACnC,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,KAAK,EAAE,KAAK,CAAC;CACd;AAiKD;;;;;GAKG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,eAAe,qCA4BnD"}
@@ -0,0 +1,187 @@
1
+ "use strict";
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ // SPDX-FileCopyrightText: 2023-Present The Kubernetes Fluent Client Authors
4
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5
+ if (k2 === undefined) k2 = k;
6
+ var desc = Object.getOwnPropertyDescriptor(m, k);
7
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
8
+ desc = { enumerable: true, get: function() { return m[k]; } };
9
+ }
10
+ Object.defineProperty(o, k2, desc);
11
+ }) : (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ o[k2] = m[k];
14
+ }));
15
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
16
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
17
+ }) : function(o, v) {
18
+ o["default"] = v;
19
+ });
20
+ var __importStar = (this && this.__importStar) || function (mod) {
21
+ if (mod && mod.__esModule) return mod;
22
+ var result = {};
23
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
24
+ __setModuleDefault(result, mod);
25
+ return result;
26
+ };
27
+ Object.defineProperty(exports, "__esModule", { value: true });
28
+ exports.generate = void 0;
29
+ const client_node_1 = require("@kubernetes/client-node");
30
+ const fs = __importStar(require("fs"));
31
+ const path = __importStar(require("path"));
32
+ const quicktype_core_1 = require("quicktype-core");
33
+ const fetch_1 = require("./fetch");
34
+ const fluent_1 = require("./fluent");
35
+ const upstream_1 = require("./upstream");
36
+ /**
37
+ * Converts a CustomResourceDefinition to TypeScript types
38
+ *
39
+ * @param crd The CustomResourceDefinition to convert
40
+ * @param opts The options to use when converting
41
+ * @returns A promise that resolves when the CustomResourceDefinition has been converted
42
+ */
43
+ async function convertCRDtoTS(crd, opts) {
44
+ // Get the name of the kind
45
+ const name = crd.spec.names.kind;
46
+ const results = {};
47
+ for (const match of crd.spec.versions) {
48
+ const version = match.name;
49
+ // Get the schema from the matched version
50
+ const schema = JSON.stringify(match?.schema?.openAPIV3Schema);
51
+ // Create a new JSONSchemaInput
52
+ const schemaInput = new quicktype_core_1.JSONSchemaInput(new quicktype_core_1.FetchingJSONSchemaStore());
53
+ opts.logFn(`- Generating ${crd.spec.group}/${version} types for ${name}`);
54
+ // Add the schema to the input
55
+ await schemaInput.addSource({ name, schema });
56
+ // Create a new InputData object
57
+ const inputData = new quicktype_core_1.InputData();
58
+ inputData.addInput(schemaInput);
59
+ // If the language is not specified, default to TypeScript
60
+ if (!opts.language) {
61
+ opts.language = "ts";
62
+ }
63
+ // Generate the types
64
+ const out = await (0, quicktype_core_1.quicktype)({
65
+ inputData,
66
+ lang: opts.language,
67
+ rendererOptions: { "just-types": "true" },
68
+ });
69
+ let processedLines = out.lines;
70
+ // If using typescript, remove the line containing `[property: string]: any;`
71
+ if (opts.language === "ts" || opts.language === "typescript") {
72
+ processedLines = out.lines.filter(line => !line.includes("[property: string]: any;"));
73
+ }
74
+ // If the language is TypeScript and plain is not specified, wire up the fluent client
75
+ if (opts.language === "ts" && !opts.plain) {
76
+ if (!opts.npmPackage) {
77
+ opts.npmPackage = "kubernetes-fluent-client";
78
+ }
79
+ processedLines.unshift(
80
+ // Add warning that the file is auto-generated
81
+ `// This file is auto-generated by ${opts.npmPackage}, do not edit manually\n`,
82
+ // Add the imports before any other lines
83
+ `import { GenericKind, RegisterKind } from "${opts.npmPackage}";\n`);
84
+ // Replace the interface with a named class that extends GenericKind
85
+ const entryIdx = processedLines.findIndex(line => line.includes(`export interface ${name} {`));
86
+ // Replace the interface with a named class that extends GenericKind
87
+ processedLines[entryIdx] = `export class ${name} extends GenericKind {`;
88
+ // Add the RegisterKind call
89
+ processedLines.push(`RegisterKind(${name}, {`);
90
+ processedLines.push(` group: "${crd.spec.group}",`);
91
+ processedLines.push(` version: "${version}",`);
92
+ processedLines.push(` kind: "${name}",`);
93
+ processedLines.push(`});`);
94
+ }
95
+ const finalContents = processedLines.join("\n");
96
+ const fileName = `${name.toLowerCase()}-${version.toLowerCase()}`;
97
+ // If an output file is specified, write the output to the file
98
+ if (opts.directory) {
99
+ // Create the directory if it doesn't exist
100
+ fs.mkdirSync(opts.directory, { recursive: true });
101
+ // Write the file
102
+ const filePath = path.join(opts.directory, `${fileName}.${opts.language}`);
103
+ fs.writeFileSync(filePath, finalContents);
104
+ }
105
+ // Add the results to the array
106
+ results[fileName] = processedLines;
107
+ }
108
+ return results;
109
+ }
110
+ /**
111
+ * Reads a CustomResourceDefinition from a file, the cluster or the internet
112
+ *
113
+ * @param opts The options to use when reading
114
+ * @returns A promise that resolves when the CustomResourceDefinition has been read
115
+ */
116
+ async function readOrFetchCrd(opts) {
117
+ const { source, logFn } = opts;
118
+ const filePath = path.join(process.cwd(), source);
119
+ // First try to read the source as a file
120
+ try {
121
+ if (fs.existsSync(filePath)) {
122
+ logFn(`Attempting to load ${source} as a local file`);
123
+ const payload = fs.readFileSync(filePath, "utf8");
124
+ return (0, client_node_1.loadAllYaml)(payload);
125
+ }
126
+ }
127
+ catch (e) {
128
+ // Ignore errors
129
+ }
130
+ // Next try to parse the source as a URL
131
+ try {
132
+ const url = new URL(source);
133
+ // If the source is a URL, fetch it
134
+ if (url.protocol === "http:" || url.protocol === "https:") {
135
+ logFn(`Attempting to load ${source} as a URL`);
136
+ const { ok, data } = await (0, fetch_1.fetch)(source);
137
+ // If the request failed, throw an error
138
+ if (!ok) {
139
+ throw new Error(`Failed to fetch ${source}: ${data}`);
140
+ }
141
+ return (0, client_node_1.loadAllYaml)(data);
142
+ }
143
+ }
144
+ catch (e) {
145
+ // If invalid, ignore the error
146
+ if (e.code !== "ERR_INVALID_URL") {
147
+ throw new Error(e);
148
+ }
149
+ }
150
+ // Finally, if the source is not a file or URL, try to read it as a CustomResourceDefinition from the cluster
151
+ try {
152
+ logFn(`Attempting to read ${source} from the current Kubernetes context`);
153
+ return [await (0, fluent_1.K8s)(upstream_1.CustomResourceDefinition).Get(source)];
154
+ }
155
+ catch (e) {
156
+ throw new Error(`Failed to read ${source} as a file, url or K8s CRD: ${e.data?.message || "Cluster not available"}`);
157
+ }
158
+ }
159
+ /**
160
+ * Generate TypeScript types from a K8s CRD
161
+ *
162
+ * @param opts The options to use when generating
163
+ * @returns A promise that resolves when the TypeScript types have been generated
164
+ */
165
+ async function generate(opts) {
166
+ const crds = (await readOrFetchCrd(opts)).filter(crd => !!crd);
167
+ const results = {};
168
+ opts.logFn("");
169
+ for (const crd of crds) {
170
+ if (crd.kind !== "CustomResourceDefinition" || !crd.spec?.versions?.length) {
171
+ opts.logFn(`Skipping ${crd?.metadata?.name}, it does not appear to be a CRD`);
172
+ // Ignore empty and non-CRD objects
173
+ continue;
174
+ }
175
+ // Add the results to the record
176
+ const out = await convertCRDtoTS(crd, opts);
177
+ for (const key of Object.keys(out)) {
178
+ results[key] = out[key];
179
+ }
180
+ }
181
+ if (opts.directory) {
182
+ // Notify the user that the files have been generated
183
+ opts.logFn(`\n✅ Generated ${Object.keys(results).length} files in the ${opts.directory} directory`);
184
+ }
185
+ return results;
186
+ }
187
+ exports.generate = generate;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=generate.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.test.d.ts","sourceRoot":"","sources":["../src/generate.test.ts"],"names":[],"mappings":""}