@r8s/recipes 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/app.d.ts +94 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +120 -0
- package/dist/app.js.map +1 -0
- package/dist/auth/components.d.ts +163 -0
- package/dist/auth/components.d.ts.map +1 -0
- package/dist/auth/components.js +134 -0
- package/dist/auth/components.js.map +1 -0
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +14 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth.d.ts +92 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +302 -0
- package/dist/auth.js.map +1 -0
- package/dist/backup.d.ts +45 -0
- package/dist/backup.d.ts.map +1 -0
- package/dist/backup.js +59 -0
- package/dist/backup.js.map +1 -0
- package/dist/cert-provider.d.ts +78 -0
- package/dist/cert-provider.d.ts.map +1 -0
- package/dist/cert-provider.js +71 -0
- package/dist/cert-provider.js.map +1 -0
- package/dist/database.d.ts +49 -0
- package/dist/database.d.ts.map +1 -0
- package/dist/database.js +212 -0
- package/dist/database.js.map +1 -0
- package/dist/dns-provider.d.ts +110 -0
- package/dist/dns-provider.d.ts.map +1 -0
- package/dist/dns-provider.js +121 -0
- package/dist/dns-provider.js.map +1 -0
- package/dist/endpoint-provider.d.ts +121 -0
- package/dist/endpoint-provider.d.ts.map +1 -0
- package/dist/endpoint-provider.js +79 -0
- package/dist/endpoint-provider.js.map +1 -0
- package/dist/endpoint.d.ts +43 -0
- package/dist/endpoint.d.ts.map +1 -0
- package/dist/endpoint.js +221 -0
- package/dist/endpoint.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -0
- package/dist/monitoring.d.ts +49 -0
- package/dist/monitoring.d.ts.map +1 -0
- package/dist/monitoring.js +128 -0
- package/dist/monitoring.js.map +1 -0
- package/dist/operators.d.ts +19 -0
- package/dist/operators.d.ts.map +1 -0
- package/dist/operators.js +30 -0
- package/dist/operators.js.map +1 -0
- package/dist/platform.d.ts +116 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/platform.js +121 -0
- package/dist/platform.js.map +1 -0
- package/dist/secret-provider.d.ts +119 -0
- package/dist/secret-provider.d.ts.map +1 -0
- package/dist/secret-provider.js +125 -0
- package/dist/secret-provider.js.map +1 -0
- package/dist/web-service.d.ts +87 -0
- package/dist/web-service.d.ts.map +1 -0
- package/dist/web-service.js +171 -0
- package/dist/web-service.js.map +1 -0
- package/package.json +48 -0
package/dist/app.d.ts
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { type SecretRef, type VaultSecretRef } from './web-service';
|
|
2
|
+
import type { TLSConfig } from '@r8s/k8s-types';
|
|
3
|
+
export interface AppProps {
|
|
4
|
+
/** Resource name */
|
|
5
|
+
name: string;
|
|
6
|
+
/** Kubernetes namespace (defaults to 'default' or the Platform namespace) */
|
|
7
|
+
namespace?: string;
|
|
8
|
+
/** Container image (e.g., 'myapp/api:v1.2.3') */
|
|
9
|
+
image: string;
|
|
10
|
+
/** Container port the app listens on (defaults to 3000) */
|
|
11
|
+
port?: number;
|
|
12
|
+
/** Number of pod replicas (defaults to 2) */
|
|
13
|
+
replicas?: number;
|
|
14
|
+
/** Domain name (e.g., 'api.example.com') the endpoint should accept traffic for */
|
|
15
|
+
host: string;
|
|
16
|
+
/** TLS certificate configuration for HTTPS */
|
|
17
|
+
tls?: TLSConfig;
|
|
18
|
+
/** Plain environment variables (non-sensitive) */
|
|
19
|
+
env?: Record<string, string>;
|
|
20
|
+
/** Secrets from Kubernetes Secrets — safe by default */
|
|
21
|
+
secrets?: Record<string, SecretRef | string>;
|
|
22
|
+
/** Secrets from Vault — creates VaultStaticSecret objects */
|
|
23
|
+
vault?: Record<string, VaultSecretRef>;
|
|
24
|
+
/** CPU and memory requests/limits for the app container */
|
|
25
|
+
resources?: {
|
|
26
|
+
requests?: {
|
|
27
|
+
cpu?: string;
|
|
28
|
+
memory?: string;
|
|
29
|
+
};
|
|
30
|
+
limits?: {
|
|
31
|
+
cpu?: string;
|
|
32
|
+
memory?: string;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
/** Add a Redis cache for this app (session store, cache, queue) */
|
|
36
|
+
cache?: boolean;
|
|
37
|
+
/** Create a DNS record via ExternalDNS (default: false) */
|
|
38
|
+
dns?: boolean;
|
|
39
|
+
/** Child components rendered as sibling resources (e.g., a BackgroundWorker) */
|
|
40
|
+
children?: unknown;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Simple application — Deployment + Service + Endpoint.
|
|
44
|
+
*
|
|
45
|
+
* @title App
|
|
46
|
+
* @category Complete Solution
|
|
47
|
+
*
|
|
48
|
+
* The simplest way to deploy an app to Kubernetes — Deployment, Service,
|
|
49
|
+
* and routing (Ingress or Gateway) with TLS.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* import { App } from '@r8s/recipes'
|
|
53
|
+
*
|
|
54
|
+
* export default <App name="myapp" image="myapp/web:v1.2.3" host="myapp.example.com" />
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* import { Platform, App } from '@r8s/recipes'
|
|
58
|
+
*
|
|
59
|
+
* export default (
|
|
60
|
+
* <Platform routing="gateway" namespace="production">
|
|
61
|
+
* <App name="myapp" image="myapp/web:v1.2.3" host="myapp.example.com" />
|
|
62
|
+
* </Platform>
|
|
63
|
+
* )
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* import { App } from '@r8s/recipes'
|
|
67
|
+
*
|
|
68
|
+
* export default (
|
|
69
|
+
* <App
|
|
70
|
+
* name="myapp"
|
|
71
|
+
* image="myapp/web:v1.2.3"
|
|
72
|
+
* host="myapp.example.com"
|
|
73
|
+
* env={{ LOG_LEVEL: 'info' }}
|
|
74
|
+
* secrets={{ DATABASE_URL: 'app-secrets' }}
|
|
75
|
+
* />
|
|
76
|
+
* )
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* import { Database, App } from '@r8s/recipes'
|
|
80
|
+
*
|
|
81
|
+
* export default (
|
|
82
|
+
* <>
|
|
83
|
+
* <Database name="myapp-db" storage="20Gi" />
|
|
84
|
+
* <App
|
|
85
|
+
* name="myapp"
|
|
86
|
+
* image="myapp/web:v1.2.3"
|
|
87
|
+
* host="myapp.example.com"
|
|
88
|
+
* tls={{ secretName: 'myapp-tls', clusterIssuer: 'letsencrypt' }}
|
|
89
|
+
* />
|
|
90
|
+
* </>
|
|
91
|
+
* )
|
|
92
|
+
*/
|
|
93
|
+
export declare function App(props: AppProps): import("@r8s/core").r8sElement;
|
|
94
|
+
//# sourceMappingURL=app.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":"AACA,OAAO,EAAc,KAAK,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAA;AAG/E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAI/C,MAAM,WAAW,QAAQ;IACvB,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAA;IACb,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,mFAAmF;IACnF,IAAI,EAAE,MAAM,CAAA;IACZ,8CAA8C;IAC9C,GAAG,CAAC,EAAE,SAAS,CAAA;IACf,kDAAkD;IAClD,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC,CAAA;IAC5C,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;IACtC,2DAA2D;IAC3D,SAAS,CAAC,EAAE;QACV,QAAQ,CAAC,EAAE;YAAE,GAAG,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;QAC5C,MAAM,CAAC,EAAE;YAAE,GAAG,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAC3C,CAAA;IACD,mEAAmE;IACnE,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,2DAA2D;IAC3D,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,gFAAgF;IAChF,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,QAAQ,kCAuFlC"}
|
package/dist/app.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.App = App;
|
|
4
|
+
const core_1 = require("@r8s/core");
|
|
5
|
+
const web_service_1 = require("./web-service");
|
|
6
|
+
const endpoint_1 = require("./endpoint");
|
|
7
|
+
const defaults_1 = require("@r8s/core/defaults");
|
|
8
|
+
const crds_1 = require("@r8s/crds");
|
|
9
|
+
const redis_1 = require("@r8s/crds/redis");
|
|
10
|
+
/**
|
|
11
|
+
* Simple application — Deployment + Service + Endpoint.
|
|
12
|
+
*
|
|
13
|
+
* @title App
|
|
14
|
+
* @category Complete Solution
|
|
15
|
+
*
|
|
16
|
+
* The simplest way to deploy an app to Kubernetes — Deployment, Service,
|
|
17
|
+
* and routing (Ingress or Gateway) with TLS.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* import { App } from '@r8s/recipes'
|
|
21
|
+
*
|
|
22
|
+
* export default <App name="myapp" image="myapp/web:v1.2.3" host="myapp.example.com" />
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* import { Platform, App } from '@r8s/recipes'
|
|
26
|
+
*
|
|
27
|
+
* export default (
|
|
28
|
+
* <Platform routing="gateway" namespace="production">
|
|
29
|
+
* <App name="myapp" image="myapp/web:v1.2.3" host="myapp.example.com" />
|
|
30
|
+
* </Platform>
|
|
31
|
+
* )
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* import { App } from '@r8s/recipes'
|
|
35
|
+
*
|
|
36
|
+
* export default (
|
|
37
|
+
* <App
|
|
38
|
+
* name="myapp"
|
|
39
|
+
* image="myapp/web:v1.2.3"
|
|
40
|
+
* host="myapp.example.com"
|
|
41
|
+
* env={{ LOG_LEVEL: 'info' }}
|
|
42
|
+
* secrets={{ DATABASE_URL: 'app-secrets' }}
|
|
43
|
+
* />
|
|
44
|
+
* )
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* import { Database, App } from '@r8s/recipes'
|
|
48
|
+
*
|
|
49
|
+
* export default (
|
|
50
|
+
* <>
|
|
51
|
+
* <Database name="myapp-db" storage="20Gi" />
|
|
52
|
+
* <App
|
|
53
|
+
* name="myapp"
|
|
54
|
+
* image="myapp/web:v1.2.3"
|
|
55
|
+
* host="myapp.example.com"
|
|
56
|
+
* tls={{ secretName: 'myapp-tls', clusterIssuer: 'letsencrypt' }}
|
|
57
|
+
* />
|
|
58
|
+
* </>
|
|
59
|
+
* )
|
|
60
|
+
*/
|
|
61
|
+
function App(props) {
|
|
62
|
+
const { name, namespace: namespaceProp, image, port = 3000, replicas = 2, host, tls, env = {}, secrets = {}, vault = {}, resources, cache = false, dns, children, } = props;
|
|
63
|
+
// Inherit namespace from <Platform> context if not explicitly set
|
|
64
|
+
const contextNamespace = (0, core_1.useContext)(defaults_1.Namespace);
|
|
65
|
+
const namespace = namespaceProp ?? (contextNamespace !== 'default' ? contextNamespace : undefined) ?? 'default';
|
|
66
|
+
const elements = [];
|
|
67
|
+
elements.push((0, core_1.jsx)(web_service_1.WebService, {
|
|
68
|
+
name,
|
|
69
|
+
namespace,
|
|
70
|
+
image,
|
|
71
|
+
port,
|
|
72
|
+
replicas,
|
|
73
|
+
env,
|
|
74
|
+
secrets,
|
|
75
|
+
vault,
|
|
76
|
+
resources,
|
|
77
|
+
}));
|
|
78
|
+
elements.push((0, core_1.jsx)(endpoint_1.Endpoint, {
|
|
79
|
+
name: `${name}-endpoint`,
|
|
80
|
+
namespace,
|
|
81
|
+
host,
|
|
82
|
+
serviceName: name,
|
|
83
|
+
servicePort: 80,
|
|
84
|
+
tls,
|
|
85
|
+
dns,
|
|
86
|
+
}));
|
|
87
|
+
// Redis cache
|
|
88
|
+
if (cache) {
|
|
89
|
+
const sharedOperators = (0, core_1.useContext)(defaults_1.OperatorContext);
|
|
90
|
+
const hasRedis = sharedOperators.some((op) => op.name === 'redis-operator');
|
|
91
|
+
if (!hasRedis) {
|
|
92
|
+
elements.push((0, core_1.declareOperator)(crds_1.operators['redis-operator']()));
|
|
93
|
+
}
|
|
94
|
+
elements.push((0, redis_1.RedisClusterComponent)({
|
|
95
|
+
metadata: { name: `${name}-cache`, namespace },
|
|
96
|
+
spec: {
|
|
97
|
+
clusterSize: 3,
|
|
98
|
+
kubernetesConfig: { image: 'redis:7.2-alpine' },
|
|
99
|
+
storage: {
|
|
100
|
+
volumeClaimTemplate: {
|
|
101
|
+
spec: {
|
|
102
|
+
accessModes: ['ReadWriteOnce'],
|
|
103
|
+
resources: { requests: { storage: '1Gi' } },
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
}));
|
|
109
|
+
// Auto-wire REDIS_URL env var
|
|
110
|
+
env.REDIS_URL = `redis://${name}-cache.${namespace}.svc.cluster.local:6379`;
|
|
111
|
+
}
|
|
112
|
+
// Children render as sibling resources (e.g. <BackgroundWorker />).
|
|
113
|
+
// WebService does not currently accept children as a prop, so we keep
|
|
114
|
+
// them as a Fragment sibling for the renderer to flatten.
|
|
115
|
+
if (children) {
|
|
116
|
+
elements.push((0, core_1.jsx)(core_1.Fragment, { children }));
|
|
117
|
+
}
|
|
118
|
+
return (0, core_1.jsx)(core_1.Fragment, { children: elements });
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=app.js.map
|
package/dist/app.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":";;AA6FA,kBAuFC;AApLD,oCAAsE;AACtE,+CAA+E;AAC/E,yCAAqC;AACrC,iDAA+D;AAE/D,oCAAqC;AACrC,2CAAuD;AAoCvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,SAAgB,GAAG,CAAC,KAAe;IACjC,MAAM,EACJ,IAAI,EACJ,SAAS,EAAE,aAAa,EACxB,KAAK,EACL,IAAI,GAAG,IAAI,EACX,QAAQ,GAAG,CAAC,EACZ,IAAI,EACJ,GAAG,EACH,GAAG,GAAG,EAAE,EACR,OAAO,GAAG,EAAE,EACZ,KAAK,GAAG,EAAE,EACV,SAAS,EACT,KAAK,GAAG,KAAK,EACb,GAAG,EACH,QAAQ,GACT,GAAG,KAAK,CAAA;IAET,kEAAkE;IAClE,MAAM,gBAAgB,GAAG,IAAA,iBAAU,EAAC,oBAAS,CAAC,CAAA;IAC9C,MAAM,SAAS,GACb,aAAa,IAAI,CAAC,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,SAAS,CAAA;IAE/F,MAAM,QAAQ,GAA6B,EAAE,CAAA;IAE7C,QAAQ,CAAC,IAAI,CACX,IAAA,UAAG,EAAC,wBAAU,EAAE;QACd,IAAI;QACJ,SAAS;QACT,KAAK;QACL,IAAI;QACJ,QAAQ;QACR,GAAG;QACH,OAAO;QACP,KAAK;QACL,SAAS;KACV,CAAC,CACH,CAAA;IAED,QAAQ,CAAC,IAAI,CACX,IAAA,UAAG,EAAC,mBAAQ,EAAE;QACZ,IAAI,EAAE,GAAG,IAAI,WAAW;QACxB,SAAS;QACT,IAAI;QACJ,WAAW,EAAE,IAAI;QACjB,WAAW,EAAE,EAAE;QACf,GAAG;QACH,GAAG;KACJ,CAAC,CACH,CAAA;IAED,cAAc;IACd,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,eAAe,GAAG,IAAA,iBAAU,EAAC,0BAAe,CAAC,CAAA;QACnD,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAA;QAC3E,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,QAAQ,CAAC,IAAI,CAAC,IAAA,sBAAe,EAAC,gBAAS,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAA;QAC/D,CAAC;QACD,QAAQ,CAAC,IAAI,CACX,IAAA,6BAAqB,EAAC;YACpB,QAAQ,EAAE,EAAE,IAAI,EAAE,GAAG,IAAI,QAAQ,EAAE,SAAS,EAAE;YAC9C,IAAI,EAAE;gBACJ,WAAW,EAAE,CAAC;gBACd,gBAAgB,EAAE,EAAE,KAAK,EAAE,kBAAkB,EAAE;gBAC/C,OAAO,EAAE;oBACP,mBAAmB,EAAE;wBACnB,IAAI,EAAE;4BACJ,WAAW,EAAE,CAAC,eAAe,CAAC;4BAC9B,SAAS,EAAE,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;yBAC5C;qBACF;iBACF;aACF;SACF,CAAC,CACH,CAAA;QACD,8BAA8B;QAC9B,GAAG,CAAC,SAAS,GAAG,WAAW,IAAI,UAAU,SAAS,yBAAyB,CAAA;IAC7E,CAAC;IAED,oEAAoE;IACpE,sEAAsE;IACtE,0DAA0D;IAC1D,IAAI,QAAQ,EAAE,CAAC;QACb,QAAQ,CAAC,IAAI,CAAC,IAAA,UAAG,EAAC,eAAQ,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAA;IAC5C,CAAC;IAED,OAAO,IAAA,UAAG,EAAC,eAAQ,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAA;AAC9C,CAAC"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Realm configuration for Keycloak.
|
|
3
|
+
*
|
|
4
|
+
* A realm manages a set of users, credentials, roles, and groups.
|
|
5
|
+
* Realms are isolated from one another and can only manage users
|
|
6
|
+
* that belong to them.
|
|
7
|
+
*/
|
|
8
|
+
export interface RealmConfig {
|
|
9
|
+
/** Realm name (e.g., 'company', 'customer') */
|
|
10
|
+
id: string;
|
|
11
|
+
/** Display name shown in login screens */
|
|
12
|
+
displayName?: string;
|
|
13
|
+
/** Whether the realm is enabled */
|
|
14
|
+
enabled?: boolean;
|
|
15
|
+
/** Identity providers for federation (e.g., EntraID, Google) */
|
|
16
|
+
identityProviders?: IdentityProviderConfig[];
|
|
17
|
+
/** Clients in this realm */
|
|
18
|
+
clients?: ClientConfig[];
|
|
19
|
+
}
|
|
20
|
+
export interface IdentityProviderConfig {
|
|
21
|
+
/** Provider alias (e.g., 'entra-id', 'google') */
|
|
22
|
+
alias: string;
|
|
23
|
+
/** Display name */
|
|
24
|
+
displayName: string;
|
|
25
|
+
/** Provider type (e.g., 'oidc', 'saml') */
|
|
26
|
+
providerId: string;
|
|
27
|
+
/** Whether the provider is enabled */
|
|
28
|
+
enabled?: boolean;
|
|
29
|
+
/** Trust email from this provider */
|
|
30
|
+
trustEmail?: boolean;
|
|
31
|
+
/** Provider-specific configuration */
|
|
32
|
+
config: Record<string, string>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* EntraID (Azure AD) identity provider configuration.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* import { Realm, EntraID } from '@r8s/recipes/auth'
|
|
39
|
+
*
|
|
40
|
+
* <Realm id="company">
|
|
41
|
+
* <EntraID
|
|
42
|
+
* tenantId="your-tenant-id"
|
|
43
|
+
* clientId="your-client-id"
|
|
44
|
+
* clientSecret="${env:ENTRA_CLIENT_SECRET}"
|
|
45
|
+
* />
|
|
46
|
+
* </Realm>
|
|
47
|
+
*/
|
|
48
|
+
export interface EntraIDConfig {
|
|
49
|
+
/** Azure AD tenant ID */
|
|
50
|
+
tenantId: string;
|
|
51
|
+
/** Application (client) ID */
|
|
52
|
+
clientId: string;
|
|
53
|
+
/** Client secret (from secrets backend) */
|
|
54
|
+
clientSecret: string;
|
|
55
|
+
/** Display name (defaults to 'Entra ID') */
|
|
56
|
+
displayName?: string;
|
|
57
|
+
/** Whether the provider is enabled (defaults to true) */
|
|
58
|
+
enabled?: boolean;
|
|
59
|
+
/** Trust email from this provider (defaults to true) */
|
|
60
|
+
trustEmail?: boolean;
|
|
61
|
+
}
|
|
62
|
+
export interface EntraIDProps extends EntraIDConfig {
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* EntraID — Microsoft Entra ID (Azure AD) identity provider.
|
|
66
|
+
*
|
|
67
|
+
* Adds EntraID as an identity provider to the parent Realm.
|
|
68
|
+
*/
|
|
69
|
+
export declare function EntraID(props: EntraIDProps): import("@r8s/core").r8sElement;
|
|
70
|
+
export interface GoogleConfig {
|
|
71
|
+
/** Google OAuth client ID */
|
|
72
|
+
clientId: string;
|
|
73
|
+
/** Google OAuth client secret */
|
|
74
|
+
clientSecret: string;
|
|
75
|
+
/** Display name (defaults to 'Google') */
|
|
76
|
+
displayName?: string;
|
|
77
|
+
/** Whether the provider is enabled (defaults to true) */
|
|
78
|
+
enabled?: boolean;
|
|
79
|
+
/** Trust email from this provider (defaults to true) */
|
|
80
|
+
trustEmail?: boolean;
|
|
81
|
+
}
|
|
82
|
+
export interface GoogleProps extends GoogleConfig {
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Google — Google OAuth identity provider.
|
|
86
|
+
*
|
|
87
|
+
* Adds Google as an identity provider to the parent Realm.
|
|
88
|
+
*/
|
|
89
|
+
export declare function Google(props: GoogleProps): import("@r8s/core").r8sElement;
|
|
90
|
+
export declare const RealmContext: import("../../../core/src/context").Context<RealmConfig[]>;
|
|
91
|
+
export interface RealmProps extends RealmConfig {
|
|
92
|
+
/** Child components (Clients) */
|
|
93
|
+
children?: unknown;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Realm — a security domain in Keycloak.
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* import { Realm, Clients, Client } from '@r8s/recipes'
|
|
100
|
+
*
|
|
101
|
+
* <Realm id="company" displayName="Company">
|
|
102
|
+
* <Clients>
|
|
103
|
+
* <Client id="api" type="bearer-only" />
|
|
104
|
+
* <Client id="web" type="public" redirectUris={['https://app.example.com/*']} />
|
|
105
|
+
* </Clients>
|
|
106
|
+
* </Realm>
|
|
107
|
+
*/
|
|
108
|
+
export declare function Realm(props: RealmProps): import("@r8s/core").r8sElement;
|
|
109
|
+
export interface ClientsProps {
|
|
110
|
+
/** Child components (Client) */
|
|
111
|
+
children?: unknown;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Clients — container for Client components.
|
|
115
|
+
*/
|
|
116
|
+
export declare function Clients(props: ClientsProps): import("@r8s/core").r8sElement;
|
|
117
|
+
/**
|
|
118
|
+
* Client configuration for Keycloak.
|
|
119
|
+
*
|
|
120
|
+
* Clients are applications and services that can request authentication
|
|
121
|
+
* of a user. Types:
|
|
122
|
+
* - 'public': SPA, mobile app (no secret, PKCE recommended)
|
|
123
|
+
* - 'confidential': Backend service (requires secret)
|
|
124
|
+
* - 'bearer-only': API service (only validates tokens)
|
|
125
|
+
*/
|
|
126
|
+
export interface ClientConfig {
|
|
127
|
+
/** Client ID */
|
|
128
|
+
id: string;
|
|
129
|
+
/** Client name */
|
|
130
|
+
name?: string;
|
|
131
|
+
/** Client type */
|
|
132
|
+
type: 'public' | 'confidential' | 'bearer-only';
|
|
133
|
+
/** Redirect URIs for the client */
|
|
134
|
+
redirectUris?: string[];
|
|
135
|
+
/** Web origins for CORS */
|
|
136
|
+
webOrigins?: string[];
|
|
137
|
+
/** Service account enabled (for confidential clients) */
|
|
138
|
+
serviceAccountsEnabled?: boolean;
|
|
139
|
+
/** Direct access grants enabled */
|
|
140
|
+
directAccessGrantsEnabled?: boolean;
|
|
141
|
+
/** Client secret (from secrets backend) */
|
|
142
|
+
secret?: string;
|
|
143
|
+
}
|
|
144
|
+
export interface ClientProps extends ClientConfig {
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Client — an application that authenticates via Keycloak.
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* <Client id="api" type="bearer-only" />
|
|
151
|
+
* <Client id="web" type="public" redirectUris={['https://app.example.com/*']} />
|
|
152
|
+
* <Client id="backend" type="confidential" secret="${env:BACKEND_SECRET}" />
|
|
153
|
+
*/
|
|
154
|
+
export declare function Client(props: ClientProps): import("@r8s/core").r8sElement;
|
|
155
|
+
export interface RealmsProps {
|
|
156
|
+
/** Child components (Realm) */
|
|
157
|
+
children?: unknown;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Realms — container for Realm components.
|
|
161
|
+
*/
|
|
162
|
+
export declare function Realms(props: RealmsProps): import("@r8s/core").r8sElement;
|
|
163
|
+
//# sourceMappingURL=components.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/auth/components.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RealmContext = void 0;
|
|
4
|
+
exports.EntraID = EntraID;
|
|
5
|
+
exports.Google = Google;
|
|
6
|
+
exports.Realm = Realm;
|
|
7
|
+
exports.Clients = Clients;
|
|
8
|
+
exports.Client = Client;
|
|
9
|
+
exports.Realms = Realms;
|
|
10
|
+
const core_1 = require("@r8s/core");
|
|
11
|
+
const defaults_1 = require("@r8s/core/defaults");
|
|
12
|
+
/**
|
|
13
|
+
* EntraID — Microsoft Entra ID (Azure AD) identity provider.
|
|
14
|
+
*
|
|
15
|
+
* Adds EntraID as an identity provider to the parent Realm.
|
|
16
|
+
*/
|
|
17
|
+
function EntraID(props) {
|
|
18
|
+
return (0, core_1.jsx)(core_1.Fragment, {});
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Google — Google OAuth identity provider.
|
|
22
|
+
*
|
|
23
|
+
* Adds Google as an identity provider to the parent Realm.
|
|
24
|
+
*/
|
|
25
|
+
function Google(props) {
|
|
26
|
+
return (0, core_1.jsx)(core_1.Fragment, {});
|
|
27
|
+
}
|
|
28
|
+
exports.RealmContext = (0, defaults_1.createContext)([]);
|
|
29
|
+
/**
|
|
30
|
+
* Realm — a security domain in Keycloak.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* import { Realm, Clients, Client } from '@r8s/recipes'
|
|
34
|
+
*
|
|
35
|
+
* <Realm id="company" displayName="Company">
|
|
36
|
+
* <Clients>
|
|
37
|
+
* <Client id="api" type="bearer-only" />
|
|
38
|
+
* <Client id="web" type="public" redirectUris={['https://app.example.com/*']} />
|
|
39
|
+
* </Clients>
|
|
40
|
+
* </Realm>
|
|
41
|
+
*/
|
|
42
|
+
function Realm(props) {
|
|
43
|
+
const { id, displayName, enabled = true, identityProviders: propIdentityProviders = [], clients: propClients = [], children, } = props;
|
|
44
|
+
// Collect clients and identity providers from children
|
|
45
|
+
const clients = [...propClients];
|
|
46
|
+
const identityProviders = [...propIdentityProviders];
|
|
47
|
+
const childArray = Array.isArray(children) ? children : [children];
|
|
48
|
+
for (const child of childArray) {
|
|
49
|
+
if (child && typeof child === 'object' && 'type' in child) {
|
|
50
|
+
// Collect Clients
|
|
51
|
+
if (child.type === Clients) {
|
|
52
|
+
const clientsProps = child.props;
|
|
53
|
+
const clientChildren = Array.isArray(clientsProps.children)
|
|
54
|
+
? clientsProps.children
|
|
55
|
+
: [clientsProps.children];
|
|
56
|
+
for (const clientChild of clientChildren) {
|
|
57
|
+
if (clientChild &&
|
|
58
|
+
typeof clientChild === 'object' &&
|
|
59
|
+
'type' in clientChild &&
|
|
60
|
+
clientChild.type === Client) {
|
|
61
|
+
clients.push(clientChild.props);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Collect EntraID
|
|
66
|
+
if (child.type === EntraID) {
|
|
67
|
+
const entraProps = child.props;
|
|
68
|
+
identityProviders.push({
|
|
69
|
+
alias: 'entra-id',
|
|
70
|
+
displayName: entraProps.displayName ?? 'Entra ID',
|
|
71
|
+
providerId: 'oidc',
|
|
72
|
+
enabled: entraProps.enabled ?? true,
|
|
73
|
+
trustEmail: entraProps.trustEmail ?? true,
|
|
74
|
+
config: {
|
|
75
|
+
clientId: entraProps.clientId,
|
|
76
|
+
clientSecret: entraProps.clientSecret,
|
|
77
|
+
tokenUrl: `https://login.microsoftonline.com/${entraProps.tenantId}/oauth2/v2.0/token`,
|
|
78
|
+
authorizationUrl: `https://login.microsoftonline.com/${entraProps.tenantId}/oauth2/v2.0/authorize`,
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
// Collect Google
|
|
83
|
+
if (child.type === Google) {
|
|
84
|
+
const googleProps = child.props;
|
|
85
|
+
identityProviders.push({
|
|
86
|
+
alias: 'google',
|
|
87
|
+
displayName: googleProps.displayName ?? 'Google',
|
|
88
|
+
providerId: 'oidc',
|
|
89
|
+
enabled: googleProps.enabled ?? true,
|
|
90
|
+
trustEmail: googleProps.trustEmail ?? true,
|
|
91
|
+
config: {
|
|
92
|
+
clientId: googleProps.clientId,
|
|
93
|
+
clientSecret: googleProps.clientSecret,
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const realm = {
|
|
100
|
+
id,
|
|
101
|
+
displayName,
|
|
102
|
+
enabled,
|
|
103
|
+
identityProviders,
|
|
104
|
+
};
|
|
105
|
+
// Store realm with clients in context for Auth to collect
|
|
106
|
+
const existingRealms = (0, core_1.useContext)(exports.RealmContext);
|
|
107
|
+
const allRealms = [...existingRealms, { ...realm, clients }];
|
|
108
|
+
// Render children so nested components (Clients, EntraID, Google) are processed
|
|
109
|
+
return (0, core_1.jsx)(exports.RealmContext.Provider, { value: allRealms, children });
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Clients — container for Client components.
|
|
113
|
+
*/
|
|
114
|
+
function Clients(props) {
|
|
115
|
+
return (0, core_1.jsx)(core_1.Fragment, { children: props.children });
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Client — an application that authenticates via Keycloak.
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* <Client id="api" type="bearer-only" />
|
|
122
|
+
* <Client id="web" type="public" redirectUris={['https://app.example.com/*']} />
|
|
123
|
+
* <Client id="backend" type="confidential" secret="${env:BACKEND_SECRET}" />
|
|
124
|
+
*/
|
|
125
|
+
function Client(props) {
|
|
126
|
+
return (0, core_1.jsx)(core_1.Fragment, {});
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Realms — container for Realm components.
|
|
130
|
+
*/
|
|
131
|
+
function Realms(props) {
|
|
132
|
+
return (0, core_1.jsx)(core_1.Fragment, { children: props.children });
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=components.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"components.js","sourceRoot":"","sources":["../../src/auth/components.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,EACL,MAAM,EACN,OAAO,EACP,MAAM,EACN,OAAO,EACP,MAAM,EACN,YAAY,EACZ,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,sBAAsB,EAC3B,KAAK,aAAa,EAClB,KAAK,YAAY,GAClB,MAAM,cAAc,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Auth sub-components — hierarchical Keycloak configuration
|
|
3
|
+
// Import from '@r8s/recipes/auth' to keep the main index clean
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.RealmContext = exports.Google = exports.EntraID = exports.Client = exports.Clients = exports.Realms = exports.Realm = void 0;
|
|
6
|
+
var components_1 = require("./components");
|
|
7
|
+
Object.defineProperty(exports, "Realm", { enumerable: true, get: function () { return components_1.Realm; } });
|
|
8
|
+
Object.defineProperty(exports, "Realms", { enumerable: true, get: function () { return components_1.Realms; } });
|
|
9
|
+
Object.defineProperty(exports, "Clients", { enumerable: true, get: function () { return components_1.Clients; } });
|
|
10
|
+
Object.defineProperty(exports, "Client", { enumerable: true, get: function () { return components_1.Client; } });
|
|
11
|
+
Object.defineProperty(exports, "EntraID", { enumerable: true, get: function () { return components_1.EntraID; } });
|
|
12
|
+
Object.defineProperty(exports, "Google", { enumerable: true, get: function () { return components_1.Google; } });
|
|
13
|
+
Object.defineProperty(exports, "RealmContext", { enumerable: true, get: function () { return components_1.RealmContext; } });
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,+DAA+D;;;AAE/D,2CAaqB;AAZnB,mGAAA,KAAK,OAAA;AACL,oGAAA,MAAM,OAAA;AACN,qGAAA,OAAO,OAAA;AACP,oGAAA,MAAM,OAAA;AACN,qGAAA,OAAO,OAAA;AACP,oGAAA,MAAM,OAAA;AACN,0GAAA,YAAY,OAAA"}
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { TLSConfig } from '@r8s/k8s-types';
|
|
2
|
+
export interface AuthProps {
|
|
3
|
+
/** Resource name */
|
|
4
|
+
name: string;
|
|
5
|
+
/** Public hostname for the identity provider (e.g., 'auth.example.com') */
|
|
6
|
+
host: string;
|
|
7
|
+
/** Kubernetes namespace (defaults to 'default') */
|
|
8
|
+
namespace?: string;
|
|
9
|
+
/** Number of Keycloak replicas (defaults to 1) */
|
|
10
|
+
instances?: number;
|
|
11
|
+
/** Database storage size (defaults to '10Gi') */
|
|
12
|
+
storage?: string;
|
|
13
|
+
/** TLS certificate configuration */
|
|
14
|
+
tls?: TLSConfig;
|
|
15
|
+
/** Child components (Realms) */
|
|
16
|
+
children?: unknown;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Identity and access management — Keycloak with database, TLS, and routing.
|
|
20
|
+
*
|
|
21
|
+
* @title Auth
|
|
22
|
+
* @category Security & Identity
|
|
23
|
+
*
|
|
24
|
+
* Composes Keycloak (identity provider), CNPG (PostgreSQL database),
|
|
25
|
+
* cert-manager (TLS), and routing (Ingress/Gateway) into a single
|
|
26
|
+
* identity solution with good defaults.
|
|
27
|
+
*
|
|
28
|
+
* The database is auto-wired: Keycloak connects to its own PostgreSQL
|
|
29
|
+
* cluster. Credentials are managed by CNPG's bootstrap secret.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* // Simple Keycloak instance
|
|
33
|
+
* import { Auth } from '@r8s/recipes'
|
|
34
|
+
*
|
|
35
|
+
* export default <Auth name="auth" host="auth.example.com" />
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* // Keycloak with custom storage and TLS
|
|
39
|
+
* import { Auth } from '@r8s/recipes'
|
|
40
|
+
*
|
|
41
|
+
* export default (
|
|
42
|
+
* <Auth
|
|
43
|
+
* name="auth"
|
|
44
|
+
* host="auth.example.com"
|
|
45
|
+
* instances={2}
|
|
46
|
+
* storage="20Gi"
|
|
47
|
+
* tls={{ secretName: 'auth-tls', clusterIssuer: 'letsencrypt-prod' }}
|
|
48
|
+
* />
|
|
49
|
+
* )
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* // Keycloak with realms and clients
|
|
53
|
+
* import { Auth } from '@r8s/recipes'
|
|
54
|
+
* import { Realms, Realm, Clients, Client } from '@r8s/recipes/auth'
|
|
55
|
+
*
|
|
56
|
+
* export default (
|
|
57
|
+
* <Auth name="auth" host="auth.example.com">
|
|
58
|
+
* <Realms>
|
|
59
|
+
* <Realm id="company" displayName="Company">
|
|
60
|
+
* <Clients>
|
|
61
|
+
* <Client id="web" type="public" redirectUris={['https://app.example.com/*']} />
|
|
62
|
+
* <Client id="api" type="bearer-only" />
|
|
63
|
+
* </Clients>
|
|
64
|
+
* </Realm>
|
|
65
|
+
* </Realms>
|
|
66
|
+
* </Auth>
|
|
67
|
+
* )
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* // Keycloak with EntraID federation
|
|
71
|
+
* import { Auth } from '@r8s/recipes'
|
|
72
|
+
* import { Realms, Realm, Clients, Client, EntraID } from '@r8s/recipes/auth'
|
|
73
|
+
*
|
|
74
|
+
* export default (
|
|
75
|
+
* <Auth name="auth" host="auth.example.com">
|
|
76
|
+
* <Realms>
|
|
77
|
+
* <Realm id="company" displayName="Company">
|
|
78
|
+
* <EntraID
|
|
79
|
+
* tenantId="your-tenant-id"
|
|
80
|
+
* clientId="your-client-id"
|
|
81
|
+
* clientSecret="${env:ENTRA_CLIENT_SECRET}"
|
|
82
|
+
* />
|
|
83
|
+
* <Clients>
|
|
84
|
+
* <Client id="web" type="public" redirectUris={['https://app.example.com/*']} />
|
|
85
|
+
* </Clients>
|
|
86
|
+
* </Realm>
|
|
87
|
+
* </Realms>
|
|
88
|
+
* </Auth>
|
|
89
|
+
* )
|
|
90
|
+
*/
|
|
91
|
+
export declare function Auth(props: AuthProps): import("@r8s/core").r8sElement;
|
|
92
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAa/C,MAAM,WAAW,SAAS;IACxB,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAA;IACZ,mDAAmD;IACnD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,oCAAoC;IACpC,GAAG,CAAC,EAAE,SAAS,CAAA;IACf,gCAAgC;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwEG;AACH,wBAAgB,IAAI,CAAC,KAAK,EAAE,SAAS,kCAmHpC"}
|