@keboola/api-fixtures 26.0.0 → 27.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/AGENTS.md +13 -7
- package/CHANGELOG.md +32 -0
- package/dist/index.cjs +139 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +62 -2
- package/dist/index.d.ts +62 -2
- package/dist/index.js +136 -7
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/AGENTS.md
CHANGED
|
@@ -11,6 +11,10 @@ becomes a TypeScript compile error.
|
|
|
11
11
|
|
|
12
12
|
Current slices:
|
|
13
13
|
|
|
14
|
+
- `storage.bootstrap` — `getStackInfo()`, `verifyStorageToken()`, `getDevBranches()`, the three
|
|
15
|
+
responses a client's ready gate needs before it is usable. Reach for it in any test that builds a
|
|
16
|
+
real client over MSW. `getStackInfo()` announces every service by default, which is what keeps a
|
|
17
|
+
test's service clients from being dummies that throw `ServiceUnavailableError`.
|
|
14
18
|
- `storage.tables` — `getTable()`, `listTables()`, `tableFixtures`
|
|
15
19
|
- `apps.apps` / `apps.deployments` / `apps.runs` — the sandboxes-service `/v2` App Deployments
|
|
16
20
|
surface. The three compose into one coherent app (an app's `production` names a deployment in
|
|
@@ -19,11 +23,11 @@ Current slices:
|
|
|
19
23
|
|
|
20
24
|
## When to use fixtures vs MSW vs real API
|
|
21
25
|
|
|
22
|
-
| Need
|
|
23
|
-
|
|
|
24
|
-
| Unit / component tests, pure rendering
|
|
25
|
-
|
|
|
26
|
-
| Full end-to-end or contract validation
|
|
26
|
+
| Need | Reach for |
|
|
27
|
+
| -------------------------------------------- | ---------------------------------------------- |
|
|
28
|
+
| Unit / component tests, pure rendering | **This package** — zero network, deterministic |
|
|
29
|
+
| Anything exercising a client or a query hook | **MSW handlers, bodies from this package** |
|
|
30
|
+
| Full end-to-end or contract validation | Real API (see `@keboola/e2e-testing`) |
|
|
27
31
|
|
|
28
32
|
## Adding a new endpoint slice
|
|
29
33
|
|
|
@@ -34,9 +38,11 @@ Current slices:
|
|
|
34
38
|
yourself; `unknown` is acceptable only when it propagates from the contract type (e.g.
|
|
35
39
|
`TableDetail['attributes']` is `unknown[]`). Prefer `T['prop']` aliases or contextual
|
|
36
40
|
typing via `satisfies T` over re-asserting the upstream type.
|
|
37
|
-
4.
|
|
41
|
+
4. When the slice has distinct variants worth naming (a fresh vs. a large table, a failed vs. a
|
|
42
|
+
running job), export them as a `<resource>Fixtures` object using
|
|
38
43
|
`satisfies Record<'<key1>' | '<key2>' | …, T>` so missing or renamed keys become a
|
|
39
|
-
compile-time error.
|
|
44
|
+
compile-time error. A slice whose factories each return one canonical shape needs no such
|
|
45
|
+
object — it would only alias their defaults.
|
|
40
46
|
5. Re-export everything from `src/index.ts`.
|
|
41
47
|
6. Add a vitest smoke test in `<resource>.test.ts` that verifies shape + assigns to the
|
|
42
48
|
typed variable (compile-time contract check).
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# @keboola/api-fixtures
|
|
2
2
|
|
|
3
|
+
## 27.0.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Add a `storage.bootstrap` fixture slice — the three responses a client's ready gate needs before
|
|
8
|
+
it is usable (`GET /v2/storage`, `/v2/storage/tokens/verify`, `/v2/storage/dev-branches`).
|
|
9
|
+
|
|
10
|
+
`getStackInfo()`, `verifyStorageToken()` and `getDevBranches()` are typed by
|
|
11
|
+
`@keboola/api-client/storage/types`, so a field the backend adds arrives with `pnpm gen:types`
|
|
12
|
+
rather than being transcribed into every MSW test that bootstraps a client. `getStackInfo()`
|
|
13
|
+
announces every service by default, which is what keeps a test's queue / data-science / vault
|
|
14
|
+
client from being a dummy that throws `ServiceUnavailableError`; pass `services` to narrow it.
|
|
15
|
+
|
|
16
|
+
`@keboola/api-client` gains a runtime `ServiceId` const in `@keboola/api-client/constants`, with
|
|
17
|
+
the `ServiceId` type now derived from it. Announcing every service is exhaustive by construction:
|
|
18
|
+
a service added to the client flows into the fixture without an edit.
|
|
19
|
+
|
|
20
|
+
`@keboola/api-client-react`'s test fixtures now come from the slice; its published output is unchanged.
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- The fixtures-vs-MSW decision table routed everything but "integration tests" away from MSW, which
|
|
25
|
+
read as "unit and component tests never intercept requests". A test whose subject is a client or a
|
|
26
|
+
query hook has to, or it asserts its own mock — so that row now names clients and query hooks, and
|
|
27
|
+
says bodies come from this package where a slice exists and `satisfies` the generated type where one
|
|
28
|
+
does not.
|
|
29
|
+
|
|
30
|
+
`AGENTS.md` ships in the tarball, so this is a republish rather than a repo-only doc edit.
|
|
31
|
+
|
|
32
|
+
- Updated dependencies:
|
|
33
|
+
- @keboola/api-client@32.0.0
|
|
34
|
+
|
|
3
35
|
## 26.0.0
|
|
4
36
|
|
|
5
37
|
### Patch Changes
|
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
let _keboola_api_client_constants = require("@keboola/api-client/constants");
|
|
2
3
|
//#region src/clients/apps/deployments.ts
|
|
3
4
|
/**
|
|
4
5
|
* Deployment ids are the deterministic Kubernetes CR name — `app-{appId}-dpl-{hash}` —
|
|
@@ -653,6 +654,125 @@ const developerPortalFixtures = {
|
|
|
653
654
|
changes: { single: appChange }
|
|
654
655
|
};
|
|
655
656
|
//#endregion
|
|
657
|
+
//#region src/clients/storage/bootstrap.ts
|
|
658
|
+
/** The stack an MSW-backed test points its client at, unless a caller passes its own. */
|
|
659
|
+
const DEFAULT_BASE_URL = "https://connection.test";
|
|
660
|
+
/**
|
|
661
|
+
* The stack index `GET /v2/storage` returns.
|
|
662
|
+
*
|
|
663
|
+
* - Announces every `ServiceId` by default, each on its own host, so no service client is a dummy
|
|
664
|
+
* that throws `ServiceUnavailableError` — a test for a queue / data-science / vault hook only
|
|
665
|
+
* adds its handler.
|
|
666
|
+
* - Defaulting to `Object.values(ServiceId)` is what keeps that exhaustive: a service added to the
|
|
667
|
+
* client arrives here without an edit.
|
|
668
|
+
*/
|
|
669
|
+
const getStackInfo = ({ baseUrl = DEFAULT_BASE_URL, services = Object.values(_keboola_api_client_constants.ServiceId) } = {}) => {
|
|
670
|
+
const { host } = new URL(baseUrl);
|
|
671
|
+
return {
|
|
672
|
+
api: host,
|
|
673
|
+
documentation: "https://developers.keboola.com",
|
|
674
|
+
host,
|
|
675
|
+
revision: "test-revision",
|
|
676
|
+
stack: "test-stack",
|
|
677
|
+
version: "test-version",
|
|
678
|
+
urlTemplates: { orchestrationJob: "" },
|
|
679
|
+
services: services.map((id) => ({
|
|
680
|
+
id,
|
|
681
|
+
url: `https://${id}.${host}`
|
|
682
|
+
})),
|
|
683
|
+
components: [],
|
|
684
|
+
features: []
|
|
685
|
+
};
|
|
686
|
+
};
|
|
687
|
+
/**
|
|
688
|
+
* The verified master token `GET /v2/storage/tokens/verify` returns.
|
|
689
|
+
*
|
|
690
|
+
* - Complete on purpose: `api.context.project.sapiToken` is this object verbatim and hooks read deep
|
|
691
|
+
* into it (`owner.id`, `admin.role`, `adminOwner.email`), so a partial body surfaces as
|
|
692
|
+
* `undefined`s far from the test that caused them.
|
|
693
|
+
* - Every permission flag is granted; a test needing a restricted token overrides the handler.
|
|
694
|
+
*/
|
|
695
|
+
const verifyStorageToken = ({ baseUrl = DEFAULT_BASE_URL, features = [] } = {}) => ({
|
|
696
|
+
id: "token-1",
|
|
697
|
+
created: "2024-01-01T00:00:00Z",
|
|
698
|
+
refreshed: "2024-01-01T00:00:00Z",
|
|
699
|
+
description: "Test token",
|
|
700
|
+
uri: baseUrl,
|
|
701
|
+
isMasterToken: true,
|
|
702
|
+
canManageBuckets: true,
|
|
703
|
+
canManageTokens: true,
|
|
704
|
+
canReadAllFileUploads: true,
|
|
705
|
+
canPurgeTrash: true,
|
|
706
|
+
canManageProtectedDefaultBranch: true,
|
|
707
|
+
canCreateJobs: true,
|
|
708
|
+
canReadAllProjectEvents: true,
|
|
709
|
+
canManageDevBranches: true,
|
|
710
|
+
creatorToken: {
|
|
711
|
+
id: 42,
|
|
712
|
+
description: "Test token"
|
|
713
|
+
},
|
|
714
|
+
expires: null,
|
|
715
|
+
isExpired: false,
|
|
716
|
+
isDisabled: false,
|
|
717
|
+
isBYODB: false,
|
|
718
|
+
dailyCapacity: 1e3,
|
|
719
|
+
bucketPermissions: {},
|
|
720
|
+
owner: {
|
|
721
|
+
id: 42,
|
|
722
|
+
name: "Test Project",
|
|
723
|
+
type: "project",
|
|
724
|
+
region: "us-east-1",
|
|
725
|
+
created: "2024-01-01T00:00:00Z",
|
|
726
|
+
expires: null,
|
|
727
|
+
features,
|
|
728
|
+
dataSizeBytes: 0,
|
|
729
|
+
rowsCount: 0,
|
|
730
|
+
hasMysql: false,
|
|
731
|
+
hasSynapse: false,
|
|
732
|
+
hasRedshift: false,
|
|
733
|
+
hasSnowflake: true,
|
|
734
|
+
hasExasol: false,
|
|
735
|
+
hasTeradata: false,
|
|
736
|
+
hasBigquery: false,
|
|
737
|
+
defaultBackend: "snowflake",
|
|
738
|
+
hasTryModeOn: "false",
|
|
739
|
+
limits: {},
|
|
740
|
+
metrics: {},
|
|
741
|
+
isDisabled: false,
|
|
742
|
+
billedMonthlyPrice: null,
|
|
743
|
+
dataRetentionTimeInDays: 30,
|
|
744
|
+
assignedBackends: ["snowflake"],
|
|
745
|
+
fileStorageProvider: "s3"
|
|
746
|
+
},
|
|
747
|
+
organization: { id: "org-1" },
|
|
748
|
+
admin: {
|
|
749
|
+
id: 100,
|
|
750
|
+
name: "Admin User",
|
|
751
|
+
features: [],
|
|
752
|
+
isOrganizationMember: true,
|
|
753
|
+
role: "admin"
|
|
754
|
+
},
|
|
755
|
+
adminOwner: {
|
|
756
|
+
id: 200,
|
|
757
|
+
name: "Owner User",
|
|
758
|
+
email: "owner@example.com"
|
|
759
|
+
}
|
|
760
|
+
});
|
|
761
|
+
/**
|
|
762
|
+
* The branch list `GET /v2/storage/dev-branches` returns — the default branch alone.
|
|
763
|
+
*
|
|
764
|
+
* - `context.defaultBranch` is read off it, so the entry must stay `isDefault: true`.
|
|
765
|
+
* - The default branch has no creator, which `DevBranch` models as an empty `creatorToken`.
|
|
766
|
+
*/
|
|
767
|
+
const getDevBranches = () => [{
|
|
768
|
+
id: 1,
|
|
769
|
+
name: "Main",
|
|
770
|
+
description: "",
|
|
771
|
+
isDefault: true,
|
|
772
|
+
created: "2024-01-01T00:00:00Z",
|
|
773
|
+
creatorToken: []
|
|
774
|
+
}];
|
|
775
|
+
//#endregion
|
|
656
776
|
//#region src/clients/storage/tables.ts
|
|
657
777
|
const bucket = {
|
|
658
778
|
id: "in.c-main",
|
|
@@ -678,7 +798,9 @@ const bucket = {
|
|
|
678
798
|
sharing: null,
|
|
679
799
|
path: "in.c-main",
|
|
680
800
|
tables: "https://connection.keboola.com/v2/storage/buckets/in.c-main/tables",
|
|
681
|
-
updated: "2024-03-10T08:30:00+0100"
|
|
801
|
+
updated: "2024-03-10T08:30:00+0100",
|
|
802
|
+
isLinkedBucket: false,
|
|
803
|
+
bucketSharingAllowed: true
|
|
682
804
|
};
|
|
683
805
|
const freshTable = {
|
|
684
806
|
id: "in.c-main.users",
|
|
@@ -778,11 +900,18 @@ const tableFixtures = {
|
|
|
778
900
|
//#endregion
|
|
779
901
|
//#region src/fixtures.ts
|
|
780
902
|
const fixtures = {
|
|
781
|
-
storage: {
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
903
|
+
storage: {
|
|
904
|
+
bootstrap: {
|
|
905
|
+
getStackInfo,
|
|
906
|
+
verifyStorageToken,
|
|
907
|
+
getDevBranches
|
|
908
|
+
},
|
|
909
|
+
tables: {
|
|
910
|
+
getTable,
|
|
911
|
+
listTables,
|
|
912
|
+
fixtures: tableFixtures
|
|
913
|
+
}
|
|
914
|
+
},
|
|
786
915
|
apps: {
|
|
787
916
|
apps: {
|
|
788
917
|
getApp,
|
|
@@ -814,6 +943,7 @@ const fixtures = {
|
|
|
814
943
|
}
|
|
815
944
|
};
|
|
816
945
|
//#endregion
|
|
946
|
+
exports.DEFAULT_BASE_URL = DEFAULT_BASE_URL;
|
|
817
947
|
exports.appFixtures = appFixtures;
|
|
818
948
|
exports.deploymentFixtures = deploymentFixtures;
|
|
819
949
|
exports.developerPortalFixtures = developerPortalFixtures;
|
|
@@ -821,6 +951,8 @@ exports.fixtures = fixtures;
|
|
|
821
951
|
exports.getApp = getApp;
|
|
822
952
|
exports.getAppRun = getAppRun;
|
|
823
953
|
exports.getDeployment = getDeployment;
|
|
954
|
+
exports.getDevBranches = getDevBranches;
|
|
955
|
+
exports.getStackInfo = getStackInfo;
|
|
824
956
|
exports.getTable = getTable;
|
|
825
957
|
exports.getVendor = getVendor;
|
|
826
958
|
exports.listAllApps = listAllApps;
|
|
@@ -837,5 +969,6 @@ exports.listVendorApps = listVendorApps;
|
|
|
837
969
|
exports.listVendors = listVendors;
|
|
838
970
|
exports.runFixtures = runFixtures;
|
|
839
971
|
exports.tableFixtures = tableFixtures;
|
|
972
|
+
exports.verifyStorageToken = verifyStorageToken;
|
|
840
973
|
|
|
841
974
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["base"],"sources":["../src/clients/apps/deployments.ts","../src/clients/apps/apps.ts","../src/clients/apps/runs.ts","../src/clients/developerPortal/apps.ts","../src/clients/storage/tables.ts","../src/fixtures.ts"],"sourcesContent":["import type { Deployment } from '@keboola/api-client/apps/types';\n\n/**\n * Deployment ids are the deterministic Kubernetes CR name — `app-{appId}-dpl-{hash}` —\n * so they are reproduced in that shape rather than as opaque strings.\n */\nexport const APP_ID = '374811';\n\nconst deploymentId = (hash: string) => `app-${APP_ID}-dpl-${hash}`;\n\n// Retired: the row outlives its CR, so it stays in history with `archived: true`.\nconst archivedDeployment = {\n id: deploymentId('350e2cf5287c5665'),\n number: 1,\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n configVersion: '14',\n gitCommitSha: null,\n size: 'tiny' as const,\n buildState: 'PREBUILT' as const,\n runState: 'STOPPED' as const,\n archived: true,\n archivedAt: '2026-08-15T11:03:02+00:00',\n createdAt: '2026-08-10T09:12:44+00:00',\n} satisfies Deployment;\n\n// Serving production — the one `appFixtures.running.production` points at.\nconst liveDeployment = {\n id: deploymentId('7a4c1b9e0d3f2a81'),\n number: 2,\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n configVersion: '16',\n gitCommitSha: null,\n size: 'small' as const,\n buildState: 'PREBUILT' as const,\n runState: 'RUNNING' as const,\n archived: false,\n archivedAt: null,\n createdAt: '2026-08-15T11:02:58+00:00',\n} satisfies Deployment;\n\n// Created with `promote: false`: pinned and built, but nothing ever started it.\nconst stagedDeployment = {\n id: deploymentId('c5e83f17b204de96'),\n number: 3,\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n configVersion: '18',\n gitCommitSha: null,\n size: 'small' as const,\n buildState: 'PREBUILT' as const,\n runState: 'NEVER_RUN' as const,\n archived: false,\n archivedAt: null,\n createdAt: '2026-08-17T08:41:19+00:00',\n} satisfies Deployment;\n\n// No artifact was produced, so this deployment can never run — a different problem,\n// with a different fix, from a run failure. Not reachable on the platform today\n// (every deployment is `PREBUILT`); the headline table treats it as a contract.\nconst buildFailedDeployment = {\n id: deploymentId('e91d47a8c6b02f35'),\n number: 4,\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n configVersion: '19',\n gitCommitSha: null,\n size: 'small' as const,\n buildState: 'FAILED' as const,\n runState: 'NEVER_RUN' as const,\n archived: false,\n archivedAt: null,\n createdAt: '2026-08-17T09:05:33+00:00',\n} satisfies Deployment;\n\n// Built fine, crashed on every run — `getAppRuns` carries the cause.\nconst runFailedDeployment = {\n id: deploymentId('2b6f0a94e7d51c83'),\n number: 5,\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n configVersion: '20',\n gitCommitSha: null,\n size: 'small' as const,\n buildState: 'PREBUILT' as const,\n runState: 'FAILED' as const,\n archived: false,\n archivedAt: null,\n createdAt: '2026-08-17T09:31:07+00:00',\n} satisfies Deployment;\n\nexport const deploymentFixtures = {\n archived: archivedDeployment,\n live: liveDeployment,\n staged: stagedDeployment,\n buildFailed: buildFailedDeployment,\n runFailed: runFailedDeployment,\n} satisfies Record<'archived' | 'live' | 'staged' | 'buildFailed' | 'runFailed', Deployment>;\n\nexport const getDeployment = (): Deployment => liveDeployment;\n\n/**\n * One continuous history: #1 retired, #2 serving, #3 staged, #4 failed to build, #5 built but its\n * run failed.\n *\n * All five, because `runFixtures.failed` names #5 as its deployment — a list that left the failed\n * ones out could not be joined to the runs, which is the join a timeline is built from.\n *\n * Returned in ascending `number` order. The endpoint does not specify an order, so consumers must\n * sort for themselves — this order is a fixture convention, not a contract to rely on, and it is\n * ascending on purpose: a consumer that assumes newest-first gets the wrong answer here rather\n * than in production.\n */\nexport const listDeployments = (): Deployment[] => [\n archivedDeployment,\n liveDeployment,\n stagedDeployment,\n buildFailedDeployment,\n runFailedDeployment,\n];\n","import type { App } from '@keboola/api-client/apps/types';\n\nimport { APP_ID, deploymentFixtures } from './deployments';\n\nconst APP_URL = 'https://hello-dashboard-374811.hub.canary-orion.keboola.dev';\n\nconst base = {\n id: APP_ID,\n projectId: '14',\n componentId: 'keboola.data-apps',\n branchId: '6',\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n type: 'streamlit' as const,\n mode: 'prod' as const,\n url: APP_URL,\n};\n\nconst production = (deployment: (typeof deploymentFixtures)[keyof typeof deploymentFixtures]) => ({\n desiredNumber: deployment.number,\n desiredId: deployment.id,\n actualNumber: deployment.number,\n actualId: deployment.id,\n});\n\n// Created through `/v2`, nothing deployed yet: the URL is reserved and publicly 404s.\nconst neverDeployedApp = {\n ...base,\n configVersion: '1',\n production: { desiredNumber: null, desiredId: null, actualNumber: null, actualId: null },\n undeployedChanges: false,\n state: 'NOT_DEPLOYED' as const,\n} satisfies App;\n\n/**\n * Transcribed verbatim from canary on 17 Aug 2026 (AJDA-3140, probe P1): an app created and\n * started through `/v1`, serving real traffic (HTTP 200, 8340 B) at the moment this was read,\n * which `/v2` nonetheless reports as `NOT_DEPLOYED` with an empty `production` because it was\n * never adopted into the deployments model.\n *\n * The Builder must never read \"is this app serving\" off `state` alone — here that answer is\n * wrong in the most damaging direction.\n */\nconst legacyV1ServingApp = {\n id: '374811',\n projectId: '14',\n componentId: 'keboola.data-apps',\n branchId: '6',\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n configVersion: '2',\n type: 'streamlit' as const,\n mode: 'dev' as const,\n url: APP_URL,\n production: { desiredNumber: null, desiredId: null, actualNumber: null, actualId: null },\n undeployedChanges: false,\n state: 'NOT_DEPLOYED' as const,\n} satisfies App;\n\n// Serving deployment #2, config unchanged since it was deployed.\nconst runningApp = {\n ...base,\n configVersion: deploymentFixtures.live.configVersion,\n production: production(deploymentFixtures.live),\n undeployedChanges: false,\n state: 'RUNNING' as const,\n} satisfies App;\n\n// Still serving #2 (config v16) while the config has moved on to v18.\nconst appWithUndeployedChanges = {\n ...base,\n configVersion: deploymentFixtures.staged.configVersion,\n production: production(deploymentFixtures.live),\n undeployedChanges: true,\n state: 'RUNNING' as const,\n} satisfies App;\n\n/**\n * A blue/green promotion in flight: #3 has been asked for, #2 is still what traffic reaches.\n * `state` stays `RUNNING` throughout — the rollout is only visible as `desiredId !== actualId`.\n */\nconst promotingApp = {\n ...base,\n configVersion: deploymentFixtures.staged.configVersion,\n production: {\n desiredNumber: deploymentFixtures.staged.number,\n desiredId: deploymentFixtures.staged.id,\n actualNumber: deploymentFixtures.live.number,\n actualId: deploymentFixtures.live.id,\n },\n undeployedChanges: true,\n state: 'RUNNING' as const,\n} satisfies App;\n\n// Idle between visits and armed to wake on the next request — normal, not an outage.\nconst sleepingApp = {\n ...base,\n configVersion: deploymentFixtures.live.configVersion,\n production: production(deploymentFixtures.live),\n undeployedChanges: false,\n state: 'SLEEPING' as const,\n} satisfies App;\n\n// Explicitly suspended: a visitor gets a 503 until someone resumes it.\nconst suspendedApp = {\n ...base,\n configVersion: deploymentFixtures.live.configVersion,\n production: production(deploymentFixtures.live),\n undeployedChanges: false,\n state: 'SUSPENDED' as const,\n} satisfies App;\n\nexport const appFixtures = {\n neverDeployed: neverDeployedApp,\n legacyV1Serving: legacyV1ServingApp,\n running: runningApp,\n undeployedChanges: appWithUndeployedChanges,\n promoting: promotingApp,\n sleeping: sleepingApp,\n suspended: suspendedApp,\n} satisfies Record<\n | 'neverDeployed'\n | 'legacyV1Serving'\n | 'running'\n | 'undeployedChanges'\n | 'promoting'\n | 'sleeping'\n | 'suspended',\n App\n>;\n\nexport const getApp = (): App => runningApp;\n\n/**\n * The named fixtures above are all the *same* app in different states, which is what a detail\n * page shows. A listing shows different apps, so each entry past the first is re-addressed —\n * including the deployment ids inside `production`, which embed the app id.\n */\nconst readdress = (app: App, id: string): App => ({\n ...app,\n id,\n url: `https://data-app-${id}.hub.canary-orion.keboola.dev`,\n production: {\n ...app.production,\n desiredId: app.production.desiredId?.replace(APP_ID, id) ?? null,\n actualId: app.production.actualId?.replace(APP_ID, id) ?? null,\n },\n});\n\nexport const listApps = (): App[] => [\n runningApp,\n readdress(appWithUndeployedChanges, '374812'),\n readdress(neverDeployedApp, '374813'),\n];\n","import type { AppRun } from '@keboola/api-client/apps/types';\n\nimport { APP_ID, deploymentFixtures } from './deployments';\n\nconst base = {\n appId: APP_ID,\n runtimeSize: 'small',\n runtimeBackendType: 'streamlit',\n imageVersion: '1.14.2',\n mode: 'prod',\n};\n\nconst runningRun = {\n ...base,\n id: '4f2d8c1a-0b76-4e35-9a12-5c8e7d3b0f41',\n deploymentId: deploymentFixtures.live.id,\n configVersion: deploymentFixtures.live.configVersion,\n state: 'running' as const,\n createdAt: '2026-08-15T11:02:58+00:00',\n startedAt: '2026-08-15T11:03:41+00:00',\n stoppedAt: null,\n startupLogs: null,\n failureReason: null,\n} satisfies AppRun;\n\nconst finishedRun = {\n ...base,\n id: '9c0a7e42-31bd-4f88-b6d5-2ea41f907c3b',\n deploymentId: deploymentFixtures.archived.id,\n configVersion: deploymentFixtures.archived.configVersion,\n state: 'finished' as const,\n createdAt: '2026-08-10T09:12:44+00:00',\n startedAt: '2026-08-10T09:13:29+00:00',\n stoppedAt: '2026-08-15T11:03:02+00:00',\n startupLogs: null,\n failureReason: null,\n} satisfies AppRun;\n\n/**\n * A classified failure transcribed from canary (AJDA-3140, probe P1). `startedAt` is `null`\n * even though a cause was attributed — the container executed but its startup probe never\n * passed, so a classified failure says nothing about how far the run got.\n */\nconst failedRun = {\n ...base,\n id: 'ba53f9d0-7c41-4a2e-8f16-d0b9e254a7c6',\n deploymentId: deploymentFixtures.runFailed.id,\n configVersion: deploymentFixtures.runFailed.configVersion,\n state: 'failed' as const,\n createdAt: '2026-08-17T09:31:07+00:00',\n startedAt: null,\n stoppedAt: '2026-08-17T09:33:52+00:00',\n startupLogs:\n '[INFO] Starting app\\n[ERROR] App must have keboola-config/nginx/ directory. Missing: /app/keboola-config/nginx\\n',\n failureReason: {\n reason: 'StartupProbeFailed',\n message: 'App must have keboola-config/nginx/ directory. Missing: /app/keboola-config/nginx',\n },\n} satisfies AppRun;\n\n/**\n * A run that belongs to the app itself rather than to a deployment — what every run of a\n * `/v1`-created app looks like. `deploymentId: null` is permanent for these, not drift.\n */\nconst legacyRun = {\n ...base,\n id: '1d7b4e05-8a92-4c63-b0f7-3e6a5c8192d4',\n deploymentId: null,\n configVersion: '2',\n state: 'running' as const,\n createdAt: '2026-08-17T10:02:11+00:00',\n startedAt: '2026-08-17T10:02:51+00:00',\n stoppedAt: null,\n startupLogs: null,\n failureReason: null,\n} satisfies AppRun;\n\nexport const runFixtures = {\n running: runningRun,\n finished: finishedRun,\n failed: failedRun,\n legacy: legacyRun,\n} satisfies Record<'running' | 'finished' | 'failed' | 'legacy', AppRun>;\n\nexport const getAppRun = (): AppRun => runningRun;\n\n/**\n * Every run this app has, newest first — the order the endpoint documents, so a consumer that\n * relies on it (`[latest] = runs`) is exercised against data that keeps the promise rather than\n * data that happens to contradict it.\n */\nexport const listAppRuns = (): AppRun[] => [legacyRun, failedRun, runningRun, finishedRun];\n","import type {\n AdminVendor,\n App,\n AppChange,\n AppVendor,\n ServiceAccount,\n User,\n Vendor,\n VendorListItem,\n} from '@keboola/api-client/developerPortal/types';\n\n// `isTrusted` is the raw tinyint here and a boolean in `vendorDetail` below. That is not a fixture\n// inconsistency: `GET /vendors` returns the row unconverted, every other vendor endpoint runs it\n// through `publicGetVendor`. A fixture that smoothed it over would hide the difference consumers\n// have to handle.\n//\n// `type: 'keboola'` is what the public catalog's \"Supported by Keboola\" filter matches on — NOT\n// `id`, so a fixture that only set the id would silently fail to exercise that filter.\nconst keboolaVendor = {\n id: 'keboola',\n name: 'Keboola',\n email: 'support@keboola.com',\n address: 'Prague, Czech Republic',\n type: 'keboola',\n projectUrl: null,\n isTrusted: 1,\n} satisfies VendorListItem;\n\nconst thirdPartyVendor = {\n id: 'acme',\n name: 'Acme Co.',\n email: 'dev@acme.example',\n address: 'Springfield',\n projectUrl: 'https://connection.keboola.com/admin/projects/1234',\n type: 'other',\n isTrusted: 0,\n} satisfies VendorListItem;\n\n/** The same vendor as `GET /vendors/{vendor}` returns it — `isTrusted` converted to a boolean. */\nconst vendorDetail = {\n ...thirdPartyVendor,\n isTrusted: false,\n} satisfies Vendor;\n\n// A pending, self-registered vendor. The `_v` id prefix is the marker that keeps it out of the\n// user-selectable vendor list until an admin approves and renames it. Only `GET /admin/vendors`\n// returns it — the public list filters on `isApproved`, and is the only response carrying the flag.\nconst pendingVendor = {\n id: '_v1699999999999',\n name: 'Pending Startup',\n email: 'hello@pending.example',\n address: 'Berlin',\n type: 'other',\n projectUrl: null,\n isApproved: false,\n isPublic: false,\n isTrusted: false,\n} satisfies AdminVendor;\n\n// The two public vendors as `GET /admin/vendors` returns them: approved, and `isTrusted` converted\n// to a boolean. They exist so the admin list is not a single pending row — a test that only ever\n// sees `pendingVendor` never exercises the approved path the admin table mostly renders.\nconst keboolaAdminVendor = {\n ...keboolaVendor,\n isApproved: true,\n isPublic: true,\n isTrusted: true,\n} satisfies AdminVendor;\n\nconst thirdPartyAdminVendor = {\n ...thirdPartyVendor,\n isApproved: true,\n isPublic: true,\n isTrusted: false,\n} satisfies AdminVendor;\n\n// The vendor as it arrives joined onto an app: five columns, none of the flags.\nconst appVendor = (vendor: VendorListItem): AppVendor => ({\n id: vendor.id,\n name: vendor.name,\n address: vendor.address,\n email: vendor.email,\n type: vendor.type,\n});\n\n/** A published, fully-populated extractor — the shape that passes `hasAllFieldsForPublishing`. */\nconst publishedExtractor = {\n id: 'keboola.ex-db-snowflake',\n vendor: appVendor(keboolaVendor),\n name: 'Snowflake',\n type: 'extractor',\n shortDescription: 'Extract data from Snowflake',\n longDescription: '## Snowflake extractor\\n\\nExtracts tables from a Snowflake database.',\n licenseUrl: 'https://github.com/keboola/ex-db-snowflake/blob/master/LICENSE.md',\n documentationUrl: 'https://help.keboola.com/components/extractors/database/snowflake/',\n sourceCodeUrl: 'https://github.com/keboola/ex-db-snowflake',\n categories: ['Database'],\n complexity: 'easy',\n uiOptions: ['genericDockerUI'],\n defaultBucket: true,\n defaultBucketStage: 'in',\n stagingStorageInput: 'local',\n stagingStorageOutput: 'local',\n logger: 'standard',\n isPublic: true,\n isDeprecated: false,\n fees: false,\n repository: { type: 'ecr', uri: 'keboola/ex-db-snowflake', tag: '1.9.0' },\n // The 128 filename ends in a 13-digit millisecond timestamp, so `getIcon` uses it. A legacy\n // incremental filename here would make `getIcon` fall back to the 64px variant.\n icon: {\n '64': 'https://ui.keboola-assets.com/developer-portal/icons/keboola.ex-db-snowflake/64/1699999999999.png',\n '128':\n 'https://ui.keboola-assets.com/developer-portal/icons/keboola.ex-db-snowflake/128/1699999999999.png',\n },\n version: 12,\n createdBy: 'support@keboola.com',\n updatedOn: '2024-06-01T09:00:00+0200',\n uri: 'docker/keboola.ex-db-snowflake',\n isPublished: true,\n publishedVersion: 12,\n publishingStatus: 'public',\n} satisfies App;\n\n/** A private third-party app with a pending publishing request. */\nconst requestedApp = {\n id: 'acme.wr-widgets',\n vendor: appVendor(thirdPartyVendor),\n name: 'Widget Writer',\n type: 'writer',\n shortDescription: 'Write data to Widgets',\n longDescription: 'Pushes tables into the Widgets API.',\n licenseUrl: 'https://acme.example/license',\n documentationUrl: 'https://acme.example/docs',\n uiOptions: ['genericDockerUI'],\n repository: { type: 'quay', uri: 'acme/wr-widgets', tag: '0.3.1' },\n icon: {\n '64': 'https://ui.keboola-assets.com/developer-portal/icons/acme.wr-widgets/64/1699999999998.png',\n '128':\n 'https://ui.keboola-assets.com/developer-portal/icons/acme.wr-widgets/128/1699999999998.png',\n },\n isPublic: false,\n isDeprecated: false,\n version: 3,\n createdBy: 'dev@acme.example',\n updatedOn: '2024-05-20T14:12:00+0200',\n uri: 'docker/acme.wr-widgets',\n isPublished: false,\n publishingStatus: 'requested',\n publishingRequest: { createdOn: '2024-05-20T14:12:00+0200', rejectionReason: null },\n} satisfies App;\n\n/** A rejected app — carries the reason the vendor sees on its detail page. */\nconst rejectedApp = {\n id: 'acme.app-analyzer',\n vendor: appVendor(thirdPartyVendor),\n name: 'Analyzer',\n type: 'application',\n shortDescription: 'Analyze things',\n isPublic: false,\n isDeprecated: false,\n version: 1,\n createdBy: 'dev@acme.example',\n uri: 'docker/acme.app-analyzer',\n isPublished: false,\n publishingStatus: 'rejected',\n publishingRequest: {\n createdOn: '2024-04-02T11:00:00+0200',\n rejectionReason: 'Documentation URL is missing and the icon is not 256×256.',\n },\n} satisfies App;\n\n/** A deprecated app with an expiry date and a suggested replacement. */\nconst deprecatedApp = {\n id: 'keboola.ex-legacy',\n vendor: appVendor(keboolaVendor),\n name: 'Legacy Extractor',\n type: 'extractor',\n shortDescription: 'Superseded',\n isPublic: true,\n isDeprecated: true,\n expiredOn: '2025-01-01',\n replacementApp: 'keboola.ex-db-snowflake',\n version: 40,\n uri: 'docker/keboola.ex-legacy',\n isPublished: true,\n publishedVersion: 38,\n publishingStatus: 'public',\n} satisfies App;\n\n/**\n * A `data-app`, the type whose edit form hides ~14 fields. Deliberately minimal: a fixture carrying\n * `configurationSchema` or `actions` here would misrepresent what the form can produce.\n */\nconst dataApp = {\n id: 'acme.data-app-dashboard',\n vendor: appVendor(thirdPartyVendor),\n name: 'Dashboard',\n type: 'data-app',\n shortDescription: 'A Streamlit dashboard',\n isPublic: false,\n isDeprecated: false,\n version: 2,\n uri: 'docker/acme.data-app-dashboard',\n isPublished: false,\n publishingStatus: 'private',\n} satisfies App;\n\n/** A `code-pattern`, whose `configurationSchema.supported_components` must be a non-empty array. */\nconst codePatternApp = {\n id: 'acme.code-pattern-etl',\n vendor: appVendor(thirdPartyVendor),\n name: 'ETL Pattern',\n type: 'code-pattern',\n shortDescription: 'Generates ETL code',\n actions: ['generate'],\n configurationSchema: { supported_components: ['keboola.snowflake-transformation'] },\n isPublic: false,\n version: 1,\n uri: 'docker/acme.code-pattern-etl',\n isPublished: false,\n publishingStatus: 'private',\n} satisfies App;\n\n/**\n * An app typed `other`. The public catalog excludes it entirely, so it exists to prove that\n * exclusion rather than to be rendered.\n */\nconst otherTypeApp = {\n id: 'acme.misc-thing',\n vendor: appVendor(thirdPartyVendor),\n name: 'Misc Thing',\n type: 'other',\n isPublic: true,\n version: 1,\n uri: 'docker/acme.misc-thing',\n isPublished: true,\n publishedVersion: 1,\n publishingStatus: 'public',\n} satisfies App;\n\n// `username` is the Cognito login, which is the user's email — the list endpoints return no\n// separate `email`, and no account state (`status`, `isEnabled`, `mfa`) either.\nconst humanUser = {\n username: 'dev@acme.example',\n name: 'Dev Eloper',\n vendors: ['acme'],\n createdOn: '2024-01-10T08:00:00+0100',\n} satisfies User;\n\n/** A recently added member, for a test that orders the list by `createdOn`. */\nconst newestUser = {\n username: 'new@acme.example',\n name: 'New Hire',\n vendors: ['acme'],\n createdOn: '2024-06-25T08:00:00+0200',\n} satisfies User;\n\n/** A member of no vendor — reachable only through the admin list. */\nconst vendorlessUser = {\n username: 'gone@acme.example',\n name: 'Alan Gone',\n vendors: [],\n createdOn: '2023-02-01T08:00:00+0100',\n} satisfies User;\n\n/** A Keboola staff member — eligible for \"make admin\" because they belong to the `keboola` vendor. */\nconst keboolaStaffUser = {\n username: 'staff@keboola.com',\n name: 'Kai Staff',\n vendors: ['keboola'],\n createdOn: '2023-09-14T08:00:00+0200',\n} satisfies User;\n\n/** A freshly created service account, including the one-time `password`. */\nconst newServiceAccount = {\n username: 'acme+ci',\n description: 'CI deploy pipeline',\n createdOn: '2024-07-01T10:00:00+0200',\n password: 'one-time-secret-shown-once',\n} satisfies ServiceAccount;\n\n/** The same account as later listed — note there is no `password`; it is unreadable after creation. */\nconst existingServiceAccount = {\n username: 'acme+release',\n description: 'Release automation',\n createdOn: '2024-03-11T10:00:00+0100',\n} satisfies ServiceAccount;\n\nconst appChange = {\n appId: 'acme.wr-widgets',\n createdOn: '2024-05-20T14:12:00+0200',\n createdBy: 'dev@acme.example',\n changes: [\n {\n attribute: 'shortDescription',\n oldValue: 'Writes widgets',\n newValue: 'Write data to Widgets',\n },\n {\n attribute: 'repository',\n oldValue: { type: 'quay', uri: 'acme/wr-widgets', tag: '0.3.0' },\n newValue: { type: 'quay', uri: 'acme/wr-widgets', tag: '0.3.1' },\n },\n ],\n} satisfies AppChange;\n\n/** The public catalog list: published, non-`other` apps only. */\nexport const listPublishedApps = (): App[] => [publishedExtractor, deprecatedApp];\n\n/** A vendor's own apps, across every publishing state the table renders. */\nexport const listVendorApps = (): App[] => [requestedApp, rejectedApp, dataApp, codePatternApp];\n\n/** The admin list — every vendor, plus the `other`-typed app the public catalog drops. */\nexport const listAllApps = (): App[] => [\n publishedExtractor,\n requestedApp,\n rejectedApp,\n deprecatedApp,\n dataApp,\n codePatternApp,\n otherTypeApp,\n];\n\n/** `GET /vendors` — approved and public only, so the pending vendor cannot appear here. */\nexport const listVendors = (): VendorListItem[] => [keboolaVendor, thirdPartyVendor];\n\n/** `GET /vendors/{vendor}` — the converted shape. */\nexport const getVendor = (): Vendor => vendorDetail;\n\n/** `GET /admin/vendors` — every vendor, and the only response carrying the approval flags. */\nexport const listAllVendors = (): AdminVendor[] => [\n keboolaAdminVendor,\n thirdPartyAdminVendor,\n pendingVendor,\n];\n\nexport const listUsers = (): User[] => [humanUser, newestUser, vendorlessUser, keboolaStaffUser];\n\nexport const listServiceAccounts = (): ServiceAccount[] => [existingServiceAccount];\n\nexport const listAppChanges = (): AppChange[] => [appChange];\n\n/** Named fixtures, for a test that needs one specific state. */\nexport const developerPortalFixtures = {\n apps: {\n published: publishedExtractor,\n requested: requestedApp,\n rejected: rejectedApp,\n deprecated: deprecatedApp,\n dataApp,\n codePattern: codePatternApp,\n otherType: otherTypeApp,\n },\n vendors: {\n keboola: keboolaVendor,\n thirdParty: thirdPartyVendor,\n detail: vendorDetail,\n pending: pendingVendor,\n keboolaAdmin: keboolaAdminVendor,\n thirdPartyAdmin: thirdPartyAdminVendor,\n },\n users: {\n human: humanUser,\n newest: newestUser,\n vendorless: vendorlessUser,\n keboolaStaff: keboolaStaffUser,\n },\n serviceAccounts: {\n created: newServiceAccount,\n existing: existingServiceAccount,\n },\n changes: { single: appChange },\n};\n","import type { Table, TableDetail } from '@keboola/api-client/storage/types';\n\nconst bucket = {\n id: 'in.c-main',\n name: 'c-main',\n displayName: 'Main',\n stage: 'in' as const,\n description: 'Main input bucket',\n created: '2024-01-15T10:00:00+0100',\n lastChangeDate: '2024-03-10T08:30:00+0100',\n isMaintenance: false,\n isReadOnly: false,\n isSnowflakeSharedDatabase: false,\n hasExternalSchema: false,\n rowsCount: 150000,\n dataSizeBytes: 52428800,\n uri: 'https://connection.keboola.com/v2/storage/buckets/in.c-main',\n backend: 'snowflake' as const,\n backendPath: [],\n databaseName: null,\n color: null,\n idBranch: 0,\n owner: null,\n sharing: null,\n path: 'in.c-main',\n tables: 'https://connection.keboola.com/v2/storage/buckets/in.c-main/tables',\n updated: '2024-03-10T08:30:00+0100',\n};\n\n// A freshly created table with no imports yet (non-typed, non-alias variant).\nconst freshTable = {\n id: 'in.c-main.users',\n name: 'users',\n displayName: 'Users',\n primaryKey: ['id'],\n metadata: [],\n columns: ['id', 'email', 'name', 'created_at'],\n columnMetadata: {},\n attributes: [],\n bucket,\n isTyped: false as const,\n isAlias: false as const,\n} satisfies TableDetail;\n\n// A recently updated table with a moderate size (non-typed, non-alias variant).\nconst recentlyUpdatedTable = {\n id: 'in.c-main.orders',\n name: 'orders',\n displayName: 'Orders',\n primaryKey: ['order_id'],\n metadata: [\n {\n id: 'mt1',\n key: 'KBC.createdBy.component.id',\n value: 'keboola.python-transformation',\n provider: 'keboola',\n timestamp: '2024-06-01T09:00:00+0200',\n },\n ],\n columns: ['order_id', 'user_id', 'total', 'status', 'created_at', 'updated_at'],\n columnMetadata: {\n order_id: [\n {\n id: 'm1',\n key: 'KBC.datatype.type',\n value: 'INTEGER',\n provider: 'keboola',\n timestamp: '2024-06-01T09:00:00+0200',\n },\n ],\n },\n attributes: [],\n bucket,\n isTyped: false as const,\n isAlias: false as const,\n} satisfies TableDetail;\n\n// A large table with many rows representing high-volume data (non-typed, non-alias variant).\nconst largeTable = {\n id: 'in.c-main.events',\n name: 'events',\n displayName: 'Events',\n primaryKey: [],\n metadata: [],\n columns: ['event_id', 'user_id', 'event_type', 'properties', 'occurred_at'],\n columnMetadata: {},\n attributes: [],\n bucket,\n isTyped: false as const,\n isAlias: false as const,\n} satisfies TableDetail;\n\n/**\n * Returns a single realistic typed TableDetail (fresh, no imports yet).\n *\n * The explicit return type ensures any divergence from the OpenAPI-derived\n * `TableDetail` in `@keboola/api-client` surfaces as a TypeScript error.\n */\nexport const getTable = (): TableDetail => freshTable;\n\n/**\n * Returns three TableDetail objects representing different lifecycle states:\n * 1. Fresh — just created, no data imported.\n * 2. Recently updated — moderate size, recent import.\n * 3. Large — high row count, large byte size.\n */\nexport const listTables = (): TableDetail[] => [freshTable, recentlyUpdatedTable, largeTable];\n\n/**\n * Named fixtures for targeted access in tests.\n */\nexport const tableFixtures = {\n fresh: freshTable,\n recentlyUpdated: recentlyUpdatedTable,\n large: largeTable,\n} satisfies Record<'fresh' | 'recentlyUpdated' | 'large', TableDetail>;\n\nexport type { Table, TableDetail };\n","import { appFixtures, getApp, listApps } from './clients/apps/apps';\nimport { deploymentFixtures, getDeployment, listDeployments } from './clients/apps/deployments';\nimport { getAppRun, listAppRuns, runFixtures } from './clients/apps/runs';\nimport {\n developerPortalFixtures,\n getVendor,\n listAllApps,\n listAllVendors,\n listAppChanges,\n listPublishedApps,\n listServiceAccounts,\n listUsers,\n listVendorApps,\n listVendors,\n} from './clients/developerPortal/apps';\nimport { getTable, listTables, tableFixtures } from './clients/storage/tables';\n\nexport const fixtures = {\n storage: {\n tables: {\n getTable,\n listTables,\n fixtures: tableFixtures,\n },\n },\n apps: {\n apps: {\n getApp,\n listApps,\n fixtures: appFixtures,\n },\n deployments: {\n getDeployment,\n listDeployments,\n fixtures: deploymentFixtures,\n },\n runs: {\n getAppRun,\n listAppRuns,\n fixtures: runFixtures,\n },\n },\n developerPortal: {\n listPublishedApps,\n listVendorApps,\n listAllApps,\n listAllVendors,\n getVendor,\n listVendors,\n listUsers,\n listServiceAccounts,\n listAppChanges,\n fixtures: developerPortalFixtures,\n },\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["base","ServiceId"],"sources":["../src/clients/apps/deployments.ts","../src/clients/apps/apps.ts","../src/clients/apps/runs.ts","../src/clients/developerPortal/apps.ts","../src/clients/storage/bootstrap.ts","../src/clients/storage/tables.ts","../src/fixtures.ts"],"sourcesContent":["import type { Deployment } from '@keboola/api-client/apps/types';\n\n/**\n * Deployment ids are the deterministic Kubernetes CR name — `app-{appId}-dpl-{hash}` —\n * so they are reproduced in that shape rather than as opaque strings.\n */\nexport const APP_ID = '374811';\n\nconst deploymentId = (hash: string) => `app-${APP_ID}-dpl-${hash}`;\n\n// Retired: the row outlives its CR, so it stays in history with `archived: true`.\nconst archivedDeployment = {\n id: deploymentId('350e2cf5287c5665'),\n number: 1,\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n configVersion: '14',\n gitCommitSha: null,\n size: 'tiny' as const,\n buildState: 'PREBUILT' as const,\n runState: 'STOPPED' as const,\n archived: true,\n archivedAt: '2026-08-15T11:03:02+00:00',\n createdAt: '2026-08-10T09:12:44+00:00',\n} satisfies Deployment;\n\n// Serving production — the one `appFixtures.running.production` points at.\nconst liveDeployment = {\n id: deploymentId('7a4c1b9e0d3f2a81'),\n number: 2,\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n configVersion: '16',\n gitCommitSha: null,\n size: 'small' as const,\n buildState: 'PREBUILT' as const,\n runState: 'RUNNING' as const,\n archived: false,\n archivedAt: null,\n createdAt: '2026-08-15T11:02:58+00:00',\n} satisfies Deployment;\n\n// Created with `promote: false`: pinned and built, but nothing ever started it.\nconst stagedDeployment = {\n id: deploymentId('c5e83f17b204de96'),\n number: 3,\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n configVersion: '18',\n gitCommitSha: null,\n size: 'small' as const,\n buildState: 'PREBUILT' as const,\n runState: 'NEVER_RUN' as const,\n archived: false,\n archivedAt: null,\n createdAt: '2026-08-17T08:41:19+00:00',\n} satisfies Deployment;\n\n// No artifact was produced, so this deployment can never run — a different problem,\n// with a different fix, from a run failure. Not reachable on the platform today\n// (every deployment is `PREBUILT`); the headline table treats it as a contract.\nconst buildFailedDeployment = {\n id: deploymentId('e91d47a8c6b02f35'),\n number: 4,\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n configVersion: '19',\n gitCommitSha: null,\n size: 'small' as const,\n buildState: 'FAILED' as const,\n runState: 'NEVER_RUN' as const,\n archived: false,\n archivedAt: null,\n createdAt: '2026-08-17T09:05:33+00:00',\n} satisfies Deployment;\n\n// Built fine, crashed on every run — `getAppRuns` carries the cause.\nconst runFailedDeployment = {\n id: deploymentId('2b6f0a94e7d51c83'),\n number: 5,\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n configVersion: '20',\n gitCommitSha: null,\n size: 'small' as const,\n buildState: 'PREBUILT' as const,\n runState: 'FAILED' as const,\n archived: false,\n archivedAt: null,\n createdAt: '2026-08-17T09:31:07+00:00',\n} satisfies Deployment;\n\nexport const deploymentFixtures = {\n archived: archivedDeployment,\n live: liveDeployment,\n staged: stagedDeployment,\n buildFailed: buildFailedDeployment,\n runFailed: runFailedDeployment,\n} satisfies Record<'archived' | 'live' | 'staged' | 'buildFailed' | 'runFailed', Deployment>;\n\nexport const getDeployment = (): Deployment => liveDeployment;\n\n/**\n * One continuous history: #1 retired, #2 serving, #3 staged, #4 failed to build, #5 built but its\n * run failed.\n *\n * All five, because `runFixtures.failed` names #5 as its deployment — a list that left the failed\n * ones out could not be joined to the runs, which is the join a timeline is built from.\n *\n * Returned in ascending `number` order. The endpoint does not specify an order, so consumers must\n * sort for themselves — this order is a fixture convention, not a contract to rely on, and it is\n * ascending on purpose: a consumer that assumes newest-first gets the wrong answer here rather\n * than in production.\n */\nexport const listDeployments = (): Deployment[] => [\n archivedDeployment,\n liveDeployment,\n stagedDeployment,\n buildFailedDeployment,\n runFailedDeployment,\n];\n","import type { App } from '@keboola/api-client/apps/types';\n\nimport { APP_ID, deploymentFixtures } from './deployments';\n\nconst APP_URL = 'https://hello-dashboard-374811.hub.canary-orion.keboola.dev';\n\nconst base = {\n id: APP_ID,\n projectId: '14',\n componentId: 'keboola.data-apps',\n branchId: '6',\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n type: 'streamlit' as const,\n mode: 'prod' as const,\n url: APP_URL,\n};\n\nconst production = (deployment: (typeof deploymentFixtures)[keyof typeof deploymentFixtures]) => ({\n desiredNumber: deployment.number,\n desiredId: deployment.id,\n actualNumber: deployment.number,\n actualId: deployment.id,\n});\n\n// Created through `/v2`, nothing deployed yet: the URL is reserved and publicly 404s.\nconst neverDeployedApp = {\n ...base,\n configVersion: '1',\n production: { desiredNumber: null, desiredId: null, actualNumber: null, actualId: null },\n undeployedChanges: false,\n state: 'NOT_DEPLOYED' as const,\n} satisfies App;\n\n/**\n * Transcribed verbatim from canary on 17 Aug 2026 (AJDA-3140, probe P1): an app created and\n * started through `/v1`, serving real traffic (HTTP 200, 8340 B) at the moment this was read,\n * which `/v2` nonetheless reports as `NOT_DEPLOYED` with an empty `production` because it was\n * never adopted into the deployments model.\n *\n * The Builder must never read \"is this app serving\" off `state` alone — here that answer is\n * wrong in the most damaging direction.\n */\nconst legacyV1ServingApp = {\n id: '374811',\n projectId: '14',\n componentId: 'keboola.data-apps',\n branchId: '6',\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n configVersion: '2',\n type: 'streamlit' as const,\n mode: 'dev' as const,\n url: APP_URL,\n production: { desiredNumber: null, desiredId: null, actualNumber: null, actualId: null },\n undeployedChanges: false,\n state: 'NOT_DEPLOYED' as const,\n} satisfies App;\n\n// Serving deployment #2, config unchanged since it was deployed.\nconst runningApp = {\n ...base,\n configVersion: deploymentFixtures.live.configVersion,\n production: production(deploymentFixtures.live),\n undeployedChanges: false,\n state: 'RUNNING' as const,\n} satisfies App;\n\n// Still serving #2 (config v16) while the config has moved on to v18.\nconst appWithUndeployedChanges = {\n ...base,\n configVersion: deploymentFixtures.staged.configVersion,\n production: production(deploymentFixtures.live),\n undeployedChanges: true,\n state: 'RUNNING' as const,\n} satisfies App;\n\n/**\n * A blue/green promotion in flight: #3 has been asked for, #2 is still what traffic reaches.\n * `state` stays `RUNNING` throughout — the rollout is only visible as `desiredId !== actualId`.\n */\nconst promotingApp = {\n ...base,\n configVersion: deploymentFixtures.staged.configVersion,\n production: {\n desiredNumber: deploymentFixtures.staged.number,\n desiredId: deploymentFixtures.staged.id,\n actualNumber: deploymentFixtures.live.number,\n actualId: deploymentFixtures.live.id,\n },\n undeployedChanges: true,\n state: 'RUNNING' as const,\n} satisfies App;\n\n// Idle between visits and armed to wake on the next request — normal, not an outage.\nconst sleepingApp = {\n ...base,\n configVersion: deploymentFixtures.live.configVersion,\n production: production(deploymentFixtures.live),\n undeployedChanges: false,\n state: 'SLEEPING' as const,\n} satisfies App;\n\n// Explicitly suspended: a visitor gets a 503 until someone resumes it.\nconst suspendedApp = {\n ...base,\n configVersion: deploymentFixtures.live.configVersion,\n production: production(deploymentFixtures.live),\n undeployedChanges: false,\n state: 'SUSPENDED' as const,\n} satisfies App;\n\nexport const appFixtures = {\n neverDeployed: neverDeployedApp,\n legacyV1Serving: legacyV1ServingApp,\n running: runningApp,\n undeployedChanges: appWithUndeployedChanges,\n promoting: promotingApp,\n sleeping: sleepingApp,\n suspended: suspendedApp,\n} satisfies Record<\n | 'neverDeployed'\n | 'legacyV1Serving'\n | 'running'\n | 'undeployedChanges'\n | 'promoting'\n | 'sleeping'\n | 'suspended',\n App\n>;\n\nexport const getApp = (): App => runningApp;\n\n/**\n * The named fixtures above are all the *same* app in different states, which is what a detail\n * page shows. A listing shows different apps, so each entry past the first is re-addressed —\n * including the deployment ids inside `production`, which embed the app id.\n */\nconst readdress = (app: App, id: string): App => ({\n ...app,\n id,\n url: `https://data-app-${id}.hub.canary-orion.keboola.dev`,\n production: {\n ...app.production,\n desiredId: app.production.desiredId?.replace(APP_ID, id) ?? null,\n actualId: app.production.actualId?.replace(APP_ID, id) ?? null,\n },\n});\n\nexport const listApps = (): App[] => [\n runningApp,\n readdress(appWithUndeployedChanges, '374812'),\n readdress(neverDeployedApp, '374813'),\n];\n","import type { AppRun } from '@keboola/api-client/apps/types';\n\nimport { APP_ID, deploymentFixtures } from './deployments';\n\nconst base = {\n appId: APP_ID,\n runtimeSize: 'small',\n runtimeBackendType: 'streamlit',\n imageVersion: '1.14.2',\n mode: 'prod',\n};\n\nconst runningRun = {\n ...base,\n id: '4f2d8c1a-0b76-4e35-9a12-5c8e7d3b0f41',\n deploymentId: deploymentFixtures.live.id,\n configVersion: deploymentFixtures.live.configVersion,\n state: 'running' as const,\n createdAt: '2026-08-15T11:02:58+00:00',\n startedAt: '2026-08-15T11:03:41+00:00',\n stoppedAt: null,\n startupLogs: null,\n failureReason: null,\n} satisfies AppRun;\n\nconst finishedRun = {\n ...base,\n id: '9c0a7e42-31bd-4f88-b6d5-2ea41f907c3b',\n deploymentId: deploymentFixtures.archived.id,\n configVersion: deploymentFixtures.archived.configVersion,\n state: 'finished' as const,\n createdAt: '2026-08-10T09:12:44+00:00',\n startedAt: '2026-08-10T09:13:29+00:00',\n stoppedAt: '2026-08-15T11:03:02+00:00',\n startupLogs: null,\n failureReason: null,\n} satisfies AppRun;\n\n/**\n * A classified failure transcribed from canary (AJDA-3140, probe P1). `startedAt` is `null`\n * even though a cause was attributed — the container executed but its startup probe never\n * passed, so a classified failure says nothing about how far the run got.\n */\nconst failedRun = {\n ...base,\n id: 'ba53f9d0-7c41-4a2e-8f16-d0b9e254a7c6',\n deploymentId: deploymentFixtures.runFailed.id,\n configVersion: deploymentFixtures.runFailed.configVersion,\n state: 'failed' as const,\n createdAt: '2026-08-17T09:31:07+00:00',\n startedAt: null,\n stoppedAt: '2026-08-17T09:33:52+00:00',\n startupLogs:\n '[INFO] Starting app\\n[ERROR] App must have keboola-config/nginx/ directory. Missing: /app/keboola-config/nginx\\n',\n failureReason: {\n reason: 'StartupProbeFailed',\n message: 'App must have keboola-config/nginx/ directory. Missing: /app/keboola-config/nginx',\n },\n} satisfies AppRun;\n\n/**\n * A run that belongs to the app itself rather than to a deployment — what every run of a\n * `/v1`-created app looks like. `deploymentId: null` is permanent for these, not drift.\n */\nconst legacyRun = {\n ...base,\n id: '1d7b4e05-8a92-4c63-b0f7-3e6a5c8192d4',\n deploymentId: null,\n configVersion: '2',\n state: 'running' as const,\n createdAt: '2026-08-17T10:02:11+00:00',\n startedAt: '2026-08-17T10:02:51+00:00',\n stoppedAt: null,\n startupLogs: null,\n failureReason: null,\n} satisfies AppRun;\n\nexport const runFixtures = {\n running: runningRun,\n finished: finishedRun,\n failed: failedRun,\n legacy: legacyRun,\n} satisfies Record<'running' | 'finished' | 'failed' | 'legacy', AppRun>;\n\nexport const getAppRun = (): AppRun => runningRun;\n\n/**\n * Every run this app has, newest first — the order the endpoint documents, so a consumer that\n * relies on it (`[latest] = runs`) is exercised against data that keeps the promise rather than\n * data that happens to contradict it.\n */\nexport const listAppRuns = (): AppRun[] => [legacyRun, failedRun, runningRun, finishedRun];\n","import type {\n AdminVendor,\n App,\n AppChange,\n AppVendor,\n ServiceAccount,\n User,\n Vendor,\n VendorListItem,\n} from '@keboola/api-client/developerPortal/types';\n\n// `isTrusted` is the raw tinyint here and a boolean in `vendorDetail` below. That is not a fixture\n// inconsistency: `GET /vendors` returns the row unconverted, every other vendor endpoint runs it\n// through `publicGetVendor`. A fixture that smoothed it over would hide the difference consumers\n// have to handle.\n//\n// `type: 'keboola'` is what the public catalog's \"Supported by Keboola\" filter matches on — NOT\n// `id`, so a fixture that only set the id would silently fail to exercise that filter.\nconst keboolaVendor = {\n id: 'keboola',\n name: 'Keboola',\n email: 'support@keboola.com',\n address: 'Prague, Czech Republic',\n type: 'keboola',\n projectUrl: null,\n isTrusted: 1,\n} satisfies VendorListItem;\n\nconst thirdPartyVendor = {\n id: 'acme',\n name: 'Acme Co.',\n email: 'dev@acme.example',\n address: 'Springfield',\n projectUrl: 'https://connection.keboola.com/admin/projects/1234',\n type: 'other',\n isTrusted: 0,\n} satisfies VendorListItem;\n\n/** The same vendor as `GET /vendors/{vendor}` returns it — `isTrusted` converted to a boolean. */\nconst vendorDetail = {\n ...thirdPartyVendor,\n isTrusted: false,\n} satisfies Vendor;\n\n// A pending, self-registered vendor. The `_v` id prefix is the marker that keeps it out of the\n// user-selectable vendor list until an admin approves and renames it. Only `GET /admin/vendors`\n// returns it — the public list filters on `isApproved`, and is the only response carrying the flag.\nconst pendingVendor = {\n id: '_v1699999999999',\n name: 'Pending Startup',\n email: 'hello@pending.example',\n address: 'Berlin',\n type: 'other',\n projectUrl: null,\n isApproved: false,\n isPublic: false,\n isTrusted: false,\n} satisfies AdminVendor;\n\n// The two public vendors as `GET /admin/vendors` returns them: approved, and `isTrusted` converted\n// to a boolean. They exist so the admin list is not a single pending row — a test that only ever\n// sees `pendingVendor` never exercises the approved path the admin table mostly renders.\nconst keboolaAdminVendor = {\n ...keboolaVendor,\n isApproved: true,\n isPublic: true,\n isTrusted: true,\n} satisfies AdminVendor;\n\nconst thirdPartyAdminVendor = {\n ...thirdPartyVendor,\n isApproved: true,\n isPublic: true,\n isTrusted: false,\n} satisfies AdminVendor;\n\n// The vendor as it arrives joined onto an app: five columns, none of the flags.\nconst appVendor = (vendor: VendorListItem): AppVendor => ({\n id: vendor.id,\n name: vendor.name,\n address: vendor.address,\n email: vendor.email,\n type: vendor.type,\n});\n\n/** A published, fully-populated extractor — the shape that passes `hasAllFieldsForPublishing`. */\nconst publishedExtractor = {\n id: 'keboola.ex-db-snowflake',\n vendor: appVendor(keboolaVendor),\n name: 'Snowflake',\n type: 'extractor',\n shortDescription: 'Extract data from Snowflake',\n longDescription: '## Snowflake extractor\\n\\nExtracts tables from a Snowflake database.',\n licenseUrl: 'https://github.com/keboola/ex-db-snowflake/blob/master/LICENSE.md',\n documentationUrl: 'https://help.keboola.com/components/extractors/database/snowflake/',\n sourceCodeUrl: 'https://github.com/keboola/ex-db-snowflake',\n categories: ['Database'],\n complexity: 'easy',\n uiOptions: ['genericDockerUI'],\n defaultBucket: true,\n defaultBucketStage: 'in',\n stagingStorageInput: 'local',\n stagingStorageOutput: 'local',\n logger: 'standard',\n isPublic: true,\n isDeprecated: false,\n fees: false,\n repository: { type: 'ecr', uri: 'keboola/ex-db-snowflake', tag: '1.9.0' },\n // The 128 filename ends in a 13-digit millisecond timestamp, so `getIcon` uses it. A legacy\n // incremental filename here would make `getIcon` fall back to the 64px variant.\n icon: {\n '64': 'https://ui.keboola-assets.com/developer-portal/icons/keboola.ex-db-snowflake/64/1699999999999.png',\n '128':\n 'https://ui.keboola-assets.com/developer-portal/icons/keboola.ex-db-snowflake/128/1699999999999.png',\n },\n version: 12,\n createdBy: 'support@keboola.com',\n updatedOn: '2024-06-01T09:00:00+0200',\n uri: 'docker/keboola.ex-db-snowflake',\n isPublished: true,\n publishedVersion: 12,\n publishingStatus: 'public',\n} satisfies App;\n\n/** A private third-party app with a pending publishing request. */\nconst requestedApp = {\n id: 'acme.wr-widgets',\n vendor: appVendor(thirdPartyVendor),\n name: 'Widget Writer',\n type: 'writer',\n shortDescription: 'Write data to Widgets',\n longDescription: 'Pushes tables into the Widgets API.',\n licenseUrl: 'https://acme.example/license',\n documentationUrl: 'https://acme.example/docs',\n uiOptions: ['genericDockerUI'],\n repository: { type: 'quay', uri: 'acme/wr-widgets', tag: '0.3.1' },\n icon: {\n '64': 'https://ui.keboola-assets.com/developer-portal/icons/acme.wr-widgets/64/1699999999998.png',\n '128':\n 'https://ui.keboola-assets.com/developer-portal/icons/acme.wr-widgets/128/1699999999998.png',\n },\n isPublic: false,\n isDeprecated: false,\n version: 3,\n createdBy: 'dev@acme.example',\n updatedOn: '2024-05-20T14:12:00+0200',\n uri: 'docker/acme.wr-widgets',\n isPublished: false,\n publishingStatus: 'requested',\n publishingRequest: { createdOn: '2024-05-20T14:12:00+0200', rejectionReason: null },\n} satisfies App;\n\n/** A rejected app — carries the reason the vendor sees on its detail page. */\nconst rejectedApp = {\n id: 'acme.app-analyzer',\n vendor: appVendor(thirdPartyVendor),\n name: 'Analyzer',\n type: 'application',\n shortDescription: 'Analyze things',\n isPublic: false,\n isDeprecated: false,\n version: 1,\n createdBy: 'dev@acme.example',\n uri: 'docker/acme.app-analyzer',\n isPublished: false,\n publishingStatus: 'rejected',\n publishingRequest: {\n createdOn: '2024-04-02T11:00:00+0200',\n rejectionReason: 'Documentation URL is missing and the icon is not 256×256.',\n },\n} satisfies App;\n\n/** A deprecated app with an expiry date and a suggested replacement. */\nconst deprecatedApp = {\n id: 'keboola.ex-legacy',\n vendor: appVendor(keboolaVendor),\n name: 'Legacy Extractor',\n type: 'extractor',\n shortDescription: 'Superseded',\n isPublic: true,\n isDeprecated: true,\n expiredOn: '2025-01-01',\n replacementApp: 'keboola.ex-db-snowflake',\n version: 40,\n uri: 'docker/keboola.ex-legacy',\n isPublished: true,\n publishedVersion: 38,\n publishingStatus: 'public',\n} satisfies App;\n\n/**\n * A `data-app`, the type whose edit form hides ~14 fields. Deliberately minimal: a fixture carrying\n * `configurationSchema` or `actions` here would misrepresent what the form can produce.\n */\nconst dataApp = {\n id: 'acme.data-app-dashboard',\n vendor: appVendor(thirdPartyVendor),\n name: 'Dashboard',\n type: 'data-app',\n shortDescription: 'A Streamlit dashboard',\n isPublic: false,\n isDeprecated: false,\n version: 2,\n uri: 'docker/acme.data-app-dashboard',\n isPublished: false,\n publishingStatus: 'private',\n} satisfies App;\n\n/** A `code-pattern`, whose `configurationSchema.supported_components` must be a non-empty array. */\nconst codePatternApp = {\n id: 'acme.code-pattern-etl',\n vendor: appVendor(thirdPartyVendor),\n name: 'ETL Pattern',\n type: 'code-pattern',\n shortDescription: 'Generates ETL code',\n actions: ['generate'],\n configurationSchema: { supported_components: ['keboola.snowflake-transformation'] },\n isPublic: false,\n version: 1,\n uri: 'docker/acme.code-pattern-etl',\n isPublished: false,\n publishingStatus: 'private',\n} satisfies App;\n\n/**\n * An app typed `other`. The public catalog excludes it entirely, so it exists to prove that\n * exclusion rather than to be rendered.\n */\nconst otherTypeApp = {\n id: 'acme.misc-thing',\n vendor: appVendor(thirdPartyVendor),\n name: 'Misc Thing',\n type: 'other',\n isPublic: true,\n version: 1,\n uri: 'docker/acme.misc-thing',\n isPublished: true,\n publishedVersion: 1,\n publishingStatus: 'public',\n} satisfies App;\n\n// `username` is the Cognito login, which is the user's email — the list endpoints return no\n// separate `email`, and no account state (`status`, `isEnabled`, `mfa`) either.\nconst humanUser = {\n username: 'dev@acme.example',\n name: 'Dev Eloper',\n vendors: ['acme'],\n createdOn: '2024-01-10T08:00:00+0100',\n} satisfies User;\n\n/** A recently added member, for a test that orders the list by `createdOn`. */\nconst newestUser = {\n username: 'new@acme.example',\n name: 'New Hire',\n vendors: ['acme'],\n createdOn: '2024-06-25T08:00:00+0200',\n} satisfies User;\n\n/** A member of no vendor — reachable only through the admin list. */\nconst vendorlessUser = {\n username: 'gone@acme.example',\n name: 'Alan Gone',\n vendors: [],\n createdOn: '2023-02-01T08:00:00+0100',\n} satisfies User;\n\n/** A Keboola staff member — eligible for \"make admin\" because they belong to the `keboola` vendor. */\nconst keboolaStaffUser = {\n username: 'staff@keboola.com',\n name: 'Kai Staff',\n vendors: ['keboola'],\n createdOn: '2023-09-14T08:00:00+0200',\n} satisfies User;\n\n/** A freshly created service account, including the one-time `password`. */\nconst newServiceAccount = {\n username: 'acme+ci',\n description: 'CI deploy pipeline',\n createdOn: '2024-07-01T10:00:00+0200',\n password: 'one-time-secret-shown-once',\n} satisfies ServiceAccount;\n\n/** The same account as later listed — note there is no `password`; it is unreadable after creation. */\nconst existingServiceAccount = {\n username: 'acme+release',\n description: 'Release automation',\n createdOn: '2024-03-11T10:00:00+0100',\n} satisfies ServiceAccount;\n\nconst appChange = {\n appId: 'acme.wr-widgets',\n createdOn: '2024-05-20T14:12:00+0200',\n createdBy: 'dev@acme.example',\n changes: [\n {\n attribute: 'shortDescription',\n oldValue: 'Writes widgets',\n newValue: 'Write data to Widgets',\n },\n {\n attribute: 'repository',\n oldValue: { type: 'quay', uri: 'acme/wr-widgets', tag: '0.3.0' },\n newValue: { type: 'quay', uri: 'acme/wr-widgets', tag: '0.3.1' },\n },\n ],\n} satisfies AppChange;\n\n/** The public catalog list: published, non-`other` apps only. */\nexport const listPublishedApps = (): App[] => [publishedExtractor, deprecatedApp];\n\n/** A vendor's own apps, across every publishing state the table renders. */\nexport const listVendorApps = (): App[] => [requestedApp, rejectedApp, dataApp, codePatternApp];\n\n/** The admin list — every vendor, plus the `other`-typed app the public catalog drops. */\nexport const listAllApps = (): App[] => [\n publishedExtractor,\n requestedApp,\n rejectedApp,\n deprecatedApp,\n dataApp,\n codePatternApp,\n otherTypeApp,\n];\n\n/** `GET /vendors` — approved and public only, so the pending vendor cannot appear here. */\nexport const listVendors = (): VendorListItem[] => [keboolaVendor, thirdPartyVendor];\n\n/** `GET /vendors/{vendor}` — the converted shape. */\nexport const getVendor = (): Vendor => vendorDetail;\n\n/** `GET /admin/vendors` — every vendor, and the only response carrying the approval flags. */\nexport const listAllVendors = (): AdminVendor[] => [\n keboolaAdminVendor,\n thirdPartyAdminVendor,\n pendingVendor,\n];\n\nexport const listUsers = (): User[] => [humanUser, newestUser, vendorlessUser, keboolaStaffUser];\n\nexport const listServiceAccounts = (): ServiceAccount[] => [existingServiceAccount];\n\nexport const listAppChanges = (): AppChange[] => [appChange];\n\n/** Named fixtures, for a test that needs one specific state. */\nexport const developerPortalFixtures = {\n apps: {\n published: publishedExtractor,\n requested: requestedApp,\n rejected: rejectedApp,\n deprecated: deprecatedApp,\n dataApp,\n codePattern: codePatternApp,\n otherType: otherTypeApp,\n },\n vendors: {\n keboola: keboolaVendor,\n thirdParty: thirdPartyVendor,\n detail: vendorDetail,\n pending: pendingVendor,\n keboolaAdmin: keboolaAdminVendor,\n thirdPartyAdmin: thirdPartyAdminVendor,\n },\n users: {\n human: humanUser,\n newest: newestUser,\n vendorless: vendorlessUser,\n keboolaStaff: keboolaStaffUser,\n },\n serviceAccounts: {\n created: newServiceAccount,\n existing: existingServiceAccount,\n },\n changes: { single: appChange },\n};\n","import { ServiceId } from '@keboola/api-client/constants';\nimport type { DevBranch, StackInfo, StorageToken } from '@keboola/api-client/storage/types';\n\n/** The stack an MSW-backed test points its client at, unless a caller passes its own. */\nexport const DEFAULT_BASE_URL = 'https://connection.test';\n\ntype StackInfoOptions = {\n /** Stack the fixture describes; its host is what the announced service URLs are built on. */\n baseUrl?: string;\n /** Services the stack announces. Narrow it to test what a client does without one. */\n services?: ServiceId[];\n};\n\ntype StorageTokenOptions = {\n /** Stack the token was issued by — its `uri`. */\n baseUrl?: string;\n /** Project features `hasFeature()` should report — the token's `owner.features`. */\n features?: string[];\n};\n\n/**\n * The stack index `GET /v2/storage` returns.\n *\n * - Announces every `ServiceId` by default, each on its own host, so no service client is a dummy\n * that throws `ServiceUnavailableError` — a test for a queue / data-science / vault hook only\n * adds its handler.\n * - Defaulting to `Object.values(ServiceId)` is what keeps that exhaustive: a service added to the\n * client arrives here without an edit.\n */\nexport const getStackInfo = ({\n baseUrl = DEFAULT_BASE_URL,\n services = Object.values(ServiceId),\n}: StackInfoOptions = {}): StackInfo => {\n const { host } = new URL(baseUrl);\n\n return {\n api: host,\n documentation: 'https://developers.keboola.com',\n host,\n revision: 'test-revision',\n stack: 'test-stack',\n version: 'test-version',\n urlTemplates: { orchestrationJob: '' },\n services: services.map((id) => ({ id, url: `https://${id}.${host}` })),\n components: [],\n features: [],\n };\n};\n\n/**\n * The verified master token `GET /v2/storage/tokens/verify` returns.\n *\n * - Complete on purpose: `api.context.project.sapiToken` is this object verbatim and hooks read deep\n * into it (`owner.id`, `admin.role`, `adminOwner.email`), so a partial body surfaces as\n * `undefined`s far from the test that caused them.\n * - Every permission flag is granted; a test needing a restricted token overrides the handler.\n */\nexport const verifyStorageToken = ({\n baseUrl = DEFAULT_BASE_URL,\n features = [],\n}: StorageTokenOptions = {}): StorageToken => ({\n id: 'token-1',\n created: '2024-01-01T00:00:00Z',\n refreshed: '2024-01-01T00:00:00Z',\n description: 'Test token',\n uri: baseUrl,\n isMasterToken: true,\n canManageBuckets: true,\n canManageTokens: true,\n canReadAllFileUploads: true,\n canPurgeTrash: true,\n canManageProtectedDefaultBranch: true,\n canCreateJobs: true,\n canReadAllProjectEvents: true,\n canManageDevBranches: true,\n creatorToken: { id: 42, description: 'Test token' },\n expires: null,\n isExpired: false,\n isDisabled: false,\n isBYODB: false,\n dailyCapacity: 1000,\n bucketPermissions: {},\n owner: {\n id: 42,\n name: 'Test Project',\n type: 'project',\n region: 'us-east-1',\n created: '2024-01-01T00:00:00Z',\n expires: null,\n features,\n dataSizeBytes: 0,\n rowsCount: 0,\n hasMysql: false,\n hasSynapse: false,\n hasRedshift: false,\n hasSnowflake: true,\n hasExasol: false,\n hasTeradata: false,\n hasBigquery: false,\n defaultBackend: 'snowflake',\n hasTryModeOn: 'false',\n limits: {},\n metrics: {},\n isDisabled: false,\n billedMonthlyPrice: null,\n dataRetentionTimeInDays: 30,\n assignedBackends: ['snowflake'],\n fileStorageProvider: 's3',\n },\n organization: { id: 'org-1' },\n admin: { id: 100, name: 'Admin User', features: [], isOrganizationMember: true, role: 'admin' },\n adminOwner: { id: 200, name: 'Owner User', email: 'owner@example.com' },\n});\n\n/**\n * The branch list `GET /v2/storage/dev-branches` returns — the default branch alone.\n *\n * - `context.defaultBranch` is read off it, so the entry must stay `isDefault: true`.\n * - The default branch has no creator, which `DevBranch` models as an empty `creatorToken`.\n */\nexport const getDevBranches = (): DevBranch[] => [\n {\n id: 1,\n name: 'Main',\n description: '',\n isDefault: true,\n created: '2024-01-01T00:00:00Z',\n creatorToken: [],\n },\n];\n","import type { Table, TableDetail } from '@keboola/api-client/storage/types';\n\nconst bucket = {\n id: 'in.c-main',\n name: 'c-main',\n displayName: 'Main',\n stage: 'in' as const,\n description: 'Main input bucket',\n created: '2024-01-15T10:00:00+0100',\n lastChangeDate: '2024-03-10T08:30:00+0100',\n isMaintenance: false,\n isReadOnly: false,\n isSnowflakeSharedDatabase: false,\n hasExternalSchema: false,\n rowsCount: 150000,\n dataSizeBytes: 52428800,\n uri: 'https://connection.keboola.com/v2/storage/buckets/in.c-main',\n backend: 'snowflake' as const,\n backendPath: [],\n databaseName: null,\n color: null,\n idBranch: 0,\n owner: null,\n sharing: null,\n path: 'in.c-main',\n tables: 'https://connection.keboola.com/v2/storage/buckets/in.c-main/tables',\n updated: '2024-03-10T08:30:00+0100',\n isLinkedBucket: false,\n bucketSharingAllowed: true,\n};\n\n// A freshly created table with no imports yet (non-typed, non-alias variant).\nconst freshTable = {\n id: 'in.c-main.users',\n name: 'users',\n displayName: 'Users',\n primaryKey: ['id'],\n metadata: [],\n columns: ['id', 'email', 'name', 'created_at'],\n columnMetadata: {},\n attributes: [],\n bucket,\n isTyped: false as const,\n isAlias: false as const,\n} satisfies TableDetail;\n\n// A recently updated table with a moderate size (non-typed, non-alias variant).\nconst recentlyUpdatedTable = {\n id: 'in.c-main.orders',\n name: 'orders',\n displayName: 'Orders',\n primaryKey: ['order_id'],\n metadata: [\n {\n id: 'mt1',\n key: 'KBC.createdBy.component.id',\n value: 'keboola.python-transformation',\n provider: 'keboola',\n timestamp: '2024-06-01T09:00:00+0200',\n },\n ],\n columns: ['order_id', 'user_id', 'total', 'status', 'created_at', 'updated_at'],\n columnMetadata: {\n order_id: [\n {\n id: 'm1',\n key: 'KBC.datatype.type',\n value: 'INTEGER',\n provider: 'keboola',\n timestamp: '2024-06-01T09:00:00+0200',\n },\n ],\n },\n attributes: [],\n bucket,\n isTyped: false as const,\n isAlias: false as const,\n} satisfies TableDetail;\n\n// A large table with many rows representing high-volume data (non-typed, non-alias variant).\nconst largeTable = {\n id: 'in.c-main.events',\n name: 'events',\n displayName: 'Events',\n primaryKey: [],\n metadata: [],\n columns: ['event_id', 'user_id', 'event_type', 'properties', 'occurred_at'],\n columnMetadata: {},\n attributes: [],\n bucket,\n isTyped: false as const,\n isAlias: false as const,\n} satisfies TableDetail;\n\n/**\n * Returns a single realistic typed TableDetail (fresh, no imports yet).\n *\n * The explicit return type ensures any divergence from the OpenAPI-derived\n * `TableDetail` in `@keboola/api-client` surfaces as a TypeScript error.\n */\nexport const getTable = (): TableDetail => freshTable;\n\n/**\n * Returns three TableDetail objects representing different lifecycle states:\n * 1. Fresh — just created, no data imported.\n * 2. Recently updated — moderate size, recent import.\n * 3. Large — high row count, large byte size.\n */\nexport const listTables = (): TableDetail[] => [freshTable, recentlyUpdatedTable, largeTable];\n\n/**\n * Named fixtures for targeted access in tests.\n */\nexport const tableFixtures = {\n fresh: freshTable,\n recentlyUpdated: recentlyUpdatedTable,\n large: largeTable,\n} satisfies Record<'fresh' | 'recentlyUpdated' | 'large', TableDetail>;\n\nexport type { Table, TableDetail };\n","import { appFixtures, getApp, listApps } from './clients/apps/apps';\nimport { deploymentFixtures, getDeployment, listDeployments } from './clients/apps/deployments';\nimport { getAppRun, listAppRuns, runFixtures } from './clients/apps/runs';\nimport {\n developerPortalFixtures,\n getVendor,\n listAllApps,\n listAllVendors,\n listAppChanges,\n listPublishedApps,\n listServiceAccounts,\n listUsers,\n listVendorApps,\n listVendors,\n} from './clients/developerPortal/apps';\nimport { getDevBranches, getStackInfo, verifyStorageToken } from './clients/storage/bootstrap';\nimport { getTable, listTables, tableFixtures } from './clients/storage/tables';\n\nexport const fixtures = {\n storage: {\n bootstrap: {\n getStackInfo,\n verifyStorageToken,\n getDevBranches,\n },\n tables: {\n getTable,\n listTables,\n fixtures: tableFixtures,\n },\n },\n apps: {\n apps: {\n getApp,\n listApps,\n fixtures: appFixtures,\n },\n deployments: {\n getDeployment,\n listDeployments,\n fixtures: deploymentFixtures,\n },\n runs: {\n getAppRun,\n listAppRuns,\n fixtures: runFixtures,\n },\n },\n developerPortal: {\n listPublishedApps,\n listVendorApps,\n listAllApps,\n listAllVendors,\n getVendor,\n listVendors,\n listUsers,\n listServiceAccounts,\n listAppChanges,\n fixtures: developerPortalFixtures,\n },\n};\n"],"mappings":"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"}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { App, AppRun, Deployment } from "@keboola/api-client/apps/types";
|
|
2
2
|
import { AdminVendor, App as App$1, AppChange, ServiceAccount, User, Vendor, VendorListItem } from "@keboola/api-client/developerPortal/types";
|
|
3
|
-
import {
|
|
3
|
+
import { ServiceId } from "@keboola/api-client/constants";
|
|
4
|
+
import { DevBranch, StackInfo, StorageToken, Table, TableDetail } from "@keboola/api-client/storage/types";
|
|
4
5
|
//#region src/clients/apps/apps.d.ts
|
|
5
6
|
declare const appFixtures: {
|
|
6
7
|
neverDeployed: {
|
|
@@ -649,6 +650,48 @@ declare const developerPortalFixtures: {
|
|
|
649
650
|
};
|
|
650
651
|
};
|
|
651
652
|
//#endregion
|
|
653
|
+
//#region src/clients/storage/bootstrap.d.ts
|
|
654
|
+
/** The stack an MSW-backed test points its client at, unless a caller passes its own. */
|
|
655
|
+
declare const DEFAULT_BASE_URL = "https://connection.test";
|
|
656
|
+
type StackInfoOptions = {
|
|
657
|
+
/** Stack the fixture describes; its host is what the announced service URLs are built on. */
|
|
658
|
+
baseUrl?: string;
|
|
659
|
+
/** Services the stack announces. Narrow it to test what a client does without one. */
|
|
660
|
+
services?: ServiceId[];
|
|
661
|
+
};
|
|
662
|
+
type StorageTokenOptions = {
|
|
663
|
+
/** Stack the token was issued by — its `uri`. */
|
|
664
|
+
baseUrl?: string;
|
|
665
|
+
/** Project features `hasFeature()` should report — the token's `owner.features`. */
|
|
666
|
+
features?: string[];
|
|
667
|
+
};
|
|
668
|
+
/**
|
|
669
|
+
* The stack index `GET /v2/storage` returns.
|
|
670
|
+
*
|
|
671
|
+
* - Announces every `ServiceId` by default, each on its own host, so no service client is a dummy
|
|
672
|
+
* that throws `ServiceUnavailableError` — a test for a queue / data-science / vault hook only
|
|
673
|
+
* adds its handler.
|
|
674
|
+
* - Defaulting to `Object.values(ServiceId)` is what keeps that exhaustive: a service added to the
|
|
675
|
+
* client arrives here without an edit.
|
|
676
|
+
*/
|
|
677
|
+
declare const getStackInfo: ({ baseUrl, services }?: StackInfoOptions) => StackInfo;
|
|
678
|
+
/**
|
|
679
|
+
* The verified master token `GET /v2/storage/tokens/verify` returns.
|
|
680
|
+
*
|
|
681
|
+
* - Complete on purpose: `api.context.project.sapiToken` is this object verbatim and hooks read deep
|
|
682
|
+
* into it (`owner.id`, `admin.role`, `adminOwner.email`), so a partial body surfaces as
|
|
683
|
+
* `undefined`s far from the test that caused them.
|
|
684
|
+
* - Every permission flag is granted; a test needing a restricted token overrides the handler.
|
|
685
|
+
*/
|
|
686
|
+
declare const verifyStorageToken: ({ baseUrl, features }?: StorageTokenOptions) => StorageToken;
|
|
687
|
+
/**
|
|
688
|
+
* The branch list `GET /v2/storage/dev-branches` returns — the default branch alone.
|
|
689
|
+
*
|
|
690
|
+
* - `context.defaultBranch` is read off it, so the entry must stay `isDefault: true`.
|
|
691
|
+
* - The default branch has no creator, which `DevBranch` models as an empty `creatorToken`.
|
|
692
|
+
*/
|
|
693
|
+
declare const getDevBranches: () => DevBranch[];
|
|
694
|
+
//#endregion
|
|
652
695
|
//#region src/clients/storage/tables.d.ts
|
|
653
696
|
/**
|
|
654
697
|
* Returns a single realistic typed TableDetail (fresh, no imports yet).
|
|
@@ -702,6 +745,8 @@ declare const tableFixtures: {
|
|
|
702
745
|
path: string;
|
|
703
746
|
tables: string;
|
|
704
747
|
updated: string;
|
|
748
|
+
isLinkedBucket: boolean;
|
|
749
|
+
bucketSharingAllowed: boolean;
|
|
705
750
|
};
|
|
706
751
|
isTyped: false;
|
|
707
752
|
isAlias: false;
|
|
@@ -754,6 +799,8 @@ declare const tableFixtures: {
|
|
|
754
799
|
path: string;
|
|
755
800
|
tables: string;
|
|
756
801
|
updated: string;
|
|
802
|
+
isLinkedBucket: boolean;
|
|
803
|
+
bucketSharingAllowed: boolean;
|
|
757
804
|
};
|
|
758
805
|
isTyped: false;
|
|
759
806
|
isAlias: false;
|
|
@@ -792,6 +839,8 @@ declare const tableFixtures: {
|
|
|
792
839
|
path: string;
|
|
793
840
|
tables: string;
|
|
794
841
|
updated: string;
|
|
842
|
+
isLinkedBucket: boolean;
|
|
843
|
+
bucketSharingAllowed: boolean;
|
|
795
844
|
};
|
|
796
845
|
isTyped: false;
|
|
797
846
|
isAlias: false;
|
|
@@ -801,6 +850,11 @@ declare const tableFixtures: {
|
|
|
801
850
|
//#region src/fixtures.d.ts
|
|
802
851
|
declare const fixtures: {
|
|
803
852
|
storage: {
|
|
853
|
+
bootstrap: {
|
|
854
|
+
getStackInfo: typeof getStackInfo;
|
|
855
|
+
verifyStorageToken: typeof verifyStorageToken;
|
|
856
|
+
getDevBranches: typeof getDevBranches;
|
|
857
|
+
};
|
|
804
858
|
tables: {
|
|
805
859
|
getTable: typeof getTable;
|
|
806
860
|
listTables: typeof listTables;
|
|
@@ -839,6 +893,8 @@ declare const fixtures: {
|
|
|
839
893
|
path: string;
|
|
840
894
|
tables: string;
|
|
841
895
|
updated: string;
|
|
896
|
+
isLinkedBucket: boolean;
|
|
897
|
+
bucketSharingAllowed: boolean;
|
|
842
898
|
};
|
|
843
899
|
isTyped: false;
|
|
844
900
|
isAlias: false;
|
|
@@ -891,6 +947,8 @@ declare const fixtures: {
|
|
|
891
947
|
path: string;
|
|
892
948
|
tables: string;
|
|
893
949
|
updated: string;
|
|
950
|
+
isLinkedBucket: boolean;
|
|
951
|
+
bucketSharingAllowed: boolean;
|
|
894
952
|
};
|
|
895
953
|
isTyped: false;
|
|
896
954
|
isAlias: false;
|
|
@@ -929,6 +987,8 @@ declare const fixtures: {
|
|
|
929
987
|
path: string;
|
|
930
988
|
tables: string;
|
|
931
989
|
updated: string;
|
|
990
|
+
isLinkedBucket: boolean;
|
|
991
|
+
bucketSharingAllowed: boolean;
|
|
932
992
|
};
|
|
933
993
|
isTyped: false;
|
|
934
994
|
isAlias: false;
|
|
@@ -1564,5 +1624,5 @@ declare const fixtures: {
|
|
|
1564
1624
|
};
|
|
1565
1625
|
};
|
|
1566
1626
|
//#endregion
|
|
1567
|
-
export { type Table, type TableDetail, appFixtures, deploymentFixtures, developerPortalFixtures, fixtures, getApp, getAppRun, getDeployment, getTable, getVendor, listAllApps, listAllVendors, listAppChanges, listAppRuns, listApps, listDeployments, listPublishedApps, listServiceAccounts, listTables, listUsers, listVendorApps, listVendors, runFixtures, tableFixtures };
|
|
1627
|
+
export { DEFAULT_BASE_URL, type Table, type TableDetail, appFixtures, deploymentFixtures, developerPortalFixtures, fixtures, getApp, getAppRun, getDeployment, getDevBranches, getStackInfo, getTable, getVendor, listAllApps, listAllVendors, listAppChanges, listAppRuns, listApps, listDeployments, listPublishedApps, listServiceAccounts, listTables, listUsers, listVendorApps, listVendors, runFixtures, tableFixtures, verifyStorageToken };
|
|
1568
1628
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { ServiceId } from "@keboola/api-client/constants";
|
|
1
2
|
import { App, AppRun, Deployment } from "@keboola/api-client/apps/types";
|
|
2
3
|
import { AdminVendor, App as App$1, AppChange, ServiceAccount, User, Vendor, VendorListItem } from "@keboola/api-client/developerPortal/types";
|
|
3
|
-
import { Table, TableDetail } from "@keboola/api-client/storage/types";
|
|
4
|
+
import { DevBranch, StackInfo, StorageToken, Table, TableDetail } from "@keboola/api-client/storage/types";
|
|
4
5
|
//#region src/clients/apps/apps.d.ts
|
|
5
6
|
declare const appFixtures: {
|
|
6
7
|
neverDeployed: {
|
|
@@ -649,6 +650,48 @@ declare const developerPortalFixtures: {
|
|
|
649
650
|
};
|
|
650
651
|
};
|
|
651
652
|
//#endregion
|
|
653
|
+
//#region src/clients/storage/bootstrap.d.ts
|
|
654
|
+
/** The stack an MSW-backed test points its client at, unless a caller passes its own. */
|
|
655
|
+
declare const DEFAULT_BASE_URL = "https://connection.test";
|
|
656
|
+
type StackInfoOptions = {
|
|
657
|
+
/** Stack the fixture describes; its host is what the announced service URLs are built on. */
|
|
658
|
+
baseUrl?: string;
|
|
659
|
+
/** Services the stack announces. Narrow it to test what a client does without one. */
|
|
660
|
+
services?: ServiceId[];
|
|
661
|
+
};
|
|
662
|
+
type StorageTokenOptions = {
|
|
663
|
+
/** Stack the token was issued by — its `uri`. */
|
|
664
|
+
baseUrl?: string;
|
|
665
|
+
/** Project features `hasFeature()` should report — the token's `owner.features`. */
|
|
666
|
+
features?: string[];
|
|
667
|
+
};
|
|
668
|
+
/**
|
|
669
|
+
* The stack index `GET /v2/storage` returns.
|
|
670
|
+
*
|
|
671
|
+
* - Announces every `ServiceId` by default, each on its own host, so no service client is a dummy
|
|
672
|
+
* that throws `ServiceUnavailableError` — a test for a queue / data-science / vault hook only
|
|
673
|
+
* adds its handler.
|
|
674
|
+
* - Defaulting to `Object.values(ServiceId)` is what keeps that exhaustive: a service added to the
|
|
675
|
+
* client arrives here without an edit.
|
|
676
|
+
*/
|
|
677
|
+
declare const getStackInfo: ({ baseUrl, services }?: StackInfoOptions) => StackInfo;
|
|
678
|
+
/**
|
|
679
|
+
* The verified master token `GET /v2/storage/tokens/verify` returns.
|
|
680
|
+
*
|
|
681
|
+
* - Complete on purpose: `api.context.project.sapiToken` is this object verbatim and hooks read deep
|
|
682
|
+
* into it (`owner.id`, `admin.role`, `adminOwner.email`), so a partial body surfaces as
|
|
683
|
+
* `undefined`s far from the test that caused them.
|
|
684
|
+
* - Every permission flag is granted; a test needing a restricted token overrides the handler.
|
|
685
|
+
*/
|
|
686
|
+
declare const verifyStorageToken: ({ baseUrl, features }?: StorageTokenOptions) => StorageToken;
|
|
687
|
+
/**
|
|
688
|
+
* The branch list `GET /v2/storage/dev-branches` returns — the default branch alone.
|
|
689
|
+
*
|
|
690
|
+
* - `context.defaultBranch` is read off it, so the entry must stay `isDefault: true`.
|
|
691
|
+
* - The default branch has no creator, which `DevBranch` models as an empty `creatorToken`.
|
|
692
|
+
*/
|
|
693
|
+
declare const getDevBranches: () => DevBranch[];
|
|
694
|
+
//#endregion
|
|
652
695
|
//#region src/clients/storage/tables.d.ts
|
|
653
696
|
/**
|
|
654
697
|
* Returns a single realistic typed TableDetail (fresh, no imports yet).
|
|
@@ -702,6 +745,8 @@ declare const tableFixtures: {
|
|
|
702
745
|
path: string;
|
|
703
746
|
tables: string;
|
|
704
747
|
updated: string;
|
|
748
|
+
isLinkedBucket: boolean;
|
|
749
|
+
bucketSharingAllowed: boolean;
|
|
705
750
|
};
|
|
706
751
|
isTyped: false;
|
|
707
752
|
isAlias: false;
|
|
@@ -754,6 +799,8 @@ declare const tableFixtures: {
|
|
|
754
799
|
path: string;
|
|
755
800
|
tables: string;
|
|
756
801
|
updated: string;
|
|
802
|
+
isLinkedBucket: boolean;
|
|
803
|
+
bucketSharingAllowed: boolean;
|
|
757
804
|
};
|
|
758
805
|
isTyped: false;
|
|
759
806
|
isAlias: false;
|
|
@@ -792,6 +839,8 @@ declare const tableFixtures: {
|
|
|
792
839
|
path: string;
|
|
793
840
|
tables: string;
|
|
794
841
|
updated: string;
|
|
842
|
+
isLinkedBucket: boolean;
|
|
843
|
+
bucketSharingAllowed: boolean;
|
|
795
844
|
};
|
|
796
845
|
isTyped: false;
|
|
797
846
|
isAlias: false;
|
|
@@ -801,6 +850,11 @@ declare const tableFixtures: {
|
|
|
801
850
|
//#region src/fixtures.d.ts
|
|
802
851
|
declare const fixtures: {
|
|
803
852
|
storage: {
|
|
853
|
+
bootstrap: {
|
|
854
|
+
getStackInfo: typeof getStackInfo;
|
|
855
|
+
verifyStorageToken: typeof verifyStorageToken;
|
|
856
|
+
getDevBranches: typeof getDevBranches;
|
|
857
|
+
};
|
|
804
858
|
tables: {
|
|
805
859
|
getTable: typeof getTable;
|
|
806
860
|
listTables: typeof listTables;
|
|
@@ -839,6 +893,8 @@ declare const fixtures: {
|
|
|
839
893
|
path: string;
|
|
840
894
|
tables: string;
|
|
841
895
|
updated: string;
|
|
896
|
+
isLinkedBucket: boolean;
|
|
897
|
+
bucketSharingAllowed: boolean;
|
|
842
898
|
};
|
|
843
899
|
isTyped: false;
|
|
844
900
|
isAlias: false;
|
|
@@ -891,6 +947,8 @@ declare const fixtures: {
|
|
|
891
947
|
path: string;
|
|
892
948
|
tables: string;
|
|
893
949
|
updated: string;
|
|
950
|
+
isLinkedBucket: boolean;
|
|
951
|
+
bucketSharingAllowed: boolean;
|
|
894
952
|
};
|
|
895
953
|
isTyped: false;
|
|
896
954
|
isAlias: false;
|
|
@@ -929,6 +987,8 @@ declare const fixtures: {
|
|
|
929
987
|
path: string;
|
|
930
988
|
tables: string;
|
|
931
989
|
updated: string;
|
|
990
|
+
isLinkedBucket: boolean;
|
|
991
|
+
bucketSharingAllowed: boolean;
|
|
932
992
|
};
|
|
933
993
|
isTyped: false;
|
|
934
994
|
isAlias: false;
|
|
@@ -1564,5 +1624,5 @@ declare const fixtures: {
|
|
|
1564
1624
|
};
|
|
1565
1625
|
};
|
|
1566
1626
|
//#endregion
|
|
1567
|
-
export { type Table, type TableDetail, appFixtures, deploymentFixtures, developerPortalFixtures, fixtures, getApp, getAppRun, getDeployment, getTable, getVendor, listAllApps, listAllVendors, listAppChanges, listAppRuns, listApps, listDeployments, listPublishedApps, listServiceAccounts, listTables, listUsers, listVendorApps, listVendors, runFixtures, tableFixtures };
|
|
1627
|
+
export { DEFAULT_BASE_URL, type Table, type TableDetail, appFixtures, deploymentFixtures, developerPortalFixtures, fixtures, getApp, getAppRun, getDeployment, getDevBranches, getStackInfo, getTable, getVendor, listAllApps, listAllVendors, listAppChanges, listAppRuns, listApps, listDeployments, listPublishedApps, listServiceAccounts, listTables, listUsers, listVendorApps, listVendors, runFixtures, tableFixtures, verifyStorageToken };
|
|
1568
1628
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ServiceId } from "@keboola/api-client/constants";
|
|
1
2
|
//#region src/clients/apps/deployments.ts
|
|
2
3
|
/**
|
|
3
4
|
* Deployment ids are the deterministic Kubernetes CR name — `app-{appId}-dpl-{hash}` —
|
|
@@ -652,6 +653,125 @@ const developerPortalFixtures = {
|
|
|
652
653
|
changes: { single: appChange }
|
|
653
654
|
};
|
|
654
655
|
//#endregion
|
|
656
|
+
//#region src/clients/storage/bootstrap.ts
|
|
657
|
+
/** The stack an MSW-backed test points its client at, unless a caller passes its own. */
|
|
658
|
+
const DEFAULT_BASE_URL = "https://connection.test";
|
|
659
|
+
/**
|
|
660
|
+
* The stack index `GET /v2/storage` returns.
|
|
661
|
+
*
|
|
662
|
+
* - Announces every `ServiceId` by default, each on its own host, so no service client is a dummy
|
|
663
|
+
* that throws `ServiceUnavailableError` — a test for a queue / data-science / vault hook only
|
|
664
|
+
* adds its handler.
|
|
665
|
+
* - Defaulting to `Object.values(ServiceId)` is what keeps that exhaustive: a service added to the
|
|
666
|
+
* client arrives here without an edit.
|
|
667
|
+
*/
|
|
668
|
+
const getStackInfo = ({ baseUrl = DEFAULT_BASE_URL, services = Object.values(ServiceId) } = {}) => {
|
|
669
|
+
const { host } = new URL(baseUrl);
|
|
670
|
+
return {
|
|
671
|
+
api: host,
|
|
672
|
+
documentation: "https://developers.keboola.com",
|
|
673
|
+
host,
|
|
674
|
+
revision: "test-revision",
|
|
675
|
+
stack: "test-stack",
|
|
676
|
+
version: "test-version",
|
|
677
|
+
urlTemplates: { orchestrationJob: "" },
|
|
678
|
+
services: services.map((id) => ({
|
|
679
|
+
id,
|
|
680
|
+
url: `https://${id}.${host}`
|
|
681
|
+
})),
|
|
682
|
+
components: [],
|
|
683
|
+
features: []
|
|
684
|
+
};
|
|
685
|
+
};
|
|
686
|
+
/**
|
|
687
|
+
* The verified master token `GET /v2/storage/tokens/verify` returns.
|
|
688
|
+
*
|
|
689
|
+
* - Complete on purpose: `api.context.project.sapiToken` is this object verbatim and hooks read deep
|
|
690
|
+
* into it (`owner.id`, `admin.role`, `adminOwner.email`), so a partial body surfaces as
|
|
691
|
+
* `undefined`s far from the test that caused them.
|
|
692
|
+
* - Every permission flag is granted; a test needing a restricted token overrides the handler.
|
|
693
|
+
*/
|
|
694
|
+
const verifyStorageToken = ({ baseUrl = DEFAULT_BASE_URL, features = [] } = {}) => ({
|
|
695
|
+
id: "token-1",
|
|
696
|
+
created: "2024-01-01T00:00:00Z",
|
|
697
|
+
refreshed: "2024-01-01T00:00:00Z",
|
|
698
|
+
description: "Test token",
|
|
699
|
+
uri: baseUrl,
|
|
700
|
+
isMasterToken: true,
|
|
701
|
+
canManageBuckets: true,
|
|
702
|
+
canManageTokens: true,
|
|
703
|
+
canReadAllFileUploads: true,
|
|
704
|
+
canPurgeTrash: true,
|
|
705
|
+
canManageProtectedDefaultBranch: true,
|
|
706
|
+
canCreateJobs: true,
|
|
707
|
+
canReadAllProjectEvents: true,
|
|
708
|
+
canManageDevBranches: true,
|
|
709
|
+
creatorToken: {
|
|
710
|
+
id: 42,
|
|
711
|
+
description: "Test token"
|
|
712
|
+
},
|
|
713
|
+
expires: null,
|
|
714
|
+
isExpired: false,
|
|
715
|
+
isDisabled: false,
|
|
716
|
+
isBYODB: false,
|
|
717
|
+
dailyCapacity: 1e3,
|
|
718
|
+
bucketPermissions: {},
|
|
719
|
+
owner: {
|
|
720
|
+
id: 42,
|
|
721
|
+
name: "Test Project",
|
|
722
|
+
type: "project",
|
|
723
|
+
region: "us-east-1",
|
|
724
|
+
created: "2024-01-01T00:00:00Z",
|
|
725
|
+
expires: null,
|
|
726
|
+
features,
|
|
727
|
+
dataSizeBytes: 0,
|
|
728
|
+
rowsCount: 0,
|
|
729
|
+
hasMysql: false,
|
|
730
|
+
hasSynapse: false,
|
|
731
|
+
hasRedshift: false,
|
|
732
|
+
hasSnowflake: true,
|
|
733
|
+
hasExasol: false,
|
|
734
|
+
hasTeradata: false,
|
|
735
|
+
hasBigquery: false,
|
|
736
|
+
defaultBackend: "snowflake",
|
|
737
|
+
hasTryModeOn: "false",
|
|
738
|
+
limits: {},
|
|
739
|
+
metrics: {},
|
|
740
|
+
isDisabled: false,
|
|
741
|
+
billedMonthlyPrice: null,
|
|
742
|
+
dataRetentionTimeInDays: 30,
|
|
743
|
+
assignedBackends: ["snowflake"],
|
|
744
|
+
fileStorageProvider: "s3"
|
|
745
|
+
},
|
|
746
|
+
organization: { id: "org-1" },
|
|
747
|
+
admin: {
|
|
748
|
+
id: 100,
|
|
749
|
+
name: "Admin User",
|
|
750
|
+
features: [],
|
|
751
|
+
isOrganizationMember: true,
|
|
752
|
+
role: "admin"
|
|
753
|
+
},
|
|
754
|
+
adminOwner: {
|
|
755
|
+
id: 200,
|
|
756
|
+
name: "Owner User",
|
|
757
|
+
email: "owner@example.com"
|
|
758
|
+
}
|
|
759
|
+
});
|
|
760
|
+
/**
|
|
761
|
+
* The branch list `GET /v2/storage/dev-branches` returns — the default branch alone.
|
|
762
|
+
*
|
|
763
|
+
* - `context.defaultBranch` is read off it, so the entry must stay `isDefault: true`.
|
|
764
|
+
* - The default branch has no creator, which `DevBranch` models as an empty `creatorToken`.
|
|
765
|
+
*/
|
|
766
|
+
const getDevBranches = () => [{
|
|
767
|
+
id: 1,
|
|
768
|
+
name: "Main",
|
|
769
|
+
description: "",
|
|
770
|
+
isDefault: true,
|
|
771
|
+
created: "2024-01-01T00:00:00Z",
|
|
772
|
+
creatorToken: []
|
|
773
|
+
}];
|
|
774
|
+
//#endregion
|
|
655
775
|
//#region src/clients/storage/tables.ts
|
|
656
776
|
const bucket = {
|
|
657
777
|
id: "in.c-main",
|
|
@@ -677,7 +797,9 @@ const bucket = {
|
|
|
677
797
|
sharing: null,
|
|
678
798
|
path: "in.c-main",
|
|
679
799
|
tables: "https://connection.keboola.com/v2/storage/buckets/in.c-main/tables",
|
|
680
|
-
updated: "2024-03-10T08:30:00+0100"
|
|
800
|
+
updated: "2024-03-10T08:30:00+0100",
|
|
801
|
+
isLinkedBucket: false,
|
|
802
|
+
bucketSharingAllowed: true
|
|
681
803
|
};
|
|
682
804
|
const freshTable = {
|
|
683
805
|
id: "in.c-main.users",
|
|
@@ -777,11 +899,18 @@ const tableFixtures = {
|
|
|
777
899
|
//#endregion
|
|
778
900
|
//#region src/fixtures.ts
|
|
779
901
|
const fixtures = {
|
|
780
|
-
storage: {
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
902
|
+
storage: {
|
|
903
|
+
bootstrap: {
|
|
904
|
+
getStackInfo,
|
|
905
|
+
verifyStorageToken,
|
|
906
|
+
getDevBranches
|
|
907
|
+
},
|
|
908
|
+
tables: {
|
|
909
|
+
getTable,
|
|
910
|
+
listTables,
|
|
911
|
+
fixtures: tableFixtures
|
|
912
|
+
}
|
|
913
|
+
},
|
|
785
914
|
apps: {
|
|
786
915
|
apps: {
|
|
787
916
|
getApp,
|
|
@@ -813,6 +942,6 @@ const fixtures = {
|
|
|
813
942
|
}
|
|
814
943
|
};
|
|
815
944
|
//#endregion
|
|
816
|
-
export { appFixtures, deploymentFixtures, developerPortalFixtures, fixtures, getApp, getAppRun, getDeployment, getTable, getVendor, listAllApps, listAllVendors, listAppChanges, listAppRuns, listApps, listDeployments, listPublishedApps, listServiceAccounts, listTables, listUsers, listVendorApps, listVendors, runFixtures, tableFixtures };
|
|
945
|
+
export { DEFAULT_BASE_URL, appFixtures, deploymentFixtures, developerPortalFixtures, fixtures, getApp, getAppRun, getDeployment, getDevBranches, getStackInfo, getTable, getVendor, listAllApps, listAllVendors, listAppChanges, listAppRuns, listApps, listDeployments, listPublishedApps, listServiceAccounts, listTables, listUsers, listVendorApps, listVendors, runFixtures, tableFixtures, verifyStorageToken };
|
|
817
946
|
|
|
818
947
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["base"],"sources":["../src/clients/apps/deployments.ts","../src/clients/apps/apps.ts","../src/clients/apps/runs.ts","../src/clients/developerPortal/apps.ts","../src/clients/storage/tables.ts","../src/fixtures.ts"],"sourcesContent":["import type { Deployment } from '@keboola/api-client/apps/types';\n\n/**\n * Deployment ids are the deterministic Kubernetes CR name — `app-{appId}-dpl-{hash}` —\n * so they are reproduced in that shape rather than as opaque strings.\n */\nexport const APP_ID = '374811';\n\nconst deploymentId = (hash: string) => `app-${APP_ID}-dpl-${hash}`;\n\n// Retired: the row outlives its CR, so it stays in history with `archived: true`.\nconst archivedDeployment = {\n id: deploymentId('350e2cf5287c5665'),\n number: 1,\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n configVersion: '14',\n gitCommitSha: null,\n size: 'tiny' as const,\n buildState: 'PREBUILT' as const,\n runState: 'STOPPED' as const,\n archived: true,\n archivedAt: '2026-08-15T11:03:02+00:00',\n createdAt: '2026-08-10T09:12:44+00:00',\n} satisfies Deployment;\n\n// Serving production — the one `appFixtures.running.production` points at.\nconst liveDeployment = {\n id: deploymentId('7a4c1b9e0d3f2a81'),\n number: 2,\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n configVersion: '16',\n gitCommitSha: null,\n size: 'small' as const,\n buildState: 'PREBUILT' as const,\n runState: 'RUNNING' as const,\n archived: false,\n archivedAt: null,\n createdAt: '2026-08-15T11:02:58+00:00',\n} satisfies Deployment;\n\n// Created with `promote: false`: pinned and built, but nothing ever started it.\nconst stagedDeployment = {\n id: deploymentId('c5e83f17b204de96'),\n number: 3,\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n configVersion: '18',\n gitCommitSha: null,\n size: 'small' as const,\n buildState: 'PREBUILT' as const,\n runState: 'NEVER_RUN' as const,\n archived: false,\n archivedAt: null,\n createdAt: '2026-08-17T08:41:19+00:00',\n} satisfies Deployment;\n\n// No artifact was produced, so this deployment can never run — a different problem,\n// with a different fix, from a run failure. Not reachable on the platform today\n// (every deployment is `PREBUILT`); the headline table treats it as a contract.\nconst buildFailedDeployment = {\n id: deploymentId('e91d47a8c6b02f35'),\n number: 4,\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n configVersion: '19',\n gitCommitSha: null,\n size: 'small' as const,\n buildState: 'FAILED' as const,\n runState: 'NEVER_RUN' as const,\n archived: false,\n archivedAt: null,\n createdAt: '2026-08-17T09:05:33+00:00',\n} satisfies Deployment;\n\n// Built fine, crashed on every run — `getAppRuns` carries the cause.\nconst runFailedDeployment = {\n id: deploymentId('2b6f0a94e7d51c83'),\n number: 5,\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n configVersion: '20',\n gitCommitSha: null,\n size: 'small' as const,\n buildState: 'PREBUILT' as const,\n runState: 'FAILED' as const,\n archived: false,\n archivedAt: null,\n createdAt: '2026-08-17T09:31:07+00:00',\n} satisfies Deployment;\n\nexport const deploymentFixtures = {\n archived: archivedDeployment,\n live: liveDeployment,\n staged: stagedDeployment,\n buildFailed: buildFailedDeployment,\n runFailed: runFailedDeployment,\n} satisfies Record<'archived' | 'live' | 'staged' | 'buildFailed' | 'runFailed', Deployment>;\n\nexport const getDeployment = (): Deployment => liveDeployment;\n\n/**\n * One continuous history: #1 retired, #2 serving, #3 staged, #4 failed to build, #5 built but its\n * run failed.\n *\n * All five, because `runFixtures.failed` names #5 as its deployment — a list that left the failed\n * ones out could not be joined to the runs, which is the join a timeline is built from.\n *\n * Returned in ascending `number` order. The endpoint does not specify an order, so consumers must\n * sort for themselves — this order is a fixture convention, not a contract to rely on, and it is\n * ascending on purpose: a consumer that assumes newest-first gets the wrong answer here rather\n * than in production.\n */\nexport const listDeployments = (): Deployment[] => [\n archivedDeployment,\n liveDeployment,\n stagedDeployment,\n buildFailedDeployment,\n runFailedDeployment,\n];\n","import type { App } from '@keboola/api-client/apps/types';\n\nimport { APP_ID, deploymentFixtures } from './deployments';\n\nconst APP_URL = 'https://hello-dashboard-374811.hub.canary-orion.keboola.dev';\n\nconst base = {\n id: APP_ID,\n projectId: '14',\n componentId: 'keboola.data-apps',\n branchId: '6',\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n type: 'streamlit' as const,\n mode: 'prod' as const,\n url: APP_URL,\n};\n\nconst production = (deployment: (typeof deploymentFixtures)[keyof typeof deploymentFixtures]) => ({\n desiredNumber: deployment.number,\n desiredId: deployment.id,\n actualNumber: deployment.number,\n actualId: deployment.id,\n});\n\n// Created through `/v2`, nothing deployed yet: the URL is reserved and publicly 404s.\nconst neverDeployedApp = {\n ...base,\n configVersion: '1',\n production: { desiredNumber: null, desiredId: null, actualNumber: null, actualId: null },\n undeployedChanges: false,\n state: 'NOT_DEPLOYED' as const,\n} satisfies App;\n\n/**\n * Transcribed verbatim from canary on 17 Aug 2026 (AJDA-3140, probe P1): an app created and\n * started through `/v1`, serving real traffic (HTTP 200, 8340 B) at the moment this was read,\n * which `/v2` nonetheless reports as `NOT_DEPLOYED` with an empty `production` because it was\n * never adopted into the deployments model.\n *\n * The Builder must never read \"is this app serving\" off `state` alone — here that answer is\n * wrong in the most damaging direction.\n */\nconst legacyV1ServingApp = {\n id: '374811',\n projectId: '14',\n componentId: 'keboola.data-apps',\n branchId: '6',\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n configVersion: '2',\n type: 'streamlit' as const,\n mode: 'dev' as const,\n url: APP_URL,\n production: { desiredNumber: null, desiredId: null, actualNumber: null, actualId: null },\n undeployedChanges: false,\n state: 'NOT_DEPLOYED' as const,\n} satisfies App;\n\n// Serving deployment #2, config unchanged since it was deployed.\nconst runningApp = {\n ...base,\n configVersion: deploymentFixtures.live.configVersion,\n production: production(deploymentFixtures.live),\n undeployedChanges: false,\n state: 'RUNNING' as const,\n} satisfies App;\n\n// Still serving #2 (config v16) while the config has moved on to v18.\nconst appWithUndeployedChanges = {\n ...base,\n configVersion: deploymentFixtures.staged.configVersion,\n production: production(deploymentFixtures.live),\n undeployedChanges: true,\n state: 'RUNNING' as const,\n} satisfies App;\n\n/**\n * A blue/green promotion in flight: #3 has been asked for, #2 is still what traffic reaches.\n * `state` stays `RUNNING` throughout — the rollout is only visible as `desiredId !== actualId`.\n */\nconst promotingApp = {\n ...base,\n configVersion: deploymentFixtures.staged.configVersion,\n production: {\n desiredNumber: deploymentFixtures.staged.number,\n desiredId: deploymentFixtures.staged.id,\n actualNumber: deploymentFixtures.live.number,\n actualId: deploymentFixtures.live.id,\n },\n undeployedChanges: true,\n state: 'RUNNING' as const,\n} satisfies App;\n\n// Idle between visits and armed to wake on the next request — normal, not an outage.\nconst sleepingApp = {\n ...base,\n configVersion: deploymentFixtures.live.configVersion,\n production: production(deploymentFixtures.live),\n undeployedChanges: false,\n state: 'SLEEPING' as const,\n} satisfies App;\n\n// Explicitly suspended: a visitor gets a 503 until someone resumes it.\nconst suspendedApp = {\n ...base,\n configVersion: deploymentFixtures.live.configVersion,\n production: production(deploymentFixtures.live),\n undeployedChanges: false,\n state: 'SUSPENDED' as const,\n} satisfies App;\n\nexport const appFixtures = {\n neverDeployed: neverDeployedApp,\n legacyV1Serving: legacyV1ServingApp,\n running: runningApp,\n undeployedChanges: appWithUndeployedChanges,\n promoting: promotingApp,\n sleeping: sleepingApp,\n suspended: suspendedApp,\n} satisfies Record<\n | 'neverDeployed'\n | 'legacyV1Serving'\n | 'running'\n | 'undeployedChanges'\n | 'promoting'\n | 'sleeping'\n | 'suspended',\n App\n>;\n\nexport const getApp = (): App => runningApp;\n\n/**\n * The named fixtures above are all the *same* app in different states, which is what a detail\n * page shows. A listing shows different apps, so each entry past the first is re-addressed —\n * including the deployment ids inside `production`, which embed the app id.\n */\nconst readdress = (app: App, id: string): App => ({\n ...app,\n id,\n url: `https://data-app-${id}.hub.canary-orion.keboola.dev`,\n production: {\n ...app.production,\n desiredId: app.production.desiredId?.replace(APP_ID, id) ?? null,\n actualId: app.production.actualId?.replace(APP_ID, id) ?? null,\n },\n});\n\nexport const listApps = (): App[] => [\n runningApp,\n readdress(appWithUndeployedChanges, '374812'),\n readdress(neverDeployedApp, '374813'),\n];\n","import type { AppRun } from '@keboola/api-client/apps/types';\n\nimport { APP_ID, deploymentFixtures } from './deployments';\n\nconst base = {\n appId: APP_ID,\n runtimeSize: 'small',\n runtimeBackendType: 'streamlit',\n imageVersion: '1.14.2',\n mode: 'prod',\n};\n\nconst runningRun = {\n ...base,\n id: '4f2d8c1a-0b76-4e35-9a12-5c8e7d3b0f41',\n deploymentId: deploymentFixtures.live.id,\n configVersion: deploymentFixtures.live.configVersion,\n state: 'running' as const,\n createdAt: '2026-08-15T11:02:58+00:00',\n startedAt: '2026-08-15T11:03:41+00:00',\n stoppedAt: null,\n startupLogs: null,\n failureReason: null,\n} satisfies AppRun;\n\nconst finishedRun = {\n ...base,\n id: '9c0a7e42-31bd-4f88-b6d5-2ea41f907c3b',\n deploymentId: deploymentFixtures.archived.id,\n configVersion: deploymentFixtures.archived.configVersion,\n state: 'finished' as const,\n createdAt: '2026-08-10T09:12:44+00:00',\n startedAt: '2026-08-10T09:13:29+00:00',\n stoppedAt: '2026-08-15T11:03:02+00:00',\n startupLogs: null,\n failureReason: null,\n} satisfies AppRun;\n\n/**\n * A classified failure transcribed from canary (AJDA-3140, probe P1). `startedAt` is `null`\n * even though a cause was attributed — the container executed but its startup probe never\n * passed, so a classified failure says nothing about how far the run got.\n */\nconst failedRun = {\n ...base,\n id: 'ba53f9d0-7c41-4a2e-8f16-d0b9e254a7c6',\n deploymentId: deploymentFixtures.runFailed.id,\n configVersion: deploymentFixtures.runFailed.configVersion,\n state: 'failed' as const,\n createdAt: '2026-08-17T09:31:07+00:00',\n startedAt: null,\n stoppedAt: '2026-08-17T09:33:52+00:00',\n startupLogs:\n '[INFO] Starting app\\n[ERROR] App must have keboola-config/nginx/ directory. Missing: /app/keboola-config/nginx\\n',\n failureReason: {\n reason: 'StartupProbeFailed',\n message: 'App must have keboola-config/nginx/ directory. Missing: /app/keboola-config/nginx',\n },\n} satisfies AppRun;\n\n/**\n * A run that belongs to the app itself rather than to a deployment — what every run of a\n * `/v1`-created app looks like. `deploymentId: null` is permanent for these, not drift.\n */\nconst legacyRun = {\n ...base,\n id: '1d7b4e05-8a92-4c63-b0f7-3e6a5c8192d4',\n deploymentId: null,\n configVersion: '2',\n state: 'running' as const,\n createdAt: '2026-08-17T10:02:11+00:00',\n startedAt: '2026-08-17T10:02:51+00:00',\n stoppedAt: null,\n startupLogs: null,\n failureReason: null,\n} satisfies AppRun;\n\nexport const runFixtures = {\n running: runningRun,\n finished: finishedRun,\n failed: failedRun,\n legacy: legacyRun,\n} satisfies Record<'running' | 'finished' | 'failed' | 'legacy', AppRun>;\n\nexport const getAppRun = (): AppRun => runningRun;\n\n/**\n * Every run this app has, newest first — the order the endpoint documents, so a consumer that\n * relies on it (`[latest] = runs`) is exercised against data that keeps the promise rather than\n * data that happens to contradict it.\n */\nexport const listAppRuns = (): AppRun[] => [legacyRun, failedRun, runningRun, finishedRun];\n","import type {\n AdminVendor,\n App,\n AppChange,\n AppVendor,\n ServiceAccount,\n User,\n Vendor,\n VendorListItem,\n} from '@keboola/api-client/developerPortal/types';\n\n// `isTrusted` is the raw tinyint here and a boolean in `vendorDetail` below. That is not a fixture\n// inconsistency: `GET /vendors` returns the row unconverted, every other vendor endpoint runs it\n// through `publicGetVendor`. A fixture that smoothed it over would hide the difference consumers\n// have to handle.\n//\n// `type: 'keboola'` is what the public catalog's \"Supported by Keboola\" filter matches on — NOT\n// `id`, so a fixture that only set the id would silently fail to exercise that filter.\nconst keboolaVendor = {\n id: 'keboola',\n name: 'Keboola',\n email: 'support@keboola.com',\n address: 'Prague, Czech Republic',\n type: 'keboola',\n projectUrl: null,\n isTrusted: 1,\n} satisfies VendorListItem;\n\nconst thirdPartyVendor = {\n id: 'acme',\n name: 'Acme Co.',\n email: 'dev@acme.example',\n address: 'Springfield',\n projectUrl: 'https://connection.keboola.com/admin/projects/1234',\n type: 'other',\n isTrusted: 0,\n} satisfies VendorListItem;\n\n/** The same vendor as `GET /vendors/{vendor}` returns it — `isTrusted` converted to a boolean. */\nconst vendorDetail = {\n ...thirdPartyVendor,\n isTrusted: false,\n} satisfies Vendor;\n\n// A pending, self-registered vendor. The `_v` id prefix is the marker that keeps it out of the\n// user-selectable vendor list until an admin approves and renames it. Only `GET /admin/vendors`\n// returns it — the public list filters on `isApproved`, and is the only response carrying the flag.\nconst pendingVendor = {\n id: '_v1699999999999',\n name: 'Pending Startup',\n email: 'hello@pending.example',\n address: 'Berlin',\n type: 'other',\n projectUrl: null,\n isApproved: false,\n isPublic: false,\n isTrusted: false,\n} satisfies AdminVendor;\n\n// The two public vendors as `GET /admin/vendors` returns them: approved, and `isTrusted` converted\n// to a boolean. They exist so the admin list is not a single pending row — a test that only ever\n// sees `pendingVendor` never exercises the approved path the admin table mostly renders.\nconst keboolaAdminVendor = {\n ...keboolaVendor,\n isApproved: true,\n isPublic: true,\n isTrusted: true,\n} satisfies AdminVendor;\n\nconst thirdPartyAdminVendor = {\n ...thirdPartyVendor,\n isApproved: true,\n isPublic: true,\n isTrusted: false,\n} satisfies AdminVendor;\n\n// The vendor as it arrives joined onto an app: five columns, none of the flags.\nconst appVendor = (vendor: VendorListItem): AppVendor => ({\n id: vendor.id,\n name: vendor.name,\n address: vendor.address,\n email: vendor.email,\n type: vendor.type,\n});\n\n/** A published, fully-populated extractor — the shape that passes `hasAllFieldsForPublishing`. */\nconst publishedExtractor = {\n id: 'keboola.ex-db-snowflake',\n vendor: appVendor(keboolaVendor),\n name: 'Snowflake',\n type: 'extractor',\n shortDescription: 'Extract data from Snowflake',\n longDescription: '## Snowflake extractor\\n\\nExtracts tables from a Snowflake database.',\n licenseUrl: 'https://github.com/keboola/ex-db-snowflake/blob/master/LICENSE.md',\n documentationUrl: 'https://help.keboola.com/components/extractors/database/snowflake/',\n sourceCodeUrl: 'https://github.com/keboola/ex-db-snowflake',\n categories: ['Database'],\n complexity: 'easy',\n uiOptions: ['genericDockerUI'],\n defaultBucket: true,\n defaultBucketStage: 'in',\n stagingStorageInput: 'local',\n stagingStorageOutput: 'local',\n logger: 'standard',\n isPublic: true,\n isDeprecated: false,\n fees: false,\n repository: { type: 'ecr', uri: 'keboola/ex-db-snowflake', tag: '1.9.0' },\n // The 128 filename ends in a 13-digit millisecond timestamp, so `getIcon` uses it. A legacy\n // incremental filename here would make `getIcon` fall back to the 64px variant.\n icon: {\n '64': 'https://ui.keboola-assets.com/developer-portal/icons/keboola.ex-db-snowflake/64/1699999999999.png',\n '128':\n 'https://ui.keboola-assets.com/developer-portal/icons/keboola.ex-db-snowflake/128/1699999999999.png',\n },\n version: 12,\n createdBy: 'support@keboola.com',\n updatedOn: '2024-06-01T09:00:00+0200',\n uri: 'docker/keboola.ex-db-snowflake',\n isPublished: true,\n publishedVersion: 12,\n publishingStatus: 'public',\n} satisfies App;\n\n/** A private third-party app with a pending publishing request. */\nconst requestedApp = {\n id: 'acme.wr-widgets',\n vendor: appVendor(thirdPartyVendor),\n name: 'Widget Writer',\n type: 'writer',\n shortDescription: 'Write data to Widgets',\n longDescription: 'Pushes tables into the Widgets API.',\n licenseUrl: 'https://acme.example/license',\n documentationUrl: 'https://acme.example/docs',\n uiOptions: ['genericDockerUI'],\n repository: { type: 'quay', uri: 'acme/wr-widgets', tag: '0.3.1' },\n icon: {\n '64': 'https://ui.keboola-assets.com/developer-portal/icons/acme.wr-widgets/64/1699999999998.png',\n '128':\n 'https://ui.keboola-assets.com/developer-portal/icons/acme.wr-widgets/128/1699999999998.png',\n },\n isPublic: false,\n isDeprecated: false,\n version: 3,\n createdBy: 'dev@acme.example',\n updatedOn: '2024-05-20T14:12:00+0200',\n uri: 'docker/acme.wr-widgets',\n isPublished: false,\n publishingStatus: 'requested',\n publishingRequest: { createdOn: '2024-05-20T14:12:00+0200', rejectionReason: null },\n} satisfies App;\n\n/** A rejected app — carries the reason the vendor sees on its detail page. */\nconst rejectedApp = {\n id: 'acme.app-analyzer',\n vendor: appVendor(thirdPartyVendor),\n name: 'Analyzer',\n type: 'application',\n shortDescription: 'Analyze things',\n isPublic: false,\n isDeprecated: false,\n version: 1,\n createdBy: 'dev@acme.example',\n uri: 'docker/acme.app-analyzer',\n isPublished: false,\n publishingStatus: 'rejected',\n publishingRequest: {\n createdOn: '2024-04-02T11:00:00+0200',\n rejectionReason: 'Documentation URL is missing and the icon is not 256×256.',\n },\n} satisfies App;\n\n/** A deprecated app with an expiry date and a suggested replacement. */\nconst deprecatedApp = {\n id: 'keboola.ex-legacy',\n vendor: appVendor(keboolaVendor),\n name: 'Legacy Extractor',\n type: 'extractor',\n shortDescription: 'Superseded',\n isPublic: true,\n isDeprecated: true,\n expiredOn: '2025-01-01',\n replacementApp: 'keboola.ex-db-snowflake',\n version: 40,\n uri: 'docker/keboola.ex-legacy',\n isPublished: true,\n publishedVersion: 38,\n publishingStatus: 'public',\n} satisfies App;\n\n/**\n * A `data-app`, the type whose edit form hides ~14 fields. Deliberately minimal: a fixture carrying\n * `configurationSchema` or `actions` here would misrepresent what the form can produce.\n */\nconst dataApp = {\n id: 'acme.data-app-dashboard',\n vendor: appVendor(thirdPartyVendor),\n name: 'Dashboard',\n type: 'data-app',\n shortDescription: 'A Streamlit dashboard',\n isPublic: false,\n isDeprecated: false,\n version: 2,\n uri: 'docker/acme.data-app-dashboard',\n isPublished: false,\n publishingStatus: 'private',\n} satisfies App;\n\n/** A `code-pattern`, whose `configurationSchema.supported_components` must be a non-empty array. */\nconst codePatternApp = {\n id: 'acme.code-pattern-etl',\n vendor: appVendor(thirdPartyVendor),\n name: 'ETL Pattern',\n type: 'code-pattern',\n shortDescription: 'Generates ETL code',\n actions: ['generate'],\n configurationSchema: { supported_components: ['keboola.snowflake-transformation'] },\n isPublic: false,\n version: 1,\n uri: 'docker/acme.code-pattern-etl',\n isPublished: false,\n publishingStatus: 'private',\n} satisfies App;\n\n/**\n * An app typed `other`. The public catalog excludes it entirely, so it exists to prove that\n * exclusion rather than to be rendered.\n */\nconst otherTypeApp = {\n id: 'acme.misc-thing',\n vendor: appVendor(thirdPartyVendor),\n name: 'Misc Thing',\n type: 'other',\n isPublic: true,\n version: 1,\n uri: 'docker/acme.misc-thing',\n isPublished: true,\n publishedVersion: 1,\n publishingStatus: 'public',\n} satisfies App;\n\n// `username` is the Cognito login, which is the user's email — the list endpoints return no\n// separate `email`, and no account state (`status`, `isEnabled`, `mfa`) either.\nconst humanUser = {\n username: 'dev@acme.example',\n name: 'Dev Eloper',\n vendors: ['acme'],\n createdOn: '2024-01-10T08:00:00+0100',\n} satisfies User;\n\n/** A recently added member, for a test that orders the list by `createdOn`. */\nconst newestUser = {\n username: 'new@acme.example',\n name: 'New Hire',\n vendors: ['acme'],\n createdOn: '2024-06-25T08:00:00+0200',\n} satisfies User;\n\n/** A member of no vendor — reachable only through the admin list. */\nconst vendorlessUser = {\n username: 'gone@acme.example',\n name: 'Alan Gone',\n vendors: [],\n createdOn: '2023-02-01T08:00:00+0100',\n} satisfies User;\n\n/** A Keboola staff member — eligible for \"make admin\" because they belong to the `keboola` vendor. */\nconst keboolaStaffUser = {\n username: 'staff@keboola.com',\n name: 'Kai Staff',\n vendors: ['keboola'],\n createdOn: '2023-09-14T08:00:00+0200',\n} satisfies User;\n\n/** A freshly created service account, including the one-time `password`. */\nconst newServiceAccount = {\n username: 'acme+ci',\n description: 'CI deploy pipeline',\n createdOn: '2024-07-01T10:00:00+0200',\n password: 'one-time-secret-shown-once',\n} satisfies ServiceAccount;\n\n/** The same account as later listed — note there is no `password`; it is unreadable after creation. */\nconst existingServiceAccount = {\n username: 'acme+release',\n description: 'Release automation',\n createdOn: '2024-03-11T10:00:00+0100',\n} satisfies ServiceAccount;\n\nconst appChange = {\n appId: 'acme.wr-widgets',\n createdOn: '2024-05-20T14:12:00+0200',\n createdBy: 'dev@acme.example',\n changes: [\n {\n attribute: 'shortDescription',\n oldValue: 'Writes widgets',\n newValue: 'Write data to Widgets',\n },\n {\n attribute: 'repository',\n oldValue: { type: 'quay', uri: 'acme/wr-widgets', tag: '0.3.0' },\n newValue: { type: 'quay', uri: 'acme/wr-widgets', tag: '0.3.1' },\n },\n ],\n} satisfies AppChange;\n\n/** The public catalog list: published, non-`other` apps only. */\nexport const listPublishedApps = (): App[] => [publishedExtractor, deprecatedApp];\n\n/** A vendor's own apps, across every publishing state the table renders. */\nexport const listVendorApps = (): App[] => [requestedApp, rejectedApp, dataApp, codePatternApp];\n\n/** The admin list — every vendor, plus the `other`-typed app the public catalog drops. */\nexport const listAllApps = (): App[] => [\n publishedExtractor,\n requestedApp,\n rejectedApp,\n deprecatedApp,\n dataApp,\n codePatternApp,\n otherTypeApp,\n];\n\n/** `GET /vendors` — approved and public only, so the pending vendor cannot appear here. */\nexport const listVendors = (): VendorListItem[] => [keboolaVendor, thirdPartyVendor];\n\n/** `GET /vendors/{vendor}` — the converted shape. */\nexport const getVendor = (): Vendor => vendorDetail;\n\n/** `GET /admin/vendors` — every vendor, and the only response carrying the approval flags. */\nexport const listAllVendors = (): AdminVendor[] => [\n keboolaAdminVendor,\n thirdPartyAdminVendor,\n pendingVendor,\n];\n\nexport const listUsers = (): User[] => [humanUser, newestUser, vendorlessUser, keboolaStaffUser];\n\nexport const listServiceAccounts = (): ServiceAccount[] => [existingServiceAccount];\n\nexport const listAppChanges = (): AppChange[] => [appChange];\n\n/** Named fixtures, for a test that needs one specific state. */\nexport const developerPortalFixtures = {\n apps: {\n published: publishedExtractor,\n requested: requestedApp,\n rejected: rejectedApp,\n deprecated: deprecatedApp,\n dataApp,\n codePattern: codePatternApp,\n otherType: otherTypeApp,\n },\n vendors: {\n keboola: keboolaVendor,\n thirdParty: thirdPartyVendor,\n detail: vendorDetail,\n pending: pendingVendor,\n keboolaAdmin: keboolaAdminVendor,\n thirdPartyAdmin: thirdPartyAdminVendor,\n },\n users: {\n human: humanUser,\n newest: newestUser,\n vendorless: vendorlessUser,\n keboolaStaff: keboolaStaffUser,\n },\n serviceAccounts: {\n created: newServiceAccount,\n existing: existingServiceAccount,\n },\n changes: { single: appChange },\n};\n","import type { Table, TableDetail } from '@keboola/api-client/storage/types';\n\nconst bucket = {\n id: 'in.c-main',\n name: 'c-main',\n displayName: 'Main',\n stage: 'in' as const,\n description: 'Main input bucket',\n created: '2024-01-15T10:00:00+0100',\n lastChangeDate: '2024-03-10T08:30:00+0100',\n isMaintenance: false,\n isReadOnly: false,\n isSnowflakeSharedDatabase: false,\n hasExternalSchema: false,\n rowsCount: 150000,\n dataSizeBytes: 52428800,\n uri: 'https://connection.keboola.com/v2/storage/buckets/in.c-main',\n backend: 'snowflake' as const,\n backendPath: [],\n databaseName: null,\n color: null,\n idBranch: 0,\n owner: null,\n sharing: null,\n path: 'in.c-main',\n tables: 'https://connection.keboola.com/v2/storage/buckets/in.c-main/tables',\n updated: '2024-03-10T08:30:00+0100',\n};\n\n// A freshly created table with no imports yet (non-typed, non-alias variant).\nconst freshTable = {\n id: 'in.c-main.users',\n name: 'users',\n displayName: 'Users',\n primaryKey: ['id'],\n metadata: [],\n columns: ['id', 'email', 'name', 'created_at'],\n columnMetadata: {},\n attributes: [],\n bucket,\n isTyped: false as const,\n isAlias: false as const,\n} satisfies TableDetail;\n\n// A recently updated table with a moderate size (non-typed, non-alias variant).\nconst recentlyUpdatedTable = {\n id: 'in.c-main.orders',\n name: 'orders',\n displayName: 'Orders',\n primaryKey: ['order_id'],\n metadata: [\n {\n id: 'mt1',\n key: 'KBC.createdBy.component.id',\n value: 'keboola.python-transformation',\n provider: 'keboola',\n timestamp: '2024-06-01T09:00:00+0200',\n },\n ],\n columns: ['order_id', 'user_id', 'total', 'status', 'created_at', 'updated_at'],\n columnMetadata: {\n order_id: [\n {\n id: 'm1',\n key: 'KBC.datatype.type',\n value: 'INTEGER',\n provider: 'keboola',\n timestamp: '2024-06-01T09:00:00+0200',\n },\n ],\n },\n attributes: [],\n bucket,\n isTyped: false as const,\n isAlias: false as const,\n} satisfies TableDetail;\n\n// A large table with many rows representing high-volume data (non-typed, non-alias variant).\nconst largeTable = {\n id: 'in.c-main.events',\n name: 'events',\n displayName: 'Events',\n primaryKey: [],\n metadata: [],\n columns: ['event_id', 'user_id', 'event_type', 'properties', 'occurred_at'],\n columnMetadata: {},\n attributes: [],\n bucket,\n isTyped: false as const,\n isAlias: false as const,\n} satisfies TableDetail;\n\n/**\n * Returns a single realistic typed TableDetail (fresh, no imports yet).\n *\n * The explicit return type ensures any divergence from the OpenAPI-derived\n * `TableDetail` in `@keboola/api-client` surfaces as a TypeScript error.\n */\nexport const getTable = (): TableDetail => freshTable;\n\n/**\n * Returns three TableDetail objects representing different lifecycle states:\n * 1. Fresh — just created, no data imported.\n * 2. Recently updated — moderate size, recent import.\n * 3. Large — high row count, large byte size.\n */\nexport const listTables = (): TableDetail[] => [freshTable, recentlyUpdatedTable, largeTable];\n\n/**\n * Named fixtures for targeted access in tests.\n */\nexport const tableFixtures = {\n fresh: freshTable,\n recentlyUpdated: recentlyUpdatedTable,\n large: largeTable,\n} satisfies Record<'fresh' | 'recentlyUpdated' | 'large', TableDetail>;\n\nexport type { Table, TableDetail };\n","import { appFixtures, getApp, listApps } from './clients/apps/apps';\nimport { deploymentFixtures, getDeployment, listDeployments } from './clients/apps/deployments';\nimport { getAppRun, listAppRuns, runFixtures } from './clients/apps/runs';\nimport {\n developerPortalFixtures,\n getVendor,\n listAllApps,\n listAllVendors,\n listAppChanges,\n listPublishedApps,\n listServiceAccounts,\n listUsers,\n listVendorApps,\n listVendors,\n} from './clients/developerPortal/apps';\nimport { getTable, listTables, tableFixtures } from './clients/storage/tables';\n\nexport const fixtures = {\n storage: {\n tables: {\n getTable,\n listTables,\n fixtures: tableFixtures,\n },\n },\n apps: {\n apps: {\n getApp,\n listApps,\n fixtures: appFixtures,\n },\n deployments: {\n getDeployment,\n listDeployments,\n fixtures: deploymentFixtures,\n },\n runs: {\n getAppRun,\n listAppRuns,\n fixtures: runFixtures,\n },\n },\n developerPortal: {\n listPublishedApps,\n listVendorApps,\n listAllApps,\n listAllVendors,\n getVendor,\n listVendors,\n listUsers,\n listServiceAccounts,\n listAppChanges,\n fixtures: developerPortalFixtures,\n },\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["base"],"sources":["../src/clients/apps/deployments.ts","../src/clients/apps/apps.ts","../src/clients/apps/runs.ts","../src/clients/developerPortal/apps.ts","../src/clients/storage/bootstrap.ts","../src/clients/storage/tables.ts","../src/fixtures.ts"],"sourcesContent":["import type { Deployment } from '@keboola/api-client/apps/types';\n\n/**\n * Deployment ids are the deterministic Kubernetes CR name — `app-{appId}-dpl-{hash}` —\n * so they are reproduced in that shape rather than as opaque strings.\n */\nexport const APP_ID = '374811';\n\nconst deploymentId = (hash: string) => `app-${APP_ID}-dpl-${hash}`;\n\n// Retired: the row outlives its CR, so it stays in history with `archived: true`.\nconst archivedDeployment = {\n id: deploymentId('350e2cf5287c5665'),\n number: 1,\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n configVersion: '14',\n gitCommitSha: null,\n size: 'tiny' as const,\n buildState: 'PREBUILT' as const,\n runState: 'STOPPED' as const,\n archived: true,\n archivedAt: '2026-08-15T11:03:02+00:00',\n createdAt: '2026-08-10T09:12:44+00:00',\n} satisfies Deployment;\n\n// Serving production — the one `appFixtures.running.production` points at.\nconst liveDeployment = {\n id: deploymentId('7a4c1b9e0d3f2a81'),\n number: 2,\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n configVersion: '16',\n gitCommitSha: null,\n size: 'small' as const,\n buildState: 'PREBUILT' as const,\n runState: 'RUNNING' as const,\n archived: false,\n archivedAt: null,\n createdAt: '2026-08-15T11:02:58+00:00',\n} satisfies Deployment;\n\n// Created with `promote: false`: pinned and built, but nothing ever started it.\nconst stagedDeployment = {\n id: deploymentId('c5e83f17b204de96'),\n number: 3,\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n configVersion: '18',\n gitCommitSha: null,\n size: 'small' as const,\n buildState: 'PREBUILT' as const,\n runState: 'NEVER_RUN' as const,\n archived: false,\n archivedAt: null,\n createdAt: '2026-08-17T08:41:19+00:00',\n} satisfies Deployment;\n\n// No artifact was produced, so this deployment can never run — a different problem,\n// with a different fix, from a run failure. Not reachable on the platform today\n// (every deployment is `PREBUILT`); the headline table treats it as a contract.\nconst buildFailedDeployment = {\n id: deploymentId('e91d47a8c6b02f35'),\n number: 4,\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n configVersion: '19',\n gitCommitSha: null,\n size: 'small' as const,\n buildState: 'FAILED' as const,\n runState: 'NEVER_RUN' as const,\n archived: false,\n archivedAt: null,\n createdAt: '2026-08-17T09:05:33+00:00',\n} satisfies Deployment;\n\n// Built fine, crashed on every run — `getAppRuns` carries the cause.\nconst runFailedDeployment = {\n id: deploymentId('2b6f0a94e7d51c83'),\n number: 5,\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n configVersion: '20',\n gitCommitSha: null,\n size: 'small' as const,\n buildState: 'PREBUILT' as const,\n runState: 'FAILED' as const,\n archived: false,\n archivedAt: null,\n createdAt: '2026-08-17T09:31:07+00:00',\n} satisfies Deployment;\n\nexport const deploymentFixtures = {\n archived: archivedDeployment,\n live: liveDeployment,\n staged: stagedDeployment,\n buildFailed: buildFailedDeployment,\n runFailed: runFailedDeployment,\n} satisfies Record<'archived' | 'live' | 'staged' | 'buildFailed' | 'runFailed', Deployment>;\n\nexport const getDeployment = (): Deployment => liveDeployment;\n\n/**\n * One continuous history: #1 retired, #2 serving, #3 staged, #4 failed to build, #5 built but its\n * run failed.\n *\n * All five, because `runFixtures.failed` names #5 as its deployment — a list that left the failed\n * ones out could not be joined to the runs, which is the join a timeline is built from.\n *\n * Returned in ascending `number` order. The endpoint does not specify an order, so consumers must\n * sort for themselves — this order is a fixture convention, not a contract to rely on, and it is\n * ascending on purpose: a consumer that assumes newest-first gets the wrong answer here rather\n * than in production.\n */\nexport const listDeployments = (): Deployment[] => [\n archivedDeployment,\n liveDeployment,\n stagedDeployment,\n buildFailedDeployment,\n runFailedDeployment,\n];\n","import type { App } from '@keboola/api-client/apps/types';\n\nimport { APP_ID, deploymentFixtures } from './deployments';\n\nconst APP_URL = 'https://hello-dashboard-374811.hub.canary-orion.keboola.dev';\n\nconst base = {\n id: APP_ID,\n projectId: '14',\n componentId: 'keboola.data-apps',\n branchId: '6',\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n type: 'streamlit' as const,\n mode: 'prod' as const,\n url: APP_URL,\n};\n\nconst production = (deployment: (typeof deploymentFixtures)[keyof typeof deploymentFixtures]) => ({\n desiredNumber: deployment.number,\n desiredId: deployment.id,\n actualNumber: deployment.number,\n actualId: deployment.id,\n});\n\n// Created through `/v2`, nothing deployed yet: the URL is reserved and publicly 404s.\nconst neverDeployedApp = {\n ...base,\n configVersion: '1',\n production: { desiredNumber: null, desiredId: null, actualNumber: null, actualId: null },\n undeployedChanges: false,\n state: 'NOT_DEPLOYED' as const,\n} satisfies App;\n\n/**\n * Transcribed verbatim from canary on 17 Aug 2026 (AJDA-3140, probe P1): an app created and\n * started through `/v1`, serving real traffic (HTTP 200, 8340 B) at the moment this was read,\n * which `/v2` nonetheless reports as `NOT_DEPLOYED` with an empty `production` because it was\n * never adopted into the deployments model.\n *\n * The Builder must never read \"is this app serving\" off `state` alone — here that answer is\n * wrong in the most damaging direction.\n */\nconst legacyV1ServingApp = {\n id: '374811',\n projectId: '14',\n componentId: 'keboola.data-apps',\n branchId: '6',\n configId: '01kz9kny4n49x3xk0e4k8ynpmq',\n configVersion: '2',\n type: 'streamlit' as const,\n mode: 'dev' as const,\n url: APP_URL,\n production: { desiredNumber: null, desiredId: null, actualNumber: null, actualId: null },\n undeployedChanges: false,\n state: 'NOT_DEPLOYED' as const,\n} satisfies App;\n\n// Serving deployment #2, config unchanged since it was deployed.\nconst runningApp = {\n ...base,\n configVersion: deploymentFixtures.live.configVersion,\n production: production(deploymentFixtures.live),\n undeployedChanges: false,\n state: 'RUNNING' as const,\n} satisfies App;\n\n// Still serving #2 (config v16) while the config has moved on to v18.\nconst appWithUndeployedChanges = {\n ...base,\n configVersion: deploymentFixtures.staged.configVersion,\n production: production(deploymentFixtures.live),\n undeployedChanges: true,\n state: 'RUNNING' as const,\n} satisfies App;\n\n/**\n * A blue/green promotion in flight: #3 has been asked for, #2 is still what traffic reaches.\n * `state` stays `RUNNING` throughout — the rollout is only visible as `desiredId !== actualId`.\n */\nconst promotingApp = {\n ...base,\n configVersion: deploymentFixtures.staged.configVersion,\n production: {\n desiredNumber: deploymentFixtures.staged.number,\n desiredId: deploymentFixtures.staged.id,\n actualNumber: deploymentFixtures.live.number,\n actualId: deploymentFixtures.live.id,\n },\n undeployedChanges: true,\n state: 'RUNNING' as const,\n} satisfies App;\n\n// Idle between visits and armed to wake on the next request — normal, not an outage.\nconst sleepingApp = {\n ...base,\n configVersion: deploymentFixtures.live.configVersion,\n production: production(deploymentFixtures.live),\n undeployedChanges: false,\n state: 'SLEEPING' as const,\n} satisfies App;\n\n// Explicitly suspended: a visitor gets a 503 until someone resumes it.\nconst suspendedApp = {\n ...base,\n configVersion: deploymentFixtures.live.configVersion,\n production: production(deploymentFixtures.live),\n undeployedChanges: false,\n state: 'SUSPENDED' as const,\n} satisfies App;\n\nexport const appFixtures = {\n neverDeployed: neverDeployedApp,\n legacyV1Serving: legacyV1ServingApp,\n running: runningApp,\n undeployedChanges: appWithUndeployedChanges,\n promoting: promotingApp,\n sleeping: sleepingApp,\n suspended: suspendedApp,\n} satisfies Record<\n | 'neverDeployed'\n | 'legacyV1Serving'\n | 'running'\n | 'undeployedChanges'\n | 'promoting'\n | 'sleeping'\n | 'suspended',\n App\n>;\n\nexport const getApp = (): App => runningApp;\n\n/**\n * The named fixtures above are all the *same* app in different states, which is what a detail\n * page shows. A listing shows different apps, so each entry past the first is re-addressed —\n * including the deployment ids inside `production`, which embed the app id.\n */\nconst readdress = (app: App, id: string): App => ({\n ...app,\n id,\n url: `https://data-app-${id}.hub.canary-orion.keboola.dev`,\n production: {\n ...app.production,\n desiredId: app.production.desiredId?.replace(APP_ID, id) ?? null,\n actualId: app.production.actualId?.replace(APP_ID, id) ?? null,\n },\n});\n\nexport const listApps = (): App[] => [\n runningApp,\n readdress(appWithUndeployedChanges, '374812'),\n readdress(neverDeployedApp, '374813'),\n];\n","import type { AppRun } from '@keboola/api-client/apps/types';\n\nimport { APP_ID, deploymentFixtures } from './deployments';\n\nconst base = {\n appId: APP_ID,\n runtimeSize: 'small',\n runtimeBackendType: 'streamlit',\n imageVersion: '1.14.2',\n mode: 'prod',\n};\n\nconst runningRun = {\n ...base,\n id: '4f2d8c1a-0b76-4e35-9a12-5c8e7d3b0f41',\n deploymentId: deploymentFixtures.live.id,\n configVersion: deploymentFixtures.live.configVersion,\n state: 'running' as const,\n createdAt: '2026-08-15T11:02:58+00:00',\n startedAt: '2026-08-15T11:03:41+00:00',\n stoppedAt: null,\n startupLogs: null,\n failureReason: null,\n} satisfies AppRun;\n\nconst finishedRun = {\n ...base,\n id: '9c0a7e42-31bd-4f88-b6d5-2ea41f907c3b',\n deploymentId: deploymentFixtures.archived.id,\n configVersion: deploymentFixtures.archived.configVersion,\n state: 'finished' as const,\n createdAt: '2026-08-10T09:12:44+00:00',\n startedAt: '2026-08-10T09:13:29+00:00',\n stoppedAt: '2026-08-15T11:03:02+00:00',\n startupLogs: null,\n failureReason: null,\n} satisfies AppRun;\n\n/**\n * A classified failure transcribed from canary (AJDA-3140, probe P1). `startedAt` is `null`\n * even though a cause was attributed — the container executed but its startup probe never\n * passed, so a classified failure says nothing about how far the run got.\n */\nconst failedRun = {\n ...base,\n id: 'ba53f9d0-7c41-4a2e-8f16-d0b9e254a7c6',\n deploymentId: deploymentFixtures.runFailed.id,\n configVersion: deploymentFixtures.runFailed.configVersion,\n state: 'failed' as const,\n createdAt: '2026-08-17T09:31:07+00:00',\n startedAt: null,\n stoppedAt: '2026-08-17T09:33:52+00:00',\n startupLogs:\n '[INFO] Starting app\\n[ERROR] App must have keboola-config/nginx/ directory. Missing: /app/keboola-config/nginx\\n',\n failureReason: {\n reason: 'StartupProbeFailed',\n message: 'App must have keboola-config/nginx/ directory. Missing: /app/keboola-config/nginx',\n },\n} satisfies AppRun;\n\n/**\n * A run that belongs to the app itself rather than to a deployment — what every run of a\n * `/v1`-created app looks like. `deploymentId: null` is permanent for these, not drift.\n */\nconst legacyRun = {\n ...base,\n id: '1d7b4e05-8a92-4c63-b0f7-3e6a5c8192d4',\n deploymentId: null,\n configVersion: '2',\n state: 'running' as const,\n createdAt: '2026-08-17T10:02:11+00:00',\n startedAt: '2026-08-17T10:02:51+00:00',\n stoppedAt: null,\n startupLogs: null,\n failureReason: null,\n} satisfies AppRun;\n\nexport const runFixtures = {\n running: runningRun,\n finished: finishedRun,\n failed: failedRun,\n legacy: legacyRun,\n} satisfies Record<'running' | 'finished' | 'failed' | 'legacy', AppRun>;\n\nexport const getAppRun = (): AppRun => runningRun;\n\n/**\n * Every run this app has, newest first — the order the endpoint documents, so a consumer that\n * relies on it (`[latest] = runs`) is exercised against data that keeps the promise rather than\n * data that happens to contradict it.\n */\nexport const listAppRuns = (): AppRun[] => [legacyRun, failedRun, runningRun, finishedRun];\n","import type {\n AdminVendor,\n App,\n AppChange,\n AppVendor,\n ServiceAccount,\n User,\n Vendor,\n VendorListItem,\n} from '@keboola/api-client/developerPortal/types';\n\n// `isTrusted` is the raw tinyint here and a boolean in `vendorDetail` below. That is not a fixture\n// inconsistency: `GET /vendors` returns the row unconverted, every other vendor endpoint runs it\n// through `publicGetVendor`. A fixture that smoothed it over would hide the difference consumers\n// have to handle.\n//\n// `type: 'keboola'` is what the public catalog's \"Supported by Keboola\" filter matches on — NOT\n// `id`, so a fixture that only set the id would silently fail to exercise that filter.\nconst keboolaVendor = {\n id: 'keboola',\n name: 'Keboola',\n email: 'support@keboola.com',\n address: 'Prague, Czech Republic',\n type: 'keboola',\n projectUrl: null,\n isTrusted: 1,\n} satisfies VendorListItem;\n\nconst thirdPartyVendor = {\n id: 'acme',\n name: 'Acme Co.',\n email: 'dev@acme.example',\n address: 'Springfield',\n projectUrl: 'https://connection.keboola.com/admin/projects/1234',\n type: 'other',\n isTrusted: 0,\n} satisfies VendorListItem;\n\n/** The same vendor as `GET /vendors/{vendor}` returns it — `isTrusted` converted to a boolean. */\nconst vendorDetail = {\n ...thirdPartyVendor,\n isTrusted: false,\n} satisfies Vendor;\n\n// A pending, self-registered vendor. The `_v` id prefix is the marker that keeps it out of the\n// user-selectable vendor list until an admin approves and renames it. Only `GET /admin/vendors`\n// returns it — the public list filters on `isApproved`, and is the only response carrying the flag.\nconst pendingVendor = {\n id: '_v1699999999999',\n name: 'Pending Startup',\n email: 'hello@pending.example',\n address: 'Berlin',\n type: 'other',\n projectUrl: null,\n isApproved: false,\n isPublic: false,\n isTrusted: false,\n} satisfies AdminVendor;\n\n// The two public vendors as `GET /admin/vendors` returns them: approved, and `isTrusted` converted\n// to a boolean. They exist so the admin list is not a single pending row — a test that only ever\n// sees `pendingVendor` never exercises the approved path the admin table mostly renders.\nconst keboolaAdminVendor = {\n ...keboolaVendor,\n isApproved: true,\n isPublic: true,\n isTrusted: true,\n} satisfies AdminVendor;\n\nconst thirdPartyAdminVendor = {\n ...thirdPartyVendor,\n isApproved: true,\n isPublic: true,\n isTrusted: false,\n} satisfies AdminVendor;\n\n// The vendor as it arrives joined onto an app: five columns, none of the flags.\nconst appVendor = (vendor: VendorListItem): AppVendor => ({\n id: vendor.id,\n name: vendor.name,\n address: vendor.address,\n email: vendor.email,\n type: vendor.type,\n});\n\n/** A published, fully-populated extractor — the shape that passes `hasAllFieldsForPublishing`. */\nconst publishedExtractor = {\n id: 'keboola.ex-db-snowflake',\n vendor: appVendor(keboolaVendor),\n name: 'Snowflake',\n type: 'extractor',\n shortDescription: 'Extract data from Snowflake',\n longDescription: '## Snowflake extractor\\n\\nExtracts tables from a Snowflake database.',\n licenseUrl: 'https://github.com/keboola/ex-db-snowflake/blob/master/LICENSE.md',\n documentationUrl: 'https://help.keboola.com/components/extractors/database/snowflake/',\n sourceCodeUrl: 'https://github.com/keboola/ex-db-snowflake',\n categories: ['Database'],\n complexity: 'easy',\n uiOptions: ['genericDockerUI'],\n defaultBucket: true,\n defaultBucketStage: 'in',\n stagingStorageInput: 'local',\n stagingStorageOutput: 'local',\n logger: 'standard',\n isPublic: true,\n isDeprecated: false,\n fees: false,\n repository: { type: 'ecr', uri: 'keboola/ex-db-snowflake', tag: '1.9.0' },\n // The 128 filename ends in a 13-digit millisecond timestamp, so `getIcon` uses it. A legacy\n // incremental filename here would make `getIcon` fall back to the 64px variant.\n icon: {\n '64': 'https://ui.keboola-assets.com/developer-portal/icons/keboola.ex-db-snowflake/64/1699999999999.png',\n '128':\n 'https://ui.keboola-assets.com/developer-portal/icons/keboola.ex-db-snowflake/128/1699999999999.png',\n },\n version: 12,\n createdBy: 'support@keboola.com',\n updatedOn: '2024-06-01T09:00:00+0200',\n uri: 'docker/keboola.ex-db-snowflake',\n isPublished: true,\n publishedVersion: 12,\n publishingStatus: 'public',\n} satisfies App;\n\n/** A private third-party app with a pending publishing request. */\nconst requestedApp = {\n id: 'acme.wr-widgets',\n vendor: appVendor(thirdPartyVendor),\n name: 'Widget Writer',\n type: 'writer',\n shortDescription: 'Write data to Widgets',\n longDescription: 'Pushes tables into the Widgets API.',\n licenseUrl: 'https://acme.example/license',\n documentationUrl: 'https://acme.example/docs',\n uiOptions: ['genericDockerUI'],\n repository: { type: 'quay', uri: 'acme/wr-widgets', tag: '0.3.1' },\n icon: {\n '64': 'https://ui.keboola-assets.com/developer-portal/icons/acme.wr-widgets/64/1699999999998.png',\n '128':\n 'https://ui.keboola-assets.com/developer-portal/icons/acme.wr-widgets/128/1699999999998.png',\n },\n isPublic: false,\n isDeprecated: false,\n version: 3,\n createdBy: 'dev@acme.example',\n updatedOn: '2024-05-20T14:12:00+0200',\n uri: 'docker/acme.wr-widgets',\n isPublished: false,\n publishingStatus: 'requested',\n publishingRequest: { createdOn: '2024-05-20T14:12:00+0200', rejectionReason: null },\n} satisfies App;\n\n/** A rejected app — carries the reason the vendor sees on its detail page. */\nconst rejectedApp = {\n id: 'acme.app-analyzer',\n vendor: appVendor(thirdPartyVendor),\n name: 'Analyzer',\n type: 'application',\n shortDescription: 'Analyze things',\n isPublic: false,\n isDeprecated: false,\n version: 1,\n createdBy: 'dev@acme.example',\n uri: 'docker/acme.app-analyzer',\n isPublished: false,\n publishingStatus: 'rejected',\n publishingRequest: {\n createdOn: '2024-04-02T11:00:00+0200',\n rejectionReason: 'Documentation URL is missing and the icon is not 256×256.',\n },\n} satisfies App;\n\n/** A deprecated app with an expiry date and a suggested replacement. */\nconst deprecatedApp = {\n id: 'keboola.ex-legacy',\n vendor: appVendor(keboolaVendor),\n name: 'Legacy Extractor',\n type: 'extractor',\n shortDescription: 'Superseded',\n isPublic: true,\n isDeprecated: true,\n expiredOn: '2025-01-01',\n replacementApp: 'keboola.ex-db-snowflake',\n version: 40,\n uri: 'docker/keboola.ex-legacy',\n isPublished: true,\n publishedVersion: 38,\n publishingStatus: 'public',\n} satisfies App;\n\n/**\n * A `data-app`, the type whose edit form hides ~14 fields. Deliberately minimal: a fixture carrying\n * `configurationSchema` or `actions` here would misrepresent what the form can produce.\n */\nconst dataApp = {\n id: 'acme.data-app-dashboard',\n vendor: appVendor(thirdPartyVendor),\n name: 'Dashboard',\n type: 'data-app',\n shortDescription: 'A Streamlit dashboard',\n isPublic: false,\n isDeprecated: false,\n version: 2,\n uri: 'docker/acme.data-app-dashboard',\n isPublished: false,\n publishingStatus: 'private',\n} satisfies App;\n\n/** A `code-pattern`, whose `configurationSchema.supported_components` must be a non-empty array. */\nconst codePatternApp = {\n id: 'acme.code-pattern-etl',\n vendor: appVendor(thirdPartyVendor),\n name: 'ETL Pattern',\n type: 'code-pattern',\n shortDescription: 'Generates ETL code',\n actions: ['generate'],\n configurationSchema: { supported_components: ['keboola.snowflake-transformation'] },\n isPublic: false,\n version: 1,\n uri: 'docker/acme.code-pattern-etl',\n isPublished: false,\n publishingStatus: 'private',\n} satisfies App;\n\n/**\n * An app typed `other`. The public catalog excludes it entirely, so it exists to prove that\n * exclusion rather than to be rendered.\n */\nconst otherTypeApp = {\n id: 'acme.misc-thing',\n vendor: appVendor(thirdPartyVendor),\n name: 'Misc Thing',\n type: 'other',\n isPublic: true,\n version: 1,\n uri: 'docker/acme.misc-thing',\n isPublished: true,\n publishedVersion: 1,\n publishingStatus: 'public',\n} satisfies App;\n\n// `username` is the Cognito login, which is the user's email — the list endpoints return no\n// separate `email`, and no account state (`status`, `isEnabled`, `mfa`) either.\nconst humanUser = {\n username: 'dev@acme.example',\n name: 'Dev Eloper',\n vendors: ['acme'],\n createdOn: '2024-01-10T08:00:00+0100',\n} satisfies User;\n\n/** A recently added member, for a test that orders the list by `createdOn`. */\nconst newestUser = {\n username: 'new@acme.example',\n name: 'New Hire',\n vendors: ['acme'],\n createdOn: '2024-06-25T08:00:00+0200',\n} satisfies User;\n\n/** A member of no vendor — reachable only through the admin list. */\nconst vendorlessUser = {\n username: 'gone@acme.example',\n name: 'Alan Gone',\n vendors: [],\n createdOn: '2023-02-01T08:00:00+0100',\n} satisfies User;\n\n/** A Keboola staff member — eligible for \"make admin\" because they belong to the `keboola` vendor. */\nconst keboolaStaffUser = {\n username: 'staff@keboola.com',\n name: 'Kai Staff',\n vendors: ['keboola'],\n createdOn: '2023-09-14T08:00:00+0200',\n} satisfies User;\n\n/** A freshly created service account, including the one-time `password`. */\nconst newServiceAccount = {\n username: 'acme+ci',\n description: 'CI deploy pipeline',\n createdOn: '2024-07-01T10:00:00+0200',\n password: 'one-time-secret-shown-once',\n} satisfies ServiceAccount;\n\n/** The same account as later listed — note there is no `password`; it is unreadable after creation. */\nconst existingServiceAccount = {\n username: 'acme+release',\n description: 'Release automation',\n createdOn: '2024-03-11T10:00:00+0100',\n} satisfies ServiceAccount;\n\nconst appChange = {\n appId: 'acme.wr-widgets',\n createdOn: '2024-05-20T14:12:00+0200',\n createdBy: 'dev@acme.example',\n changes: [\n {\n attribute: 'shortDescription',\n oldValue: 'Writes widgets',\n newValue: 'Write data to Widgets',\n },\n {\n attribute: 'repository',\n oldValue: { type: 'quay', uri: 'acme/wr-widgets', tag: '0.3.0' },\n newValue: { type: 'quay', uri: 'acme/wr-widgets', tag: '0.3.1' },\n },\n ],\n} satisfies AppChange;\n\n/** The public catalog list: published, non-`other` apps only. */\nexport const listPublishedApps = (): App[] => [publishedExtractor, deprecatedApp];\n\n/** A vendor's own apps, across every publishing state the table renders. */\nexport const listVendorApps = (): App[] => [requestedApp, rejectedApp, dataApp, codePatternApp];\n\n/** The admin list — every vendor, plus the `other`-typed app the public catalog drops. */\nexport const listAllApps = (): App[] => [\n publishedExtractor,\n requestedApp,\n rejectedApp,\n deprecatedApp,\n dataApp,\n codePatternApp,\n otherTypeApp,\n];\n\n/** `GET /vendors` — approved and public only, so the pending vendor cannot appear here. */\nexport const listVendors = (): VendorListItem[] => [keboolaVendor, thirdPartyVendor];\n\n/** `GET /vendors/{vendor}` — the converted shape. */\nexport const getVendor = (): Vendor => vendorDetail;\n\n/** `GET /admin/vendors` — every vendor, and the only response carrying the approval flags. */\nexport const listAllVendors = (): AdminVendor[] => [\n keboolaAdminVendor,\n thirdPartyAdminVendor,\n pendingVendor,\n];\n\nexport const listUsers = (): User[] => [humanUser, newestUser, vendorlessUser, keboolaStaffUser];\n\nexport const listServiceAccounts = (): ServiceAccount[] => [existingServiceAccount];\n\nexport const listAppChanges = (): AppChange[] => [appChange];\n\n/** Named fixtures, for a test that needs one specific state. */\nexport const developerPortalFixtures = {\n apps: {\n published: publishedExtractor,\n requested: requestedApp,\n rejected: rejectedApp,\n deprecated: deprecatedApp,\n dataApp,\n codePattern: codePatternApp,\n otherType: otherTypeApp,\n },\n vendors: {\n keboola: keboolaVendor,\n thirdParty: thirdPartyVendor,\n detail: vendorDetail,\n pending: pendingVendor,\n keboolaAdmin: keboolaAdminVendor,\n thirdPartyAdmin: thirdPartyAdminVendor,\n },\n users: {\n human: humanUser,\n newest: newestUser,\n vendorless: vendorlessUser,\n keboolaStaff: keboolaStaffUser,\n },\n serviceAccounts: {\n created: newServiceAccount,\n existing: existingServiceAccount,\n },\n changes: { single: appChange },\n};\n","import { ServiceId } from '@keboola/api-client/constants';\nimport type { DevBranch, StackInfo, StorageToken } from '@keboola/api-client/storage/types';\n\n/** The stack an MSW-backed test points its client at, unless a caller passes its own. */\nexport const DEFAULT_BASE_URL = 'https://connection.test';\n\ntype StackInfoOptions = {\n /** Stack the fixture describes; its host is what the announced service URLs are built on. */\n baseUrl?: string;\n /** Services the stack announces. Narrow it to test what a client does without one. */\n services?: ServiceId[];\n};\n\ntype StorageTokenOptions = {\n /** Stack the token was issued by — its `uri`. */\n baseUrl?: string;\n /** Project features `hasFeature()` should report — the token's `owner.features`. */\n features?: string[];\n};\n\n/**\n * The stack index `GET /v2/storage` returns.\n *\n * - Announces every `ServiceId` by default, each on its own host, so no service client is a dummy\n * that throws `ServiceUnavailableError` — a test for a queue / data-science / vault hook only\n * adds its handler.\n * - Defaulting to `Object.values(ServiceId)` is what keeps that exhaustive: a service added to the\n * client arrives here without an edit.\n */\nexport const getStackInfo = ({\n baseUrl = DEFAULT_BASE_URL,\n services = Object.values(ServiceId),\n}: StackInfoOptions = {}): StackInfo => {\n const { host } = new URL(baseUrl);\n\n return {\n api: host,\n documentation: 'https://developers.keboola.com',\n host,\n revision: 'test-revision',\n stack: 'test-stack',\n version: 'test-version',\n urlTemplates: { orchestrationJob: '' },\n services: services.map((id) => ({ id, url: `https://${id}.${host}` })),\n components: [],\n features: [],\n };\n};\n\n/**\n * The verified master token `GET /v2/storage/tokens/verify` returns.\n *\n * - Complete on purpose: `api.context.project.sapiToken` is this object verbatim and hooks read deep\n * into it (`owner.id`, `admin.role`, `adminOwner.email`), so a partial body surfaces as\n * `undefined`s far from the test that caused them.\n * - Every permission flag is granted; a test needing a restricted token overrides the handler.\n */\nexport const verifyStorageToken = ({\n baseUrl = DEFAULT_BASE_URL,\n features = [],\n}: StorageTokenOptions = {}): StorageToken => ({\n id: 'token-1',\n created: '2024-01-01T00:00:00Z',\n refreshed: '2024-01-01T00:00:00Z',\n description: 'Test token',\n uri: baseUrl,\n isMasterToken: true,\n canManageBuckets: true,\n canManageTokens: true,\n canReadAllFileUploads: true,\n canPurgeTrash: true,\n canManageProtectedDefaultBranch: true,\n canCreateJobs: true,\n canReadAllProjectEvents: true,\n canManageDevBranches: true,\n creatorToken: { id: 42, description: 'Test token' },\n expires: null,\n isExpired: false,\n isDisabled: false,\n isBYODB: false,\n dailyCapacity: 1000,\n bucketPermissions: {},\n owner: {\n id: 42,\n name: 'Test Project',\n type: 'project',\n region: 'us-east-1',\n created: '2024-01-01T00:00:00Z',\n expires: null,\n features,\n dataSizeBytes: 0,\n rowsCount: 0,\n hasMysql: false,\n hasSynapse: false,\n hasRedshift: false,\n hasSnowflake: true,\n hasExasol: false,\n hasTeradata: false,\n hasBigquery: false,\n defaultBackend: 'snowflake',\n hasTryModeOn: 'false',\n limits: {},\n metrics: {},\n isDisabled: false,\n billedMonthlyPrice: null,\n dataRetentionTimeInDays: 30,\n assignedBackends: ['snowflake'],\n fileStorageProvider: 's3',\n },\n organization: { id: 'org-1' },\n admin: { id: 100, name: 'Admin User', features: [], isOrganizationMember: true, role: 'admin' },\n adminOwner: { id: 200, name: 'Owner User', email: 'owner@example.com' },\n});\n\n/**\n * The branch list `GET /v2/storage/dev-branches` returns — the default branch alone.\n *\n * - `context.defaultBranch` is read off it, so the entry must stay `isDefault: true`.\n * - The default branch has no creator, which `DevBranch` models as an empty `creatorToken`.\n */\nexport const getDevBranches = (): DevBranch[] => [\n {\n id: 1,\n name: 'Main',\n description: '',\n isDefault: true,\n created: '2024-01-01T00:00:00Z',\n creatorToken: [],\n },\n];\n","import type { Table, TableDetail } from '@keboola/api-client/storage/types';\n\nconst bucket = {\n id: 'in.c-main',\n name: 'c-main',\n displayName: 'Main',\n stage: 'in' as const,\n description: 'Main input bucket',\n created: '2024-01-15T10:00:00+0100',\n lastChangeDate: '2024-03-10T08:30:00+0100',\n isMaintenance: false,\n isReadOnly: false,\n isSnowflakeSharedDatabase: false,\n hasExternalSchema: false,\n rowsCount: 150000,\n dataSizeBytes: 52428800,\n uri: 'https://connection.keboola.com/v2/storage/buckets/in.c-main',\n backend: 'snowflake' as const,\n backendPath: [],\n databaseName: null,\n color: null,\n idBranch: 0,\n owner: null,\n sharing: null,\n path: 'in.c-main',\n tables: 'https://connection.keboola.com/v2/storage/buckets/in.c-main/tables',\n updated: '2024-03-10T08:30:00+0100',\n isLinkedBucket: false,\n bucketSharingAllowed: true,\n};\n\n// A freshly created table with no imports yet (non-typed, non-alias variant).\nconst freshTable = {\n id: 'in.c-main.users',\n name: 'users',\n displayName: 'Users',\n primaryKey: ['id'],\n metadata: [],\n columns: ['id', 'email', 'name', 'created_at'],\n columnMetadata: {},\n attributes: [],\n bucket,\n isTyped: false as const,\n isAlias: false as const,\n} satisfies TableDetail;\n\n// A recently updated table with a moderate size (non-typed, non-alias variant).\nconst recentlyUpdatedTable = {\n id: 'in.c-main.orders',\n name: 'orders',\n displayName: 'Orders',\n primaryKey: ['order_id'],\n metadata: [\n {\n id: 'mt1',\n key: 'KBC.createdBy.component.id',\n value: 'keboola.python-transformation',\n provider: 'keboola',\n timestamp: '2024-06-01T09:00:00+0200',\n },\n ],\n columns: ['order_id', 'user_id', 'total', 'status', 'created_at', 'updated_at'],\n columnMetadata: {\n order_id: [\n {\n id: 'm1',\n key: 'KBC.datatype.type',\n value: 'INTEGER',\n provider: 'keboola',\n timestamp: '2024-06-01T09:00:00+0200',\n },\n ],\n },\n attributes: [],\n bucket,\n isTyped: false as const,\n isAlias: false as const,\n} satisfies TableDetail;\n\n// A large table with many rows representing high-volume data (non-typed, non-alias variant).\nconst largeTable = {\n id: 'in.c-main.events',\n name: 'events',\n displayName: 'Events',\n primaryKey: [],\n metadata: [],\n columns: ['event_id', 'user_id', 'event_type', 'properties', 'occurred_at'],\n columnMetadata: {},\n attributes: [],\n bucket,\n isTyped: false as const,\n isAlias: false as const,\n} satisfies TableDetail;\n\n/**\n * Returns a single realistic typed TableDetail (fresh, no imports yet).\n *\n * The explicit return type ensures any divergence from the OpenAPI-derived\n * `TableDetail` in `@keboola/api-client` surfaces as a TypeScript error.\n */\nexport const getTable = (): TableDetail => freshTable;\n\n/**\n * Returns three TableDetail objects representing different lifecycle states:\n * 1. Fresh — just created, no data imported.\n * 2. Recently updated — moderate size, recent import.\n * 3. Large — high row count, large byte size.\n */\nexport const listTables = (): TableDetail[] => [freshTable, recentlyUpdatedTable, largeTable];\n\n/**\n * Named fixtures for targeted access in tests.\n */\nexport const tableFixtures = {\n fresh: freshTable,\n recentlyUpdated: recentlyUpdatedTable,\n large: largeTable,\n} satisfies Record<'fresh' | 'recentlyUpdated' | 'large', TableDetail>;\n\nexport type { Table, TableDetail };\n","import { appFixtures, getApp, listApps } from './clients/apps/apps';\nimport { deploymentFixtures, getDeployment, listDeployments } from './clients/apps/deployments';\nimport { getAppRun, listAppRuns, runFixtures } from './clients/apps/runs';\nimport {\n developerPortalFixtures,\n getVendor,\n listAllApps,\n listAllVendors,\n listAppChanges,\n listPublishedApps,\n listServiceAccounts,\n listUsers,\n listVendorApps,\n listVendors,\n} from './clients/developerPortal/apps';\nimport { getDevBranches, getStackInfo, verifyStorageToken } from './clients/storage/bootstrap';\nimport { getTable, listTables, tableFixtures } from './clients/storage/tables';\n\nexport const fixtures = {\n storage: {\n bootstrap: {\n getStackInfo,\n verifyStorageToken,\n getDevBranches,\n },\n tables: {\n getTable,\n listTables,\n fixtures: tableFixtures,\n },\n },\n apps: {\n apps: {\n getApp,\n listApps,\n fixtures: appFixtures,\n },\n deployments: {\n getDeployment,\n listDeployments,\n fixtures: deploymentFixtures,\n },\n runs: {\n getAppRun,\n listAppRuns,\n fixtures: runFixtures,\n },\n },\n developerPortal: {\n listPublishedApps,\n listVendorApps,\n listAllApps,\n listAllVendors,\n getVendor,\n listVendors,\n listUsers,\n listServiceAccounts,\n listAppChanges,\n fixtures: developerPortalFixtures,\n },\n};\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@keboola/api-fixtures",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "27.0.0",
|
|
4
4
|
"description": "Typed test fixtures keyed by Keboola API endpoint",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"typescript"
|
|
50
50
|
],
|
|
51
51
|
"peerDependencies": {
|
|
52
|
-
"@keboola/api-client": "^
|
|
52
|
+
"@keboola/api-client": "^32.0.0"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@arethetypeswrong/cli": "^0.18.2",
|
|
@@ -61,9 +61,9 @@
|
|
|
61
61
|
"typescript": "npm:@typescript/typescript6@^6.0.2",
|
|
62
62
|
"vite": "^8.1.5",
|
|
63
63
|
"vitest": "^4.1.10",
|
|
64
|
+
"@keboola/api-client": "^32.0.0",
|
|
64
65
|
"@keboola/oxlint-config": "^10.0.2",
|
|
65
|
-
"@keboola/tsconfig": "^0.2.1"
|
|
66
|
-
"@keboola/api-client": "^31.0.0"
|
|
66
|
+
"@keboola/tsconfig": "^0.2.1"
|
|
67
67
|
},
|
|
68
68
|
"scripts": {
|
|
69
69
|
"type-check": "tsc",
|