ankka-console 0.10.0 → 0.12.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.
Files changed (75) hide show
  1. package/dist/client/control-plane.d.ts +87 -1
  2. package/dist/client/control-plane.js +201 -1
  3. package/dist/client/schemas.d.ts +1835 -0
  4. package/dist/client/schemas.js +595 -0
  5. package/dist/context.d.ts +98 -0
  6. package/dist/context.js +73 -0
  7. package/dist/extensions/render.d.ts +2 -0
  8. package/dist/extensions/render.js +5 -0
  9. package/dist/extensions/types.d.ts +1 -1
  10. package/dist/extensions/types.js +29 -0
  11. package/dist/fonts/inter-latin-ext-wght-normal.woff2 +0 -0
  12. package/dist/fonts/inter-latin-wght-normal.woff2 +0 -0
  13. package/dist/index.d.ts +9 -2
  14. package/dist/index.js +7 -1
  15. package/dist/routes/auth.sign-out.js +8 -3
  16. package/dist/routes/front.d.ts +62 -2
  17. package/dist/routes/front.js +45 -10
  18. package/dist/routes/logs.d.ts +92 -0
  19. package/dist/routes/logs.js +15 -14
  20. package/dist/routes/machines.d.ts +78 -0
  21. package/dist/routes/machines.js +78 -0
  22. package/dist/routes/members.js +11 -8
  23. package/dist/routes/organization-new.js +7 -4
  24. package/dist/routes/organization.d.ts +29 -1
  25. package/dist/routes/organization.js +38 -9
  26. package/dist/routes/project-new.js +8 -4
  27. package/dist/routes/project.d.ts +347 -2
  28. package/dist/routes/project.js +182 -9
  29. package/dist/routes/service-apply.d.ts +5 -2
  30. package/dist/routes/service-apply.js +17 -14
  31. package/dist/routes/service-history.d.ts +32 -0
  32. package/dist/routes/service-history.js +82 -0
  33. package/dist/routes/service-topology.d.ts +210 -0
  34. package/dist/routes/service-topology.js +54 -0
  35. package/dist/routes/service.d.ts +91 -10
  36. package/dist/routes/service.js +87 -23
  37. package/dist/routes/stream.service.js +18 -1
  38. package/dist/routes/tokens.js +8 -6
  39. package/dist/routes.js +3 -0
  40. package/dist/runtime.d.ts +3 -1
  41. package/dist/runtime.js +1 -0
  42. package/dist/styles.css +2 -481
  43. package/dist/testing/fake-control-plane.d.ts +334 -1
  44. package/dist/testing/fake-control-plane.js +1194 -15
  45. package/dist/testing/index.d.ts +1 -1
  46. package/dist/testing/scenarios.js +6 -0
  47. package/dist/theme.css +66 -0
  48. package/dist/ui/console.d.ts +19 -6
  49. package/dist/ui/console.js +9 -2
  50. package/dist/ui/errors.js +7 -5
  51. package/dist/ui/grants.d.ts +3 -0
  52. package/dist/ui/grants.js +13 -0
  53. package/dist/ui/hosting.d.ts +11 -0
  54. package/dist/ui/hosting.js +20 -0
  55. package/dist/ui/primitives/button.d.ts +11 -0
  56. package/dist/ui/primitives/button.js +21 -0
  57. package/dist/ui/primitives/select.d.ts +10 -0
  58. package/dist/ui/primitives/select.js +4 -0
  59. package/dist/ui/primitives/switch.d.ts +9 -0
  60. package/dist/ui/primitives/switch.js +4 -0
  61. package/dist/ui/shape.d.ts +4 -0
  62. package/dist/ui/shape.js +36 -0
  63. package/dist/ui/shell.d.ts +76 -0
  64. package/dist/ui/shell.js +114 -0
  65. package/dist/ui/tokens.d.ts +82 -0
  66. package/dist/ui/tokens.js +172 -0
  67. package/dist/ui/topology/Graph.d.ts +13 -0
  68. package/dist/ui/topology/Graph.js +56 -0
  69. package/dist/ui/topology/Table.d.ts +10 -0
  70. package/dist/ui/topology/Table.js +14 -0
  71. package/dist/ui/topology/layout.d.ts +113 -0
  72. package/dist/ui/topology/layout.js +177 -0
  73. package/dist/ui/use-stream.d.ts +251 -1
  74. package/dist/ui/use-stream.js +11 -1
  75. package/package.json +11 -3
@@ -2,7 +2,8 @@
2
2
  * A control plane in one process: every route the console uses, over in-memory state, with the
3
3
  * control plane's rules as the console can observe them — who sees what, `404` rather than `403`
4
4
  * for an outsider, owner-only operations, tombstoned ids, `409` for a non-empty delete, a disabled
5
- * organization refusing changes, descriptor validation, a deploy token shown once.
5
+ * organization refusing changes, descriptor validation, a deploy token shown once, grants made,
6
+ * listed and ended with their effect, and machines registered with a secret shown once.
6
7
  *
7
8
  * It answers from state rather than from a script, so it cannot run out quietly. What a test needs
8
9
  * to steer is explicit: `script()` makes the next answer on one route a given status, `tick()` moves
@@ -32,6 +33,10 @@ export interface FakeControlPlaneOptions {
32
33
  signupUrl?: string;
33
34
  baseDomain?: string;
34
35
  port?: number;
36
+ /** The broker's address outside the cluster; unset, the installation does not expose its broker and a machine's topic grant opens nothing. */
37
+ brokerBootstrap?: string;
38
+ /** The most bytes a second a machine may be given on either side; the control plane's default is 32 MiB. */
39
+ byteRateCeiling?: number;
35
40
  }
36
41
  type Role = "owner" | "member";
37
42
  interface Member {
@@ -66,16 +71,144 @@ interface Registry {
66
71
  setAt: string;
67
72
  setBy?: string;
68
73
  }
74
+ interface ProjectSecret {
75
+ /** Values held as the cluster holds them; the control plane never answers with one. */
76
+ entries: Map<string, string>;
77
+ setAt: string;
78
+ setBy?: string;
79
+ }
69
80
  interface Project {
70
81
  id: string;
71
82
  name: string;
72
83
  organizationId: string;
73
84
  registry?: Registry;
85
+ secrets?: Map<string, ProjectSecret>;
86
+ /** Declared topics, by name: their partitions, compaction, contract and what the broker reported of each. */
87
+ topics?: Map<string, TopicRecord>;
88
+ /** Declared brokers beside the installation's, by name. */
89
+ brokers?: Map<string, BrokerRecord>;
90
+ /** Where the project's new buckets in Google Cloud Storage are made (feature 039). */
91
+ location?: string;
92
+ /** Feature 041: restores asked for, in order, and rehearsals. Restores verify at once here. */
93
+ restores?: {
94
+ name: string;
95
+ line: string;
96
+ moment: string;
97
+ requestedBy?: string;
98
+ requestedAt: string;
99
+ }[];
100
+ rehearsals?: {
101
+ name: string;
102
+ line: string;
103
+ moment: string;
104
+ requestedBy?: string;
105
+ requestedAt: string;
106
+ }[];
107
+ databaseHistory?: {
108
+ kind: string;
109
+ by?: string;
110
+ at: string;
111
+ detail?: string;
112
+ }[];
113
+ credentialGeneration?: number;
114
+ database?: {
115
+ replicas: number;
116
+ synchronous: boolean;
117
+ retentionDays?: number;
118
+ rehearse?: string;
119
+ };
120
+ /** The changes to its topics, newest first. */
121
+ history?: ProjectHistoryRecord[];
74
122
  hidden: boolean;
75
123
  }
124
+ interface ProjectHistoryRecord {
125
+ kind: string;
126
+ topic: string;
127
+ actor?: {
128
+ subject: string;
129
+ display?: string;
130
+ administrative: boolean;
131
+ };
132
+ at?: string;
133
+ changes: {
134
+ setting: string;
135
+ from: string;
136
+ to: string;
137
+ }[];
138
+ }
139
+ interface BrokerRecord {
140
+ bootstrap: string;
141
+ shape: string;
142
+ secret: string;
143
+ declaredAt: string;
144
+ }
145
+ /** A topic source as an instance reports it, with how far behind it is. */
146
+ interface TopicSourceRecord {
147
+ kind: string;
148
+ component: string;
149
+ topic: string;
150
+ group: string;
151
+ start?: string;
152
+ version?: number;
153
+ broker?: string;
154
+ contract?: string;
155
+ lag?: number;
156
+ failing?: string;
157
+ /** What the broker still holds of the topic, per partition. */
158
+ gap?: {
159
+ partitions: {
160
+ partition: number;
161
+ beginning: number;
162
+ earliestRetained?: string;
163
+ }[];
164
+ compacted?: boolean;
165
+ gone?: boolean;
166
+ readAt?: string;
167
+ };
168
+ }
169
+ /** A topic's settings, in the words a member types, as the control plane keeps them. */
170
+ interface TopicSettingsRecord {
171
+ retention: string;
172
+ retentionSize: string;
173
+ cleanup: string;
174
+ tombstoneWindow: string;
175
+ minCompactionLag: string;
176
+ maxCompactionLag: string;
177
+ copies?: number;
178
+ minInSync?: number;
179
+ }
180
+ declare const SettingNames: readonly ["retention", "retentionSize", "cleanup", "tombstoneWindow", "minCompactionLag", "maxCompactionLag", "copies", "minInSync"];
181
+ type SettingName = (typeof SettingNames)[number];
182
+ interface TopicRecord {
183
+ partitions: number;
184
+ phase?: string;
185
+ detail?: string;
186
+ compacted?: boolean;
187
+ contract?: {
188
+ name: string;
189
+ fingerprint: string;
190
+ schema: unknown;
191
+ };
192
+ /** Every setting, and the ones the installation supplied; absent for a topic seeded without them. */
193
+ settings?: TopicSettingsRecord;
194
+ defaulted?: SettingName[];
195
+ /** How many copies the broker holds, as a seed says. */
196
+ copiesHeld?: number;
197
+ }
198
+ /** One side a running service takes on a declared topic with a contract, against it; `topic` is the fake's own, for the project's listing. */
199
+ interface TopicCheckRecord {
200
+ topic?: string;
201
+ service: string;
202
+ component: string;
203
+ direction: string;
204
+ stated?: string;
205
+ state: string;
206
+ }
76
207
  interface Service {
77
208
  name: string;
78
209
  projectId: string;
210
+ /** Custom hostnames (feature 045), in the order added; the fake serves each at once. */
211
+ customHostnames?: string[];
79
212
  lifecycle: string;
80
213
  generation: number;
81
214
  image: string;
@@ -84,6 +217,10 @@ interface Service {
84
217
  detail?: string;
85
218
  exposed: boolean;
86
219
  paused: boolean;
220
+ /** What the cluster reports of its database; `null` until it has reported one. */
221
+ database: string | null;
222
+ /** The restore a member switched it to (feature 041); the project database when absent. */
223
+ databaseCluster?: string;
87
224
  history: {
88
225
  kind: string;
89
226
  generation: number;
@@ -93,9 +230,72 @@ interface Service {
93
230
  administrative: boolean;
94
231
  };
95
232
  at: string;
233
+ image?: string;
234
+ digest?: string;
235
+ hostname?: string;
236
+ rolledBackTo?: number;
237
+ }[];
238
+ /** The descriptor in force, and the applied ones a rollback can return to, newest first, at most fifty. */
239
+ descriptor?: unknown;
240
+ kept: {
241
+ generation: number;
242
+ descriptor: unknown;
96
243
  }[];
97
244
  logs: Map<string, string[]>;
98
245
  previousLogs: Map<string, string[]>;
246
+ /** The platform's container's output: the sidecar beside a process, the proxy beside a web-hosted one. */
247
+ platformLogs: Map<string, string[]>;
248
+ hosting?: string;
249
+ mounts?: {
250
+ path: string;
251
+ service: string;
252
+ state: string;
253
+ }[];
254
+ callers?: string[];
255
+ processPort?: number;
256
+ /** What the operator reported of the service's credential on the installation's broker. */
257
+ broker?: string;
258
+ /** Topics the service's components use that its project does not declare, as last read. */
259
+ undeclaredTopics?: string[];
260
+ /** The sides it takes on declared topics with a contract, as last read. */
261
+ topicChecks?: TopicCheckRecord[];
262
+ /** Its topic sources with how far behind each is, as last read. */
263
+ topicSources?: TopicSourceRecord[];
264
+ /** The descriptor asked for a bucket (feature 034). */
265
+ provisionObjectStorage?: boolean;
266
+ /** The descriptor gave an ANKKA_S3_ variable: an object store of its own. */
267
+ ownObjectStore?: boolean;
268
+ /** The descriptor asked that the bucket be reachable from the internet. */
269
+ exposeObjectStorage?: boolean;
270
+ /** The store the bucket is in, `garage` or `gcs`, as the operator reports it (feature 039). */
271
+ objectStore?: string;
272
+ /** Where its bucket in Google Cloud Storage is. */
273
+ bucketLocation?: string;
274
+ /** Where a move of its bucket from Garage is, as the control plane phrases it. */
275
+ storageMove?: string;
276
+ /** What the instances report when asked for the topology; generated from the service when unset. */
277
+ topology?: FakeTopology;
278
+ }
279
+ /** A service's instances, what each answered, and the merged document, as a suite scripts it. */
280
+ export interface FakeTopology {
281
+ instances: {
282
+ pod: string;
283
+ status: "ok" | "unreachable" | "unsupported" | "failed";
284
+ problem?: string;
285
+ }[];
286
+ nodes: unknown[];
287
+ declared: unknown[];
288
+ calls: unknown[];
289
+ differences?: {
290
+ node: string;
291
+ presentOn: string[];
292
+ }[];
293
+ window?: {
294
+ seconds: number;
295
+ since: string;
296
+ calls: number;
297
+ unanswered?: number;
298
+ };
99
299
  }
100
300
  interface Token {
101
301
  id: string;
@@ -108,6 +308,48 @@ interface Token {
108
308
  expiresAt?: string;
109
309
  revoked: boolean;
110
310
  }
311
+ /** What one grant opens, flat as the control plane holds it (feature 040). */
312
+ export interface FakeGrantTarget {
313
+ kind: string;
314
+ service?: string;
315
+ method?: string;
316
+ path?: string;
317
+ topic?: string;
318
+ right?: string;
319
+ decrypt?: boolean;
320
+ }
321
+ interface GrantAct {
322
+ by?: string;
323
+ at: string;
324
+ }
325
+ /** A grant a project made; `changes` is what the grantee's side records of it. */
326
+ interface Grant {
327
+ id: string;
328
+ projectId: string;
329
+ grantee: string;
330
+ target: FakeGrantTarget;
331
+ state: string;
332
+ granted: GrantAct;
333
+ answered?: GrantAct;
334
+ ended?: GrantAct;
335
+ changes: {
336
+ change: string;
337
+ by?: string;
338
+ at: string;
339
+ }[];
340
+ }
341
+ interface Machine {
342
+ organizationId: string;
343
+ name: string;
344
+ registeredBy?: string;
345
+ registeredAt: string;
346
+ byteRates?: {
347
+ produceBytesPerSecond: number;
348
+ consumeBytesPerSecond: number;
349
+ requestPercentage: number;
350
+ };
351
+ hidden: boolean;
352
+ }
111
353
  export interface FakeControlPlane {
112
354
  url: string;
113
355
  server: Server;
@@ -120,6 +362,8 @@ export interface FakeControlPlane {
120
362
  /** Advance every service in a transitional state by one step. */
121
363
  tick(): void;
122
364
  appendLog(projectId: string, name: string, line: string, instance?: string): void;
365
+ /** What a service's instances report when its topology is read, from now on. */
366
+ scriptTopology(projectId: string, name: string, topology: FakeTopology): void;
123
367
  /** Who may create organizations from now on, and where the refusal sends people. */
124
368
  policy(creation: "open" | "platform-admin", signupUrl?: string): void;
125
369
  /** From now on, created organizations and projects are missing from listings until `settle()`. */
@@ -132,11 +376,36 @@ export interface FakeControlPlane {
132
376
  services: Map<string, Service>;
133
377
  tokens: Map<string, Token>;
134
378
  tombstones: Set<string>;
379
+ /** Every project's grants, by id. */
380
+ grants: Map<string, Grant>;
381
+ /** Registered machines, by `<organization>/<name>`. */
382
+ machines: Map<string, Machine>;
135
383
  };
136
384
  seed(seed: FakeSeed): void;
137
385
  close(): Promise<void>;
138
386
  }
387
+ /** The installation's cloud, as `GET /installation` reports it (feature 044). */
388
+ export interface FakeCloud {
389
+ provider: string;
390
+ account: string;
391
+ location: string;
392
+ kmsKey?: string;
393
+ }
139
394
  export interface FakeSeed {
395
+ /** The installation's cloud (feature 044); `null` for an installation that names none, as until seeded. */
396
+ cloud?: FakeCloud | null;
397
+ /** Where the installation keeps new buckets (feature 039); Garage until a suite says otherwise. */
398
+ objectStore?: "garage" | "gcs";
399
+ /** Feature 041: start held, as a control plane whose own database was restored. */
400
+ held?: {
401
+ targetTime: string;
402
+ services?: {
403
+ project: string;
404
+ service: string;
405
+ recordedImage?: string;
406
+ clusterImage?: string;
407
+ }[];
408
+ };
140
409
  organizations?: {
141
410
  id: string;
142
411
  name: string;
@@ -155,6 +424,70 @@ export interface FakeSeed {
155
424
  image?: string;
156
425
  lifecycle?: string;
157
426
  instances?: number;
427
+ hosting?: string;
428
+ mounts?: {
429
+ path: string;
430
+ service: string;
431
+ state: string;
432
+ }[];
433
+ callers?: string[];
434
+ processPort?: number;
435
+ exposed?: boolean;
436
+ /** What the cluster reports of its database; `null` until it has reported one. */
437
+ database?: string | null;
438
+ broker?: string;
439
+ undeclaredTopics?: string[];
440
+ topicChecks?: TopicCheckRecord[];
441
+ topicSources?: TopicSourceRecord[];
442
+ provisionObjectStorage?: boolean;
443
+ exposeObjectStorage?: boolean;
444
+ ownObjectStore?: boolean;
445
+ /** The store its bucket is in, `garage` or `gcs`. */
446
+ objectStore?: string;
447
+ bucketLocation?: string;
448
+ }[];
449
+ /** Project secrets, by name and entry: a value each, never listed. */
450
+ secrets?: {
451
+ projectId: string;
452
+ name: string;
453
+ entries: Record<string, string>;
454
+ }[];
455
+ /** Brokers a project declares beside the installation's. */
456
+ brokers?: {
457
+ projectId: string;
458
+ name: string;
459
+ bootstrap: string;
460
+ shape: string;
461
+ secret: string;
462
+ }[];
463
+ /** Topics a project declares, as the control plane holds them, with the broker's report. */
464
+ topics?: {
465
+ projectId: string;
466
+ name: string;
467
+ partitions: number;
468
+ phase?: string;
469
+ detail?: string;
470
+ compacted?: boolean;
471
+ contract?: {
472
+ name: string;
473
+ schema: unknown;
474
+ };
475
+ /** Its settings, each the installation's shipped default unless given; none for a topic from before settings. */
476
+ settings?: Partial<TopicSettingsRecord>;
477
+ }[];
478
+ /** Grants a project made, as if an owner had made them: accepted within its organization, pending to another, unless `state` says. */
479
+ grants?: {
480
+ projectId: string;
481
+ grantee: string;
482
+ target: FakeGrantTarget;
483
+ state?: string;
484
+ by?: string;
485
+ }[];
486
+ /** Machines registered on an organization. */
487
+ machines?: {
488
+ organizationId: string;
489
+ name: string;
490
+ byteRates?: Machine["byteRates"];
158
491
  }[];
159
492
  }
160
493
  export declare function fakeControlPlane(options?: FakeControlPlaneOptions): Promise<FakeControlPlane>;