@keboola/api-fixtures 22.0.0 → 26.0.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/CHANGELOG.md +255 -0
- package/dist/index.cjs +821 -374
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1438 -746
- package/dist/index.d.ts +1438 -746
- package/dist/index.js +810 -372
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
package/dist/index.cjs
CHANGED
|
@@ -1,394 +1,841 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/clients/apps/deployments.ts
|
|
3
|
+
/**
|
|
4
|
+
* Deployment ids are the deterministic Kubernetes CR name — `app-{appId}-dpl-{hash}` —
|
|
5
|
+
* so they are reproduced in that shape rather than as opaque strings.
|
|
6
|
+
*/
|
|
7
|
+
const APP_ID = "374811";
|
|
8
|
+
const deploymentId = (hash) => `app-${APP_ID}-dpl-${hash}`;
|
|
9
|
+
const archivedDeployment = {
|
|
10
|
+
id: deploymentId("350e2cf5287c5665"),
|
|
11
|
+
number: 1,
|
|
12
|
+
configId: "01kz9kny4n49x3xk0e4k8ynpmq",
|
|
13
|
+
configVersion: "14",
|
|
14
|
+
gitCommitSha: null,
|
|
15
|
+
size: "tiny",
|
|
16
|
+
buildState: "PREBUILT",
|
|
17
|
+
runState: "STOPPED",
|
|
18
|
+
archived: true,
|
|
19
|
+
archivedAt: "2026-08-15T11:03:02+00:00",
|
|
20
|
+
createdAt: "2026-08-10T09:12:44+00:00"
|
|
21
|
+
};
|
|
22
|
+
const liveDeployment = {
|
|
23
|
+
id: deploymentId("7a4c1b9e0d3f2a81"),
|
|
24
|
+
number: 2,
|
|
25
|
+
configId: "01kz9kny4n49x3xk0e4k8ynpmq",
|
|
26
|
+
configVersion: "16",
|
|
27
|
+
gitCommitSha: null,
|
|
28
|
+
size: "small",
|
|
29
|
+
buildState: "PREBUILT",
|
|
30
|
+
runState: "RUNNING",
|
|
31
|
+
archived: false,
|
|
32
|
+
archivedAt: null,
|
|
33
|
+
createdAt: "2026-08-15T11:02:58+00:00"
|
|
34
|
+
};
|
|
35
|
+
const stagedDeployment = {
|
|
36
|
+
id: deploymentId("c5e83f17b204de96"),
|
|
37
|
+
number: 3,
|
|
38
|
+
configId: "01kz9kny4n49x3xk0e4k8ynpmq",
|
|
39
|
+
configVersion: "18",
|
|
40
|
+
gitCommitSha: null,
|
|
41
|
+
size: "small",
|
|
42
|
+
buildState: "PREBUILT",
|
|
43
|
+
runState: "NEVER_RUN",
|
|
44
|
+
archived: false,
|
|
45
|
+
archivedAt: null,
|
|
46
|
+
createdAt: "2026-08-17T08:41:19+00:00"
|
|
47
|
+
};
|
|
48
|
+
const buildFailedDeployment = {
|
|
49
|
+
id: deploymentId("e91d47a8c6b02f35"),
|
|
50
|
+
number: 4,
|
|
51
|
+
configId: "01kz9kny4n49x3xk0e4k8ynpmq",
|
|
52
|
+
configVersion: "19",
|
|
53
|
+
gitCommitSha: null,
|
|
54
|
+
size: "small",
|
|
55
|
+
buildState: "FAILED",
|
|
56
|
+
runState: "NEVER_RUN",
|
|
57
|
+
archived: false,
|
|
58
|
+
archivedAt: null,
|
|
59
|
+
createdAt: "2026-08-17T09:05:33+00:00"
|
|
60
|
+
};
|
|
61
|
+
const runFailedDeployment = {
|
|
62
|
+
id: deploymentId("2b6f0a94e7d51c83"),
|
|
63
|
+
number: 5,
|
|
64
|
+
configId: "01kz9kny4n49x3xk0e4k8ynpmq",
|
|
65
|
+
configVersion: "20",
|
|
66
|
+
gitCommitSha: null,
|
|
67
|
+
size: "small",
|
|
68
|
+
buildState: "PREBUILT",
|
|
69
|
+
runState: "FAILED",
|
|
70
|
+
archived: false,
|
|
71
|
+
archivedAt: null,
|
|
72
|
+
createdAt: "2026-08-17T09:31:07+00:00"
|
|
73
|
+
};
|
|
74
|
+
const deploymentFixtures = {
|
|
75
|
+
archived: archivedDeployment,
|
|
76
|
+
live: liveDeployment,
|
|
77
|
+
staged: stagedDeployment,
|
|
78
|
+
buildFailed: buildFailedDeployment,
|
|
79
|
+
runFailed: runFailedDeployment
|
|
80
|
+
};
|
|
81
|
+
const getDeployment = () => liveDeployment;
|
|
82
|
+
/**
|
|
83
|
+
* One continuous history: #1 retired, #2 serving, #3 staged, #4 failed to build, #5 built but its
|
|
84
|
+
* run failed.
|
|
85
|
+
*
|
|
86
|
+
* All five, because `runFixtures.failed` names #5 as its deployment — a list that left the failed
|
|
87
|
+
* ones out could not be joined to the runs, which is the join a timeline is built from.
|
|
88
|
+
*
|
|
89
|
+
* Returned in ascending `number` order. The endpoint does not specify an order, so consumers must
|
|
90
|
+
* sort for themselves — this order is a fixture convention, not a contract to rely on, and it is
|
|
91
|
+
* ascending on purpose: a consumer that assumes newest-first gets the wrong answer here rather
|
|
92
|
+
* than in production.
|
|
93
|
+
*/
|
|
94
|
+
const listDeployments = () => [
|
|
95
|
+
archivedDeployment,
|
|
96
|
+
liveDeployment,
|
|
97
|
+
stagedDeployment,
|
|
98
|
+
buildFailedDeployment,
|
|
99
|
+
runFailedDeployment
|
|
85
100
|
];
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
//#endregion
|
|
102
|
+
//#region src/clients/apps/apps.ts
|
|
103
|
+
const APP_URL = "https://hello-dashboard-374811.hub.canary-orion.keboola.dev";
|
|
104
|
+
const base$1 = {
|
|
105
|
+
id: APP_ID,
|
|
106
|
+
projectId: "14",
|
|
107
|
+
componentId: "keboola.data-apps",
|
|
108
|
+
branchId: "6",
|
|
109
|
+
configId: "01kz9kny4n49x3xk0e4k8ynpmq",
|
|
110
|
+
type: "streamlit",
|
|
111
|
+
mode: "prod",
|
|
112
|
+
url: APP_URL
|
|
113
|
+
};
|
|
114
|
+
const production = (deployment) => ({
|
|
115
|
+
desiredNumber: deployment.number,
|
|
116
|
+
desiredId: deployment.id,
|
|
117
|
+
actualNumber: deployment.number,
|
|
118
|
+
actualId: deployment.id
|
|
104
119
|
});
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
120
|
+
const neverDeployedApp = {
|
|
121
|
+
...base$1,
|
|
122
|
+
configVersion: "1",
|
|
123
|
+
production: {
|
|
124
|
+
desiredNumber: null,
|
|
125
|
+
desiredId: null,
|
|
126
|
+
actualNumber: null,
|
|
127
|
+
actualId: null
|
|
128
|
+
},
|
|
129
|
+
undeployedChanges: false,
|
|
130
|
+
state: "NOT_DEPLOYED"
|
|
131
|
+
};
|
|
132
|
+
/**
|
|
133
|
+
* Transcribed verbatim from canary on 17 Aug 2026 (AJDA-3140, probe P1): an app created and
|
|
134
|
+
* started through `/v1`, serving real traffic (HTTP 200, 8340 B) at the moment this was read,
|
|
135
|
+
* which `/v2` nonetheless reports as `NOT_DEPLOYED` with an empty `production` because it was
|
|
136
|
+
* never adopted into the deployments model.
|
|
137
|
+
*
|
|
138
|
+
* The Builder must never read "is this app serving" off `state` alone — here that answer is
|
|
139
|
+
* wrong in the most damaging direction.
|
|
140
|
+
*/
|
|
141
|
+
const legacyV1ServingApp = {
|
|
142
|
+
id: "374811",
|
|
143
|
+
projectId: "14",
|
|
144
|
+
componentId: "keboola.data-apps",
|
|
145
|
+
branchId: "6",
|
|
146
|
+
configId: "01kz9kny4n49x3xk0e4k8ynpmq",
|
|
147
|
+
configVersion: "2",
|
|
148
|
+
type: "streamlit",
|
|
149
|
+
mode: "dev",
|
|
150
|
+
url: APP_URL,
|
|
151
|
+
production: {
|
|
152
|
+
desiredNumber: null,
|
|
153
|
+
desiredId: null,
|
|
154
|
+
actualNumber: null,
|
|
155
|
+
actualId: null
|
|
156
|
+
},
|
|
157
|
+
undeployedChanges: false,
|
|
158
|
+
state: "NOT_DEPLOYED"
|
|
159
|
+
};
|
|
160
|
+
const runningApp = {
|
|
161
|
+
...base$1,
|
|
162
|
+
configVersion: deploymentFixtures.live.configVersion,
|
|
163
|
+
production: production(deploymentFixtures.live),
|
|
164
|
+
undeployedChanges: false,
|
|
165
|
+
state: "RUNNING"
|
|
166
|
+
};
|
|
167
|
+
const appWithUndeployedChanges = {
|
|
168
|
+
...base$1,
|
|
169
|
+
configVersion: deploymentFixtures.staged.configVersion,
|
|
170
|
+
production: production(deploymentFixtures.live),
|
|
171
|
+
undeployedChanges: true,
|
|
172
|
+
state: "RUNNING"
|
|
173
|
+
};
|
|
174
|
+
const appFixtures = {
|
|
175
|
+
neverDeployed: neverDeployedApp,
|
|
176
|
+
legacyV1Serving: legacyV1ServingApp,
|
|
177
|
+
running: runningApp,
|
|
178
|
+
undeployedChanges: appWithUndeployedChanges,
|
|
179
|
+
promoting: {
|
|
180
|
+
...base$1,
|
|
181
|
+
configVersion: deploymentFixtures.staged.configVersion,
|
|
182
|
+
production: {
|
|
183
|
+
desiredNumber: deploymentFixtures.staged.number,
|
|
184
|
+
desiredId: deploymentFixtures.staged.id,
|
|
185
|
+
actualNumber: deploymentFixtures.live.number,
|
|
186
|
+
actualId: deploymentFixtures.live.id
|
|
187
|
+
},
|
|
188
|
+
undeployedChanges: true,
|
|
189
|
+
state: "RUNNING"
|
|
190
|
+
},
|
|
191
|
+
sleeping: {
|
|
192
|
+
...base$1,
|
|
193
|
+
configVersion: deploymentFixtures.live.configVersion,
|
|
194
|
+
production: production(deploymentFixtures.live),
|
|
195
|
+
undeployedChanges: false,
|
|
196
|
+
state: "SLEEPING"
|
|
197
|
+
},
|
|
198
|
+
suspended: {
|
|
199
|
+
...base$1,
|
|
200
|
+
configVersion: deploymentFixtures.live.configVersion,
|
|
201
|
+
production: production(deploymentFixtures.live),
|
|
202
|
+
undeployedChanges: false,
|
|
203
|
+
state: "SUSPENDED"
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
const getApp = () => runningApp;
|
|
207
|
+
/**
|
|
208
|
+
* The named fixtures above are all the *same* app in different states, which is what a detail
|
|
209
|
+
* page shows. A listing shows different apps, so each entry past the first is re-addressed —
|
|
210
|
+
* including the deployment ids inside `production`, which embed the app id.
|
|
211
|
+
*/
|
|
212
|
+
const readdress = (app, id) => ({
|
|
213
|
+
...app,
|
|
214
|
+
id,
|
|
215
|
+
url: `https://data-app-${id}.hub.canary-orion.keboola.dev`,
|
|
216
|
+
production: {
|
|
217
|
+
...app.production,
|
|
218
|
+
desiredId: app.production.desiredId?.replace("374811", id) ?? null,
|
|
219
|
+
actualId: app.production.actualId?.replace("374811", id) ?? null
|
|
220
|
+
}
|
|
185
221
|
});
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
222
|
+
const listApps = () => [
|
|
223
|
+
runningApp,
|
|
224
|
+
readdress(appWithUndeployedChanges, "374812"),
|
|
225
|
+
readdress(neverDeployedApp, "374813")
|
|
190
226
|
];
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
};
|
|
200
|
-
var runningRun = {
|
|
201
|
-
...base2,
|
|
202
|
-
id: "4f2d8c1a-0b76-4e35-9a12-5c8e7d3b0f41",
|
|
203
|
-
deploymentId: deploymentFixtures.live.id,
|
|
204
|
-
configVersion: deploymentFixtures.live.configVersion,
|
|
205
|
-
state: "running",
|
|
206
|
-
createdAt: "2026-08-15T11:02:58+00:00",
|
|
207
|
-
startedAt: "2026-08-15T11:03:41+00:00",
|
|
208
|
-
stoppedAt: null,
|
|
209
|
-
startupLogs: null,
|
|
210
|
-
failureReason: null
|
|
211
|
-
};
|
|
212
|
-
var finishedRun = {
|
|
213
|
-
...base2,
|
|
214
|
-
id: "9c0a7e42-31bd-4f88-b6d5-2ea41f907c3b",
|
|
215
|
-
deploymentId: deploymentFixtures.archived.id,
|
|
216
|
-
configVersion: deploymentFixtures.archived.configVersion,
|
|
217
|
-
state: "finished",
|
|
218
|
-
createdAt: "2026-08-10T09:12:44+00:00",
|
|
219
|
-
startedAt: "2026-08-10T09:13:29+00:00",
|
|
220
|
-
stoppedAt: "2026-08-15T11:03:02+00:00",
|
|
221
|
-
startupLogs: null,
|
|
222
|
-
failureReason: null
|
|
223
|
-
};
|
|
224
|
-
var failedRun = {
|
|
225
|
-
...base2,
|
|
226
|
-
id: "ba53f9d0-7c41-4a2e-8f16-d0b9e254a7c6",
|
|
227
|
-
deploymentId: deploymentFixtures.runFailed.id,
|
|
228
|
-
configVersion: deploymentFixtures.runFailed.configVersion,
|
|
229
|
-
state: "failed",
|
|
230
|
-
createdAt: "2026-08-17T09:31:07+00:00",
|
|
231
|
-
startedAt: null,
|
|
232
|
-
stoppedAt: "2026-08-17T09:33:52+00:00",
|
|
233
|
-
startupLogs: "[INFO] Starting app\n[ERROR] App must have keboola-config/nginx/ directory. Missing: /app/keboola-config/nginx\n",
|
|
234
|
-
failureReason: {
|
|
235
|
-
reason: "StartupProbeFailed",
|
|
236
|
-
message: "App must have keboola-config/nginx/ directory. Missing: /app/keboola-config/nginx"
|
|
237
|
-
}
|
|
238
|
-
};
|
|
239
|
-
var legacyRun = {
|
|
240
|
-
...base2,
|
|
241
|
-
id: "1d7b4e05-8a92-4c63-b0f7-3e6a5c8192d4",
|
|
242
|
-
deploymentId: null,
|
|
243
|
-
configVersion: "2",
|
|
244
|
-
state: "running",
|
|
245
|
-
createdAt: "2026-08-17T10:02:11+00:00",
|
|
246
|
-
startedAt: "2026-08-17T10:02:51+00:00",
|
|
247
|
-
stoppedAt: null,
|
|
248
|
-
startupLogs: null,
|
|
249
|
-
failureReason: null
|
|
250
|
-
};
|
|
251
|
-
var runFixtures = {
|
|
252
|
-
running: runningRun,
|
|
253
|
-
finished: finishedRun,
|
|
254
|
-
failed: failedRun,
|
|
255
|
-
legacy: legacyRun
|
|
256
|
-
};
|
|
257
|
-
var getAppRun = () => runningRun;
|
|
258
|
-
var listAppRuns = () => [legacyRun, failedRun, runningRun, finishedRun];
|
|
259
|
-
|
|
260
|
-
// src/clients/storage/tables.ts
|
|
261
|
-
var bucket = {
|
|
262
|
-
id: "in.c-main",
|
|
263
|
-
name: "c-main",
|
|
264
|
-
displayName: "Main",
|
|
265
|
-
stage: "in",
|
|
266
|
-
description: "Main input bucket",
|
|
267
|
-
created: "2024-01-15T10:00:00+0100",
|
|
268
|
-
lastChangeDate: "2024-03-10T08:30:00+0100",
|
|
269
|
-
isMaintenance: false,
|
|
270
|
-
isReadOnly: false,
|
|
271
|
-
isSnowflakeSharedDatabase: false,
|
|
272
|
-
hasExternalSchema: false,
|
|
273
|
-
rowsCount: 15e4,
|
|
274
|
-
dataSizeBytes: 52428800,
|
|
275
|
-
uri: "https://connection.keboola.com/v2/storage/buckets/in.c-main",
|
|
276
|
-
backend: "snowflake",
|
|
277
|
-
backendPath: [],
|
|
278
|
-
databaseName: null,
|
|
279
|
-
color: null,
|
|
280
|
-
idBranch: 0,
|
|
281
|
-
owner: null,
|
|
282
|
-
sharing: null,
|
|
283
|
-
path: "in.c-main",
|
|
284
|
-
tables: "https://connection.keboola.com/v2/storage/buckets/in.c-main/tables",
|
|
285
|
-
updated: "2024-03-10T08:30:00+0100"
|
|
286
|
-
};
|
|
287
|
-
var freshTable = {
|
|
288
|
-
id: "in.c-main.users",
|
|
289
|
-
name: "users",
|
|
290
|
-
displayName: "Users",
|
|
291
|
-
primaryKey: ["id"],
|
|
292
|
-
metadata: [],
|
|
293
|
-
columns: ["id", "email", "name", "created_at"],
|
|
294
|
-
columnMetadata: {},
|
|
295
|
-
attributes: [],
|
|
296
|
-
bucket,
|
|
297
|
-
isTyped: false,
|
|
298
|
-
isAlias: false
|
|
299
|
-
};
|
|
300
|
-
var recentlyUpdatedTable = {
|
|
301
|
-
id: "in.c-main.orders",
|
|
302
|
-
name: "orders",
|
|
303
|
-
displayName: "Orders",
|
|
304
|
-
primaryKey: ["order_id"],
|
|
305
|
-
metadata: [
|
|
306
|
-
{
|
|
307
|
-
id: "mt1",
|
|
308
|
-
key: "KBC.createdBy.component.id",
|
|
309
|
-
value: "keboola.python-transformation",
|
|
310
|
-
provider: "keboola",
|
|
311
|
-
timestamp: "2024-06-01T09:00:00+0200"
|
|
312
|
-
}
|
|
313
|
-
],
|
|
314
|
-
columns: ["order_id", "user_id", "total", "status", "created_at", "updated_at"],
|
|
315
|
-
columnMetadata: {
|
|
316
|
-
order_id: [
|
|
317
|
-
{
|
|
318
|
-
id: "m1",
|
|
319
|
-
key: "KBC.datatype.type",
|
|
320
|
-
value: "INTEGER",
|
|
321
|
-
provider: "keboola",
|
|
322
|
-
timestamp: "2024-06-01T09:00:00+0200"
|
|
323
|
-
}
|
|
324
|
-
]
|
|
325
|
-
},
|
|
326
|
-
attributes: [],
|
|
327
|
-
bucket,
|
|
328
|
-
isTyped: false,
|
|
329
|
-
isAlias: false
|
|
330
|
-
};
|
|
331
|
-
var largeTable = {
|
|
332
|
-
id: "in.c-main.events",
|
|
333
|
-
name: "events",
|
|
334
|
-
displayName: "Events",
|
|
335
|
-
primaryKey: [],
|
|
336
|
-
metadata: [],
|
|
337
|
-
columns: ["event_id", "user_id", "event_type", "properties", "occurred_at"],
|
|
338
|
-
columnMetadata: {},
|
|
339
|
-
attributes: [],
|
|
340
|
-
bucket,
|
|
341
|
-
isTyped: false,
|
|
342
|
-
isAlias: false
|
|
343
|
-
};
|
|
344
|
-
var getTable = () => freshTable;
|
|
345
|
-
var listTables = () => [freshTable, recentlyUpdatedTable, largeTable];
|
|
346
|
-
var tableFixtures = {
|
|
347
|
-
fresh: freshTable,
|
|
348
|
-
recentlyUpdated: recentlyUpdatedTable,
|
|
349
|
-
large: largeTable
|
|
227
|
+
//#endregion
|
|
228
|
+
//#region src/clients/apps/runs.ts
|
|
229
|
+
const base = {
|
|
230
|
+
appId: APP_ID,
|
|
231
|
+
runtimeSize: "small",
|
|
232
|
+
runtimeBackendType: "streamlit",
|
|
233
|
+
imageVersion: "1.14.2",
|
|
234
|
+
mode: "prod"
|
|
350
235
|
};
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
apps: {
|
|
363
|
-
getApp,
|
|
364
|
-
listApps,
|
|
365
|
-
fixtures: appFixtures
|
|
366
|
-
},
|
|
367
|
-
deployments: {
|
|
368
|
-
getDeployment,
|
|
369
|
-
listDeployments,
|
|
370
|
-
fixtures: deploymentFixtures
|
|
371
|
-
},
|
|
372
|
-
runs: {
|
|
373
|
-
getAppRun,
|
|
374
|
-
listAppRuns,
|
|
375
|
-
fixtures: runFixtures
|
|
376
|
-
}
|
|
377
|
-
}
|
|
236
|
+
const runningRun = {
|
|
237
|
+
...base,
|
|
238
|
+
id: "4f2d8c1a-0b76-4e35-9a12-5c8e7d3b0f41",
|
|
239
|
+
deploymentId: deploymentFixtures.live.id,
|
|
240
|
+
configVersion: deploymentFixtures.live.configVersion,
|
|
241
|
+
state: "running",
|
|
242
|
+
createdAt: "2026-08-15T11:02:58+00:00",
|
|
243
|
+
startedAt: "2026-08-15T11:03:41+00:00",
|
|
244
|
+
stoppedAt: null,
|
|
245
|
+
startupLogs: null,
|
|
246
|
+
failureReason: null
|
|
378
247
|
};
|
|
379
|
-
|
|
248
|
+
const finishedRun = {
|
|
249
|
+
...base,
|
|
250
|
+
id: "9c0a7e42-31bd-4f88-b6d5-2ea41f907c3b",
|
|
251
|
+
deploymentId: deploymentFixtures.archived.id,
|
|
252
|
+
configVersion: deploymentFixtures.archived.configVersion,
|
|
253
|
+
state: "finished",
|
|
254
|
+
createdAt: "2026-08-10T09:12:44+00:00",
|
|
255
|
+
startedAt: "2026-08-10T09:13:29+00:00",
|
|
256
|
+
stoppedAt: "2026-08-15T11:03:02+00:00",
|
|
257
|
+
startupLogs: null,
|
|
258
|
+
failureReason: null
|
|
259
|
+
};
|
|
260
|
+
/**
|
|
261
|
+
* A classified failure transcribed from canary (AJDA-3140, probe P1). `startedAt` is `null`
|
|
262
|
+
* even though a cause was attributed — the container executed but its startup probe never
|
|
263
|
+
* passed, so a classified failure says nothing about how far the run got.
|
|
264
|
+
*/
|
|
265
|
+
const failedRun = {
|
|
266
|
+
...base,
|
|
267
|
+
id: "ba53f9d0-7c41-4a2e-8f16-d0b9e254a7c6",
|
|
268
|
+
deploymentId: deploymentFixtures.runFailed.id,
|
|
269
|
+
configVersion: deploymentFixtures.runFailed.configVersion,
|
|
270
|
+
state: "failed",
|
|
271
|
+
createdAt: "2026-08-17T09:31:07+00:00",
|
|
272
|
+
startedAt: null,
|
|
273
|
+
stoppedAt: "2026-08-17T09:33:52+00:00",
|
|
274
|
+
startupLogs: "[INFO] Starting app\n[ERROR] App must have keboola-config/nginx/ directory. Missing: /app/keboola-config/nginx\n",
|
|
275
|
+
failureReason: {
|
|
276
|
+
reason: "StartupProbeFailed",
|
|
277
|
+
message: "App must have keboola-config/nginx/ directory. Missing: /app/keboola-config/nginx"
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
/**
|
|
281
|
+
* A run that belongs to the app itself rather than to a deployment — what every run of a
|
|
282
|
+
* `/v1`-created app looks like. `deploymentId: null` is permanent for these, not drift.
|
|
283
|
+
*/
|
|
284
|
+
const legacyRun = {
|
|
285
|
+
...base,
|
|
286
|
+
id: "1d7b4e05-8a92-4c63-b0f7-3e6a5c8192d4",
|
|
287
|
+
deploymentId: null,
|
|
288
|
+
configVersion: "2",
|
|
289
|
+
state: "running",
|
|
290
|
+
createdAt: "2026-08-17T10:02:11+00:00",
|
|
291
|
+
startedAt: "2026-08-17T10:02:51+00:00",
|
|
292
|
+
stoppedAt: null,
|
|
293
|
+
startupLogs: null,
|
|
294
|
+
failureReason: null
|
|
295
|
+
};
|
|
296
|
+
const runFixtures = {
|
|
297
|
+
running: runningRun,
|
|
298
|
+
finished: finishedRun,
|
|
299
|
+
failed: failedRun,
|
|
300
|
+
legacy: legacyRun
|
|
301
|
+
};
|
|
302
|
+
const getAppRun = () => runningRun;
|
|
303
|
+
/**
|
|
304
|
+
* Every run this app has, newest first — the order the endpoint documents, so a consumer that
|
|
305
|
+
* relies on it (`[latest] = runs`) is exercised against data that keeps the promise rather than
|
|
306
|
+
* data that happens to contradict it.
|
|
307
|
+
*/
|
|
308
|
+
const listAppRuns = () => [
|
|
309
|
+
legacyRun,
|
|
310
|
+
failedRun,
|
|
311
|
+
runningRun,
|
|
312
|
+
finishedRun
|
|
313
|
+
];
|
|
314
|
+
//#endregion
|
|
315
|
+
//#region src/clients/developerPortal/apps.ts
|
|
316
|
+
const keboolaVendor = {
|
|
317
|
+
id: "keboola",
|
|
318
|
+
name: "Keboola",
|
|
319
|
+
email: "support@keboola.com",
|
|
320
|
+
address: "Prague, Czech Republic",
|
|
321
|
+
type: "keboola",
|
|
322
|
+
projectUrl: null,
|
|
323
|
+
isTrusted: 1
|
|
324
|
+
};
|
|
325
|
+
const thirdPartyVendor = {
|
|
326
|
+
id: "acme",
|
|
327
|
+
name: "Acme Co.",
|
|
328
|
+
email: "dev@acme.example",
|
|
329
|
+
address: "Springfield",
|
|
330
|
+
projectUrl: "https://connection.keboola.com/admin/projects/1234",
|
|
331
|
+
type: "other",
|
|
332
|
+
isTrusted: 0
|
|
333
|
+
};
|
|
334
|
+
/** The same vendor as `GET /vendors/{vendor}` returns it — `isTrusted` converted to a boolean. */
|
|
335
|
+
const vendorDetail = {
|
|
336
|
+
...thirdPartyVendor,
|
|
337
|
+
isTrusted: false
|
|
338
|
+
};
|
|
339
|
+
const pendingVendor = {
|
|
340
|
+
id: "_v1699999999999",
|
|
341
|
+
name: "Pending Startup",
|
|
342
|
+
email: "hello@pending.example",
|
|
343
|
+
address: "Berlin",
|
|
344
|
+
type: "other",
|
|
345
|
+
projectUrl: null,
|
|
346
|
+
isApproved: false,
|
|
347
|
+
isPublic: false,
|
|
348
|
+
isTrusted: false
|
|
349
|
+
};
|
|
350
|
+
const keboolaAdminVendor = {
|
|
351
|
+
...keboolaVendor,
|
|
352
|
+
isApproved: true,
|
|
353
|
+
isPublic: true,
|
|
354
|
+
isTrusted: true
|
|
355
|
+
};
|
|
356
|
+
const thirdPartyAdminVendor = {
|
|
357
|
+
...thirdPartyVendor,
|
|
358
|
+
isApproved: true,
|
|
359
|
+
isPublic: true,
|
|
360
|
+
isTrusted: false
|
|
361
|
+
};
|
|
362
|
+
const appVendor = (vendor) => ({
|
|
363
|
+
id: vendor.id,
|
|
364
|
+
name: vendor.name,
|
|
365
|
+
address: vendor.address,
|
|
366
|
+
email: vendor.email,
|
|
367
|
+
type: vendor.type
|
|
368
|
+
});
|
|
369
|
+
/** A published, fully-populated extractor — the shape that passes `hasAllFieldsForPublishing`. */
|
|
370
|
+
const publishedExtractor = {
|
|
371
|
+
id: "keboola.ex-db-snowflake",
|
|
372
|
+
vendor: appVendor(keboolaVendor),
|
|
373
|
+
name: "Snowflake",
|
|
374
|
+
type: "extractor",
|
|
375
|
+
shortDescription: "Extract data from Snowflake",
|
|
376
|
+
longDescription: "## Snowflake extractor\n\nExtracts tables from a Snowflake database.",
|
|
377
|
+
licenseUrl: "https://github.com/keboola/ex-db-snowflake/blob/master/LICENSE.md",
|
|
378
|
+
documentationUrl: "https://help.keboola.com/components/extractors/database/snowflake/",
|
|
379
|
+
sourceCodeUrl: "https://github.com/keboola/ex-db-snowflake",
|
|
380
|
+
categories: ["Database"],
|
|
381
|
+
complexity: "easy",
|
|
382
|
+
uiOptions: ["genericDockerUI"],
|
|
383
|
+
defaultBucket: true,
|
|
384
|
+
defaultBucketStage: "in",
|
|
385
|
+
stagingStorageInput: "local",
|
|
386
|
+
stagingStorageOutput: "local",
|
|
387
|
+
logger: "standard",
|
|
388
|
+
isPublic: true,
|
|
389
|
+
isDeprecated: false,
|
|
390
|
+
fees: false,
|
|
391
|
+
repository: {
|
|
392
|
+
type: "ecr",
|
|
393
|
+
uri: "keboola/ex-db-snowflake",
|
|
394
|
+
tag: "1.9.0"
|
|
395
|
+
},
|
|
396
|
+
icon: {
|
|
397
|
+
"64": "https://ui.keboola-assets.com/developer-portal/icons/keboola.ex-db-snowflake/64/1699999999999.png",
|
|
398
|
+
"128": "https://ui.keboola-assets.com/developer-portal/icons/keboola.ex-db-snowflake/128/1699999999999.png"
|
|
399
|
+
},
|
|
400
|
+
version: 12,
|
|
401
|
+
createdBy: "support@keboola.com",
|
|
402
|
+
updatedOn: "2024-06-01T09:00:00+0200",
|
|
403
|
+
uri: "docker/keboola.ex-db-snowflake",
|
|
404
|
+
isPublished: true,
|
|
405
|
+
publishedVersion: 12,
|
|
406
|
+
publishingStatus: "public"
|
|
407
|
+
};
|
|
408
|
+
/** A private third-party app with a pending publishing request. */
|
|
409
|
+
const requestedApp = {
|
|
410
|
+
id: "acme.wr-widgets",
|
|
411
|
+
vendor: appVendor(thirdPartyVendor),
|
|
412
|
+
name: "Widget Writer",
|
|
413
|
+
type: "writer",
|
|
414
|
+
shortDescription: "Write data to Widgets",
|
|
415
|
+
longDescription: "Pushes tables into the Widgets API.",
|
|
416
|
+
licenseUrl: "https://acme.example/license",
|
|
417
|
+
documentationUrl: "https://acme.example/docs",
|
|
418
|
+
uiOptions: ["genericDockerUI"],
|
|
419
|
+
repository: {
|
|
420
|
+
type: "quay",
|
|
421
|
+
uri: "acme/wr-widgets",
|
|
422
|
+
tag: "0.3.1"
|
|
423
|
+
},
|
|
424
|
+
icon: {
|
|
425
|
+
"64": "https://ui.keboola-assets.com/developer-portal/icons/acme.wr-widgets/64/1699999999998.png",
|
|
426
|
+
"128": "https://ui.keboola-assets.com/developer-portal/icons/acme.wr-widgets/128/1699999999998.png"
|
|
427
|
+
},
|
|
428
|
+
isPublic: false,
|
|
429
|
+
isDeprecated: false,
|
|
430
|
+
version: 3,
|
|
431
|
+
createdBy: "dev@acme.example",
|
|
432
|
+
updatedOn: "2024-05-20T14:12:00+0200",
|
|
433
|
+
uri: "docker/acme.wr-widgets",
|
|
434
|
+
isPublished: false,
|
|
435
|
+
publishingStatus: "requested",
|
|
436
|
+
publishingRequest: {
|
|
437
|
+
createdOn: "2024-05-20T14:12:00+0200",
|
|
438
|
+
rejectionReason: null
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
/** A rejected app — carries the reason the vendor sees on its detail page. */
|
|
442
|
+
const rejectedApp = {
|
|
443
|
+
id: "acme.app-analyzer",
|
|
444
|
+
vendor: appVendor(thirdPartyVendor),
|
|
445
|
+
name: "Analyzer",
|
|
446
|
+
type: "application",
|
|
447
|
+
shortDescription: "Analyze things",
|
|
448
|
+
isPublic: false,
|
|
449
|
+
isDeprecated: false,
|
|
450
|
+
version: 1,
|
|
451
|
+
createdBy: "dev@acme.example",
|
|
452
|
+
uri: "docker/acme.app-analyzer",
|
|
453
|
+
isPublished: false,
|
|
454
|
+
publishingStatus: "rejected",
|
|
455
|
+
publishingRequest: {
|
|
456
|
+
createdOn: "2024-04-02T11:00:00+0200",
|
|
457
|
+
rejectionReason: "Documentation URL is missing and the icon is not 256×256."
|
|
458
|
+
}
|
|
459
|
+
};
|
|
460
|
+
/** A deprecated app with an expiry date and a suggested replacement. */
|
|
461
|
+
const deprecatedApp = {
|
|
462
|
+
id: "keboola.ex-legacy",
|
|
463
|
+
vendor: appVendor(keboolaVendor),
|
|
464
|
+
name: "Legacy Extractor",
|
|
465
|
+
type: "extractor",
|
|
466
|
+
shortDescription: "Superseded",
|
|
467
|
+
isPublic: true,
|
|
468
|
+
isDeprecated: true,
|
|
469
|
+
expiredOn: "2025-01-01",
|
|
470
|
+
replacementApp: "keboola.ex-db-snowflake",
|
|
471
|
+
version: 40,
|
|
472
|
+
uri: "docker/keboola.ex-legacy",
|
|
473
|
+
isPublished: true,
|
|
474
|
+
publishedVersion: 38,
|
|
475
|
+
publishingStatus: "public"
|
|
476
|
+
};
|
|
477
|
+
/**
|
|
478
|
+
* A `data-app`, the type whose edit form hides ~14 fields. Deliberately minimal: a fixture carrying
|
|
479
|
+
* `configurationSchema` or `actions` here would misrepresent what the form can produce.
|
|
480
|
+
*/
|
|
481
|
+
const dataApp = {
|
|
482
|
+
id: "acme.data-app-dashboard",
|
|
483
|
+
vendor: appVendor(thirdPartyVendor),
|
|
484
|
+
name: "Dashboard",
|
|
485
|
+
type: "data-app",
|
|
486
|
+
shortDescription: "A Streamlit dashboard",
|
|
487
|
+
isPublic: false,
|
|
488
|
+
isDeprecated: false,
|
|
489
|
+
version: 2,
|
|
490
|
+
uri: "docker/acme.data-app-dashboard",
|
|
491
|
+
isPublished: false,
|
|
492
|
+
publishingStatus: "private"
|
|
493
|
+
};
|
|
494
|
+
/** A `code-pattern`, whose `configurationSchema.supported_components` must be a non-empty array. */
|
|
495
|
+
const codePatternApp = {
|
|
496
|
+
id: "acme.code-pattern-etl",
|
|
497
|
+
vendor: appVendor(thirdPartyVendor),
|
|
498
|
+
name: "ETL Pattern",
|
|
499
|
+
type: "code-pattern",
|
|
500
|
+
shortDescription: "Generates ETL code",
|
|
501
|
+
actions: ["generate"],
|
|
502
|
+
configurationSchema: { supported_components: ["keboola.snowflake-transformation"] },
|
|
503
|
+
isPublic: false,
|
|
504
|
+
version: 1,
|
|
505
|
+
uri: "docker/acme.code-pattern-etl",
|
|
506
|
+
isPublished: false,
|
|
507
|
+
publishingStatus: "private"
|
|
508
|
+
};
|
|
509
|
+
/**
|
|
510
|
+
* An app typed `other`. The public catalog excludes it entirely, so it exists to prove that
|
|
511
|
+
* exclusion rather than to be rendered.
|
|
512
|
+
*/
|
|
513
|
+
const otherTypeApp = {
|
|
514
|
+
id: "acme.misc-thing",
|
|
515
|
+
vendor: appVendor(thirdPartyVendor),
|
|
516
|
+
name: "Misc Thing",
|
|
517
|
+
type: "other",
|
|
518
|
+
isPublic: true,
|
|
519
|
+
version: 1,
|
|
520
|
+
uri: "docker/acme.misc-thing",
|
|
521
|
+
isPublished: true,
|
|
522
|
+
publishedVersion: 1,
|
|
523
|
+
publishingStatus: "public"
|
|
524
|
+
};
|
|
525
|
+
const humanUser = {
|
|
526
|
+
username: "dev@acme.example",
|
|
527
|
+
name: "Dev Eloper",
|
|
528
|
+
vendors: ["acme"],
|
|
529
|
+
createdOn: "2024-01-10T08:00:00+0100"
|
|
530
|
+
};
|
|
531
|
+
/** A recently added member, for a test that orders the list by `createdOn`. */
|
|
532
|
+
const newestUser = {
|
|
533
|
+
username: "new@acme.example",
|
|
534
|
+
name: "New Hire",
|
|
535
|
+
vendors: ["acme"],
|
|
536
|
+
createdOn: "2024-06-25T08:00:00+0200"
|
|
537
|
+
};
|
|
538
|
+
/** A member of no vendor — reachable only through the admin list. */
|
|
539
|
+
const vendorlessUser = {
|
|
540
|
+
username: "gone@acme.example",
|
|
541
|
+
name: "Alan Gone",
|
|
542
|
+
vendors: [],
|
|
543
|
+
createdOn: "2023-02-01T08:00:00+0100"
|
|
544
|
+
};
|
|
545
|
+
/** A Keboola staff member — eligible for "make admin" because they belong to the `keboola` vendor. */
|
|
546
|
+
const keboolaStaffUser = {
|
|
547
|
+
username: "staff@keboola.com",
|
|
548
|
+
name: "Kai Staff",
|
|
549
|
+
vendors: ["keboola"],
|
|
550
|
+
createdOn: "2023-09-14T08:00:00+0200"
|
|
551
|
+
};
|
|
552
|
+
/** A freshly created service account, including the one-time `password`. */
|
|
553
|
+
const newServiceAccount = {
|
|
554
|
+
username: "acme+ci",
|
|
555
|
+
description: "CI deploy pipeline",
|
|
556
|
+
createdOn: "2024-07-01T10:00:00+0200",
|
|
557
|
+
password: "one-time-secret-shown-once"
|
|
558
|
+
};
|
|
559
|
+
/** The same account as later listed — note there is no `password`; it is unreadable after creation. */
|
|
560
|
+
const existingServiceAccount = {
|
|
561
|
+
username: "acme+release",
|
|
562
|
+
description: "Release automation",
|
|
563
|
+
createdOn: "2024-03-11T10:00:00+0100"
|
|
564
|
+
};
|
|
565
|
+
const appChange = {
|
|
566
|
+
appId: "acme.wr-widgets",
|
|
567
|
+
createdOn: "2024-05-20T14:12:00+0200",
|
|
568
|
+
createdBy: "dev@acme.example",
|
|
569
|
+
changes: [{
|
|
570
|
+
attribute: "shortDescription",
|
|
571
|
+
oldValue: "Writes widgets",
|
|
572
|
+
newValue: "Write data to Widgets"
|
|
573
|
+
}, {
|
|
574
|
+
attribute: "repository",
|
|
575
|
+
oldValue: {
|
|
576
|
+
type: "quay",
|
|
577
|
+
uri: "acme/wr-widgets",
|
|
578
|
+
tag: "0.3.0"
|
|
579
|
+
},
|
|
580
|
+
newValue: {
|
|
581
|
+
type: "quay",
|
|
582
|
+
uri: "acme/wr-widgets",
|
|
583
|
+
tag: "0.3.1"
|
|
584
|
+
}
|
|
585
|
+
}]
|
|
586
|
+
};
|
|
587
|
+
/** The public catalog list: published, non-`other` apps only. */
|
|
588
|
+
const listPublishedApps = () => [publishedExtractor, deprecatedApp];
|
|
589
|
+
/** A vendor's own apps, across every publishing state the table renders. */
|
|
590
|
+
const listVendorApps = () => [
|
|
591
|
+
requestedApp,
|
|
592
|
+
rejectedApp,
|
|
593
|
+
dataApp,
|
|
594
|
+
codePatternApp
|
|
595
|
+
];
|
|
596
|
+
/** The admin list — every vendor, plus the `other`-typed app the public catalog drops. */
|
|
597
|
+
const listAllApps = () => [
|
|
598
|
+
publishedExtractor,
|
|
599
|
+
requestedApp,
|
|
600
|
+
rejectedApp,
|
|
601
|
+
deprecatedApp,
|
|
602
|
+
dataApp,
|
|
603
|
+
codePatternApp,
|
|
604
|
+
otherTypeApp
|
|
605
|
+
];
|
|
606
|
+
/** `GET /vendors` — approved and public only, so the pending vendor cannot appear here. */
|
|
607
|
+
const listVendors = () => [keboolaVendor, thirdPartyVendor];
|
|
608
|
+
/** `GET /vendors/{vendor}` — the converted shape. */
|
|
609
|
+
const getVendor = () => vendorDetail;
|
|
610
|
+
/** `GET /admin/vendors` — every vendor, and the only response carrying the approval flags. */
|
|
611
|
+
const listAllVendors = () => [
|
|
612
|
+
keboolaAdminVendor,
|
|
613
|
+
thirdPartyAdminVendor,
|
|
614
|
+
pendingVendor
|
|
615
|
+
];
|
|
616
|
+
const listUsers = () => [
|
|
617
|
+
humanUser,
|
|
618
|
+
newestUser,
|
|
619
|
+
vendorlessUser,
|
|
620
|
+
keboolaStaffUser
|
|
621
|
+
];
|
|
622
|
+
const listServiceAccounts = () => [existingServiceAccount];
|
|
623
|
+
const listAppChanges = () => [appChange];
|
|
624
|
+
/** Named fixtures, for a test that needs one specific state. */
|
|
625
|
+
const developerPortalFixtures = {
|
|
626
|
+
apps: {
|
|
627
|
+
published: publishedExtractor,
|
|
628
|
+
requested: requestedApp,
|
|
629
|
+
rejected: rejectedApp,
|
|
630
|
+
deprecated: deprecatedApp,
|
|
631
|
+
dataApp,
|
|
632
|
+
codePattern: codePatternApp,
|
|
633
|
+
otherType: otherTypeApp
|
|
634
|
+
},
|
|
635
|
+
vendors: {
|
|
636
|
+
keboola: keboolaVendor,
|
|
637
|
+
thirdParty: thirdPartyVendor,
|
|
638
|
+
detail: vendorDetail,
|
|
639
|
+
pending: pendingVendor,
|
|
640
|
+
keboolaAdmin: keboolaAdminVendor,
|
|
641
|
+
thirdPartyAdmin: thirdPartyAdminVendor
|
|
642
|
+
},
|
|
643
|
+
users: {
|
|
644
|
+
human: humanUser,
|
|
645
|
+
newest: newestUser,
|
|
646
|
+
vendorless: vendorlessUser,
|
|
647
|
+
keboolaStaff: keboolaStaffUser
|
|
648
|
+
},
|
|
649
|
+
serviceAccounts: {
|
|
650
|
+
created: newServiceAccount,
|
|
651
|
+
existing: existingServiceAccount
|
|
652
|
+
},
|
|
653
|
+
changes: { single: appChange }
|
|
654
|
+
};
|
|
655
|
+
//#endregion
|
|
656
|
+
//#region src/clients/storage/tables.ts
|
|
657
|
+
const bucket = {
|
|
658
|
+
id: "in.c-main",
|
|
659
|
+
name: "c-main",
|
|
660
|
+
displayName: "Main",
|
|
661
|
+
stage: "in",
|
|
662
|
+
description: "Main input bucket",
|
|
663
|
+
created: "2024-01-15T10:00:00+0100",
|
|
664
|
+
lastChangeDate: "2024-03-10T08:30:00+0100",
|
|
665
|
+
isMaintenance: false,
|
|
666
|
+
isReadOnly: false,
|
|
667
|
+
isSnowflakeSharedDatabase: false,
|
|
668
|
+
hasExternalSchema: false,
|
|
669
|
+
rowsCount: 15e4,
|
|
670
|
+
dataSizeBytes: 52428800,
|
|
671
|
+
uri: "https://connection.keboola.com/v2/storage/buckets/in.c-main",
|
|
672
|
+
backend: "snowflake",
|
|
673
|
+
backendPath: [],
|
|
674
|
+
databaseName: null,
|
|
675
|
+
color: null,
|
|
676
|
+
idBranch: 0,
|
|
677
|
+
owner: null,
|
|
678
|
+
sharing: null,
|
|
679
|
+
path: "in.c-main",
|
|
680
|
+
tables: "https://connection.keboola.com/v2/storage/buckets/in.c-main/tables",
|
|
681
|
+
updated: "2024-03-10T08:30:00+0100"
|
|
682
|
+
};
|
|
683
|
+
const freshTable = {
|
|
684
|
+
id: "in.c-main.users",
|
|
685
|
+
name: "users",
|
|
686
|
+
displayName: "Users",
|
|
687
|
+
primaryKey: ["id"],
|
|
688
|
+
metadata: [],
|
|
689
|
+
columns: [
|
|
690
|
+
"id",
|
|
691
|
+
"email",
|
|
692
|
+
"name",
|
|
693
|
+
"created_at"
|
|
694
|
+
],
|
|
695
|
+
columnMetadata: {},
|
|
696
|
+
attributes: [],
|
|
697
|
+
bucket,
|
|
698
|
+
isTyped: false,
|
|
699
|
+
isAlias: false
|
|
700
|
+
};
|
|
701
|
+
const recentlyUpdatedTable = {
|
|
702
|
+
id: "in.c-main.orders",
|
|
703
|
+
name: "orders",
|
|
704
|
+
displayName: "Orders",
|
|
705
|
+
primaryKey: ["order_id"],
|
|
706
|
+
metadata: [{
|
|
707
|
+
id: "mt1",
|
|
708
|
+
key: "KBC.createdBy.component.id",
|
|
709
|
+
value: "keboola.python-transformation",
|
|
710
|
+
provider: "keboola",
|
|
711
|
+
timestamp: "2024-06-01T09:00:00+0200"
|
|
712
|
+
}],
|
|
713
|
+
columns: [
|
|
714
|
+
"order_id",
|
|
715
|
+
"user_id",
|
|
716
|
+
"total",
|
|
717
|
+
"status",
|
|
718
|
+
"created_at",
|
|
719
|
+
"updated_at"
|
|
720
|
+
],
|
|
721
|
+
columnMetadata: { order_id: [{
|
|
722
|
+
id: "m1",
|
|
723
|
+
key: "KBC.datatype.type",
|
|
724
|
+
value: "INTEGER",
|
|
725
|
+
provider: "keboola",
|
|
726
|
+
timestamp: "2024-06-01T09:00:00+0200"
|
|
727
|
+
}] },
|
|
728
|
+
attributes: [],
|
|
729
|
+
bucket,
|
|
730
|
+
isTyped: false,
|
|
731
|
+
isAlias: false
|
|
732
|
+
};
|
|
733
|
+
const largeTable = {
|
|
734
|
+
id: "in.c-main.events",
|
|
735
|
+
name: "events",
|
|
736
|
+
displayName: "Events",
|
|
737
|
+
primaryKey: [],
|
|
738
|
+
metadata: [],
|
|
739
|
+
columns: [
|
|
740
|
+
"event_id",
|
|
741
|
+
"user_id",
|
|
742
|
+
"event_type",
|
|
743
|
+
"properties",
|
|
744
|
+
"occurred_at"
|
|
745
|
+
],
|
|
746
|
+
columnMetadata: {},
|
|
747
|
+
attributes: [],
|
|
748
|
+
bucket,
|
|
749
|
+
isTyped: false,
|
|
750
|
+
isAlias: false
|
|
751
|
+
};
|
|
752
|
+
/**
|
|
753
|
+
* Returns a single realistic typed TableDetail (fresh, no imports yet).
|
|
754
|
+
*
|
|
755
|
+
* The explicit return type ensures any divergence from the OpenAPI-derived
|
|
756
|
+
* `TableDetail` in `@keboola/api-client` surfaces as a TypeScript error.
|
|
757
|
+
*/
|
|
758
|
+
const getTable = () => freshTable;
|
|
759
|
+
/**
|
|
760
|
+
* Returns three TableDetail objects representing different lifecycle states:
|
|
761
|
+
* 1. Fresh — just created, no data imported.
|
|
762
|
+
* 2. Recently updated — moderate size, recent import.
|
|
763
|
+
* 3. Large — high row count, large byte size.
|
|
764
|
+
*/
|
|
765
|
+
const listTables = () => [
|
|
766
|
+
freshTable,
|
|
767
|
+
recentlyUpdatedTable,
|
|
768
|
+
largeTable
|
|
769
|
+
];
|
|
770
|
+
/**
|
|
771
|
+
* Named fixtures for targeted access in tests.
|
|
772
|
+
*/
|
|
773
|
+
const tableFixtures = {
|
|
774
|
+
fresh: freshTable,
|
|
775
|
+
recentlyUpdated: recentlyUpdatedTable,
|
|
776
|
+
large: largeTable
|
|
777
|
+
};
|
|
778
|
+
//#endregion
|
|
779
|
+
//#region src/fixtures.ts
|
|
780
|
+
const fixtures = {
|
|
781
|
+
storage: { tables: {
|
|
782
|
+
getTable,
|
|
783
|
+
listTables,
|
|
784
|
+
fixtures: tableFixtures
|
|
785
|
+
} },
|
|
786
|
+
apps: {
|
|
787
|
+
apps: {
|
|
788
|
+
getApp,
|
|
789
|
+
listApps,
|
|
790
|
+
fixtures: appFixtures
|
|
791
|
+
},
|
|
792
|
+
deployments: {
|
|
793
|
+
getDeployment,
|
|
794
|
+
listDeployments,
|
|
795
|
+
fixtures: deploymentFixtures
|
|
796
|
+
},
|
|
797
|
+
runs: {
|
|
798
|
+
getAppRun,
|
|
799
|
+
listAppRuns,
|
|
800
|
+
fixtures: runFixtures
|
|
801
|
+
}
|
|
802
|
+
},
|
|
803
|
+
developerPortal: {
|
|
804
|
+
listPublishedApps,
|
|
805
|
+
listVendorApps,
|
|
806
|
+
listAllApps,
|
|
807
|
+
listAllVendors,
|
|
808
|
+
getVendor,
|
|
809
|
+
listVendors,
|
|
810
|
+
listUsers,
|
|
811
|
+
listServiceAccounts,
|
|
812
|
+
listAppChanges,
|
|
813
|
+
fixtures: developerPortalFixtures
|
|
814
|
+
}
|
|
815
|
+
};
|
|
816
|
+
//#endregion
|
|
380
817
|
exports.appFixtures = appFixtures;
|
|
381
818
|
exports.deploymentFixtures = deploymentFixtures;
|
|
819
|
+
exports.developerPortalFixtures = developerPortalFixtures;
|
|
382
820
|
exports.fixtures = fixtures;
|
|
383
821
|
exports.getApp = getApp;
|
|
384
822
|
exports.getAppRun = getAppRun;
|
|
385
823
|
exports.getDeployment = getDeployment;
|
|
386
824
|
exports.getTable = getTable;
|
|
825
|
+
exports.getVendor = getVendor;
|
|
826
|
+
exports.listAllApps = listAllApps;
|
|
827
|
+
exports.listAllVendors = listAllVendors;
|
|
828
|
+
exports.listAppChanges = listAppChanges;
|
|
387
829
|
exports.listAppRuns = listAppRuns;
|
|
388
830
|
exports.listApps = listApps;
|
|
389
831
|
exports.listDeployments = listDeployments;
|
|
832
|
+
exports.listPublishedApps = listPublishedApps;
|
|
833
|
+
exports.listServiceAccounts = listServiceAccounts;
|
|
390
834
|
exports.listTables = listTables;
|
|
835
|
+
exports.listUsers = listUsers;
|
|
836
|
+
exports.listVendorApps = listVendorApps;
|
|
837
|
+
exports.listVendors = listVendors;
|
|
391
838
|
exports.runFixtures = runFixtures;
|
|
392
839
|
exports.tableFixtures = tableFixtures;
|
|
393
|
-
|
|
840
|
+
|
|
394
841
|
//# sourceMappingURL=index.cjs.map
|