@gezelligate/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/LICENSE +21 -0
- package/README.md +29 -0
- package/dist/bridgeManifest.d.ts +67 -0
- package/dist/bridgeManifest.d.ts.map +1 -0
- package/dist/bridgeManifest.js +35 -0
- package/dist/bridgeManifest.js.map +1 -0
- package/dist/capabilities.d.ts +23 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +15 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/catalog/bootstrap.d.ts +25 -0
- package/dist/catalog/bootstrap.d.ts.map +1 -0
- package/dist/catalog/bootstrap.js +56 -0
- package/dist/catalog/bootstrap.js.map +1 -0
- package/dist/catalog/index.d.ts +4 -0
- package/dist/catalog/index.d.ts.map +1 -0
- package/dist/catalog/index.js +4 -0
- package/dist/catalog/index.js.map +1 -0
- package/dist/catalog/projectPin.d.ts +22 -0
- package/dist/catalog/projectPin.d.ts.map +1 -0
- package/dist/catalog/projectPin.js +39 -0
- package/dist/catalog/projectPin.js.map +1 -0
- package/dist/catalog/reader.d.ts +44 -0
- package/dist/catalog/reader.d.ts.map +1 -0
- package/dist/catalog/reader.js +7 -0
- package/dist/catalog/reader.js.map +1 -0
- package/dist/catalog/tarball.d.ts +48 -0
- package/dist/catalog/tarball.d.ts.map +1 -0
- package/dist/catalog/tarball.js +114 -0
- package/dist/catalog/tarball.js.map +1 -0
- package/dist/cluster.d.ts +4 -0
- package/dist/cluster.d.ts.map +1 -0
- package/dist/cluster.js +46 -0
- package/dist/cluster.js.map +1 -0
- package/dist/dedicatedPeer.d.ts +43 -0
- package/dist/dedicatedPeer.d.ts.map +1 -0
- package/dist/dedicatedPeer.js +38 -0
- package/dist/dedicatedPeer.js.map +1 -0
- package/dist/dependencies.d.ts +6 -0
- package/dist/dependencies.d.ts.map +1 -0
- package/dist/dependencies.js +124 -0
- package/dist/dependencies.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/ingress.d.ts +4 -0
- package/dist/ingress.d.ts.map +1 -0
- package/dist/ingress.js +17 -0
- package/dist/ingress.js.map +1 -0
- package/dist/keycloak.d.ts +61 -0
- package/dist/keycloak.d.ts.map +1 -0
- package/dist/keycloak.js +161 -0
- package/dist/keycloak.js.map +1 -0
- package/dist/numericId.d.ts +2 -0
- package/dist/numericId.d.ts.map +1 -0
- package/dist/numericId.js +22 -0
- package/dist/numericId.js.map +1 -0
- package/dist/providers/lifecycle.d.ts +81 -0
- package/dist/providers/lifecycle.d.ts.map +1 -0
- package/dist/providers/lifecycle.js +22 -0
- package/dist/providers/lifecycle.js.map +1 -0
- package/dist/providers.d.ts +4 -0
- package/dist/providers.d.ts.map +1 -0
- package/dist/providers.js +45 -0
- package/dist/providers.js.map +1 -0
- package/dist/render.d.ts +22 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +354 -0
- package/dist/render.js.map +1 -0
- package/dist/repository.d.ts +4 -0
- package/dist/repository.d.ts.map +1 -0
- package/dist/repository.js +31 -0
- package/dist/repository.js.map +1 -0
- package/dist/schema/clusterYaml.d.ts +39 -0
- package/dist/schema/clusterYaml.d.ts.map +1 -0
- package/dist/schema/clusterYaml.js +24 -0
- package/dist/schema/clusterYaml.js.map +1 -0
- package/dist/schema/configYaml.d.ts +90 -0
- package/dist/schema/configYaml.d.ts.map +1 -0
- package/dist/schema/configYaml.js +32 -0
- package/dist/schema/configYaml.js.map +1 -0
- package/dist/schema/providerYaml.d.ts +312 -0
- package/dist/schema/providerYaml.d.ts.map +1 -0
- package/dist/schema/providerYaml.js +54 -0
- package/dist/schema/providerYaml.js.map +1 -0
- package/dist/schema/serviceYaml.d.ts +2407 -0
- package/dist/schema/serviceYaml.d.ts.map +1 -0
- package/dist/schema/serviceYaml.js +200 -0
- package/dist/schema/serviceYaml.js.map +1 -0
- package/dist/secrets.d.ts +4 -0
- package/dist/secrets.d.ts.map +1 -0
- package/dist/secrets.js +31 -0
- package/dist/secrets.js.map +1 -0
- package/dist/secretsSummary.d.ts +2 -0
- package/dist/secretsSummary.d.ts.map +1 -0
- package/dist/secretsSummary.js +50 -0
- package/dist/secretsSummary.js.map +1 -0
- package/dist/services.d.ts +7 -0
- package/dist/services.d.ts.map +1 -0
- package/dist/services.js +66 -0
- package/dist/services.js.map +1 -0
- package/dist/sharedDb.d.ts +3 -0
- package/dist/sharedDb.d.ts.map +1 -0
- package/dist/sharedDb.js +104 -0
- package/dist/sharedDb.js.map +1 -0
- package/dist/target.d.ts +35 -0
- package/dist/target.d.ts.map +1 -0
- package/dist/target.js +7 -0
- package/dist/target.js.map +1 -0
- package/dist/templates/dedicated-postgres.docker.yaml.tmpl +12 -0
- package/dist/templates/dedicated-postgres.k8s.yaml.tmpl +57 -0
- package/dist/templates/dedicated-redis.docker.yaml.tmpl +9 -0
- package/dist/templates/dedicated-redis.k8s.yaml.tmpl +46 -0
- package/dist/templating.d.ts +2 -0
- package/dist/templating.d.ts.map +1 -0
- package/dist/templating.js +15 -0
- package/dist/templating.js.map +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serviceYaml.d.ts","sourceRoot":"","sources":["../../src/schema/serviceYaml.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAQ1B,CAAC;AAEH,QAAA,MAAM,gBAAgB;;;;;;;;;;;;;;;EAKpB,CAAC;AAEH,QAAA,MAAM,YAAY;;;;;;;;;;;;EAIhB,CAAC;AAQH,QAAA,MAAM,cAAc;;;;;;;;;;;;;;;;;;EAMT,CAAC;AAMZ,QAAA,MAAM,WAAW;;;;;;EAEN,CAAC;AAuHZ,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAMhB,CAAC;AAEH,QAAA,MAAM,cAAc;;;;;;EAElB,CAAC;AAYH,QAAA,MAAM,kBAAkB;;;;;;;;;EAGtB,CAAC;AAEH,QAAA,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EASlB,CAAC;AAoBH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgB5B,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC5D,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AACxD,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC1D,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAClD,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AACtD,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AACtD,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAChD,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAClD,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC9D,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const FormFieldSchema = z.object({
|
|
3
|
+
key: z.string().min(1),
|
|
4
|
+
label: z.string().min(1),
|
|
5
|
+
type: z.enum(["string", "email", "boolean", "number", "select"]),
|
|
6
|
+
default: z.union([z.string(), z.number(), z.boolean()]).optional(),
|
|
7
|
+
required: z.boolean().optional(),
|
|
8
|
+
help: z.string().optional(),
|
|
9
|
+
options: z.array(z.object({ value: z.string(), label: z.string() })).optional()
|
|
10
|
+
});
|
|
11
|
+
const DependencySchema = z.object({
|
|
12
|
+
service: z.string().min(1),
|
|
13
|
+
reason: z.string().min(1),
|
|
14
|
+
required: z.boolean(),
|
|
15
|
+
when: z.string().optional()
|
|
16
|
+
});
|
|
17
|
+
const SecretSchema = z.object({
|
|
18
|
+
key: z.string().regex(/^[A-Z][A-Z0-9_]*$/, "must be UPPER_SNAKE_CASE"),
|
|
19
|
+
generator: z.enum(["password", "hex", "uuid"]),
|
|
20
|
+
length: z.number().int().positive().optional()
|
|
21
|
+
});
|
|
22
|
+
// Services declare a database NEED with `preferShared` (default true). The
|
|
23
|
+
// renderer decides where that need is satisfied by matching against a service
|
|
24
|
+
// that provides `sharedDatabase` (when preferShared is true and such a
|
|
25
|
+
// provider is in the dependency closure). When no provider exists, or when
|
|
26
|
+
// preferShared is false, the renderer falls back to a per-service sidecar
|
|
27
|
+
// using the optional `storage` field.
|
|
28
|
+
const DatabaseSchema = z.object({
|
|
29
|
+
engine: z.literal("postgres"),
|
|
30
|
+
preferShared: z.boolean().default(true),
|
|
31
|
+
name: z.string().min(1),
|
|
32
|
+
user: z.string().min(1),
|
|
33
|
+
storage: z.string().optional()
|
|
34
|
+
}).strict();
|
|
35
|
+
// Services declare a redis NEED with `preferShared` (default true). The
|
|
36
|
+
// renderer routes the service's Redis traffic to whichever service provides
|
|
37
|
+
// `sharedRedis` in the dependency closure. Consumers must namespace their
|
|
38
|
+
// keys; every consumer uses logical DB 0.
|
|
39
|
+
const RedisSchema = z.object({
|
|
40
|
+
preferShared: z.boolean().default(true)
|
|
41
|
+
}).strict();
|
|
42
|
+
const OidcClientSchema = z.object({
|
|
43
|
+
clientId: z.string().min(1),
|
|
44
|
+
redirectUris: z.array(z.string().min(1)),
|
|
45
|
+
scopes: z.array(z.string().min(1)),
|
|
46
|
+
// Shape of the `/userinfo` response we ask Keycloak to emit for this
|
|
47
|
+
// client. "oidc" is the standard set of OIDC claims (sub, preferred_username,
|
|
48
|
+
// email, ...). "gitlab" mimics GitLab's `/api/v4/user` shape (numeric `id`,
|
|
49
|
+
// `username`, `name`, `email`) — required by Mattermost Team Edition's
|
|
50
|
+
// `gitlab` OAuth provider, which is the only provider compiled into the
|
|
51
|
+
// open-source Mattermost binary.
|
|
52
|
+
userinfoFormat: z.enum(["oidc", "gitlab"]).optional(),
|
|
53
|
+
// When true, the realm-import enables Keycloak's standard token-exchange
|
|
54
|
+
// grant on this client. Any service whose backend exchanges its session
|
|
55
|
+
// token for vendor-audience tokens (e.g. the bridge) opts in here.
|
|
56
|
+
tokenExchange: z.boolean().optional()
|
|
57
|
+
});
|
|
58
|
+
const IngressSchema = z.object({
|
|
59
|
+
host: z.string().min(1),
|
|
60
|
+
port: z.number().int().positive(),
|
|
61
|
+
// Optional override for the Kubernetes backend Service. Defaults: service
|
|
62
|
+
// name equals the gezelligate service name; port equals `ingress.port`.
|
|
63
|
+
// Helm charts that name their Service something other than the release
|
|
64
|
+
// (e.g. keycloakx creates `<release>-keycloakx-http`) must set this.
|
|
65
|
+
k8s: z
|
|
66
|
+
.object({
|
|
67
|
+
service: z.string().min(1).optional(),
|
|
68
|
+
port: z.number().int().positive().optional(),
|
|
69
|
+
// Optional path-based overrides. Each entry routes requests
|
|
70
|
+
// whose path starts with `prefix` to a different Service+port,
|
|
71
|
+
// higher priority than the default catch-all route. Used by
|
|
72
|
+
// multi-component services (e.g. meet — SPA at /, Django API
|
|
73
|
+
// at /api/*) so a single Host() can fan out across backends.
|
|
74
|
+
pathOverrides: z
|
|
75
|
+
.array(z.object({
|
|
76
|
+
prefix: z.string().min(1),
|
|
77
|
+
service: z.string().min(1),
|
|
78
|
+
port: z.number().int().positive()
|
|
79
|
+
}))
|
|
80
|
+
.optional()
|
|
81
|
+
})
|
|
82
|
+
.optional()
|
|
83
|
+
});
|
|
84
|
+
const BridgeTileSchema = z.object({
|
|
85
|
+
name: z.string().min(1),
|
|
86
|
+
icon: z.string().min(1),
|
|
87
|
+
url: z.string().min(1)
|
|
88
|
+
});
|
|
89
|
+
const BridgeActivitySchema = z.object({
|
|
90
|
+
api: z.object({
|
|
91
|
+
unreadEndpoint: z.string().min(1),
|
|
92
|
+
auth: z.enum(["oidc-passthrough", "service-token"])
|
|
93
|
+
})
|
|
94
|
+
});
|
|
95
|
+
const BridgeRecentItemsSchema = z.object({
|
|
96
|
+
api: z.object({
|
|
97
|
+
endpoint: z.string().min(1),
|
|
98
|
+
limit: z.number().int().positive(),
|
|
99
|
+
mapping: z.object({
|
|
100
|
+
id: z.string().min(1),
|
|
101
|
+
title: z.string().min(1),
|
|
102
|
+
url: z.string().min(1),
|
|
103
|
+
timestamp: z.string().min(1)
|
|
104
|
+
})
|
|
105
|
+
})
|
|
106
|
+
});
|
|
107
|
+
const BridgeDbReadSchema = z.object({
|
|
108
|
+
tables: z.array(z.string().min(1)).min(1)
|
|
109
|
+
});
|
|
110
|
+
const BridgeSearchApiSchema = z.object({
|
|
111
|
+
method: z.enum(["GET", "POST"]),
|
|
112
|
+
endpoint: z.string().min(1),
|
|
113
|
+
body: z.string().optional(),
|
|
114
|
+
auth: z.enum(["oidc-passthrough", "service-token"]),
|
|
115
|
+
mapping: z.object({
|
|
116
|
+
id: z.string().min(1),
|
|
117
|
+
title: z.string().min(1),
|
|
118
|
+
url: z.string().min(1),
|
|
119
|
+
timestamp: z.string().min(1),
|
|
120
|
+
snippet: z.string().min(1).optional()
|
|
121
|
+
})
|
|
122
|
+
});
|
|
123
|
+
const SqlColumnIdent = z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/, "must be a SQL column identifier");
|
|
124
|
+
const BridgeSearchIndexSchema = z.object({
|
|
125
|
+
table: z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)?$/, "table must be a SQL identifier (schema.name or name)"),
|
|
126
|
+
where: z.string().optional(),
|
|
127
|
+
watermark: SqlColumnIdent,
|
|
128
|
+
fields: z.object({
|
|
129
|
+
id: SqlColumnIdent,
|
|
130
|
+
title: SqlColumnIdent,
|
|
131
|
+
body: SqlColumnIdent,
|
|
132
|
+
url: SqlColumnIdent,
|
|
133
|
+
timestamp: SqlColumnIdent
|
|
134
|
+
})
|
|
135
|
+
});
|
|
136
|
+
const BridgeSearchSchema = z.object({
|
|
137
|
+
api: BridgeSearchApiSchema.optional(),
|
|
138
|
+
index: BridgeSearchIndexSchema.optional()
|
|
139
|
+
}).refine((s) => s.api !== undefined || s.index !== undefined, { message: "bridge.search must declare at least one of api or index" });
|
|
140
|
+
const BridgeSchema = z.object({
|
|
141
|
+
tile: BridgeTileSchema,
|
|
142
|
+
activity: BridgeActivitySchema.optional(),
|
|
143
|
+
recentItems: BridgeRecentItemsSchema.optional(),
|
|
144
|
+
dbRead: BridgeDbReadSchema.optional(),
|
|
145
|
+
search: BridgeSearchSchema.optional()
|
|
146
|
+
});
|
|
147
|
+
const UserSeedSchema = z.object({
|
|
148
|
+
passwordEnv: z.string().regex(/^[A-Z][A-Z0-9_]*$/, "must be UPPER_SNAKE_CASE")
|
|
149
|
+
});
|
|
150
|
+
const OidcServerSchema = z.object({
|
|
151
|
+
realmEnv: z.string().regex(/^[A-Z][A-Z0-9_]*$/).optional()
|
|
152
|
+
});
|
|
153
|
+
const SharedDatabaseSchema = z.object({
|
|
154
|
+
engine: z.literal("postgres")
|
|
155
|
+
});
|
|
156
|
+
const SharedRedisSchema = z.object({}).default({});
|
|
157
|
+
const BridgeReaderSchema = z.object({
|
|
158
|
+
roleName: z.string().min(1),
|
|
159
|
+
passwordEnv: z.string().regex(/^[A-Z][A-Z0-9_]*$/, "must be UPPER_SNAKE_CASE")
|
|
160
|
+
});
|
|
161
|
+
const ProvidesSchema = z.object({
|
|
162
|
+
oidcClient: OidcClientSchema.optional(),
|
|
163
|
+
oidcServer: OidcServerSchema.optional(),
|
|
164
|
+
userSeed: UserSeedSchema.optional(),
|
|
165
|
+
ingress: IngressSchema.optional(),
|
|
166
|
+
bridge: BridgeSchema.optional(),
|
|
167
|
+
bridgeReader: BridgeReaderSchema.optional(),
|
|
168
|
+
sharedDatabase: SharedDatabaseSchema.optional(),
|
|
169
|
+
sharedRedis: SharedRedisSchema.optional()
|
|
170
|
+
});
|
|
171
|
+
const DockerTargetSchema = z.object({
|
|
172
|
+
template: z.string().min(1)
|
|
173
|
+
});
|
|
174
|
+
const KubernetesTargetSchema = z.object({
|
|
175
|
+
helmChart: z.string().min(1),
|
|
176
|
+
helmVersion: z.string().min(1),
|
|
177
|
+
valuesTemplate: z.string().min(1)
|
|
178
|
+
});
|
|
179
|
+
const TargetsSchema = z.object({
|
|
180
|
+
docker: DockerTargetSchema.optional(),
|
|
181
|
+
kubernetes: KubernetesTargetSchema.optional()
|
|
182
|
+
}).refine((t) => t.docker !== undefined || t.kubernetes !== undefined, { message: "at least one target (docker or kubernetes) must be defined" });
|
|
183
|
+
export const ServiceYamlSchema = z.object({
|
|
184
|
+
name: z.string().regex(/^[a-z][a-z0-9-]*$/, "must be kebab-case"),
|
|
185
|
+
displayName: z.string().min(1),
|
|
186
|
+
description: z.string(),
|
|
187
|
+
category: z.string().min(1),
|
|
188
|
+
required: z.boolean(),
|
|
189
|
+
hidden: z.boolean().optional(),
|
|
190
|
+
kernel: z.boolean().optional(),
|
|
191
|
+
icon: z.string().optional(),
|
|
192
|
+
form: z.array(FormFieldSchema),
|
|
193
|
+
dependencies: z.array(DependencySchema),
|
|
194
|
+
secrets: z.array(SecretSchema),
|
|
195
|
+
database: DatabaseSchema.optional(),
|
|
196
|
+
redis: RedisSchema.optional(),
|
|
197
|
+
provides: ProvidesSchema,
|
|
198
|
+
targets: TargetsSchema
|
|
199
|
+
});
|
|
200
|
+
//# sourceMappingURL=serviceYaml.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serviceYaml.js","sourceRoot":"","sources":["../../src/schema/serviceYaml.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Secret } from "./schema/serviceYaml.js";
|
|
2
|
+
export declare function generateSecret(secret: Secret): string;
|
|
3
|
+
export declare function generateMissingSecrets(declared: Secret[], existing: Record<string, string>): Record<string, string>;
|
|
4
|
+
//# sourceMappingURL=secrets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secrets.d.ts","sourceRoot":"","sources":["../src/secrets.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAItD,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAkBrD;AAED,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAAE,EAClB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQxB"}
|
package/dist/secrets.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { randomBytes, randomUUID } from "node:crypto";
|
|
2
|
+
const PASSWORD_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
|
|
3
|
+
export function generateSecret(secret) {
|
|
4
|
+
switch (secret.generator) {
|
|
5
|
+
case "password": {
|
|
6
|
+
const length = secret.length ?? 32;
|
|
7
|
+
const bytes = randomBytes(length);
|
|
8
|
+
let out = "";
|
|
9
|
+
for (let i = 0; i < length; i++) {
|
|
10
|
+
out += PASSWORD_ALPHABET[bytes[i] % PASSWORD_ALPHABET.length];
|
|
11
|
+
}
|
|
12
|
+
return out;
|
|
13
|
+
}
|
|
14
|
+
case "hex": {
|
|
15
|
+
const length = secret.length ?? 32;
|
|
16
|
+
return randomBytes(Math.ceil(length / 2)).toString("hex").slice(0, length);
|
|
17
|
+
}
|
|
18
|
+
case "uuid":
|
|
19
|
+
return randomUUID();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function generateMissingSecrets(declared, existing) {
|
|
23
|
+
const out = { ...existing };
|
|
24
|
+
for (const s of declared) {
|
|
25
|
+
if (!(s.key in out)) {
|
|
26
|
+
out[s.key] = generateSecret(s);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return out;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=secrets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secrets.js","sourceRoot":"","sources":["../src/secrets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGtD,MAAM,iBAAiB,GAAG,kEAAkE,CAAC;AAE7F,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,QAAQ,MAAM,CAAC,SAAS,EAAE,CAAC;QACzB,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;YACnC,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;YAClC,IAAI,GAAG,GAAG,EAAE,CAAC;YACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAChC,GAAG,IAAI,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAE,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;YACjE,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC;QACD,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;YACnC,OAAO,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QAC7E,CAAC;QACD,KAAK,MAAM;YACT,OAAO,UAAU,EAAE,CAAC;IACxB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,QAAkB,EAClB,QAAgC;IAEhC,MAAM,GAAG,GAA2B,EAAE,GAAG,QAAQ,EAAE,CAAC;IACpD,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC;YACpB,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secretsSummary.d.ts","sourceRoot":"","sources":["../src/secretsSummary.ts"],"names":[],"mappings":"AAAA,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EACpD,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,GAClC,MAAM,CAqDR"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export function buildSecretsSummary(envByService, hiddenServices) {
|
|
2
|
+
const lines = [];
|
|
3
|
+
lines.push("# Secrets Summary");
|
|
4
|
+
lines.push("");
|
|
5
|
+
lines.push("> **Save these to a password manager now.** This file is regenerated on every build and is gitignored. The secrets it contains are required to administer your stack.");
|
|
6
|
+
lines.push("");
|
|
7
|
+
const keycloakEnv = envByService["keycloak"] ?? {};
|
|
8
|
+
const userPasswords = Object.entries(keycloakEnv)
|
|
9
|
+
.filter(([k]) => k.startsWith("USER_") && k.endsWith("_TEMP_PASSWORD"))
|
|
10
|
+
.sort();
|
|
11
|
+
if (userPasswords.length > 0) {
|
|
12
|
+
lines.push("## Initial user first-login credentials");
|
|
13
|
+
lines.push("");
|
|
14
|
+
lines.push("> These are **temporary** passwords. Each user will be prompted to set a new password on their first login; after that, Keycloak stores only the hash and these values become meaningless. Share each password with its user via a secure channel.");
|
|
15
|
+
lines.push("");
|
|
16
|
+
for (const [k, v] of userPasswords) {
|
|
17
|
+
// USER_ALICE_TEMP_PASSWORD → alice
|
|
18
|
+
const username = k.slice("USER_".length, -"_TEMP_PASSWORD".length).toLowerCase();
|
|
19
|
+
lines.push(`- **${username}**: \`${v}\``);
|
|
20
|
+
}
|
|
21
|
+
lines.push("");
|
|
22
|
+
}
|
|
23
|
+
const names = Object.keys(envByService).sort();
|
|
24
|
+
const infraNames = names.filter((n) => hiddenServices.has(n));
|
|
25
|
+
const appNames = names.filter((n) => !hiddenServices.has(n));
|
|
26
|
+
if (infraNames.length > 0) {
|
|
27
|
+
lines.push("## Shared infrastructure");
|
|
28
|
+
lines.push("");
|
|
29
|
+
lines.push("> These credentials administer the cluster-wide services (like the shared Postgres superuser). Back them up first.");
|
|
30
|
+
lines.push("");
|
|
31
|
+
for (const n of infraNames) {
|
|
32
|
+
lines.push(`### ${n}`);
|
|
33
|
+
lines.push("");
|
|
34
|
+
for (const [k, v] of Object.entries(envByService[n] ?? {}).sort()) {
|
|
35
|
+
lines.push(`- ${k}: \`${v}\``);
|
|
36
|
+
}
|
|
37
|
+
lines.push("");
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
for (const n of appNames) {
|
|
41
|
+
lines.push(`## ${n}`);
|
|
42
|
+
lines.push("");
|
|
43
|
+
for (const [k, v] of Object.entries(envByService[n] ?? {}).sort()) {
|
|
44
|
+
lines.push(`- ${k}: \`${v}\``);
|
|
45
|
+
}
|
|
46
|
+
lines.push("");
|
|
47
|
+
}
|
|
48
|
+
return lines.join("\n");
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=secretsSummary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secretsSummary.js","sourceRoot":"","sources":["../src/secretsSummary.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type ConfigYaml } from "./schema/configYaml.js";
|
|
2
|
+
export type Services = Map<string, ConfigYaml>;
|
|
3
|
+
export declare function loadServices(rootDir: string): Promise<Services>;
|
|
4
|
+
export declare function writeServiceConfig(rootDir: string, name: string, config: ConfigYaml): Promise<void>;
|
|
5
|
+
export declare function loadEnv(rootDir: string, name: string): Promise<Record<string, string>>;
|
|
6
|
+
export declare function writeEnv(rootDir: string, name: string, env: Record<string, string>): Promise<void>;
|
|
7
|
+
//# sourceMappingURL=services.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../src/services.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAE3E,MAAM,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAE/C,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAqBrE;AAED,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,IAAI,CAAC,CAIf;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAkB5F;AAED,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC1B,OAAO,CAAC,IAAI,CAAC,CAKf"}
|
package/dist/services.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import yaml from "js-yaml";
|
|
4
|
+
import { ConfigYamlSchema } from "./schema/configYaml.js";
|
|
5
|
+
export async function loadServices(rootDir) {
|
|
6
|
+
const out = new Map();
|
|
7
|
+
const entries = await fs.readdir(rootDir, { withFileTypes: true }).catch((err) => {
|
|
8
|
+
if (err.code === "ENOENT")
|
|
9
|
+
return null;
|
|
10
|
+
throw err;
|
|
11
|
+
});
|
|
12
|
+
if (entries === null)
|
|
13
|
+
return out;
|
|
14
|
+
for (const entry of entries) {
|
|
15
|
+
if (!entry.isDirectory())
|
|
16
|
+
continue;
|
|
17
|
+
const cfgPath = path.join(rootDir, entry.name, "config.yaml");
|
|
18
|
+
let raw;
|
|
19
|
+
try {
|
|
20
|
+
raw = await fs.readFile(cfgPath, "utf8");
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
if (err.code === "ENOENT")
|
|
24
|
+
continue;
|
|
25
|
+
throw err;
|
|
26
|
+
}
|
|
27
|
+
const parsed = ConfigYamlSchema.parse(yaml.load(raw));
|
|
28
|
+
out.set(entry.name, parsed);
|
|
29
|
+
}
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
export async function writeServiceConfig(rootDir, name, config) {
|
|
33
|
+
const dir = path.join(rootDir, name);
|
|
34
|
+
await fs.mkdir(dir, { recursive: true });
|
|
35
|
+
await fs.writeFile(path.join(dir, "config.yaml"), yaml.dump(config), "utf8");
|
|
36
|
+
}
|
|
37
|
+
export async function loadEnv(rootDir, name) {
|
|
38
|
+
const envPath = path.join(rootDir, name, ".env");
|
|
39
|
+
let raw;
|
|
40
|
+
try {
|
|
41
|
+
raw = await fs.readFile(envPath, "utf8");
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
if (err.code === "ENOENT")
|
|
45
|
+
return {};
|
|
46
|
+
throw err;
|
|
47
|
+
}
|
|
48
|
+
const out = {};
|
|
49
|
+
for (const line of raw.split("\n")) {
|
|
50
|
+
const trimmed = line.trim();
|
|
51
|
+
if (!trimmed || trimmed.startsWith("#"))
|
|
52
|
+
continue;
|
|
53
|
+
const eq = trimmed.indexOf("=");
|
|
54
|
+
if (eq === -1)
|
|
55
|
+
continue;
|
|
56
|
+
out[trimmed.slice(0, eq)] = trimmed.slice(eq + 1);
|
|
57
|
+
}
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
60
|
+
export async function writeEnv(rootDir, name, env) {
|
|
61
|
+
const dir = path.join(rootDir, name);
|
|
62
|
+
await fs.mkdir(dir, { recursive: true });
|
|
63
|
+
const lines = Object.entries(env).map(([k, v]) => `${k}=${v}`);
|
|
64
|
+
await fs.writeFile(path.join(dir, ".env"), lines.join("\n") + "\n", "utf8");
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=services.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"services.js","sourceRoot":"","sources":["../src/services.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sharedDb.d.ts","sourceRoot":"","sources":["../src/sharedDb.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAwBlD,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,CAgH3D"}
|
package/dist/sharedDb.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { findOne } from "./capabilities.js";
|
|
2
|
+
// Postgres identifiers: letters, digits, underscores; max 63 bytes. We enforce
|
|
3
|
+
// a safe subset because db.name / db.user are free-form strings in the schema.
|
|
4
|
+
// Valid chars: [A-Za-z_][A-Za-z0-9_]*
|
|
5
|
+
const IDENT_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
6
|
+
function assertIdent(kind, value) {
|
|
7
|
+
if (!IDENT_RE.test(value)) {
|
|
8
|
+
throw new Error(`sharedDb: invalid ${kind} ${JSON.stringify(value)} — must match ${IDENT_RE.source}`);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function assertSafePassword(value) {
|
|
12
|
+
if (value.includes("'") || value.includes("\\")) {
|
|
13
|
+
throw new Error("sharedDb: password contains single-quote or backslash — cannot safely embed in init SQL");
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function buildInitSql(states) {
|
|
17
|
+
const shared = states.filter((s) => s.def.database !== undefined && (s.db?.mode ?? (s.def.database.preferShared ? "shared" : "dedicated")) === "shared");
|
|
18
|
+
if (shared.length === 0)
|
|
19
|
+
return "";
|
|
20
|
+
const stanzas = [];
|
|
21
|
+
for (const s of shared) {
|
|
22
|
+
const db = s.def.database;
|
|
23
|
+
const password = s.env.DB_PASSWORD;
|
|
24
|
+
if (!password) {
|
|
25
|
+
throw new Error(`sharedDb: service ${s.def.name} has database.preferShared but no DB_PASSWORD in env`);
|
|
26
|
+
}
|
|
27
|
+
assertIdent("database name", db.name);
|
|
28
|
+
assertIdent("database user", db.user);
|
|
29
|
+
assertSafePassword(password);
|
|
30
|
+
stanzas.push(`-- ${s.def.name}
|
|
31
|
+
DO $$
|
|
32
|
+
BEGIN
|
|
33
|
+
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = '${db.user}') THEN
|
|
34
|
+
CREATE USER ${db.user} WITH PASSWORD '${password}';
|
|
35
|
+
END IF;
|
|
36
|
+
END$$;
|
|
37
|
+
|
|
38
|
+
SELECT 'CREATE DATABASE ${db.name} OWNER ${db.user}'
|
|
39
|
+
WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '${db.name}')\\gexec
|
|
40
|
+
`);
|
|
41
|
+
}
|
|
42
|
+
// Helper to collect tables from both dbRead.tables and search.index.table
|
|
43
|
+
function readerTablesFor(s) {
|
|
44
|
+
const tables = new Set();
|
|
45
|
+
// Add tables from explicit dbRead declaration
|
|
46
|
+
for (const t of s.def.provides.bridge?.dbRead?.tables ?? []) {
|
|
47
|
+
tables.add(t);
|
|
48
|
+
}
|
|
49
|
+
// Add table from search.index if present
|
|
50
|
+
const idx = s.def.provides.bridge?.search?.index;
|
|
51
|
+
if (idx) {
|
|
52
|
+
tables.add(idx.table);
|
|
53
|
+
}
|
|
54
|
+
return [...tables];
|
|
55
|
+
}
|
|
56
|
+
// Handle bridge_reader grants for services that declare provides.bridge.dbRead
|
|
57
|
+
// or provides.bridge.search.index.table. The reader role identity (name +
|
|
58
|
+
// password env) comes from whichever service declares `provides.bridgeReader`
|
|
59
|
+
// — looked up by capability so the engine never depends on the string "bridge".
|
|
60
|
+
const readerServices = states.filter((s) => readerTablesFor(s).length > 0);
|
|
61
|
+
if (readerServices.length > 0) {
|
|
62
|
+
const readerProvider = findOne(states, "bridgeReader");
|
|
63
|
+
const readerCap = readerProvider?.def.provides.bridgeReader;
|
|
64
|
+
const readerPw = readerProvider && readerCap
|
|
65
|
+
? readerProvider.env[readerCap.passwordEnv]
|
|
66
|
+
: undefined;
|
|
67
|
+
if (!readerProvider || !readerCap || !readerPw) {
|
|
68
|
+
throw new Error("sharedDb: a service declares provides.bridge.dbRead or provides.bridge.search.index but no enabled service declares provides.bridgeReader with a populated password env");
|
|
69
|
+
}
|
|
70
|
+
assertSafePassword(readerPw);
|
|
71
|
+
const readerRole = readerCap.roleName;
|
|
72
|
+
assertIdent("bridgeReader.roleName", readerRole);
|
|
73
|
+
stanzas.push(`-- ${readerRole} (cross-DB SELECT for the launcher's indexer + aggregate widgets)
|
|
74
|
+
DO $$
|
|
75
|
+
BEGIN
|
|
76
|
+
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = '${readerRole}') THEN
|
|
77
|
+
CREATE USER ${readerRole} WITH PASSWORD '${readerPw}';
|
|
78
|
+
END IF;
|
|
79
|
+
END$$;
|
|
80
|
+
`);
|
|
81
|
+
for (const s of readerServices) {
|
|
82
|
+
const db = s.def.database;
|
|
83
|
+
if (!db) {
|
|
84
|
+
throw new Error(`sharedDb: service ${s.def.name} declares provides.bridge.dbRead or provides.bridge.search.index but has no database`);
|
|
85
|
+
}
|
|
86
|
+
assertIdent("database name", db.name);
|
|
87
|
+
const tables = readerTablesFor(s);
|
|
88
|
+
const grants = [];
|
|
89
|
+
grants.push(`GRANT CONNECT ON DATABASE ${db.name} TO ${readerRole};`);
|
|
90
|
+
grants.push(`\\c ${db.name}`);
|
|
91
|
+
grants.push(`GRANT USAGE ON SCHEMA public TO ${readerRole};`);
|
|
92
|
+
for (const table of tables) {
|
|
93
|
+
// Validate table identifier (schema.table form allowed)
|
|
94
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)?$/.test(table)) {
|
|
95
|
+
throw new Error(`sharedDb: invalid table identifier ${JSON.stringify(table)}`);
|
|
96
|
+
}
|
|
97
|
+
grants.push(`GRANT SELECT ON ${table} TO ${readerRole};`);
|
|
98
|
+
}
|
|
99
|
+
stanzas.push(`-- bridge_reader grants for ${s.def.name}\n${grants.join("\n")}\n`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return stanzas.join("\n");
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=sharedDb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sharedDb.js","sourceRoot":"","sources":["../src/sharedDb.ts"],"names":[],"mappings":"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"}
|
package/dist/target.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { GlobalConfig } from "./schema/configYaml.js";
|
|
2
|
+
import type { ServiceState } from "./keycloak.js";
|
|
3
|
+
/** Map of relative-output-path → file contents. */
|
|
4
|
+
export type FileTree = Record<string, string>;
|
|
5
|
+
export interface KubernetesExtras {
|
|
6
|
+
/** When provided, an `/opt/keycloak/data/import/realm-import.json` ConfigMap is emitted. */
|
|
7
|
+
realmImport?: string;
|
|
8
|
+
/**
|
|
9
|
+
* When provided, a `postgres-init` ConfigMap is emitted. The shared postgres
|
|
10
|
+
* StatefulSet mounts it at `/docker-entrypoint-initdb.d`, so Postgres runs
|
|
11
|
+
* every `CREATE USER` / `CREATE DATABASE` stanza on first boot.
|
|
12
|
+
*/
|
|
13
|
+
postgresInitSql?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Stringified bridge manifest JSON. When provided, a `bridge-manifest`
|
|
16
|
+
* ConfigMap is emitted under configmaps/. The bridge Deployment mounts it
|
|
17
|
+
* at /app/manifest/bridge-manifest.json.
|
|
18
|
+
*/
|
|
19
|
+
bridgeManifestJson?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Per-service icon SVG bodies, keyed by service name (no extension).
|
|
22
|
+
* When non-empty, a `bridge-icons` ConfigMap is emitted with one data key
|
|
23
|
+
* per entry: `<name>.svg`. The bridge Deployment mounts it at /app/icons.
|
|
24
|
+
*/
|
|
25
|
+
bridgeIconsByService?: Record<string, string>;
|
|
26
|
+
/** Per-file dedicated-peer manifests. Key is the relative output path (e.g. "manifests/drive-postgres.yaml"). */
|
|
27
|
+
dedicatedPeerManifests?: Record<string, string>;
|
|
28
|
+
}
|
|
29
|
+
export type RenderDockerFn = (states: ServiceState[], global: GlobalConfig, templates: Map<string, string>, extraTopLevel: Record<string, string>, extraFragments?: string[]) => FileTree;
|
|
30
|
+
export type RenderKubernetesFn = (states: ServiceState[], global: GlobalConfig, templates: Map<string, string>, extras: KubernetesExtras, lbAnnotations?: Record<string, string>) => FileTree;
|
|
31
|
+
export interface RenderTargets {
|
|
32
|
+
docker?: RenderDockerFn;
|
|
33
|
+
kubernetes?: RenderKubernetesFn;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=target.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"target.d.ts","sourceRoot":"","sources":["../src/target.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,mDAAmD;AACnD,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE9C,MAAM,WAAW,gBAAgB;IAC/B,4FAA4F;IAC5F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9C,iHAAiH;IACjH,sBAAsB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjD;AAED,MAAM,MAAM,cAAc,GAAG,CAC3B,MAAM,EAAE,YAAY,EAAE,EACtB,MAAM,EAAE,YAAY,EACpB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACrC,cAAc,CAAC,EAAE,MAAM,EAAE,KACtB,QAAQ,CAAC;AAEd,MAAM,MAAM,kBAAkB,GAAG,CAC/B,MAAM,EAAE,YAAY,EAAE,EACtB,MAAM,EAAE,YAAY,EACpB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,MAAM,EAAE,gBAAgB,EACxB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KACnC,QAAQ,CAAC;AAEd,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,UAAU,CAAC,EAAE,kBAAkB,CAAC;CACjC"}
|
package/dist/target.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Target abstraction. The core renderer is target-agnostic — it builds the
|
|
2
|
+
// shared service plan, then delegates emission of artifact files to injected
|
|
3
|
+
// target functions. Concrete renderers live in @gezelligate/{docker,k8s} and
|
|
4
|
+
// are wired in by the caller (cli, studio). Core has no compile-time dep on
|
|
5
|
+
// either renderer package; this is what breaks the workspace cycle.
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=target.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"target.js","sourceRoot":"","sources":["../src/target.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,6EAA6E;AAC7E,6EAA6E;AAC7E,4EAA4E;AAC5E,oEAAoE"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{{name}}:
|
|
2
|
+
image: postgres:16-alpine
|
|
3
|
+
restart: unless-stopped
|
|
4
|
+
environment:
|
|
5
|
+
POSTGRES_DB: {{dbName}}
|
|
6
|
+
POSTGRES_USER: {{dbUser}}
|
|
7
|
+
POSTGRES_PASSWORD: {{envref passwordRef}}
|
|
8
|
+
volumes:
|
|
9
|
+
- {{name}}-data:/var/lib/postgresql/data
|
|
10
|
+
|
|
11
|
+
volumes:
|
|
12
|
+
{{name}}-data:
|