@theholocron/holocron-plugin-axiom 3.54.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Newton Koumantzelis
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,75 @@
1
+ <!-- editorconfig-checker-disable-file -->
2
+
3
+ # `@theholocron/holocron-plugin-axiom`
4
+
5
+ Axiom plugin for [Holocron](../cli). Implements the `logs` capability
6
+ against [Axiom's REST API](https://axiom.co/docs/restapi/introduction),
7
+ plus exports `verifyToken` + `AUTH_HINT` for use by `holocron auth`.
8
+
9
+ > This plugin does **not** ship log lines. `@theholocron/logger`'s Axiom
10
+ > transport reads `HOLOCRON_AXIOM_TOKEN` / `HOLOCRON_AXIOM_DATASET`
11
+ > directly at startup. The `logs` capability exists only for the
12
+ > management surface — `holocron setup` provisions the aggregation
13
+ > datasets and `holocron doctor` checks connectivity.
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ pnpm add -D @theholocron/holocron-plugin-axiom
19
+ ```
20
+
21
+ ## Auth
22
+
23
+ Token resolution order:
24
+
25
+ 1. `--token <TOKEN>` flag on the holocron invocation
26
+ 2. `HOLOCRON_AXIOM_TOKEN` env var (preferred — explicit intent)
27
+ 3. `AXIOM_TOKEN` env var (Axiom-native, works in CI)
28
+ 4. Keyring `axiom.<org>` — tried first when an org is active via `--org`, `HOLOCRON_ORG`, or `org` in `holocron.config.ts`
29
+ 5. Keyring `axiom` — unnamespaced fallback; set via `holocron auth set axiom <token>`
30
+ 6. `AuthError` naming both env vars + the auth hint
31
+
32
+ Generate an API token at **app.axiom.co/settings/api-tokens** with
33
+ permission to read and create datasets.
34
+
35
+ ```bash
36
+ holocron auth set axiom.theholocron <TOKEN>
37
+ ```
38
+
39
+ **CI**: the keyring is unavailable in headless containers — expose the
40
+ token as `HOLOCRON_AXIOM_TOKEN` (or `AXIOM_TOKEN`) in the workflow env.
41
+
42
+ ## Config
43
+
44
+ ```jsonc
45
+ {
46
+ "providers": {
47
+ "logs": "axiom",
48
+ },
49
+ }
50
+ ```
51
+
52
+ No options are required. `holocron setup` provisions the `holocron-ci`
53
+ and `holocron-local` datasets; `holocron doctor` checks the dataset
54
+ named by `HOLOCRON_AXIOM_DATASET` / `AXIOM_DATASET`. An explicit
55
+ `logs: ["axiom", { "dataset": "holocron-ci" }]` overrides the env var
56
+ for `doctor`.
57
+
58
+ `HOLOCRON_AXIOM_DATASET` is **not a secret** — set it in your shell
59
+ profile locally (`holocron-local`) or as an org CI secret
60
+ (`holocron-ci`). Leave it unset locally to skip Axiom entirely.
61
+
62
+ ## What's implemented
63
+
64
+ | Method | Behavior |
65
+ | --------------- | ------------------------------------------------------------------------------------------------ |
66
+ | `describe` | Returns `{ provider: "axiom", envKeys: ["HOLOCRON_AXIOM_TOKEN", "HOLOCRON_AXIOM_DATASET"] }`. |
67
+ | `whoami` | `GET /v2/datasets/{dataset}` — verifies the token and the configured dataset's reachability. |
68
+ | `ensureDataset` | `GET /v2/datasets/{name}`; on 404, `POST /v2/datasets`. Returns `{ alreadyExists }`. Idempotent. |
69
+
70
+ Plugin-level exports (not capability methods, per the auth-bootstrap convention):
71
+
72
+ | Export | Purpose |
73
+ | ------------- | ------------------------------------------------------------------------------------------- |
74
+ | `verifyToken` | `GET /v2/user` — returns `{ ok: true, subject: "user @ …" }` or `{ ok: false, message }`. |
75
+ | `AUTH_HINT` | One-line hint printed by `holocron auth set` when no token is supplied or the token is bad. |
@@ -0,0 +1,115 @@
1
+ import { AuthError, Logs, ResolveTokenInput } from "@theholocron/cli";
2
+ //#region src/auth.d.ts
3
+ declare const resolveToken: (input?: ResolveTokenInput) => string;
4
+ //#endregion
5
+ //#region src/rest.d.ts
6
+ /** Axiom dataset — the subset of fields Holocron reads. */
7
+ interface AxiomDataset {
8
+ id: string;
9
+ name: string;
10
+ description?: string;
11
+ }
12
+ /** Axiom user — the subset returned by `GET /v2/user`. */
13
+ interface AxiomUser {
14
+ id: string;
15
+ name?: string;
16
+ email?: string;
17
+ emails?: string[];
18
+ }
19
+ interface AxiomClientOptions {
20
+ token: string;
21
+ /** Override the API base URL (default `https://api.axiom.co`). */
22
+ baseUrl?: string;
23
+ /** Override `fetch` for tests. */
24
+ fetch?: typeof fetch;
25
+ }
26
+ interface AxiomRestClient {
27
+ getDataset(name: string): Promise<AxiomDataset>;
28
+ createDataset(input: {
29
+ name: string;
30
+ description?: string;
31
+ }): Promise<AxiomDataset>;
32
+ getCurrentUser(): Promise<AxiomUser>;
33
+ }
34
+ declare function createAxiomClient(opts: AxiomClientOptions): AxiomRestClient;
35
+ //#endregion
36
+ //#region src/capabilities/logs.d.ts
37
+ interface AxiomLogsOptions {
38
+ /**
39
+ * Target dataset, resolved from `HOLOCRON_AXIOM_DATASET` /
40
+ * `AXIOM_DATASET`. Required for `whoami`; not needed for `describe`
41
+ * or `ensureDataset` (which takes an explicit name).
42
+ */
43
+ dataset?: string;
44
+ }
45
+ declare class AxiomLogs implements Logs {
46
+ private readonly client;
47
+ private readonly opts;
48
+ readonly key: "logs";
49
+ readonly providerName = "axiom";
50
+ constructor(client: AxiomRestClient, opts: AxiomLogsOptions);
51
+ describe(): Promise<{
52
+ provider: string;
53
+ envKeys: string[];
54
+ }>;
55
+ whoami(): Promise<{
56
+ ok: boolean;
57
+ dataset: string;
58
+ }>;
59
+ ensureDataset(name: string): Promise<{
60
+ alreadyExists: boolean;
61
+ }>;
62
+ }
63
+ //#endregion
64
+ //#region src/verify-token.d.ts
65
+ /**
66
+ * `verifyToken` — plugin-level export used by `holocron auth set axiom`
67
+ * + `holocron auth check`. Hits `GET /v2/user` and translates the
68
+ * response into the normalized `VerifyTokenResult` shape.
69
+ *
70
+ * Kept as a standalone function (not a capability method) so the auth
71
+ * command can call it without initializing the full plugin.
72
+ */
73
+ interface VerifyTokenSuccess {
74
+ ok: true;
75
+ subject: string;
76
+ }
77
+ interface VerifyTokenFailure {
78
+ ok: false;
79
+ message: string;
80
+ }
81
+ type VerifyTokenResult = VerifyTokenSuccess | VerifyTokenFailure;
82
+ interface VerifyTokenOptions {
83
+ baseUrl?: string;
84
+ fetch?: typeof fetch;
85
+ }
86
+ declare function verifyToken(token: string, opts?: VerifyTokenOptions): Promise<VerifyTokenResult>;
87
+ //#endregion
88
+ //#region src/index.d.ts
89
+ interface AxiomPluginOptions extends ResolveTokenInput, AxiomLogsOptions {
90
+ /** Override base URL for tests. */
91
+ baseUrl?: string;
92
+ /** Override `fetch` for tests. */
93
+ fetch?: typeof fetch;
94
+ }
95
+ interface PluginContext {
96
+ options: AxiomPluginOptions & {
97
+ dataset?: string;
98
+ };
99
+ client: AxiomRestClient;
100
+ }
101
+ declare function createContext(options: AxiomPluginOptions): PluginContext;
102
+ declare function logs(ctx: PluginContext): Logs;
103
+ declare function createPlugin(options: AxiomPluginOptions): {
104
+ name: string;
105
+ capabilities: {
106
+ logs: () => Logs;
107
+ };
108
+ };
109
+ /**
110
+ * One-line hint shown by `holocron auth set axiom` when no token is
111
+ * supplied or when the supplied token is rejected.
112
+ */
113
+ declare const AUTH_HINT: string;
114
+ //#endregion
115
+ export { AUTH_HINT, AuthError, type AxiomClientOptions, type AxiomDataset, AxiomLogs, type AxiomLogsOptions, AxiomPluginOptions, type AxiomRestClient, type AxiomUser, PluginContext, type ResolveTokenInput, type VerifyTokenFailure, type VerifyTokenResult, type VerifyTokenSuccess, createAxiomClient, createContext, createPlugin, logs, resolveToken, verifyToken };
package/dist/index.mjs ADDED
@@ -0,0 +1,128 @@
1
+ import { AuthError, ProviderApiError, createResolveToken, createRestClient } from "@theholocron/cli";
2
+ //#region src/auth.ts
3
+ const resolveToken = createResolveToken({
4
+ envName: "HOLOCRON_AXIOM_TOKEN",
5
+ vendorEnvName: "AXIOM_TOKEN",
6
+ keyringService: "axiom",
7
+ errorMessage: "no Axiom token found. Pass --token <TOKEN>, set HOLOCRON_AXIOM_TOKEN / AXIOM_TOKEN, or run: holocron auth set axiom <TOKEN>"
8
+ });
9
+ //#endregion
10
+ //#region src/capabilities/logs.ts
11
+ var AxiomLogs = class {
12
+ client;
13
+ opts;
14
+ key = "logs";
15
+ providerName = "axiom";
16
+ constructor(client, opts) {
17
+ this.client = client;
18
+ this.opts = opts;
19
+ }
20
+ async describe() {
21
+ return {
22
+ provider: "axiom",
23
+ envKeys: ["HOLOCRON_AXIOM_TOKEN", "HOLOCRON_AXIOM_DATASET"]
24
+ };
25
+ }
26
+ async whoami() {
27
+ const dataset = this.opts.dataset;
28
+ if (!dataset) throw new Error("@theholocron/holocron-plugin-axiom needs a dataset (HOLOCRON_AXIOM_DATASET / AXIOM_DATASET) for whoami");
29
+ await this.client.getDataset(dataset);
30
+ return {
31
+ ok: true,
32
+ dataset
33
+ };
34
+ }
35
+ async ensureDataset(name) {
36
+ try {
37
+ await this.client.getDataset(name);
38
+ return { alreadyExists: true };
39
+ } catch (err) {
40
+ if (!(err instanceof ProviderApiError) || err.status !== 404) throw err;
41
+ }
42
+ await this.client.createDataset({
43
+ name,
44
+ description: "Managed by holocron"
45
+ });
46
+ return { alreadyExists: false };
47
+ }
48
+ };
49
+ function createAxiomClient(opts) {
50
+ const rest = createRestClient({
51
+ baseUrl: opts.baseUrl ?? "https://api.axiom.co",
52
+ token: opts.token,
53
+ vendor: "Axiom",
54
+ fetch: opts.fetch
55
+ });
56
+ return {
57
+ getDataset: (name) => rest.request(`/v2/datasets/${encodeURIComponent(name)}`),
58
+ createDataset: (input) => rest.request("/v2/datasets", {
59
+ method: "POST",
60
+ body: input
61
+ }),
62
+ getCurrentUser: () => rest.request("/v2/user")
63
+ };
64
+ }
65
+ //#endregion
66
+ //#region src/verify-token.ts
67
+ /**
68
+ * `verifyToken` — plugin-level export used by `holocron auth set axiom`
69
+ * + `holocron auth check`. Hits `GET /v2/user` and translates the
70
+ * response into the normalized `VerifyTokenResult` shape.
71
+ *
72
+ * Kept as a standalone function (not a capability method) so the auth
73
+ * command can call it without initializing the full plugin.
74
+ */
75
+ async function verifyToken(token, opts = {}) {
76
+ const client = createAxiomClient({
77
+ token,
78
+ baseUrl: opts.baseUrl,
79
+ fetch: opts.fetch
80
+ });
81
+ try {
82
+ const me = await client.getCurrentUser();
83
+ return {
84
+ ok: true,
85
+ subject: `user @ ${me.email ?? me.emails?.[0] ?? me.name ?? me.id ?? "unknown"}`
86
+ };
87
+ } catch (err) {
88
+ return {
89
+ ok: false,
90
+ message: err instanceof Error ? err.message : String(err)
91
+ };
92
+ }
93
+ }
94
+ //#endregion
95
+ //#region src/index.ts
96
+ function createContext(options) {
97
+ const token = resolveToken(options);
98
+ const env = options.env ?? process.env;
99
+ const dataset = options.dataset ?? env.HOLOCRON_AXIOM_DATASET ?? env.AXIOM_DATASET;
100
+ return {
101
+ options: {
102
+ ...options,
103
+ dataset
104
+ },
105
+ client: createAxiomClient({
106
+ token,
107
+ baseUrl: options.baseUrl,
108
+ fetch: options.fetch
109
+ })
110
+ };
111
+ }
112
+ function logs(ctx) {
113
+ return new AxiomLogs(ctx.client, { dataset: ctx.options.dataset });
114
+ }
115
+ function createPlugin(options) {
116
+ const ctx = createContext(options);
117
+ return {
118
+ name: "@theholocron/holocron-plugin-axiom",
119
+ capabilities: { logs: () => logs(ctx) }
120
+ };
121
+ }
122
+ /**
123
+ * One-line hint shown by `holocron auth set axiom` when no token is
124
+ * supplied or when the supplied token is rejected.
125
+ */
126
+ const AUTH_HINT = "generate an Axiom API token at https://app.axiom.co/settings/api-tokens with dataset read + create permissions, then run: holocron auth set axiom <TOKEN>";
127
+ //#endregion
128
+ export { AUTH_HINT, AuthError, AxiomLogs, createAxiomClient, createContext, createPlugin, logs, resolveToken, verifyToken };
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@theholocron/holocron-plugin-axiom",
3
+ "version": "3.54.0",
4
+ "description": "Holocron plugin for Axiom. Implements the logs capability against Axiom's REST API — dataset provisioning and connectivity checks, plus verifyToken + AUTH_HINT for `holocron auth`.",
5
+ "keywords": [
6
+ "axiom",
7
+ "holocron",
8
+ "logs",
9
+ "plugin"
10
+ ],
11
+ "homepage": "https://github.com/theholocron/holocron/tree/main/packages/holocron-plugin-axiom#readme",
12
+ "bugs": "https://github.com/theholocron/holocron/issues",
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/theholocron/holocron.git",
16
+ "directory": "packages/holocron-plugin-axiom"
17
+ },
18
+ "license": "MIT",
19
+ "author": "Newton Koumantzelis",
20
+ "sideEffects": false,
21
+ "type": "module",
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/index.d.mts",
25
+ "import": "./dist/index.mjs",
26
+ "default": "./dist/index.mjs"
27
+ }
28
+ },
29
+ "files": [
30
+ "dist"
31
+ ],
32
+ "devDependencies": {
33
+ "@theholocron/eslint-config": "^7.32.1",
34
+ "@theholocron/tsconfig": "^7.32.1",
35
+ "@theholocron/tsdown-config": "^7.32.1",
36
+ "@theholocron/vitest-config": "^7.32.1",
37
+ "@types/node": "^26",
38
+ "@vitest/coverage-v8": "^4.1.11",
39
+ "@vitest/eslint-plugin": "^1.6.27",
40
+ "eslint": "^10.8.1",
41
+ "eslint-plugin-n": "^18.3.0",
42
+ "globals": "^17.11.0",
43
+ "tsdown": "^0.22.14",
44
+ "tsx": "4.23.12",
45
+ "typescript": "^5.9.3",
46
+ "vitest": "^4.1.11",
47
+ "@theholocron/cli": "3.54.0"
48
+ },
49
+ "peerDependencies": {
50
+ "@theholocron/cli": "3.54.0"
51
+ },
52
+ "engines": {
53
+ "node": ">=22"
54
+ },
55
+ "publishConfig": {
56
+ "access": "public"
57
+ },
58
+ "scripts": {
59
+ "build": "tsdown",
60
+ "lint": "eslint .",
61
+ "typecheck": "tsc --noEmit",
62
+ "test": "vitest run",
63
+ "test:watch": "vitest",
64
+ "test:coverage": "vitest run --coverage",
65
+ "validate": "tsx scripts/validate.mjs"
66
+ }
67
+ }