@r8s/core 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/dist/context.d.ts +17 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +60 -0
- package/dist/context.js.map +1 -0
- package/dist/defaults.d.ts +205 -0
- package/dist/defaults.d.ts.map +1 -0
- package/dist/defaults.js +117 -0
- package/dist/defaults.js.map +1 -0
- package/dist/fetch-operators.d.ts +7 -0
- package/dist/fetch-operators.d.ts.map +1 -0
- package/dist/fetch-operators.js +29 -0
- package/dist/fetch-operators.js.map +1 -0
- package/dist/guardrails.d.ts +34 -0
- package/dist/guardrails.d.ts.map +1 -0
- package/dist/guardrails.js +225 -0
- package/dist/guardrails.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/jsx-runtime.d.ts +11 -0
- package/dist/jsx-runtime.d.ts.map +1 -0
- package/dist/jsx-runtime.js +20 -0
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/operator.d.ts +28 -0
- package/dist/operator.d.ts.map +1 -0
- package/dist/operator.js +51 -0
- package/dist/operator.js.map +1 -0
- package/dist/renderer.d.ts +10 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/renderer.js +115 -0
- package/dist/renderer.js.map +1 -0
- package/dist/validate.d.ts +30 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +309 -0
- package/dist/validate.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface Context<T> {
|
|
2
|
+
Provider: (props: {
|
|
3
|
+
value: T;
|
|
4
|
+
children?: unknown;
|
|
5
|
+
}) => unknown;
|
|
6
|
+
_defaultValue: T;
|
|
7
|
+
_contextId: symbol;
|
|
8
|
+
}
|
|
9
|
+
export declare function createContext<T>(defaultValue: T): Context<T>;
|
|
10
|
+
export declare function getContextValue<T>(context: Context<T>): T;
|
|
11
|
+
export declare function pushContextValue<T>(context: Context<T>, value: T): void;
|
|
12
|
+
export declare function setContextValue<T>(contextId: symbol, value: T): void;
|
|
13
|
+
export declare function hasContextValue(contextId: symbol): boolean;
|
|
14
|
+
export declare function getContextValueById<T>(contextId: symbol): T | undefined;
|
|
15
|
+
export declare function restoreContextValue(contextId: symbol, hadPrevious: boolean, previousValue: unknown): void;
|
|
16
|
+
export declare function clearContextStack(): void;
|
|
17
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,OAAO,CAAC,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,CAAC,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAA;IAC9D,aAAa,EAAE,CAAC,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAc5D;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAKzD;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAEvE;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAEpE;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAEvE;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,OAAO,EACpB,aAAa,EAAE,OAAO,GACrB,IAAI,CAMN;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createContext = createContext;
|
|
4
|
+
exports.getContextValue = getContextValue;
|
|
5
|
+
exports.pushContextValue = pushContextValue;
|
|
6
|
+
exports.setContextValue = setContextValue;
|
|
7
|
+
exports.hasContextValue = hasContextValue;
|
|
8
|
+
exports.getContextValueById = getContextValueById;
|
|
9
|
+
exports.restoreContextValue = restoreContextValue;
|
|
10
|
+
exports.clearContextStack = clearContextStack;
|
|
11
|
+
// Context stack — shared across all context operations.
|
|
12
|
+
// Uses a Symbol.for() key on globalThis so that createContext and useContext
|
|
13
|
+
// reference the same Map even when @r8s/core and @r8s/core/defaults are
|
|
14
|
+
// bundled as separate module instances by esbuild.
|
|
15
|
+
const CONTEXT_STACK_KEY = Symbol.for('r8s.contextStack');
|
|
16
|
+
const contextStack = (globalThis[CONTEXT_STACK_KEY] ??= new Map());
|
|
17
|
+
function createContext(defaultValue) {
|
|
18
|
+
const contextId = Symbol('r8s.context');
|
|
19
|
+
return {
|
|
20
|
+
Provider: ({ value, children }) => {
|
|
21
|
+
return {
|
|
22
|
+
type: Symbol.for('r8s.context.provider'),
|
|
23
|
+
props: { contextId, value, children },
|
|
24
|
+
key: null,
|
|
25
|
+
};
|
|
26
|
+
},
|
|
27
|
+
_defaultValue: defaultValue,
|
|
28
|
+
_contextId: contextId,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function getContextValue(context) {
|
|
32
|
+
if (contextStack.has(context._contextId)) {
|
|
33
|
+
return contextStack.get(context._contextId);
|
|
34
|
+
}
|
|
35
|
+
return context._defaultValue;
|
|
36
|
+
}
|
|
37
|
+
function pushContextValue(context, value) {
|
|
38
|
+
contextStack.set(context._contextId, value);
|
|
39
|
+
}
|
|
40
|
+
function setContextValue(contextId, value) {
|
|
41
|
+
contextStack.set(contextId, value);
|
|
42
|
+
}
|
|
43
|
+
function hasContextValue(contextId) {
|
|
44
|
+
return contextStack.has(contextId);
|
|
45
|
+
}
|
|
46
|
+
function getContextValueById(contextId) {
|
|
47
|
+
return contextStack.get(contextId);
|
|
48
|
+
}
|
|
49
|
+
function restoreContextValue(contextId, hadPrevious, previousValue) {
|
|
50
|
+
if (hadPrevious) {
|
|
51
|
+
contextStack.set(contextId, previousValue);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
contextStack.delete(contextId);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function clearContextStack() {
|
|
58
|
+
contextStack.clear();
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":";;AAaA,sCAcC;AAED,0CAKC;AAED,4CAEC;AAED,0CAEC;AAED,0CAEC;AAED,kDAEC;AAED,kDAUC;AAED,8CAEC;AAlED,wDAAwD;AACxD,6EAA6E;AAC7E,wEAAwE;AACxE,mDAAmD;AACnD,MAAM,iBAAiB,GAAG,MAAM,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAA;AACxD,MAAM,YAAY,GAAyB,CAAE,UAAkB,CAAC,iBAAiB,CAAC,KAAK,IAAI,GAAG,EAAE,CAAC,CAAA;AAQjG,SAAgB,aAAa,CAAI,YAAe;IAC9C,MAAM,SAAS,GAAG,MAAM,CAAC,aAAa,CAAC,CAAA;IAEvC,OAAO;QACL,QAAQ,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAoC,EAAE,EAAE;YAClE,OAAO;gBACL,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,sBAAsB,CAAC;gBACxC,KAAK,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE;gBACrC,GAAG,EAAE,IAAI;aACV,CAAA;QACH,CAAC;QACD,aAAa,EAAE,YAAY;QAC3B,UAAU,EAAE,SAAS;KACtB,CAAA;AACH,CAAC;AAED,SAAgB,eAAe,CAAI,OAAmB;IACpD,IAAI,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QACzC,OAAO,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAM,CAAA;IAClD,CAAC;IACD,OAAO,OAAO,CAAC,aAAa,CAAA;AAC9B,CAAC;AAED,SAAgB,gBAAgB,CAAI,OAAmB,EAAE,KAAQ;IAC/D,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,CAAA;AAC7C,CAAC;AAED,SAAgB,eAAe,CAAI,SAAiB,EAAE,KAAQ;IAC5D,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;AACpC,CAAC;AAED,SAAgB,eAAe,CAAC,SAAiB;IAC/C,OAAO,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;AACpC,CAAC;AAED,SAAgB,mBAAmB,CAAI,SAAiB;IACtD,OAAO,YAAY,CAAC,GAAG,CAAC,SAAS,CAAkB,CAAA;AACrD,CAAC;AAED,SAAgB,mBAAmB,CACjC,SAAiB,EACjB,WAAoB,EACpB,aAAsB;IAEtB,IAAI,WAAW,EAAE,CAAC;QAChB,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;IAC5C,CAAC;SAAM,CAAC;QACN,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IAChC,CAAC;AACH,CAAC;AAED,SAAgB,iBAAiB;IAC/B,YAAY,CAAC,KAAK,EAAE,CAAA;AACtB,CAAC"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import type { Operator } from '@r8s/k8s-types';
|
|
2
|
+
/** Database connection info passed via context */
|
|
3
|
+
export interface DatabaseConnection {
|
|
4
|
+
host: string;
|
|
5
|
+
port: number;
|
|
6
|
+
database: string;
|
|
7
|
+
username: string;
|
|
8
|
+
passwordSecret: {
|
|
9
|
+
name: string;
|
|
10
|
+
key: string;
|
|
11
|
+
};
|
|
12
|
+
/** Key for the password within the secret (defaults to 'password') */
|
|
13
|
+
passwordKey?: string;
|
|
14
|
+
vendor?: string;
|
|
15
|
+
}
|
|
16
|
+
/** Secret provider configuration */
|
|
17
|
+
export interface SecretProvider {
|
|
18
|
+
backend: 'vault' | 'openbao' | 'sealed-secrets' | 'manual-secrets';
|
|
19
|
+
mount?: string;
|
|
20
|
+
path?: string;
|
|
21
|
+
authRef?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Default contexts for shared infrastructure properties.
|
|
25
|
+
*
|
|
26
|
+
* These contexts allow properties to be inherited down the component tree,
|
|
27
|
+
* eliminating the need to pass the same values to every component.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```tsx
|
|
31
|
+
* import { Namespace, Labels } from '@r8s/core/defaults';
|
|
32
|
+
*
|
|
33
|
+
* export default function App() {
|
|
34
|
+
* return (
|
|
35
|
+
* <Namespace.Provider value="production">
|
|
36
|
+
* <Labels.Provider value={{ app: 'myapp', team: 'platform' }}>
|
|
37
|
+
* <Database name="app-db" />
|
|
38
|
+
* <WebService name="api" image="myapp/api:v1" />
|
|
39
|
+
* </Labels.Provider>
|
|
40
|
+
* </Namespace.Provider>
|
|
41
|
+
* );
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
/** Inherits namespace to all child resources */
|
|
46
|
+
export declare const Namespace: import("./context").Context<string>;
|
|
47
|
+
/** Inherits labels to all child resources */
|
|
48
|
+
export declare const Labels: import("./context").Context<Record<string, string>>;
|
|
49
|
+
/** Inherits annotations to all child resources */
|
|
50
|
+
export declare const Annotations: import("./context").Context<Record<string, string>>;
|
|
51
|
+
/** Inherits environment variables to all child containers */
|
|
52
|
+
export declare const Environment: import("./context").Context<{
|
|
53
|
+
name: string;
|
|
54
|
+
value: string;
|
|
55
|
+
}[]>;
|
|
56
|
+
/** Inherits resource requests/limits to all child containers */
|
|
57
|
+
export declare const Resources: import("./context").Context<{
|
|
58
|
+
requests?: Record<string, string>;
|
|
59
|
+
limits?: Record<string, string>;
|
|
60
|
+
}>;
|
|
61
|
+
/** Inherits service account name to all child pods */
|
|
62
|
+
export declare const ServiceAccount: import("./context").Context<string>;
|
|
63
|
+
/** Inherits image registry prefix (e.g., 'ghcr.io/myorg') */
|
|
64
|
+
export declare const ImageRegistry: import("./context").Context<string>;
|
|
65
|
+
/** Inherits domain suffix for ingresses */
|
|
66
|
+
export declare const Domain: import("./context").Context<string>;
|
|
67
|
+
/** Inherits TLS configuration */
|
|
68
|
+
export declare const TLS: import("./context").Context<{
|
|
69
|
+
enabled: boolean;
|
|
70
|
+
issuer?: string;
|
|
71
|
+
secretName?: string;
|
|
72
|
+
}>;
|
|
73
|
+
/**
|
|
74
|
+
* Cluster context for shared PostgreSQL clusters.
|
|
75
|
+
*
|
|
76
|
+
* When multiple databases should share the same CNPG cluster,
|
|
77
|
+
* wrap them in a Cluster component. Each Database reads this
|
|
78
|
+
* context and reuses the shared cluster's connection info instead
|
|
79
|
+
* of creating a dedicated cluster.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```tsx
|
|
83
|
+
* import { Cluster } from '@r8s/recipes';
|
|
84
|
+
*
|
|
85
|
+
* <Cluster name="main" storage="100Gi">
|
|
86
|
+
* <Database name="user-db" />
|
|
87
|
+
* <Database name="order-db" />
|
|
88
|
+
* </Cluster>
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
export interface ClusterConfig {
|
|
92
|
+
name: string;
|
|
93
|
+
namespace: string;
|
|
94
|
+
storage: string;
|
|
95
|
+
host: string;
|
|
96
|
+
secretName: string;
|
|
97
|
+
/**
|
|
98
|
+
* Reference to the Kubernetes Secret holding the shared cluster's password.
|
|
99
|
+
* Optional because the `Cluster` component itself does not create a Secret —
|
|
100
|
+
* CNPG provisions secrets automatically with its own naming. Consumers that
|
|
101
|
+
* need an explicit reference should set this when they know the secret name
|
|
102
|
+
* (e.g. when a `<Database />` child creates its own credentials secret).
|
|
103
|
+
*/
|
|
104
|
+
passwordSecret?: {
|
|
105
|
+
name: string;
|
|
106
|
+
key: string;
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
export declare const ClusterContext: import("./context").Context<ClusterConfig | null>;
|
|
110
|
+
/**
|
|
111
|
+
* Database connection context for component composition.
|
|
112
|
+
*
|
|
113
|
+
* When a Database component renders, it sets this context so that
|
|
114
|
+
* downstream components can automatically wire up their connections.
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```tsx
|
|
118
|
+
* import { DatabaseContext } from '@r8s/core/defaults';
|
|
119
|
+
*
|
|
120
|
+
* export default function Platform() {
|
|
121
|
+
* return (
|
|
122
|
+
* <Database name="keycloak-db" storage="10Gi">
|
|
123
|
+
* <KeycloakInstance name="keycloak" hostname="auth.example.com" />
|
|
124
|
+
* </Database>
|
|
125
|
+
* );
|
|
126
|
+
* }
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
export declare const DatabaseContext: import("./context").Context<DatabaseConnection | null>;
|
|
130
|
+
/**
|
|
131
|
+
* Secret provider context for pluggable secret management.
|
|
132
|
+
*
|
|
133
|
+
* Components read this to determine how credentials should be stored:
|
|
134
|
+
* - Vault: Creates VaultStaticSecret + VaultAuth (VSO)
|
|
135
|
+
* - OpenBao: Creates OpenBaoStaticSecret + OpenBaoAuth
|
|
136
|
+
* - Kubernetes: Plain Kubernetes Secret
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```tsx
|
|
140
|
+
* import { SecretContext } from '@r8s/core/defaults';
|
|
141
|
+
*
|
|
142
|
+
* // Use Vault for all secrets in this subtree
|
|
143
|
+
* <SecretContext.Provider value={{ backend: 'vault', mount: 'secret', path: 'app/db', authRef: 'vault-auth' }}>
|
|
144
|
+
* <Database name="app-db" storage="10Gi" />
|
|
145
|
+
* <KeycloakInstance name="keycloak" hostname="auth.example.com" />
|
|
146
|
+
* </SecretContext.Provider>
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
export declare const SecretContext: import("./context").Context<SecretProvider | null>;
|
|
150
|
+
/**
|
|
151
|
+
* Operator context for declaring Kubernetes operator dependencies.
|
|
152
|
+
*
|
|
153
|
+
* Components that require operators (CNPG, cert-manager, etc.) can either:
|
|
154
|
+
* 1. Read operators from this context (shared operators)
|
|
155
|
+
* 2. Create their own operator instances and return them as resources
|
|
156
|
+
*
|
|
157
|
+
* The renderer collects all operators so the deployment pipeline can
|
|
158
|
+
* install them before applying application resources.
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* ```tsx
|
|
162
|
+
* import { OperatorContext } from '@r8s/core/defaults';
|
|
163
|
+
* import { cnpgOperator } from '@r8s/recipes';
|
|
164
|
+
* import { certManagerOperator } from '@r8s/cert-manager';
|
|
165
|
+
*
|
|
166
|
+
* // Shared operators for entire stack
|
|
167
|
+
* <OperatorContext.Provider value={[
|
|
168
|
+
* cnpgOperator('1.22.5'),
|
|
169
|
+
* certManagerOperator('1.14.0'),
|
|
170
|
+
* ]}>
|
|
171
|
+
* <Database name="app-db" storage="10Gi" />
|
|
172
|
+
* <App name="myapp" host="myapp.example.com" tls={{ secretName: "myapp-tls", clusterIssuer: "letsencrypt" }} />
|
|
173
|
+
* </OperatorContext.Provider>
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
export declare const OperatorContext: import("./context").Context<Operator[]>;
|
|
177
|
+
/**
|
|
178
|
+
* Routing context for cluster-wide routing implementation.
|
|
179
|
+
*
|
|
180
|
+
* Set this once at the top of the tree to tell <Endpoint /> and <App />
|
|
181
|
+
* whether the cluster uses nginx Ingress or Envoy Gateway (Gateway API).
|
|
182
|
+
* Components read this and render the appropriate resources.
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* ```tsx
|
|
186
|
+
* import { RoutingContext } from '@r8s/core/defaults';
|
|
187
|
+
*
|
|
188
|
+
* // Envoy Gateway cluster
|
|
189
|
+
* <RoutingContext.Provider value={{ mode: 'gateway', gatewayClassName: 'eg' }}>
|
|
190
|
+
* <App name="myapp" host="myapp.example.com" />
|
|
191
|
+
* </RoutingContext.Provider>
|
|
192
|
+
*
|
|
193
|
+
* // nginx Ingress cluster (default, no provider needed)
|
|
194
|
+
* <App name="myapp" host="myapp.example.com" />
|
|
195
|
+
* ```
|
|
196
|
+
*/
|
|
197
|
+
export interface RoutingConfig {
|
|
198
|
+
/** Routing implementation: 'ingress' (nginx) or 'gateway' (Envoy Gateway API) */
|
|
199
|
+
mode: 'ingress' | 'gateway';
|
|
200
|
+
/** Gateway class name (only used when mode='gateway', default: 'eg') */
|
|
201
|
+
gatewayClassName?: string;
|
|
202
|
+
}
|
|
203
|
+
export declare const RoutingContext: import("./context").Context<RoutingConfig>;
|
|
204
|
+
export { createContext } from './context';
|
|
205
|
+
//# sourceMappingURL=defaults.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAE9C,kDAAkD;AAClD,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,cAAc,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;IAC7C,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,oCAAoC;AACpC,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,gBAAgB,GAAG,gBAAgB,CAAA;IAClE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,gDAAgD;AAChD,eAAO,MAAM,SAAS,qCAAmC,CAAA;AAEzD,6CAA6C;AAC7C,eAAO,MAAM,MAAM,qDAA4C,CAAA;AAE/D,kDAAkD;AAClD,eAAO,MAAM,WAAW,qDAA4C,CAAA;AAEpE,6DAA6D;AAC7D,eAAO,MAAM,WAAW;UAA+B,MAAM;WAAS,MAAM;IAAQ,CAAA;AAEpF,gEAAgE;AAChE,eAAO,MAAM,SAAS;eACT,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;aACxB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;EAC3B,CAAA;AAEN,sDAAsD;AACtD,eAAO,MAAM,cAAc,qCAAmC,CAAA;AAE9D,6DAA6D;AAC7D,eAAO,MAAM,aAAa,qCAA4B,CAAA;AAEtD,2CAA2C;AAC3C,eAAO,MAAM,MAAM,qCAA4B,CAAA;AAE/C,iCAAiC;AACjC,eAAO,MAAM,GAAG;aACL,OAAO;aACP,MAAM;iBACF,MAAM;EACC,CAAA;AAEtB;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB;;;;;;OAMG;IACH,cAAc,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;CAC/C;AAED,eAAO,MAAM,cAAc,mDAA4C,CAAA;AAEvE;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,eAAe,wDAAiD,CAAA;AAE7E;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,aAAa,oDAA6C,CAAA;AAEvE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,eAAe,yCAAgC,CAAA;AAE5D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,aAAa;IAC5B,iFAAiF;IACjF,IAAI,EAAE,SAAS,GAAG,SAAS,CAAA;IAC3B,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED,eAAO,MAAM,cAAc,4CAAoD,CAAA;AAG/E,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA"}
|
package/dist/defaults.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createContext = exports.RoutingContext = exports.OperatorContext = exports.SecretContext = exports.DatabaseContext = exports.ClusterContext = exports.TLS = exports.Domain = exports.ImageRegistry = exports.ServiceAccount = exports.Resources = exports.Environment = exports.Annotations = exports.Labels = exports.Namespace = void 0;
|
|
4
|
+
const context_1 = require("./context");
|
|
5
|
+
/**
|
|
6
|
+
* Default contexts for shared infrastructure properties.
|
|
7
|
+
*
|
|
8
|
+
* These contexts allow properties to be inherited down the component tree,
|
|
9
|
+
* eliminating the need to pass the same values to every component.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* import { Namespace, Labels } from '@r8s/core/defaults';
|
|
14
|
+
*
|
|
15
|
+
* export default function App() {
|
|
16
|
+
* return (
|
|
17
|
+
* <Namespace.Provider value="production">
|
|
18
|
+
* <Labels.Provider value={{ app: 'myapp', team: 'platform' }}>
|
|
19
|
+
* <Database name="app-db" />
|
|
20
|
+
* <WebService name="api" image="myapp/api:v1" />
|
|
21
|
+
* </Labels.Provider>
|
|
22
|
+
* </Namespace.Provider>
|
|
23
|
+
* );
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
/** Inherits namespace to all child resources */
|
|
28
|
+
exports.Namespace = (0, context_1.createContext)('default');
|
|
29
|
+
/** Inherits labels to all child resources */
|
|
30
|
+
exports.Labels = (0, context_1.createContext)({});
|
|
31
|
+
/** Inherits annotations to all child resources */
|
|
32
|
+
exports.Annotations = (0, context_1.createContext)({});
|
|
33
|
+
/** Inherits environment variables to all child containers */
|
|
34
|
+
exports.Environment = (0, context_1.createContext)([]);
|
|
35
|
+
/** Inherits resource requests/limits to all child containers */
|
|
36
|
+
exports.Resources = (0, context_1.createContext)({});
|
|
37
|
+
/** Inherits service account name to all child pods */
|
|
38
|
+
exports.ServiceAccount = (0, context_1.createContext)('default');
|
|
39
|
+
/** Inherits image registry prefix (e.g., 'ghcr.io/myorg') */
|
|
40
|
+
exports.ImageRegistry = (0, context_1.createContext)('');
|
|
41
|
+
/** Inherits domain suffix for ingresses */
|
|
42
|
+
exports.Domain = (0, context_1.createContext)('');
|
|
43
|
+
/** Inherits TLS configuration */
|
|
44
|
+
exports.TLS = (0, context_1.createContext)({ enabled: false });
|
|
45
|
+
exports.ClusterContext = (0, context_1.createContext)(null);
|
|
46
|
+
/**
|
|
47
|
+
* Database connection context for component composition.
|
|
48
|
+
*
|
|
49
|
+
* When a Database component renders, it sets this context so that
|
|
50
|
+
* downstream components can automatically wire up their connections.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```tsx
|
|
54
|
+
* import { DatabaseContext } from '@r8s/core/defaults';
|
|
55
|
+
*
|
|
56
|
+
* export default function Platform() {
|
|
57
|
+
* return (
|
|
58
|
+
* <Database name="keycloak-db" storage="10Gi">
|
|
59
|
+
* <KeycloakInstance name="keycloak" hostname="auth.example.com" />
|
|
60
|
+
* </Database>
|
|
61
|
+
* );
|
|
62
|
+
* }
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
exports.DatabaseContext = (0, context_1.createContext)(null);
|
|
66
|
+
/**
|
|
67
|
+
* Secret provider context for pluggable secret management.
|
|
68
|
+
*
|
|
69
|
+
* Components read this to determine how credentials should be stored:
|
|
70
|
+
* - Vault: Creates VaultStaticSecret + VaultAuth (VSO)
|
|
71
|
+
* - OpenBao: Creates OpenBaoStaticSecret + OpenBaoAuth
|
|
72
|
+
* - Kubernetes: Plain Kubernetes Secret
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```tsx
|
|
76
|
+
* import { SecretContext } from '@r8s/core/defaults';
|
|
77
|
+
*
|
|
78
|
+
* // Use Vault for all secrets in this subtree
|
|
79
|
+
* <SecretContext.Provider value={{ backend: 'vault', mount: 'secret', path: 'app/db', authRef: 'vault-auth' }}>
|
|
80
|
+
* <Database name="app-db" storage="10Gi" />
|
|
81
|
+
* <KeycloakInstance name="keycloak" hostname="auth.example.com" />
|
|
82
|
+
* </SecretContext.Provider>
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
exports.SecretContext = (0, context_1.createContext)(null);
|
|
86
|
+
/**
|
|
87
|
+
* Operator context for declaring Kubernetes operator dependencies.
|
|
88
|
+
*
|
|
89
|
+
* Components that require operators (CNPG, cert-manager, etc.) can either:
|
|
90
|
+
* 1. Read operators from this context (shared operators)
|
|
91
|
+
* 2. Create their own operator instances and return them as resources
|
|
92
|
+
*
|
|
93
|
+
* The renderer collects all operators so the deployment pipeline can
|
|
94
|
+
* install them before applying application resources.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```tsx
|
|
98
|
+
* import { OperatorContext } from '@r8s/core/defaults';
|
|
99
|
+
* import { cnpgOperator } from '@r8s/recipes';
|
|
100
|
+
* import { certManagerOperator } from '@r8s/cert-manager';
|
|
101
|
+
*
|
|
102
|
+
* // Shared operators for entire stack
|
|
103
|
+
* <OperatorContext.Provider value={[
|
|
104
|
+
* cnpgOperator('1.22.5'),
|
|
105
|
+
* certManagerOperator('1.14.0'),
|
|
106
|
+
* ]}>
|
|
107
|
+
* <Database name="app-db" storage="10Gi" />
|
|
108
|
+
* <App name="myapp" host="myapp.example.com" tls={{ secretName: "myapp-tls", clusterIssuer: "letsencrypt" }} />
|
|
109
|
+
* </OperatorContext.Provider>
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
exports.OperatorContext = (0, context_1.createContext)([]);
|
|
113
|
+
exports.RoutingContext = (0, context_1.createContext)({ mode: 'ingress' });
|
|
114
|
+
// Re-export createContext for provider components in recipes
|
|
115
|
+
var context_2 = require("./context");
|
|
116
|
+
Object.defineProperty(exports, "createContext", { enumerable: true, get: function () { return context_2.createContext; } });
|
|
117
|
+
//# sourceMappingURL=defaults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":";;;AAAA,uCAAyC;AAuBzC;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,gDAAgD;AACnC,QAAA,SAAS,GAAG,IAAA,uBAAa,EAAS,SAAS,CAAC,CAAA;AAEzD,6CAA6C;AAChC,QAAA,MAAM,GAAG,IAAA,uBAAa,EAAyB,EAAE,CAAC,CAAA;AAE/D,kDAAkD;AACrC,QAAA,WAAW,GAAG,IAAA,uBAAa,EAAyB,EAAE,CAAC,CAAA;AAEpE,6DAA6D;AAChD,QAAA,WAAW,GAAG,IAAA,uBAAa,EAAyC,EAAE,CAAC,CAAA;AAEpF,gEAAgE;AACnD,QAAA,SAAS,GAAG,IAAA,uBAAa,EAGnC,EAAE,CAAC,CAAA;AAEN,sDAAsD;AACzC,QAAA,cAAc,GAAG,IAAA,uBAAa,EAAS,SAAS,CAAC,CAAA;AAE9D,6DAA6D;AAChD,QAAA,aAAa,GAAG,IAAA,uBAAa,EAAS,EAAE,CAAC,CAAA;AAEtD,2CAA2C;AAC9B,QAAA,MAAM,GAAG,IAAA,uBAAa,EAAS,EAAE,CAAC,CAAA;AAE/C,iCAAiC;AACpB,QAAA,GAAG,GAAG,IAAA,uBAAa,EAI7B,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAA;AAoCT,QAAA,cAAc,GAAG,IAAA,uBAAa,EAAuB,IAAI,CAAC,CAAA;AAEvE;;;;;;;;;;;;;;;;;;GAkBG;AACU,QAAA,eAAe,GAAG,IAAA,uBAAa,EAA4B,IAAI,CAAC,CAAA;AAE7E;;;;;;;;;;;;;;;;;;GAkBG;AACU,QAAA,aAAa,GAAG,IAAA,uBAAa,EAAwB,IAAI,CAAC,CAAA;AAEvE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACU,QAAA,eAAe,GAAG,IAAA,uBAAa,EAAa,EAAE,CAAC,CAAA;AA6B/C,QAAA,cAAc,GAAG,IAAA,uBAAa,EAAgB,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAA;AAE/E,6DAA6D;AAC7D,qCAAyC;AAAhC,wGAAA,aAAa,OAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Operator } from '@r8s/k8s-types';
|
|
2
|
+
/**
|
|
3
|
+
* Fetch operator manifests from their source URLs.
|
|
4
|
+
* Returns YAML strings that can be prepended to rendered output.
|
|
5
|
+
*/
|
|
6
|
+
export declare function fetchOperatorManifests(operators: Operator[]): Promise<string[]>;
|
|
7
|
+
//# sourceMappingURL=fetch-operators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-operators.d.ts","sourceRoot":"","sources":["../src/fetch-operators.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAE9C;;;GAGG;AACH,wBAAsB,sBAAsB,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAwBrF"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fetchOperatorManifests = fetchOperatorManifests;
|
|
4
|
+
/**
|
|
5
|
+
* Fetch operator manifests from their source URLs.
|
|
6
|
+
* Returns YAML strings that can be prepended to rendered output.
|
|
7
|
+
*/
|
|
8
|
+
async function fetchOperatorManifests(operators) {
|
|
9
|
+
const manifests = [];
|
|
10
|
+
for (const op of operators) {
|
|
11
|
+
if (op.source.type !== 'manifest' || !op.source.url) {
|
|
12
|
+
// Skip non-manifest operators (helm, olm, flux) — they need external tooling
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const response = await fetch(op.source.url);
|
|
17
|
+
if (!response.ok) {
|
|
18
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
19
|
+
}
|
|
20
|
+
const yaml = await response.text();
|
|
21
|
+
manifests.push(`# Operator: ${op.name} v${op.version}\n${yaml}`);
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
throw new Error(`Failed to fetch operator manifest for ${op.name}: ${error instanceof Error ? error.message : String(error)}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return manifests;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=fetch-operators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-operators.js","sourceRoot":"","sources":["../src/fetch-operators.ts"],"names":[],"mappings":";;AAMA,wDAwBC;AA5BD;;;GAGG;AACI,KAAK,UAAU,sBAAsB,CAAC,SAAqB;IAChE,MAAM,SAAS,GAAa,EAAE,CAAA;IAE9B,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;QAC3B,IAAI,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;YACpD,6EAA6E;YAC7E,SAAQ;QACV,CAAC;QAED,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC3C,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,QAAQ,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAA;YACpE,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;YAClC,SAAS,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC,CAAA;QAClE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACb,yCAAyC,EAAE,CAAC,IAAI,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAC9G,CAAA;QACH,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAA;AAClB,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { KubernetesResource } from '@r8s/k8s-types';
|
|
2
|
+
import { ValidationError } from './validate';
|
|
3
|
+
export interface GuardrailRule {
|
|
4
|
+
/** Unique rule identifier */
|
|
5
|
+
id: string;
|
|
6
|
+
/** Human-readable description */
|
|
7
|
+
description: string;
|
|
8
|
+
/** Severity level */
|
|
9
|
+
severity: 'error' | 'warning' | 'info';
|
|
10
|
+
/** Test function - returns empty array if rule passes, ValidationError[] if it fails */
|
|
11
|
+
test: (resources: KubernetesResource[]) => ValidationError[];
|
|
12
|
+
}
|
|
13
|
+
/** Check that all namespaces have NetworkPolicies */
|
|
14
|
+
export declare const requireNetworkPolicies: GuardrailRule;
|
|
15
|
+
/** Check that all Deployments have resource limits */
|
|
16
|
+
export declare const requireResourceLimits: GuardrailRule;
|
|
17
|
+
/** Check that all resources have required labels */
|
|
18
|
+
export declare const requireLabels: (requiredLabels: string[]) => GuardrailRule;
|
|
19
|
+
/** Check that no secrets contain plaintext passwords */
|
|
20
|
+
export declare const noPlaintextSecrets: GuardrailRule;
|
|
21
|
+
/** Check that Ingresses have TLS configured */
|
|
22
|
+
export declare const requireTLS: GuardrailRule;
|
|
23
|
+
/** Check that Pods don't run as root */
|
|
24
|
+
export declare const noRootContainers: GuardrailRule;
|
|
25
|
+
/** Default set of guardrails for production use */
|
|
26
|
+
export declare const defaultGuardrails: GuardrailRule[];
|
|
27
|
+
/** Run all guardrail rules against a set of resources */
|
|
28
|
+
export declare function runGuardrails(resources: KubernetesResource[], rules?: GuardrailRule[]): {
|
|
29
|
+
passed: boolean;
|
|
30
|
+
errors: ValidationError[];
|
|
31
|
+
warnings: ValidationError[];
|
|
32
|
+
info: ValidationError[];
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=guardrails.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guardrails.d.ts","sourceRoot":"","sources":["../src/guardrails.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAE5C,MAAM,WAAW,aAAa;IAC5B,6BAA6B;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,iCAAiC;IACjC,WAAW,EAAE,MAAM,CAAA;IACnB,qBAAqB;IACrB,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAA;IACtC,wFAAwF;IACxF,IAAI,EAAE,CAAC,SAAS,EAAE,kBAAkB,EAAE,KAAK,eAAe,EAAE,CAAA;CAC7D;AAED,qDAAqD;AACrD,eAAO,MAAM,sBAAsB,EAAE,aAgCpC,CAAA;AAED,sDAAsD;AACtD,eAAO,MAAM,qBAAqB,EAAE,aAwCnC,CAAA;AAED,oDAAoD;AACpD,eAAO,MAAM,aAAa,GAAI,gBAAgB,MAAM,EAAE,KAAG,aAwBvD,CAAA;AAEF,wDAAwD;AACxD,eAAO,MAAM,kBAAkB,EAAE,aA8BhC,CAAA;AAED,+CAA+C;AAC/C,eAAO,MAAM,UAAU,EAAE,aAyBxB,CAAA;AAED,wCAAwC;AACxC,eAAO,MAAM,gBAAgB,EAAE,aA4C9B,CAAA;AAED,mDAAmD;AACnD,eAAO,MAAM,iBAAiB,EAAE,aAAa,EAM5C,CAAA;AAED,yDAAyD;AACzD,wBAAgB,aAAa,CAC3B,SAAS,EAAE,kBAAkB,EAAE,EAC/B,KAAK,GAAE,aAAa,EAAsB,GACzC;IACD,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,EAAE,eAAe,EAAE,CAAA;IACzB,QAAQ,EAAE,eAAe,EAAE,CAAA;IAC3B,IAAI,EAAE,eAAe,EAAE,CAAA;CACxB,CAwBA"}
|