@qontoctl/core 0.0.0 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/README.md +93 -0
- package/dist/api-types.d.ts +38 -0
- package/dist/api-types.d.ts.map +1 -0
- package/dist/api-types.js +4 -0
- package/dist/api-types.js.map +1 -0
- package/dist/auth/api-key.d.ts +16 -0
- package/dist/auth/api-key.d.ts.map +1 -0
- package/dist/auth/api-key.js +28 -0
- package/dist/auth/api-key.js.map +1 -0
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +4 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/config/env.d.ts +17 -0
- package/dist/config/env.d.ts.map +1 -0
- package/dist/config/env.js +52 -0
- package/dist/config/env.js.map +1 -0
- package/dist/config/index.d.ts +8 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +7 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/loader.d.ts +18 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +49 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/resolve.d.ts +19 -0
- package/dist/config/resolve.d.ts.map +1 -0
- package/dist/config/resolve.js +84 -0
- package/dist/config/resolve.js.map +1 -0
- package/dist/config/types.d.ts +38 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +4 -0
- package/dist/config/types.js.map +1 -0
- package/dist/config/validate.d.ts +22 -0
- package/dist/config/validate.d.ts.map +1 -0
- package/dist/config/validate.js +99 -0
- package/dist/config/validate.js.map +1 -0
- package/dist/constants.d.ts +7 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +9 -0
- package/dist/constants.js.map +1 -0
- package/dist/http-client.d.ts +100 -0
- package/dist/http-client.d.ts.map +1 -0
- package/dist/http-client.js +210 -0
- package/dist/http-client.js.map +1 -0
- package/dist/index.d.ts +12 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/services/bank-accounts.d.ts +18 -0
- package/dist/services/bank-accounts.d.ts.map +1 -0
- package/dist/services/bank-accounts.js +23 -0
- package/dist/services/bank-accounts.js.map +1 -0
- package/dist/services/index.d.ts +3 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +5 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/organization.d.ts +10 -0
- package/dist/services/organization.d.ts.map +1 -0
- package/dist/services/organization.js +13 -0
- package/dist/services/organization.js.map +1 -0
- package/dist/statements/index.d.ts +2 -0
- package/dist/statements/index.d.ts.map +1 -0
- package/dist/statements/index.js +4 -0
- package/dist/statements/index.js.map +1 -0
- package/dist/statements/types.d.ts +19 -0
- package/dist/statements/types.d.ts.map +1 -0
- package/dist/statements/types.js +4 -0
- package/dist/statements/types.js.map +1 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +4 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/json-response.d.ts +6 -0
- package/dist/testing/json-response.d.ts.map +1 -0
- package/dist/testing/json-response.js +14 -0
- package/dist/testing/json-response.js.map +1 -0
- package/dist/transactions/index.d.ts +3 -0
- package/dist/transactions/index.d.ts.map +1 -0
- package/dist/transactions/index.js +4 -0
- package/dist/transactions/index.js.map +1 -0
- package/dist/transactions/service.d.ts +13 -0
- package/dist/transactions/service.d.ts.map +1 -0
- package/dist/transactions/service.js +65 -0
- package/dist/transactions/service.js.map +1 -0
- package/dist/transactions/types.d.ts +70 -0
- package/dist/transactions/types.d.ts.map +1 -0
- package/dist/transactions/types.js +4 -0
- package/dist/transactions/types.js.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +4 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/label.d.ts +10 -0
- package/dist/types/label.d.ts.map +1 -0
- package/dist/types/label.js +4 -0
- package/dist/types/label.js.map +1 -0
- package/dist/types/membership.d.ts +17 -0
- package/dist/types/membership.d.ts.map +1 -0
- package/dist/types/membership.js +4 -0
- package/dist/types/membership.js.map +1 -0
- package/package.json +32 -11
package/README.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# @qontoctl/core
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@qontoctl/core)
|
|
4
|
+
|
|
5
|
+
Core library for [Qonto](https://qonto.com) API integration — HTTP client, authentication, configuration, and typed service functions.
|
|
6
|
+
|
|
7
|
+
Part of the [QontoCtl](https://github.com/alexey-pelykh/qontoctl) project.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install @qontoctl/core
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { resolveConfig, buildApiKeyAuthorization, HttpClient, getOrganization } from "@qontoctl/core";
|
|
19
|
+
|
|
20
|
+
// Resolve configuration from file or environment
|
|
21
|
+
const { config, endpoint } = await resolveConfig();
|
|
22
|
+
|
|
23
|
+
// Build authorization headers
|
|
24
|
+
const authorization = buildApiKeyAuthorization(config.apiKey);
|
|
25
|
+
|
|
26
|
+
// Create an HTTP client
|
|
27
|
+
const client = new HttpClient({ baseUrl: endpoint, authorization });
|
|
28
|
+
|
|
29
|
+
// Fetch organization details
|
|
30
|
+
const org = await getOrganization(client);
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## API
|
|
34
|
+
|
|
35
|
+
### Configuration
|
|
36
|
+
|
|
37
|
+
- **`resolveConfig(options?): Promise<ConfigResult>`** — resolve credentials from config files and environment variables. Returns `{ config, endpoint, warnings }`.
|
|
38
|
+
- **`loadConfigFile(path)`** — load a YAML configuration file
|
|
39
|
+
- **`validateConfig(config)`** — validate configuration structure
|
|
40
|
+
- **`applyEnvOverlay(config, prefix?)`** — overlay environment variable overrides
|
|
41
|
+
- **`ConfigError`** — error thrown on configuration validation failures or missing credentials
|
|
42
|
+
|
|
43
|
+
### Authentication
|
|
44
|
+
|
|
45
|
+
- **`buildApiKeyAuthorization(credentials)`** — build authorization headers from API key credentials
|
|
46
|
+
- **`AuthError`** — error thrown when API key credentials are missing or invalid
|
|
47
|
+
|
|
48
|
+
### HTTP Client
|
|
49
|
+
|
|
50
|
+
- **`HttpClient`** — HTTP client for the Qonto API with rate-limit handling
|
|
51
|
+
- **`QontoApiError`** — typed error for Qonto API error responses
|
|
52
|
+
- **`QontoRateLimitError`** — error for rate-limit (429) responses
|
|
53
|
+
|
|
54
|
+
### Constants
|
|
55
|
+
|
|
56
|
+
- **`API_BASE_URL`** — production API base URL (`https://thirdparty.qonto.com`)
|
|
57
|
+
- **`SANDBOX_BASE_URL`** — sandbox API base URL (`https://thirdparty-sandbox.staging.qonto.co`)
|
|
58
|
+
|
|
59
|
+
### Services
|
|
60
|
+
|
|
61
|
+
- **`getOrganization(client)`** — fetch organization details
|
|
62
|
+
- **`getBankAccount(client, id)`** — fetch a bank account by ID
|
|
63
|
+
- **`getTransaction(client, id)`** — fetch a transaction by ID
|
|
64
|
+
- **`buildTransactionQueryParams(params)`** — build query parameters for transaction listing
|
|
65
|
+
|
|
66
|
+
### Types
|
|
67
|
+
|
|
68
|
+
- `Organization`, `BankAccount`, `Transaction`, `TransactionLabel`
|
|
69
|
+
- `Label`, `Membership`, `Statement`, `StatementFile`
|
|
70
|
+
- `QontoctlConfig`, `ApiKeyCredentials`, `ListTransactionsParams`
|
|
71
|
+
- `ConfigResult`, `ResolveOptions`, `LoadResult`, `ValidationResult`
|
|
72
|
+
- `HttpClientOptions`, `HttpClientLogger`, `QueryParams`, `QueryParamValue`, `QontoApiErrorEntry`
|
|
73
|
+
|
|
74
|
+
## Configuration Resolution
|
|
75
|
+
|
|
76
|
+
QontoCtl resolves credentials in this order:
|
|
77
|
+
|
|
78
|
+
1. `QONTOCTL_*` environment variables (highest priority)
|
|
79
|
+
2. `.qontoctl.yaml` in the current directory
|
|
80
|
+
3. `~/.qontoctl.yaml` (home default)
|
|
81
|
+
|
|
82
|
+
With `--profile <name>`:
|
|
83
|
+
|
|
84
|
+
1. `QONTOCTL_<NAME>_*` environment variables
|
|
85
|
+
2. `~/.qontoctl/<name>.yaml`
|
|
86
|
+
|
|
87
|
+
## Requirements
|
|
88
|
+
|
|
89
|
+
- Node.js >= 24
|
|
90
|
+
|
|
91
|
+
## License
|
|
92
|
+
|
|
93
|
+
[AGPL-3.0-only](https://github.com/alexey-pelykh/qontoctl/blob/main/LICENSE) — For commercial licensing, contact the maintainer.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A bank account as returned by the Qonto API.
|
|
3
|
+
*/
|
|
4
|
+
export interface BankAccount {
|
|
5
|
+
readonly id: string;
|
|
6
|
+
readonly name: string;
|
|
7
|
+
readonly status: string;
|
|
8
|
+
readonly main: boolean;
|
|
9
|
+
readonly organization_id: string;
|
|
10
|
+
readonly iban: string;
|
|
11
|
+
readonly bic: string;
|
|
12
|
+
readonly currency: string;
|
|
13
|
+
readonly balance: number;
|
|
14
|
+
readonly balance_cents: number;
|
|
15
|
+
readonly authorized_balance: number;
|
|
16
|
+
readonly authorized_balance_cents: number;
|
|
17
|
+
readonly slug: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Organization details as returned by `GET /v2/organization`.
|
|
21
|
+
*/
|
|
22
|
+
export interface Organization {
|
|
23
|
+
readonly slug: string;
|
|
24
|
+
readonly legal_name: string;
|
|
25
|
+
readonly bank_accounts: readonly BankAccount[];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Pagination metadata returned by the Qonto API.
|
|
29
|
+
*/
|
|
30
|
+
export interface PaginationMeta {
|
|
31
|
+
readonly current_page: number;
|
|
32
|
+
readonly next_page: number | null;
|
|
33
|
+
readonly prev_page: number | null;
|
|
34
|
+
readonly total_pages: number;
|
|
35
|
+
readonly total_count: number;
|
|
36
|
+
readonly per_page: number;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=api-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-types.d.ts","sourceRoot":"","sources":["../src/api-types.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,wBAAwB,EAAE,MAAM,CAAC;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,aAAa,EAAE,SAAS,WAAW,EAAE,CAAC;CAChD;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-types.js","sourceRoot":"","sources":["../src/api-types.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ApiKeyCredentials } from "../config/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Error thrown when API key authentication fails due to missing or invalid credentials.
|
|
4
|
+
*/
|
|
5
|
+
export declare class AuthError extends Error {
|
|
6
|
+
constructor(message: string);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Builds the Authorization header value from API key credentials.
|
|
10
|
+
*
|
|
11
|
+
* The Qonto API uses a simple `{slug}:{key}` format (no Base64 encoding).
|
|
12
|
+
*
|
|
13
|
+
* @throws {AuthError} when credentials are missing or incomplete
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildApiKeyAuthorization(credentials: ApiKeyCredentials): string;
|
|
16
|
+
//# sourceMappingURL=api-key.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-key.d.ts","sourceRoot":"","sources":["../../src/auth/api-key.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D;;GAEG;AACH,qBAAa,SAAU,SAAQ,KAAK;gBACtB,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,iBAAiB,GAAG,MAAM,CAU/E"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
2
|
+
// Copyright (C) 2026 Oleksii PELYKH
|
|
3
|
+
/**
|
|
4
|
+
* Error thrown when API key authentication fails due to missing or invalid credentials.
|
|
5
|
+
*/
|
|
6
|
+
export class AuthError extends Error {
|
|
7
|
+
constructor(message) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "AuthError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Builds the Authorization header value from API key credentials.
|
|
14
|
+
*
|
|
15
|
+
* The Qonto API uses a simple `{slug}:{key}` format (no Base64 encoding).
|
|
16
|
+
*
|
|
17
|
+
* @throws {AuthError} when credentials are missing or incomplete
|
|
18
|
+
*/
|
|
19
|
+
export function buildApiKeyAuthorization(credentials) {
|
|
20
|
+
if (credentials.organizationSlug === "") {
|
|
21
|
+
throw new AuthError("Missing organization slug in API key credentials");
|
|
22
|
+
}
|
|
23
|
+
if (credentials.secretKey === "") {
|
|
24
|
+
throw new AuthError("Missing secret key in API key credentials");
|
|
25
|
+
}
|
|
26
|
+
return `${credentials.organizationSlug}:${credentials.secretKey}`;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=api-key.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-key.js","sourceRoot":"","sources":["../../src/auth/api-key.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAIpC;;GAEG;AACH,MAAM,OAAO,SAAU,SAAQ,KAAK;IAClC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;IAC1B,CAAC;CACF;AAED;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB,CAAC,WAA8B;IACrE,IAAI,WAAW,CAAC,gBAAgB,KAAK,EAAE,EAAE,CAAC;QACxC,MAAM,IAAI,SAAS,CAAC,kDAAkD,CAAC,CAAC;IAC1E,CAAC;IAED,IAAI,WAAW,CAAC,SAAS,KAAK,EAAE,EAAE,CAAC;QACjC,MAAM,IAAI,SAAS,CAAC,2CAA2C,CAAC,CAAC;IACnE,CAAC;IAED,OAAO,GAAG,WAAW,CAAC,gBAAgB,IAAI,WAAW,CAAC,SAAS,EAAE,CAAC;AACpE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EAAE,SAAS,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { QontoctlConfig } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Overlays environment variables onto a config.
|
|
4
|
+
*
|
|
5
|
+
* - Without profile: reads `QONTOCTL_ORGANIZATION_SLUG`, `QONTOCTL_SECRET_KEY`,
|
|
6
|
+
* `QONTOCTL_ENDPOINT`, and `QONTOCTL_SANDBOX`
|
|
7
|
+
* - With profile: reads `QONTOCTL_{PROFILE}_ORGANIZATION_SLUG`,
|
|
8
|
+
* `QONTOCTL_{PROFILE}_SECRET_KEY`, `QONTOCTL_{PROFILE}_ENDPOINT`, and
|
|
9
|
+
* `QONTOCTL_{PROFILE}_SANDBOX` (profile name uppercased, hyphens→underscores)
|
|
10
|
+
*
|
|
11
|
+
* Env vars take precedence over file values.
|
|
12
|
+
*/
|
|
13
|
+
export declare function applyEnvOverlay(config: QontoctlConfig, options?: {
|
|
14
|
+
profile?: string | undefined;
|
|
15
|
+
env?: Record<string, string | undefined> | undefined;
|
|
16
|
+
}): QontoctlConfig;
|
|
17
|
+
//# sourceMappingURL=env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAQjD;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,cAAc,EACtB,OAAO,CAAC,EAAE;IACR,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;CACtD,GACA,cAAc,CA+BhB"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
2
|
+
// Copyright (C) 2026 Oleksii PELYKH
|
|
3
|
+
const ENV_PREFIX = "QONTOCTL";
|
|
4
|
+
const ORG_SLUG_SUFFIX = "ORGANIZATION_SLUG";
|
|
5
|
+
const SECRET_KEY_SUFFIX = "SECRET_KEY";
|
|
6
|
+
const ENDPOINT_SUFFIX = "ENDPOINT";
|
|
7
|
+
const SANDBOX_SUFFIX = "SANDBOX";
|
|
8
|
+
/**
|
|
9
|
+
* Overlays environment variables onto a config.
|
|
10
|
+
*
|
|
11
|
+
* - Without profile: reads `QONTOCTL_ORGANIZATION_SLUG`, `QONTOCTL_SECRET_KEY`,
|
|
12
|
+
* `QONTOCTL_ENDPOINT`, and `QONTOCTL_SANDBOX`
|
|
13
|
+
* - With profile: reads `QONTOCTL_{PROFILE}_ORGANIZATION_SLUG`,
|
|
14
|
+
* `QONTOCTL_{PROFILE}_SECRET_KEY`, `QONTOCTL_{PROFILE}_ENDPOINT`, and
|
|
15
|
+
* `QONTOCTL_{PROFILE}_SANDBOX` (profile name uppercased, hyphens→underscores)
|
|
16
|
+
*
|
|
17
|
+
* Env vars take precedence over file values.
|
|
18
|
+
*/
|
|
19
|
+
export function applyEnvOverlay(config, options) {
|
|
20
|
+
const env = options?.env ?? process.env;
|
|
21
|
+
const prefix = buildPrefix(options?.profile);
|
|
22
|
+
const orgSlug = env[`${prefix}_${ORG_SLUG_SUFFIX}`];
|
|
23
|
+
const secretKey = env[`${prefix}_${SECRET_KEY_SUFFIX}`];
|
|
24
|
+
const endpoint = env[`${prefix}_${ENDPOINT_SUFFIX}`];
|
|
25
|
+
const sandbox = env[`${prefix}_${SANDBOX_SUFFIX}`];
|
|
26
|
+
let result = config;
|
|
27
|
+
if (orgSlug !== undefined || secretKey !== undefined) {
|
|
28
|
+
const existing = result.apiKey;
|
|
29
|
+
result = {
|
|
30
|
+
...result,
|
|
31
|
+
apiKey: {
|
|
32
|
+
organizationSlug: orgSlug ?? existing?.organizationSlug ?? "",
|
|
33
|
+
secretKey: secretKey ?? existing?.secretKey ?? "",
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
if (endpoint !== undefined) {
|
|
38
|
+
result = { ...result, endpoint };
|
|
39
|
+
}
|
|
40
|
+
if (sandbox !== undefined) {
|
|
41
|
+
result = { ...result, sandbox: sandbox === "1" || sandbox === "true" };
|
|
42
|
+
}
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
function buildPrefix(profile) {
|
|
46
|
+
if (profile === undefined) {
|
|
47
|
+
return ENV_PREFIX;
|
|
48
|
+
}
|
|
49
|
+
const normalized = profile.toUpperCase().replaceAll("-", "_");
|
|
50
|
+
return `${ENV_PREFIX}_${normalized}`;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAIpC,MAAM,UAAU,GAAG,UAAU,CAAC;AAC9B,MAAM,eAAe,GAAG,mBAAmB,CAAC;AAC5C,MAAM,iBAAiB,GAAG,YAAY,CAAC;AACvC,MAAM,eAAe,GAAG,UAAU,CAAC;AACnC,MAAM,cAAc,GAAG,SAAS,CAAC;AAEjC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAsB,EACtB,OAGC;IAED,MAAM,GAAG,GAAG,OAAO,EAAE,GAAG,IAAK,OAAO,CAAC,GAA0C,CAAC;IAChF,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAE7C,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,MAAM,IAAI,eAAe,EAAE,CAAC,CAAC;IACpD,MAAM,SAAS,GAAG,GAAG,CAAC,GAAG,MAAM,IAAI,iBAAiB,EAAE,CAAC,CAAC;IACxD,MAAM,QAAQ,GAAG,GAAG,CAAC,GAAG,MAAM,IAAI,eAAe,EAAE,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,MAAM,IAAI,cAAc,EAAE,CAAC,CAAC;IAEnD,IAAI,MAAM,GAAG,MAAM,CAAC;IAEpB,IAAI,OAAO,KAAK,SAAS,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QACrD,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC;QAC/B,MAAM,GAAG;YACP,GAAG,MAAM;YACT,MAAM,EAAE;gBACN,gBAAgB,EAAE,OAAO,IAAI,QAAQ,EAAE,gBAAgB,IAAI,EAAE;gBAC7D,SAAS,EAAE,SAAS,IAAI,QAAQ,EAAE,SAAS,IAAI,EAAE;aAClD;SACF,CAAC;IACJ,CAAC;IAED,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnC,CAAC;IAED,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;IACzE,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,WAAW,CAAC,OAA2B;IAC9C,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC9D,OAAO,GAAG,UAAU,IAAI,UAAU,EAAE,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type { ApiKeyCredentials, QontoctlConfig, ConfigResult, ResolveOptions } from "./types.js";
|
|
2
|
+
export { resolveConfig, ConfigError } from "./resolve.js";
|
|
3
|
+
export { loadConfigFile } from "./loader.js";
|
|
4
|
+
export type { LoadResult } from "./loader.js";
|
|
5
|
+
export { isValidProfileName, validateConfig } from "./validate.js";
|
|
6
|
+
export type { ValidationResult } from "./validate.js";
|
|
7
|
+
export { applyEnvOverlay } from "./env.js";
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAGA,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAClG,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACnE,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
2
|
+
// Copyright (C) 2026 Oleksii PELYKH
|
|
3
|
+
export { resolveConfig, ConfigError } from "./resolve.js";
|
|
4
|
+
export { loadConfigFile } from "./loader.js";
|
|
5
|
+
export { isValidProfileName, validateConfig } from "./validate.js";
|
|
6
|
+
export { applyEnvOverlay } from "./env.js";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAGpC,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEnE,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface LoadResult {
|
|
2
|
+
/** Parsed YAML content, or `undefined` if no file was found. */
|
|
3
|
+
raw: unknown;
|
|
4
|
+
/** Path of the file that was loaded, or `undefined` if none found. */
|
|
5
|
+
path: string | undefined;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Resolves and loads the appropriate config file.
|
|
9
|
+
*
|
|
10
|
+
* - With `profile`: loads `~/.qontoctl/{profile}.yaml`
|
|
11
|
+
* - Without `profile`: tries CWD `.qontoctl.yaml`, then `~/.qontoctl.yaml`
|
|
12
|
+
*/
|
|
13
|
+
export declare function loadConfigFile(options?: {
|
|
14
|
+
profile?: string | undefined;
|
|
15
|
+
cwd?: string | undefined;
|
|
16
|
+
home?: string | undefined;
|
|
17
|
+
}): Promise<LoadResult>;
|
|
18
|
+
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,UAAU;IACzB,gEAAgE;IAChE,GAAG,EAAE,OAAO,CAAC;IACb,sEAAsE;IACtE,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,OAAO,CAAC,EAAE;IAC7C,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B,GAAG,OAAO,CAAC,UAAU,CAAC,CAqBtB"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
2
|
+
// Copyright (C) 2026 Oleksii PELYKH
|
|
3
|
+
import { readFile } from "node:fs/promises";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { homedir } from "node:os";
|
|
6
|
+
import { parse as parseYaml } from "yaml";
|
|
7
|
+
import { CONFIG_DIR } from "../constants.js";
|
|
8
|
+
const CONFIG_FILENAME = ".qontoctl.yaml";
|
|
9
|
+
/**
|
|
10
|
+
* Resolves and loads the appropriate config file.
|
|
11
|
+
*
|
|
12
|
+
* - With `profile`: loads `~/.qontoctl/{profile}.yaml`
|
|
13
|
+
* - Without `profile`: tries CWD `.qontoctl.yaml`, then `~/.qontoctl.yaml`
|
|
14
|
+
*/
|
|
15
|
+
export async function loadConfigFile(options) {
|
|
16
|
+
const home = options?.home ?? homedir();
|
|
17
|
+
const profile = options?.profile;
|
|
18
|
+
if (profile !== undefined) {
|
|
19
|
+
const path = join(home, CONFIG_DIR, `${profile}.yaml`);
|
|
20
|
+
return loadFromPath(path);
|
|
21
|
+
}
|
|
22
|
+
const cwd = options?.cwd ?? process.cwd();
|
|
23
|
+
// Try CWD first
|
|
24
|
+
const cwdPath = join(cwd, CONFIG_FILENAME);
|
|
25
|
+
const cwdResult = await loadFromPath(cwdPath);
|
|
26
|
+
if (cwdResult.raw !== undefined) {
|
|
27
|
+
return cwdResult;
|
|
28
|
+
}
|
|
29
|
+
// Fall back to home directory
|
|
30
|
+
const homePath = join(home, CONFIG_FILENAME);
|
|
31
|
+
return loadFromPath(homePath);
|
|
32
|
+
}
|
|
33
|
+
async function loadFromPath(path) {
|
|
34
|
+
try {
|
|
35
|
+
const content = await readFile(path, "utf-8");
|
|
36
|
+
const raw = parseYaml(content);
|
|
37
|
+
return { raw, path };
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
if (isNodeError(error) && error.code === "ENOENT") {
|
|
41
|
+
return { raw: undefined, path: undefined };
|
|
42
|
+
}
|
|
43
|
+
throw new Error(`Failed to read config file "${path}": ${String(error)}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function isNodeError(error) {
|
|
47
|
+
return error instanceof Error && "code" in error;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,eAAe,GAAG,gBAAgB,CAAC;AASzC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAIpC;IACC,MAAM,IAAI,GAAG,OAAO,EAAE,IAAI,IAAI,OAAO,EAAE,CAAC;IACxC,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,CAAC;IAEjC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,OAAO,OAAO,CAAC,CAAC;QACvD,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,MAAM,GAAG,GAAG,OAAO,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAE1C,gBAAgB;IAChB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,CAAC;IAC9C,IAAI,SAAS,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,8BAA8B;IAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IAC7C,OAAO,YAAY,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,IAAY;IACtC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC9C,MAAM,GAAG,GAAY,SAAS,CAAC,OAAO,CAAC,CAAC;QACxC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;IACvB,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,IAAI,WAAW,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAClD,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QAC7C,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,+BAA+B,IAAI,MAAM,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC5E,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IACjC,OAAO,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ConfigResult, ResolveOptions } from "./types.js";
|
|
2
|
+
export declare class ConfigError extends Error {
|
|
3
|
+
constructor(message: string);
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Resolves the full configuration by:
|
|
7
|
+
* 1. Loading the appropriate YAML config file (profile-aware)
|
|
8
|
+
* 2. Validating the schema (producing warnings for unknown keys)
|
|
9
|
+
* 3. Overlaying environment variables
|
|
10
|
+
* 4. Verifying that credentials are present
|
|
11
|
+
* 5. Resolving the API endpoint
|
|
12
|
+
*
|
|
13
|
+
* Endpoint precedence:
|
|
14
|
+
* QONTOCTL_ENDPOINT > QONTOCTL_SANDBOX > profile endpoint > profile sandbox > default
|
|
15
|
+
*
|
|
16
|
+
* @throws {ConfigError} on validation errors or missing credentials
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveConfig(options?: ResolveOptions): Promise<ConfigResult>;
|
|
19
|
+
//# sourceMappingURL=resolve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/config/resolve.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAM/D,qBAAa,WAAY,SAAQ,KAAK;gBACxB,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,aAAa,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CA0CnF"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
2
|
+
// Copyright (C) 2026 Oleksii PELYKH
|
|
3
|
+
import { loadConfigFile } from "./loader.js";
|
|
4
|
+
import { validateConfig } from "./validate.js";
|
|
5
|
+
import { applyEnvOverlay } from "./env.js";
|
|
6
|
+
import { API_BASE_URL, SANDBOX_BASE_URL } from "../constants.js";
|
|
7
|
+
export class ConfigError extends Error {
|
|
8
|
+
constructor(message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = "ConfigError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Resolves the full configuration by:
|
|
15
|
+
* 1. Loading the appropriate YAML config file (profile-aware)
|
|
16
|
+
* 2. Validating the schema (producing warnings for unknown keys)
|
|
17
|
+
* 3. Overlaying environment variables
|
|
18
|
+
* 4. Verifying that credentials are present
|
|
19
|
+
* 5. Resolving the API endpoint
|
|
20
|
+
*
|
|
21
|
+
* Endpoint precedence:
|
|
22
|
+
* QONTOCTL_ENDPOINT > QONTOCTL_SANDBOX > profile endpoint > profile sandbox > default
|
|
23
|
+
*
|
|
24
|
+
* @throws {ConfigError} on validation errors or missing credentials
|
|
25
|
+
*/
|
|
26
|
+
export async function resolveConfig(options) {
|
|
27
|
+
const profile = options?.profile;
|
|
28
|
+
// 1. Load config file
|
|
29
|
+
const { raw, path } = await loadConfigFile({
|
|
30
|
+
profile,
|
|
31
|
+
cwd: options?.cwd,
|
|
32
|
+
home: options?.home,
|
|
33
|
+
});
|
|
34
|
+
// 2. Validate
|
|
35
|
+
const { config: fileConfig, warnings, errors } = validateConfig(raw);
|
|
36
|
+
if (errors.length > 0) {
|
|
37
|
+
const location = path !== undefined ? ` (${path})` : "";
|
|
38
|
+
throw new ConfigError(`Invalid configuration${location}:\n - ${errors.join("\n - ")}`);
|
|
39
|
+
}
|
|
40
|
+
// 3. Overlay env vars
|
|
41
|
+
const config = applyEnvOverlay(fileConfig, {
|
|
42
|
+
profile,
|
|
43
|
+
env: options?.env,
|
|
44
|
+
});
|
|
45
|
+
// 4. Verify credentials are present
|
|
46
|
+
if (config.apiKey === undefined) {
|
|
47
|
+
const searchedLocations = describeSearchLocations(profile, path);
|
|
48
|
+
throw new ConfigError(`No credentials found. ${searchedLocations}`);
|
|
49
|
+
}
|
|
50
|
+
if (config.apiKey.organizationSlug === "") {
|
|
51
|
+
throw new ConfigError('Missing required field "organization-slug" in api-key credentials');
|
|
52
|
+
}
|
|
53
|
+
if (config.apiKey.secretKey === "") {
|
|
54
|
+
throw new ConfigError('Missing required field "secret-key" in api-key credentials');
|
|
55
|
+
}
|
|
56
|
+
// 5. Resolve endpoint
|
|
57
|
+
const endpoint = resolveEndpoint(config);
|
|
58
|
+
return { config, endpoint, warnings };
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Resolves the API endpoint from config.
|
|
62
|
+
*
|
|
63
|
+
* Precedence (env overlay already applied, so env vars win over file values):
|
|
64
|
+
* explicit endpoint > sandbox flag > default (production)
|
|
65
|
+
*/
|
|
66
|
+
function resolveEndpoint(config) {
|
|
67
|
+
if (config.endpoint !== undefined) {
|
|
68
|
+
return config.endpoint;
|
|
69
|
+
}
|
|
70
|
+
if (config.sandbox === true) {
|
|
71
|
+
return SANDBOX_BASE_URL;
|
|
72
|
+
}
|
|
73
|
+
return API_BASE_URL;
|
|
74
|
+
}
|
|
75
|
+
function describeSearchLocations(profile, loadedPath) {
|
|
76
|
+
if (profile !== undefined) {
|
|
77
|
+
return `Checked ~/.qontoctl/${profile}.yaml and QONTOCTL_${profile.toUpperCase().replaceAll("-", "_")}_* env vars.`;
|
|
78
|
+
}
|
|
79
|
+
if (loadedPath !== undefined) {
|
|
80
|
+
return `Found config at ${loadedPath} but it contains no api-key credentials. Also checked QONTOCTL_* env vars.`;
|
|
81
|
+
}
|
|
82
|
+
return "Checked .qontoctl.yaml (CWD), ~/.qontoctl.yaml (home), and QONTOCTL_* env vars.";
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/config/resolve.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API key credentials for authenticating with the Qonto API.
|
|
3
|
+
*/
|
|
4
|
+
export interface ApiKeyCredentials {
|
|
5
|
+
organizationSlug: string;
|
|
6
|
+
secretKey: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Parsed configuration from a `.qontoctl.yaml` file.
|
|
10
|
+
*/
|
|
11
|
+
export interface QontoctlConfig {
|
|
12
|
+
apiKey?: ApiKeyCredentials;
|
|
13
|
+
endpoint?: string;
|
|
14
|
+
sandbox?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Result of resolving configuration, including any warnings encountered.
|
|
18
|
+
*/
|
|
19
|
+
export interface ConfigResult {
|
|
20
|
+
config: QontoctlConfig;
|
|
21
|
+
/** Resolved API endpoint URL. */
|
|
22
|
+
endpoint: string;
|
|
23
|
+
warnings: string[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Options for resolving configuration.
|
|
27
|
+
*/
|
|
28
|
+
export interface ResolveOptions {
|
|
29
|
+
/** Named profile to load from `~/.qontoctl/{profile}.yaml`. */
|
|
30
|
+
profile?: string | undefined;
|
|
31
|
+
/** Override CWD for file resolution (useful for testing). */
|
|
32
|
+
cwd?: string | undefined;
|
|
33
|
+
/** Override home directory for file resolution (useful for testing). */
|
|
34
|
+
home?: string | undefined;
|
|
35
|
+
/** Override environment variables (useful for testing). */
|
|
36
|
+
env?: Record<string, string | undefined> | undefined;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,cAAc,CAAC;IACvB,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,6DAA6D;IAC7D,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,wEAAwE;IACxE,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,2DAA2D;IAC3D,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;CACtD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { QontoctlConfig } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Check whether a profile name is safe to use as a filename.
|
|
4
|
+
*
|
|
5
|
+
* Rejects names containing path separators (`/`, `\`) or parent-directory
|
|
6
|
+
* references (`..`) to prevent path-traversal attacks.
|
|
7
|
+
*/
|
|
8
|
+
export declare function isValidProfileName(name: string): boolean;
|
|
9
|
+
export interface ValidationResult {
|
|
10
|
+
config: QontoctlConfig;
|
|
11
|
+
warnings: string[];
|
|
12
|
+
errors: string[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Validates a parsed YAML document against the expected config schema.
|
|
16
|
+
*
|
|
17
|
+
* - Known keys with wrong types produce errors.
|
|
18
|
+
* - Unknown keys produce warnings (forward compatibility).
|
|
19
|
+
* - Returns a partially-populated config for valid fields.
|
|
20
|
+
*/
|
|
21
|
+
export declare function validateConfig(raw: unknown): ValidationResult;
|
|
22
|
+
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/config/validate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAKD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,CAsF7D"}
|