@benzenejs/mesh-discovery-kubernetes 0.0.0-stage → 0.1.0-beta.2
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/Extensions.d.ts +8 -0
- package/dist/Extensions.js +24 -0
- package/dist/IKubernetesServiceLister.d.ts +28 -0
- package/dist/IKubernetesServiceLister.js +7 -0
- package/dist/KubernetesApiServiceLister.d.ts +18 -0
- package/dist/KubernetesApiServiceLister.js +39 -0
- package/dist/KubernetesServiceDiscoveryProvider.d.ts +31 -0
- package/dist/KubernetesServiceDiscoveryProvider.js +82 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +27 -0
- package/package.json +15 -4
- package/README.md +0 -3
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { IBenzeneServiceContainer } from '@benzenejs/abstractions';
|
|
2
|
+
/**
|
|
3
|
+
* Registers `KubernetesServiceDiscoveryProvider` (as an additional `IMeshDiscoveryProvider`) over an
|
|
4
|
+
* in-cluster `CoreV1Api` client, plus a `MeshDiscoveryRunner` over all registered providers. Intended for a
|
|
5
|
+
* mesh running inside the cluster (uses `KubeConfig.loadFromCluster()` - the port of
|
|
6
|
+
* `KubernetesClientConfiguration.InClusterConfig`); its ServiceAccount needs RBAC to list Services.
|
|
7
|
+
*/
|
|
8
|
+
export declare function addMeshKubernetesDiscovery(services: IBenzeneServiceContainer): IBenzeneServiceContainer;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.addMeshKubernetesDiscovery = addMeshKubernetesDiscovery;
|
|
4
|
+
/** Port of Benzene.Mesh.Discovery.Kubernetes.Extensions. */
|
|
5
|
+
const client_node_1 = require("@kubernetes/client-node");
|
|
6
|
+
const mesh_contracts_1 = require("@benzenejs/mesh-contracts");
|
|
7
|
+
const IKubernetesServiceLister_1 = require("./IKubernetesServiceLister");
|
|
8
|
+
const KubernetesApiServiceLister_1 = require("./KubernetesApiServiceLister");
|
|
9
|
+
const KubernetesServiceDiscoveryProvider_1 = require("./KubernetesServiceDiscoveryProvider");
|
|
10
|
+
/**
|
|
11
|
+
* Registers `KubernetesServiceDiscoveryProvider` (as an additional `IMeshDiscoveryProvider`) over an
|
|
12
|
+
* in-cluster `CoreV1Api` client, plus a `MeshDiscoveryRunner` over all registered providers. Intended for a
|
|
13
|
+
* mesh running inside the cluster (uses `KubeConfig.loadFromCluster()` - the port of
|
|
14
|
+
* `KubernetesClientConfiguration.InClusterConfig`); its ServiceAccount needs RBAC to list Services.
|
|
15
|
+
*/
|
|
16
|
+
function addMeshKubernetesDiscovery(services) {
|
|
17
|
+
const kubeConfig = new client_node_1.KubeConfig();
|
|
18
|
+
kubeConfig.loadFromCluster();
|
|
19
|
+
const client = kubeConfig.makeApiClient(client_node_1.CoreV1Api);
|
|
20
|
+
services.addSingletonFactory(IKubernetesServiceLister_1.IKubernetesServiceLister, () => new KubernetesApiServiceLister_1.KubernetesApiServiceLister(client));
|
|
21
|
+
services.addSingletonFactory(mesh_contracts_1.IMeshDiscoveryProvider, (resolver) => new KubernetesServiceDiscoveryProvider_1.KubernetesServiceDiscoveryProvider(resolver.getService(IKubernetesServiceLister_1.IKubernetesServiceLister)));
|
|
22
|
+
services.addSingletonFactory(mesh_contracts_1.MeshDiscoveryRunner, (resolver) => new mesh_contracts_1.MeshDiscoveryRunner(resolver.getServices(mesh_contracts_1.IMeshDiscoveryProvider)));
|
|
23
|
+
return services;
|
|
24
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Port of Benzene.Mesh.Discovery.Kubernetes.IKubernetesServiceLister (+ KubernetesServiceInfo). */
|
|
2
|
+
import { ServiceToken } from '@benzenejs/abstractions';
|
|
3
|
+
/**
|
|
4
|
+
* The subset of a Kubernetes Service that mesh discovery needs. C# `record` -> a plain interface;
|
|
5
|
+
* `IReadOnlyDictionary` -> `Record`.
|
|
6
|
+
*/
|
|
7
|
+
export interface KubernetesServiceInfo {
|
|
8
|
+
/** The Service's metadata name (used as the mesh service name and DNS host). */
|
|
9
|
+
readonly name: string;
|
|
10
|
+
/** The Service's namespace (part of its in-cluster DNS). */
|
|
11
|
+
readonly namespace: string;
|
|
12
|
+
/** The Service's first exposed port (the port its cluster DNS resolves traffic to). */
|
|
13
|
+
readonly port: number;
|
|
14
|
+
/** The Service's labels (matched against the discovery filter). */
|
|
15
|
+
readonly labels: Record<string, string>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* A minimal port over the Kubernetes API for listing Services, so `KubernetesServiceDiscoveryProvider`'s
|
|
19
|
+
* discovery logic (label-selector construction, URL building, filtering) is unit-testable without the
|
|
20
|
+
* Kubernetes client SDK. The real implementation is `KubernetesApiServiceLister`. `CancellationToken` ->
|
|
21
|
+
* optional `AbortSignal`; `string?` namespace -> `string | undefined` (`undefined` = all namespaces).
|
|
22
|
+
*/
|
|
23
|
+
export interface IKubernetesServiceLister {
|
|
24
|
+
/** Lists Services matching `labelSelector` in `namespace` (or across all namespaces when it is `undefined`). */
|
|
25
|
+
listServicesAsync(namespace: string | undefined, labelSelector: string, cancellationToken?: AbortSignal): Promise<KubernetesServiceInfo[]>;
|
|
26
|
+
}
|
|
27
|
+
/** Container token: the discovery provider resolves its lister by this interface. */
|
|
28
|
+
export declare const IKubernetesServiceLister: ServiceToken<IKubernetesServiceLister>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IKubernetesServiceLister = void 0;
|
|
4
|
+
/** Port of Benzene.Mesh.Discovery.Kubernetes.IKubernetesServiceLister (+ KubernetesServiceInfo). */
|
|
5
|
+
const abstractions_1 = require("@benzenejs/abstractions");
|
|
6
|
+
/** Container token: the discovery provider resolves its lister by this interface. */
|
|
7
|
+
exports.IKubernetesServiceLister = (0, abstractions_1.serviceToken)('IKubernetesServiceLister');
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Port of Benzene.Mesh.Discovery.Kubernetes.KubernetesApiServiceLister. */
|
|
2
|
+
import { CoreV1Api } from '@kubernetes/client-node';
|
|
3
|
+
import { IKubernetesServiceLister, KubernetesServiceInfo } from './IKubernetesServiceLister';
|
|
4
|
+
/**
|
|
5
|
+
* The real `IKubernetesServiceLister` over the Kubernetes client SDK's `CoreV1Api`. Kept thin (no discovery
|
|
6
|
+
* logic) so the SDK coupling lives in one place and `KubernetesServiceDiscoveryProvider` stays
|
|
7
|
+
* unit-testable against the port.
|
|
8
|
+
*
|
|
9
|
+
* `KubernetesClient`/`IKubernetes` -> `@kubernetes/client-node`'s `CoreV1Api`; the v1 client's list methods
|
|
10
|
+
* take a single param object (`listServiceForAllNamespaces({ labelSelector })` /
|
|
11
|
+
* `listNamespacedService({ namespace, labelSelector })`). The `CancellationToken` isn't threaded - the JS
|
|
12
|
+
* client's abort handling is via `ConfigurationOptions`, not a token, and this thin lister isn't unit-tested.
|
|
13
|
+
*/
|
|
14
|
+
export declare class KubernetesApiServiceLister implements IKubernetesServiceLister {
|
|
15
|
+
private readonly client;
|
|
16
|
+
constructor(client: CoreV1Api);
|
|
17
|
+
listServicesAsync(namespace: string | undefined, labelSelector: string, _cancellationToken?: AbortSignal): Promise<KubernetesServiceInfo[]>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KubernetesApiServiceLister = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* The real `IKubernetesServiceLister` over the Kubernetes client SDK's `CoreV1Api`. Kept thin (no discovery
|
|
6
|
+
* logic) so the SDK coupling lives in one place and `KubernetesServiceDiscoveryProvider` stays
|
|
7
|
+
* unit-testable against the port.
|
|
8
|
+
*
|
|
9
|
+
* `KubernetesClient`/`IKubernetes` -> `@kubernetes/client-node`'s `CoreV1Api`; the v1 client's list methods
|
|
10
|
+
* take a single param object (`listServiceForAllNamespaces({ labelSelector })` /
|
|
11
|
+
* `listNamespacedService({ namespace, labelSelector })`). The `CancellationToken` isn't threaded - the JS
|
|
12
|
+
* client's abort handling is via `ConfigurationOptions`, not a token, and this thin lister isn't unit-tested.
|
|
13
|
+
*/
|
|
14
|
+
class KubernetesApiServiceLister {
|
|
15
|
+
client;
|
|
16
|
+
constructor(client) {
|
|
17
|
+
this.client = client;
|
|
18
|
+
}
|
|
19
|
+
async listServicesAsync(namespace, labelSelector, _cancellationToken) {
|
|
20
|
+
const list = namespace === undefined
|
|
21
|
+
? await this.client.listServiceForAllNamespaces({ labelSelector })
|
|
22
|
+
: await this.client.listNamespacedService({ namespace, labelSelector });
|
|
23
|
+
const services = [];
|
|
24
|
+
for (const service of list.items ?? []) {
|
|
25
|
+
const name = service.metadata?.name;
|
|
26
|
+
if (name === undefined || name.length === 0) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
services.push({
|
|
30
|
+
name,
|
|
31
|
+
namespace: service.metadata?.namespace ?? 'default',
|
|
32
|
+
port: service.spec?.ports?.[0]?.port ?? 80,
|
|
33
|
+
labels: service.metadata?.labels ?? {},
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return services;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.KubernetesApiServiceLister = KubernetesApiServiceLister;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** Port of Benzene.Mesh.Discovery.Kubernetes.KubernetesServiceDiscoveryProvider. */
|
|
2
|
+
import { IMeshDiscoveryProvider, MeshDiscoveryFilter, MeshServiceRegistryEntry } from '@benzenejs/mesh-contracts';
|
|
3
|
+
import { IKubernetesServiceLister } from './IKubernetesServiceLister';
|
|
4
|
+
/**
|
|
5
|
+
* Discovers Benzene services by listing the Kubernetes Services that match the `MeshDiscoveryFilter` (by
|
|
6
|
+
* default, carry the `benzene` label) via the Kubernetes API, and emitting an HTTP registry entry per
|
|
7
|
+
* Service pointing at its in-cluster DNS (`http://{name}.{namespace}.svc.cluster.local[:port]/benzene/spec|health`).
|
|
8
|
+
* The services are HTTP-addressable in-cluster, so entries use the default HTTP interrogation source
|
|
9
|
+
* (`MeshServiceSource.http`) - `HttpMeshServiceSource` interrogates each.
|
|
10
|
+
*
|
|
11
|
+
* The mesh's ServiceAccount needs RBAC to `list` Services. Spec/health paths follow the Cloud Service
|
|
12
|
+
* Profile defaults; a Service can override them with `benzene.spec-path`/`benzene.health-path` labels, and
|
|
13
|
+
* its scheme/port with `benzene.scheme`.
|
|
14
|
+
*/
|
|
15
|
+
export declare class KubernetesServiceDiscoveryProvider implements IMeshDiscoveryProvider {
|
|
16
|
+
private readonly lister;
|
|
17
|
+
/** Label overriding the spec path (default `/benzene/spec?type=benzene`). */
|
|
18
|
+
static readonly SpecPathLabel = "benzene.spec-path";
|
|
19
|
+
/** Label overriding the health path (default `/benzene/health`). */
|
|
20
|
+
static readonly HealthPathLabel = "benzene.health-path";
|
|
21
|
+
/** Label overriding the URL scheme (default `http`). */
|
|
22
|
+
static readonly SchemeLabel = "benzene.scheme";
|
|
23
|
+
constructor(lister: IKubernetesServiceLister);
|
|
24
|
+
get key(): string;
|
|
25
|
+
discoverAsync(filter: MeshDiscoveryFilter, cancellationToken?: AbortSignal): Promise<readonly MeshServiceRegistryEntry[]>;
|
|
26
|
+
/**
|
|
27
|
+
* Builds a Kubernetes label selector from the filter's tags: `key` (present with any value) or
|
|
28
|
+
* `key=value` (exact match), comma-joined - the same semantics Kubernetes applies natively.
|
|
29
|
+
*/
|
|
30
|
+
static buildLabelSelector(filter: MeshDiscoveryFilter): string;
|
|
31
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KubernetesServiceDiscoveryProvider = void 0;
|
|
4
|
+
/** Port of Benzene.Mesh.Discovery.Kubernetes.KubernetesServiceDiscoveryProvider. */
|
|
5
|
+
const mesh_contracts_1 = require("@benzenejs/mesh-contracts");
|
|
6
|
+
const DefaultSpecPath = '/benzene/spec?type=benzene';
|
|
7
|
+
const DefaultHealthPath = '/benzene/health';
|
|
8
|
+
/**
|
|
9
|
+
* Discovers Benzene services by listing the Kubernetes Services that match the `MeshDiscoveryFilter` (by
|
|
10
|
+
* default, carry the `benzene` label) via the Kubernetes API, and emitting an HTTP registry entry per
|
|
11
|
+
* Service pointing at its in-cluster DNS (`http://{name}.{namespace}.svc.cluster.local[:port]/benzene/spec|health`).
|
|
12
|
+
* The services are HTTP-addressable in-cluster, so entries use the default HTTP interrogation source
|
|
13
|
+
* (`MeshServiceSource.http`) - `HttpMeshServiceSource` interrogates each.
|
|
14
|
+
*
|
|
15
|
+
* The mesh's ServiceAccount needs RBAC to `list` Services. Spec/health paths follow the Cloud Service
|
|
16
|
+
* Profile defaults; a Service can override them with `benzene.spec-path`/`benzene.health-path` labels, and
|
|
17
|
+
* its scheme/port with `benzene.scheme`.
|
|
18
|
+
*/
|
|
19
|
+
class KubernetesServiceDiscoveryProvider {
|
|
20
|
+
lister;
|
|
21
|
+
/** Label overriding the spec path (default `/benzene/spec?type=benzene`). */
|
|
22
|
+
static SpecPathLabel = 'benzene.spec-path';
|
|
23
|
+
/** Label overriding the health path (default `/benzene/health`). */
|
|
24
|
+
static HealthPathLabel = 'benzene.health-path';
|
|
25
|
+
/** Label overriding the URL scheme (default `http`). */
|
|
26
|
+
static SchemeLabel = 'benzene.scheme';
|
|
27
|
+
constructor(lister) {
|
|
28
|
+
this.lister = lister;
|
|
29
|
+
}
|
|
30
|
+
get key() {
|
|
31
|
+
return 'Kubernetes';
|
|
32
|
+
}
|
|
33
|
+
async discoverAsync(filter, cancellationToken) {
|
|
34
|
+
const services = await this.lister.listServicesAsync(filter.namespace, KubernetesServiceDiscoveryProvider.buildLabelSelector(filter), cancellationToken);
|
|
35
|
+
const entries = [];
|
|
36
|
+
for (const service of services) {
|
|
37
|
+
// The lister already applied the label selector server-side, but re-check locally so the provider
|
|
38
|
+
// honours the filter's exact-value semantics uniformly across platforms.
|
|
39
|
+
if (!filter.matches(service.labels)) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const scheme = sanitizeScheme(labelOrDefault(service.labels, KubernetesServiceDiscoveryProvider.SchemeLabel, 'http'));
|
|
43
|
+
const authority = `${service.name}.${service.namespace}.svc.cluster.local${portSuffix(scheme, service.port)}`;
|
|
44
|
+
const specPath = sanitizePath(labelOrDefault(service.labels, KubernetesServiceDiscoveryProvider.SpecPathLabel, DefaultSpecPath), DefaultSpecPath);
|
|
45
|
+
const healthPath = sanitizePath(labelOrDefault(service.labels, KubernetesServiceDiscoveryProvider.HealthPathLabel, DefaultHealthPath), DefaultHealthPath);
|
|
46
|
+
entries.push(new mesh_contracts_1.MeshServiceRegistryEntry(service.name, `${scheme}://${authority}${specPath}`, `${scheme}://${authority}${healthPath}`));
|
|
47
|
+
}
|
|
48
|
+
return entries;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Builds a Kubernetes label selector from the filter's tags: `key` (present with any value) or
|
|
52
|
+
* `key=value` (exact match), comma-joined - the same semantics Kubernetes applies natively.
|
|
53
|
+
*/
|
|
54
|
+
static buildLabelSelector(filter) {
|
|
55
|
+
return Object.entries(filter.tags)
|
|
56
|
+
.map(([key, value]) => (value === null ? key : `${key}=${value}`))
|
|
57
|
+
.join(',');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.KubernetesServiceDiscoveryProvider = KubernetesServiceDiscoveryProvider;
|
|
61
|
+
function portSuffix(scheme, port) {
|
|
62
|
+
const defaultPort = scheme.toLowerCase() === 'https' ? 443 : 80;
|
|
63
|
+
return port === defaultPort || port <= 0 ? '' : `:${port}`;
|
|
64
|
+
}
|
|
65
|
+
// The scheme label carries an attacker-influenceable value (anyone who can label the Service). Only
|
|
66
|
+
// http/https may be used: a value like "https://evil.com/" would otherwise restructure the
|
|
67
|
+
// "{scheme}://{authority}{path}" URL and redirect the aggregator's fetch off-cluster (SSRF). An
|
|
68
|
+
// unrecognised scheme falls back to the safe http default rather than aborting discovery.
|
|
69
|
+
function sanitizeScheme(scheme) {
|
|
70
|
+
const lower = scheme.toLowerCase();
|
|
71
|
+
return lower === 'http' || lower === 'https' ? scheme : 'http';
|
|
72
|
+
}
|
|
73
|
+
// A path override must be a real path (start with '/'); otherwise "{authority}{path}" would graft the value
|
|
74
|
+
// onto the authority and redirect the fetch off the in-cluster host. An invalid override falls back to the
|
|
75
|
+
// safe default path.
|
|
76
|
+
function sanitizePath(path, fallback) {
|
|
77
|
+
return path.startsWith('/') ? path : fallback;
|
|
78
|
+
}
|
|
79
|
+
function labelOrDefault(labels, key, fallback) {
|
|
80
|
+
const value = labels[key];
|
|
81
|
+
return value !== undefined && value.trim().length > 0 ? value : fallback;
|
|
82
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Port of Benzene.Mesh.Discovery.Kubernetes - self-discovery of Benzene services from Kubernetes Services.
|
|
3
|
+
* `KubernetesServiceDiscoveryProvider` (pure label-selector construction, in-cluster-DNS URL building,
|
|
4
|
+
* SSRF-safe scheme/path sanitisation) sits over the `IKubernetesServiceLister` seam, whose real
|
|
5
|
+
* implementation (`KubernetesApiServiceLister`) adapts the Kubernetes client SDK to `@kubernetes/client-node`.
|
|
6
|
+
* Wired via `addMeshKubernetesDiscovery`.
|
|
7
|
+
*/
|
|
8
|
+
export * from './IKubernetesServiceLister';
|
|
9
|
+
export * from './KubernetesServiceDiscoveryProvider';
|
|
10
|
+
export * from './KubernetesApiServiceLister';
|
|
11
|
+
export * from './Extensions';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
/**
|
|
18
|
+
* Port of Benzene.Mesh.Discovery.Kubernetes - self-discovery of Benzene services from Kubernetes Services.
|
|
19
|
+
* `KubernetesServiceDiscoveryProvider` (pure label-selector construction, in-cluster-DNS URL building,
|
|
20
|
+
* SSRF-safe scheme/path sanitisation) sits over the `IKubernetesServiceLister` seam, whose real
|
|
21
|
+
* implementation (`KubernetesApiServiceLister`) adapts the Kubernetes client SDK to `@kubernetes/client-node`.
|
|
22
|
+
* Wired via `addMeshKubernetesDiscovery`.
|
|
23
|
+
*/
|
|
24
|
+
__exportStar(require("./IKubernetesServiceLister"), exports);
|
|
25
|
+
__exportStar(require("./KubernetesServiceDiscoveryProvider"), exports);
|
|
26
|
+
__exportStar(require("./KubernetesApiServiceLister"), exports);
|
|
27
|
+
__exportStar(require("./Extensions"), exports);
|
package/package.json
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@benzenejs/mesh-discovery-kubernetes",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0-beta.2",
|
|
4
|
+
"description": "TypeScript port of Benzene.Mesh.Discovery.Kubernetes",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "commonjs",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@benzenejs/abstractions": "0.1.0-beta.2",
|
|
11
|
+
"@benzenejs/mesh-contracts": "0.1.0-beta.2",
|
|
12
|
+
"@kubernetes/client-node": "^1.4.0"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
]
|
|
17
|
+
}
|
package/README.md
DELETED