@bsb/observable-axiom 1.0.1 → 1.1.3

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/bsb-tests.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "nodejs": [
3
+ {
4
+ "id": "observable-axiom",
5
+ "skip": true,
6
+ "default": {
7
+ "config": {},
8
+ "setup": null,
9
+ "dispose": null
10
+ },
11
+ "tests": []
12
+ }
13
+ ]
14
+ }
@@ -26,27 +26,27 @@
26
26
  */
27
27
  import { BSBObservable, BSBObservableConstructor, BSBError } from "@bsb/base";
28
28
  import { DTrace, LogMeta } from "@bsb/base";
29
- import { z } from "zod";
30
- export declare const Config: import("@bsb/base").BSBPluginConfigClass<z.ZodObject<{
31
- serviceName: z.ZodDefault<z.ZodString>;
32
- serviceVersion: z.ZodOptional<z.ZodString>;
33
- axiom: z.ZodObject<{
34
- token: z.ZodString;
35
- dataset: z.ZodDefault<z.ZodString>;
36
- orgId: z.ZodOptional<z.ZodString>;
37
- url: z.ZodOptional<z.ZodURL>;
38
- }, z.core.$strip>;
39
- enabled: z.ZodObject<{
40
- logs: z.ZodDefault<z.ZodBoolean>;
41
- metrics: z.ZodDefault<z.ZodBoolean>;
42
- traces: z.ZodDefault<z.ZodBoolean>;
43
- }, z.core.$strip>;
44
- export: z.ZodObject<{
45
- flushIntervalMs: z.ZodDefault<z.ZodNumber>;
46
- maxBatchSize: z.ZodDefault<z.ZodNumber>;
47
- }, z.core.$strip>;
48
- resourceAttributes: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
49
- }, z.core.$strip>>;
29
+ import * as av from "@anyvali/js";
30
+ export declare const Config: import("@bsb/base").BSBPluginConfigClass<av.ObjectSchema<{
31
+ serviceName: av.OptionalSchema<av.StringSchema>;
32
+ serviceVersion: av.OptionalSchema<av.StringSchema>;
33
+ axiom: av.ObjectSchema<{
34
+ token: av.StringSchema;
35
+ dataset: av.OptionalSchema<av.StringSchema>;
36
+ orgId: av.OptionalSchema<av.StringSchema>;
37
+ url: av.OptionalSchema<av.StringSchema>;
38
+ }>;
39
+ enabled: av.ObjectSchema<{
40
+ logs: av.OptionalSchema<av.BoolSchema>;
41
+ metrics: av.OptionalSchema<av.BoolSchema>;
42
+ traces: av.OptionalSchema<av.BoolSchema>;
43
+ }>;
44
+ export: av.ObjectSchema<{
45
+ flushIntervalMs: av.OptionalSchema<av.Int32Schema>;
46
+ maxBatchSize: av.OptionalSchema<av.Int32Schema>;
47
+ }>;
48
+ resourceAttributes: av.OptionalSchema<av.RecordSchema<av.StringSchema>>;
49
+ }>>;
50
50
  /**
51
51
  * Axiom observable plugin for unified observability
52
52
  *
@@ -55,26 +55,26 @@ export declare const Config: import("@bsb/base").BSBPluginConfigClass<z.ZodObjec
55
55
  * Exports metrics as structured events
56
56
  */
57
57
  export declare class Plugin extends BSBObservable<InstanceType<typeof Config>> {
58
- static Config: import("@bsb/base").BSBPluginConfigClass<z.ZodObject<{
59
- serviceName: z.ZodDefault<z.ZodString>;
60
- serviceVersion: z.ZodOptional<z.ZodString>;
61
- axiom: z.ZodObject<{
62
- token: z.ZodString;
63
- dataset: z.ZodDefault<z.ZodString>;
64
- orgId: z.ZodOptional<z.ZodString>;
65
- url: z.ZodOptional<z.ZodURL>;
66
- }, z.core.$strip>;
67
- enabled: z.ZodObject<{
68
- logs: z.ZodDefault<z.ZodBoolean>;
69
- metrics: z.ZodDefault<z.ZodBoolean>;
70
- traces: z.ZodDefault<z.ZodBoolean>;
71
- }, z.core.$strip>;
72
- export: z.ZodObject<{
73
- flushIntervalMs: z.ZodDefault<z.ZodNumber>;
74
- maxBatchSize: z.ZodDefault<z.ZodNumber>;
75
- }, z.core.$strip>;
76
- resourceAttributes: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
77
- }, z.core.$strip>>;
58
+ static Config: import("@bsb/base").BSBPluginConfigClass<av.ObjectSchema<{
59
+ serviceName: av.OptionalSchema<av.StringSchema>;
60
+ serviceVersion: av.OptionalSchema<av.StringSchema>;
61
+ axiom: av.ObjectSchema<{
62
+ token: av.StringSchema;
63
+ dataset: av.OptionalSchema<av.StringSchema>;
64
+ orgId: av.OptionalSchema<av.StringSchema>;
65
+ url: av.OptionalSchema<av.StringSchema>;
66
+ }>;
67
+ enabled: av.ObjectSchema<{
68
+ logs: av.OptionalSchema<av.BoolSchema>;
69
+ metrics: av.OptionalSchema<av.BoolSchema>;
70
+ traces: av.OptionalSchema<av.BoolSchema>;
71
+ }>;
72
+ export: av.ObjectSchema<{
73
+ flushIntervalMs: av.OptionalSchema<av.Int32Schema>;
74
+ maxBatchSize: av.OptionalSchema<av.Int32Schema>;
75
+ }>;
76
+ resourceAttributes: av.OptionalSchema<av.RecordSchema<av.StringSchema>>;
77
+ }>>;
78
78
  private logFormatter;
79
79
  private axiom;
80
80
  private tracerProvider;
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /**
3
2
  * BSB (Better-Service-Base) is an event-bus based microservice framework.
4
3
  * Copyright (C) 2016 - 2025 BetterCorp (PTY) Ltd
@@ -25,74 +24,38 @@
25
24
  * You should have received a copy of the GNU Affero General Public License
26
25
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
27
26
  */
28
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
29
- if (k2 === undefined) k2 = k;
30
- var desc = Object.getOwnPropertyDescriptor(m, k);
31
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
32
- desc = { enumerable: true, get: function() { return m[k]; } };
33
- }
34
- Object.defineProperty(o, k2, desc);
35
- }) : (function(o, m, k, k2) {
36
- if (k2 === undefined) k2 = k;
37
- o[k2] = m[k];
38
- }));
39
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
40
- Object.defineProperty(o, "default", { enumerable: true, value: v });
41
- }) : function(o, v) {
42
- o["default"] = v;
43
- });
44
- var __importStar = (this && this.__importStar) || (function () {
45
- var ownKeys = function(o) {
46
- ownKeys = Object.getOwnPropertyNames || function (o) {
47
- var ar = [];
48
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
49
- return ar;
50
- };
51
- return ownKeys(o);
52
- };
53
- return function (mod) {
54
- if (mod && mod.__esModule) return mod;
55
- var result = {};
56
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
57
- __setModuleDefault(result, mod);
58
- return result;
59
- };
60
- })();
61
- Object.defineProperty(exports, "__esModule", { value: true });
62
- exports.Plugin = exports.Config = void 0;
63
- const base_1 = require("@bsb/base");
64
- const zod_1 = require("zod");
65
- const js_1 = require("@axiomhq/js");
66
- const api = __importStar(require("@opentelemetry/api"));
67
- const resources_1 = require("@opentelemetry/resources");
68
- const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
69
- const sdk_trace_node_1 = require("@opentelemetry/sdk-trace-node");
70
- const sdk_trace_base_1 = require("@opentelemetry/sdk-trace-base");
71
- const exporter_trace_otlp_http_1 = require("@opentelemetry/exporter-trace-otlp-http");
72
- const ConfigSchema = zod_1.z.object({
73
- serviceName: zod_1.z.string().default("bsb-service"),
74
- serviceVersion: zod_1.z.string().optional(),
75
- axiom: zod_1.z.object({
76
- token: zod_1.z.string().describe("Axiom API token"),
77
- dataset: zod_1.z.string().default("bsb-logs").describe("Axiom dataset name"),
78
- orgId: zod_1.z.string().optional().describe("Axiom organization ID (for cloud)"),
79
- url: zod_1.z.url().optional().describe("Custom Axiom URL (for self-hosted)"),
80
- }),
81
- enabled: zod_1.z.object({
82
- logs: zod_1.z.boolean().default(true),
83
- metrics: zod_1.z.boolean().default(true),
84
- traces: zod_1.z.boolean().default(true),
85
- }),
86
- export: zod_1.z.object({
87
- flushIntervalMs: zod_1.z.number().int().min(100).default(5000),
88
- maxBatchSize: zod_1.z.number().int().min(1).default(1000),
89
- }),
90
- resourceAttributes: zod_1.z.record(zod_1.z.string(), zod_1.z.string()).default({}),
91
- });
92
- exports.Config = (0, base_1.createConfigSchema)({
27
+ import { BSBObservable, createConfigSchema, LogFormatter, BSBError } from "@bsb/base";
28
+ import * as av from "@anyvali/js";
29
+ import { Axiom } from "@axiomhq/js";
30
+ import * as api from "@opentelemetry/api";
31
+ import { defaultResource, resourceFromAttributes } from "@opentelemetry/resources";
32
+ import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from "@opentelemetry/semantic-conventions";
33
+ import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
34
+ import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
35
+ import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
36
+ const ConfigSchema = av.object({
37
+ serviceName: av.optional(av.string()).default("bsb-service"),
38
+ serviceVersion: av.optional(av.string()),
39
+ axiom: av.object({
40
+ token: av.string(),
41
+ dataset: av.optional(av.string()).default("bsb-logs"),
42
+ orgId: av.optional(av.string()),
43
+ url: av.optional(av.string().format("url")),
44
+ }, { unknownKeys: "strip" }),
45
+ enabled: av.object({
46
+ logs: av.optional(av.bool()).default(true),
47
+ metrics: av.optional(av.bool()).default(true),
48
+ traces: av.optional(av.bool()).default(true),
49
+ }, { unknownKeys: "strip" }),
50
+ export: av.object({
51
+ flushIntervalMs: av.optional(av.int32().min(100)).default(5000),
52
+ maxBatchSize: av.optional(av.int32().min(1)).default(1000),
53
+ }, { unknownKeys: "strip" }),
54
+ resourceAttributes: av.optional(av.record(av.string())).default({}),
55
+ }, { unknownKeys: "strip" });
56
+ export const Config = createConfigSchema({
93
57
  name: 'observable-axiom',
94
58
  description: 'Axiom.co observability integration for logs, metrics, and traces',
95
- version: '1.0.0',
96
59
  image: './axiom-co-logo.png',
97
60
  tags: ['axiom', 'observability', 'logs', 'metrics', 'traces', 'analytics'],
98
61
  }, ConfigSchema);
@@ -140,10 +103,10 @@ class BSBIdGenerator {
140
103
  * Exports traces via OTLP (Axiom supports OpenTelemetry)
141
104
  * Exports metrics as structured events
142
105
  */
143
- class Plugin extends base_1.BSBObservable {
106
+ export class Plugin extends BSBObservable {
144
107
  constructor(config) {
145
108
  super(config);
146
- this.logFormatter = new base_1.LogFormatter();
109
+ this.logFormatter = new LogFormatter();
147
110
  this.axiom = null;
148
111
  this.tracerProvider = null;
149
112
  this.tracer = null;
@@ -165,20 +128,20 @@ class Plugin extends base_1.BSBObservable {
165
128
  if (this.config.axiom.url) {
166
129
  axiomOptions.url = this.config.axiom.url;
167
130
  }
168
- this.axiom = new js_1.Axiom(axiomOptions);
131
+ this.axiom = new Axiom(axiomOptions);
169
132
  }
170
133
  // Initialize OpenTelemetry for traces (Axiom supports OTLP natively)
171
134
  if (this.config.enabled.traces) {
172
- const resource = (0, resources_1.defaultResource)().merge((0, resources_1.resourceFromAttributes)({
173
- [semantic_conventions_1.ATTR_SERVICE_NAME]: this.config.serviceName,
174
- ...(this.config.serviceVersion && { [semantic_conventions_1.ATTR_SERVICE_VERSION]: this.config.serviceVersion }),
135
+ const resource = defaultResource().merge(resourceFromAttributes({
136
+ [ATTR_SERVICE_NAME]: this.config.serviceName,
137
+ ...(this.config.serviceVersion && { [ATTR_SERVICE_VERSION]: this.config.serviceVersion }),
175
138
  ...this.config.resourceAttributes,
176
139
  }));
177
140
  // Axiom OTLP endpoint (from docs: https://axiom.co/docs/send-data/opentelemetry)
178
141
  const otlpUrl = this.config.axiom.url
179
142
  ? `${this.config.axiom.url}/v1/traces`
180
143
  : `https://api.axiom.co/v1/traces`;
181
- const traceExporter = new exporter_trace_otlp_http_1.OTLPTraceExporter({
144
+ const traceExporter = new OTLPTraceExporter({
182
145
  url: otlpUrl,
183
146
  headers: {
184
147
  "Authorization": `Bearer ${this.config.axiom.token}`,
@@ -189,11 +152,11 @@ class Plugin extends base_1.BSBObservable {
189
152
  this.idGenerator = new BSBIdGenerator();
190
153
  // Create tracer provider with custom ID generator and span processor
191
154
  // Use shorter batch delay for faster exports during debugging
192
- this.tracerProvider = new sdk_trace_node_1.NodeTracerProvider({
155
+ this.tracerProvider = new NodeTracerProvider({
193
156
  resource,
194
157
  idGenerator: this.idGenerator,
195
158
  spanProcessors: [
196
- new sdk_trace_base_1.BatchSpanProcessor(traceExporter, {
159
+ new BatchSpanProcessor(traceExporter, {
197
160
  scheduledDelayMillis: 1000, // Export every 1 second (default is 5000)
198
161
  maxQueueSize: 2048,
199
162
  maxExportBatchSize: 512,
@@ -280,7 +243,7 @@ class Plugin extends base_1.BSBObservable {
280
243
  this.queueLog("warn", trace, pluginName, message, meta);
281
244
  }
282
245
  error(trace, pluginName, message, meta) {
283
- if (message instanceof base_1.BSBError) {
246
+ if (message instanceof BSBError) {
284
247
  if (message.raw !== null) {
285
248
  this.queueLog("error", message.raw.trace, pluginName, message.raw.message, message.raw.meta);
286
249
  }
@@ -441,5 +404,4 @@ class Plugin extends base_1.BSBObservable {
441
404
  this.axiom = null;
442
405
  }
443
406
  }
444
- exports.Plugin = Plugin;
445
- Plugin.Config = exports.Config;
407
+ Plugin.Config = Config;
@@ -1,110 +1,129 @@
1
1
  {
2
2
  "pluginName": "observable-axiom",
3
- "version": "1.0.0",
4
3
  "events": {},
4
+ "version": "1.1.3",
5
5
  "configSchema": {
6
- "$schema": "https://json-schema.org/draft/2020-12/schema",
7
- "type": "object",
8
- "properties": {
9
- "serviceName": {
10
- "default": "bsb-service",
11
- "type": "string"
12
- },
13
- "serviceVersion": {
14
- "type": "string"
15
- },
16
- "axiom": {
17
- "type": "object",
18
- "properties": {
19
- "token": {
20
- "type": "string",
21
- "description": "Axiom API token"
22
- },
23
- "dataset": {
24
- "default": "bsb-logs",
25
- "description": "Axiom dataset name",
26
- "type": "string"
27
- },
28
- "orgId": {
29
- "description": "Axiom organization ID (for cloud)",
30
- "type": "string"
6
+ "anyvaliVersion": "1.0",
7
+ "schemaVersion": "1",
8
+ "root": {
9
+ "kind": "object",
10
+ "properties": {
11
+ "serviceName": {
12
+ "kind": "optional",
13
+ "inner": {
14
+ "kind": "string"
31
15
  },
32
- "url": {
33
- "description": "Custom Axiom URL (for self-hosted)",
34
- "type": "string",
35
- "format": "uri"
16
+ "default": "bsb-service"
17
+ },
18
+ "serviceVersion": {
19
+ "kind": "optional",
20
+ "inner": {
21
+ "kind": "string"
36
22
  }
37
23
  },
38
- "required": [
39
- "token",
40
- "dataset"
41
- ],
42
- "additionalProperties": false
43
- },
44
- "enabled": {
45
- "type": "object",
46
- "properties": {
47
- "logs": {
48
- "default": true,
49
- "type": "boolean"
50
- },
51
- "metrics": {
52
- "default": true,
53
- "type": "boolean"
24
+ "axiom": {
25
+ "kind": "object",
26
+ "properties": {
27
+ "token": {
28
+ "kind": "string"
29
+ },
30
+ "dataset": {
31
+ "kind": "optional",
32
+ "inner": {
33
+ "kind": "string"
34
+ },
35
+ "default": "bsb-logs"
36
+ },
37
+ "orgId": {
38
+ "kind": "optional",
39
+ "inner": {
40
+ "kind": "string"
41
+ }
42
+ },
43
+ "url": {
44
+ "kind": "optional",
45
+ "inner": {
46
+ "kind": "string",
47
+ "format": "url"
48
+ }
49
+ }
54
50
  },
55
- "traces": {
56
- "default": true,
57
- "type": "boolean"
58
- }
51
+ "required": [
52
+ "token"
53
+ ],
54
+ "unknownKeys": "strip"
59
55
  },
60
- "required": [
61
- "logs",
62
- "metrics",
63
- "traces"
64
- ],
65
- "additionalProperties": false
66
- },
67
- "export": {
68
- "type": "object",
69
- "properties": {
70
- "flushIntervalMs": {
71
- "default": 5000,
72
- "type": "integer",
73
- "minimum": 100,
74
- "maximum": 9007199254740991
56
+ "enabled": {
57
+ "kind": "object",
58
+ "properties": {
59
+ "logs": {
60
+ "kind": "optional",
61
+ "inner": {
62
+ "kind": "bool"
63
+ },
64
+ "default": true
65
+ },
66
+ "metrics": {
67
+ "kind": "optional",
68
+ "inner": {
69
+ "kind": "bool"
70
+ },
71
+ "default": true
72
+ },
73
+ "traces": {
74
+ "kind": "optional",
75
+ "inner": {
76
+ "kind": "bool"
77
+ },
78
+ "default": true
79
+ }
75
80
  },
76
- "maxBatchSize": {
77
- "default": 1000,
78
- "type": "integer",
79
- "minimum": 1,
80
- "maximum": 9007199254740991
81
- }
81
+ "required": [],
82
+ "unknownKeys": "strip"
82
83
  },
83
- "required": [
84
- "flushIntervalMs",
85
- "maxBatchSize"
86
- ],
87
- "additionalProperties": false
88
- },
89
- "resourceAttributes": {
90
- "default": {},
91
- "type": "object",
92
- "propertyNames": {
93
- "type": "string"
84
+ "export": {
85
+ "kind": "object",
86
+ "properties": {
87
+ "flushIntervalMs": {
88
+ "kind": "optional",
89
+ "inner": {
90
+ "kind": "int32",
91
+ "min": 100
92
+ },
93
+ "default": 5000
94
+ },
95
+ "maxBatchSize": {
96
+ "kind": "optional",
97
+ "inner": {
98
+ "kind": "int32",
99
+ "min": 1
100
+ },
101
+ "default": 1000
102
+ }
103
+ },
104
+ "required": [],
105
+ "unknownKeys": "strip"
94
106
  },
95
- "additionalProperties": {
96
- "type": "string"
107
+ "resourceAttributes": {
108
+ "kind": "optional",
109
+ "inner": {
110
+ "kind": "record",
111
+ "valueSchema": {
112
+ "kind": "string"
113
+ }
114
+ },
115
+ "default": {}
97
116
  }
98
- }
117
+ },
118
+ "required": [
119
+ "axiom",
120
+ "enabled",
121
+ "export"
122
+ ],
123
+ "unknownKeys": "strip"
99
124
  },
100
- "required": [
101
- "serviceName",
102
- "axiom",
103
- "enabled",
104
- "export",
105
- "resourceAttributes"
106
- ],
107
- "additionalProperties": false
125
+ "definitions": {},
126
+ "extensions": {}
108
127
  },
109
128
  "pluginType": "observable",
110
129
  "capabilities": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "observable-axiom",
3
3
  "name": "observable-axiom",
4
- "version": "1.0.0",
4
+ "version": "1.1.3",
5
5
  "description": "Axiom.co observability integration for logs, metrics, and traces",
6
6
  "category": "observable",
7
7
  "tags": [
@@ -14,109 +14,134 @@
14
14
  ],
15
15
  "documentation": [],
16
16
  "dependencies": [],
17
+ "author": {
18
+ "name": "BetterCorp (PTY) Ltd",
19
+ "email": "ninja@bettercorp.dev",
20
+ "url": "https://bettercorp.dev/"
21
+ },
22
+ "license": "(AGPL-3.0-only OR Commercial)",
17
23
  "image": "./axiom-co-logo.png",
18
24
  "configSchema": {
19
- "$schema": "https://json-schema.org/draft/2020-12/schema",
20
- "type": "object",
21
- "properties": {
22
- "serviceName": {
23
- "default": "bsb-service",
24
- "type": "string"
25
- },
26
- "serviceVersion": {
27
- "type": "string"
28
- },
29
- "axiom": {
30
- "type": "object",
31
- "properties": {
32
- "token": {
33
- "type": "string",
34
- "description": "Axiom API token"
35
- },
36
- "dataset": {
37
- "default": "bsb-logs",
38
- "description": "Axiom dataset name",
39
- "type": "string"
40
- },
41
- "orgId": {
42
- "description": "Axiom organization ID (for cloud)",
43
- "type": "string"
25
+ "anyvaliVersion": "1.0",
26
+ "schemaVersion": "1",
27
+ "root": {
28
+ "kind": "object",
29
+ "properties": {
30
+ "serviceName": {
31
+ "kind": "optional",
32
+ "inner": {
33
+ "kind": "string"
44
34
  },
45
- "url": {
46
- "description": "Custom Axiom URL (for self-hosted)",
47
- "type": "string",
48
- "format": "uri"
35
+ "default": "bsb-service"
36
+ },
37
+ "serviceVersion": {
38
+ "kind": "optional",
39
+ "inner": {
40
+ "kind": "string"
49
41
  }
50
42
  },
51
- "required": [
52
- "token",
53
- "dataset"
54
- ],
55
- "additionalProperties": false
56
- },
57
- "enabled": {
58
- "type": "object",
59
- "properties": {
60
- "logs": {
61
- "default": true,
62
- "type": "boolean"
63
- },
64
- "metrics": {
65
- "default": true,
66
- "type": "boolean"
43
+ "axiom": {
44
+ "kind": "object",
45
+ "properties": {
46
+ "token": {
47
+ "kind": "string"
48
+ },
49
+ "dataset": {
50
+ "kind": "optional",
51
+ "inner": {
52
+ "kind": "string"
53
+ },
54
+ "default": "bsb-logs"
55
+ },
56
+ "orgId": {
57
+ "kind": "optional",
58
+ "inner": {
59
+ "kind": "string"
60
+ }
61
+ },
62
+ "url": {
63
+ "kind": "optional",
64
+ "inner": {
65
+ "kind": "string",
66
+ "format": "url"
67
+ }
68
+ }
67
69
  },
68
- "traces": {
69
- "default": true,
70
- "type": "boolean"
71
- }
70
+ "required": [
71
+ "token"
72
+ ],
73
+ "unknownKeys": "strip"
72
74
  },
73
- "required": [
74
- "logs",
75
- "metrics",
76
- "traces"
77
- ],
78
- "additionalProperties": false
79
- },
80
- "export": {
81
- "type": "object",
82
- "properties": {
83
- "flushIntervalMs": {
84
- "default": 5000,
85
- "type": "integer",
86
- "minimum": 100,
87
- "maximum": 9007199254740991
75
+ "enabled": {
76
+ "kind": "object",
77
+ "properties": {
78
+ "logs": {
79
+ "kind": "optional",
80
+ "inner": {
81
+ "kind": "bool"
82
+ },
83
+ "default": true
84
+ },
85
+ "metrics": {
86
+ "kind": "optional",
87
+ "inner": {
88
+ "kind": "bool"
89
+ },
90
+ "default": true
91
+ },
92
+ "traces": {
93
+ "kind": "optional",
94
+ "inner": {
95
+ "kind": "bool"
96
+ },
97
+ "default": true
98
+ }
88
99
  },
89
- "maxBatchSize": {
90
- "default": 1000,
91
- "type": "integer",
92
- "minimum": 1,
93
- "maximum": 9007199254740991
94
- }
100
+ "required": [],
101
+ "unknownKeys": "strip"
95
102
  },
96
- "required": [
97
- "flushIntervalMs",
98
- "maxBatchSize"
99
- ],
100
- "additionalProperties": false
101
- },
102
- "resourceAttributes": {
103
- "default": {},
104
- "type": "object",
105
- "propertyNames": {
106
- "type": "string"
103
+ "export": {
104
+ "kind": "object",
105
+ "properties": {
106
+ "flushIntervalMs": {
107
+ "kind": "optional",
108
+ "inner": {
109
+ "kind": "int32",
110
+ "min": 100
111
+ },
112
+ "default": 5000
113
+ },
114
+ "maxBatchSize": {
115
+ "kind": "optional",
116
+ "inner": {
117
+ "kind": "int32",
118
+ "min": 1
119
+ },
120
+ "default": 1000
121
+ }
122
+ },
123
+ "required": [],
124
+ "unknownKeys": "strip"
107
125
  },
108
- "additionalProperties": {
109
- "type": "string"
126
+ "resourceAttributes": {
127
+ "kind": "optional",
128
+ "inner": {
129
+ "kind": "record",
130
+ "valueSchema": {
131
+ "kind": "string"
132
+ }
133
+ },
134
+ "default": {}
110
135
  }
111
- }
136
+ },
137
+ "required": [
138
+ "axiom",
139
+ "enabled",
140
+ "export"
141
+ ],
142
+ "unknownKeys": "strip"
112
143
  },
113
- "required": [
114
- "serviceName",
115
- "axiom",
116
- "enabled",
117
- "export",
118
- "resourceAttributes"
119
- ],
120
- "additionalProperties": false
144
+ "definitions": {},
145
+ "extensions": {}
121
146
  }
122
147
  }
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@bsb/observable-axiom",
3
- "version": "1.0.1",
3
+ "version": "1.1.3",
4
4
  "description": "Axiom.co observability integration for BSB framework",
5
+ "type": "module",
5
6
  "main": "lib/plugins/observable-axiom/index.js",
6
7
  "types": "lib/plugins/observable-axiom/index.d.ts",
7
8
  "scripts": {
@@ -30,9 +31,10 @@
30
31
  "url": "https://bettercorp.dev/"
31
32
  },
32
33
  "peerDependencies": {
33
- "@bsb/base": "^9.0.0"
34
+ "@bsb/base": "^9.1.6"
34
35
  },
35
36
  "dependencies": {
37
+ "@anyvali/js": "^0.2.0",
36
38
  "@axiomhq/js": "^1.4.0",
37
39
  "@opentelemetry/api": "^1.9.0",
38
40
  "@opentelemetry/exporter-trace-otlp-http": "^0.211.0",
@@ -40,18 +42,13 @@
40
42
  "@opentelemetry/sdk-node": "^0.211.0",
41
43
  "@opentelemetry/sdk-trace-base": "^2.5.0",
42
44
  "@opentelemetry/sdk-trace-node": "^2.5.0",
43
- "@opentelemetry/semantic-conventions": "^1.39.0",
44
- "zod": "^4.3.6"
45
+ "@opentelemetry/semantic-conventions": "^1.39.0"
45
46
  },
46
47
  "devDependencies": {
47
- "@bsb/base": "file:../../../nodejs",
48
- "@types/node": "^25.2.1",
48
+ "@bsb/base": "^9.1.6",
49
+ "@types/node": "^25.6.0",
49
50
  "rimraf": "^6.1.2",
50
51
  "typescript": "^5.9.3"
51
52
  },
52
53
  "homepage": "https://io.bsbcode.dev/packages/nodejs/@bsb/observable-axiom"
53
54
  }
54
-
55
-
56
-
57
-
@@ -33,7 +33,7 @@ import {
33
33
  BSBError
34
34
  } from "@bsb/base";
35
35
  import { DTrace, LogMeta } from "@bsb/base";
36
- import { z } from "zod";
36
+ import * as av from "@anyvali/js";
37
37
  import { Axiom } from "@axiomhq/js";
38
38
  import * as api from "@opentelemetry/api";
39
39
  import { defaultResource, resourceFromAttributes } from "@opentelemetry/resources";
@@ -43,36 +43,31 @@ import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
43
43
  import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
44
44
  import type { IdGenerator } from "@opentelemetry/sdk-trace-base";
45
45
 
46
- const ConfigSchema = z.object({
47
- serviceName: z.string().default("bsb-service"),
48
- serviceVersion: z.string().optional(),
49
-
50
- axiom: z.object({
51
- token: z.string().describe("Axiom API token"),
52
- dataset: z.string().default("bsb-logs").describe("Axiom dataset name"),
53
- orgId: z.string().optional().describe("Axiom organization ID (for cloud)"),
54
- url: z.url().optional().describe("Custom Axiom URL (for self-hosted)"),
55
- }),
56
-
57
- enabled: z.object({
58
- logs: z.boolean().default(true),
59
- metrics: z.boolean().default(true),
60
- traces: z.boolean().default(true),
61
- }),
62
-
63
- export: z.object({
64
- flushIntervalMs: z.number().int().min(100).default(5000),
65
- maxBatchSize: z.number().int().min(1).default(1000),
66
- }),
67
-
68
- resourceAttributes: z.record(z.string(), z.string()).default({}),
69
- });
46
+ const ConfigSchema = av.object({
47
+ serviceName: av.optional(av.string()).default("bsb-service"),
48
+ serviceVersion: av.optional(av.string()),
49
+ axiom: av.object({
50
+ token: av.string(),
51
+ dataset: av.optional(av.string()).default("bsb-logs"),
52
+ orgId: av.optional(av.string()),
53
+ url: av.optional(av.string().format("url")),
54
+ }, { unknownKeys: "strip" }),
55
+ enabled: av.object({
56
+ logs: av.optional(av.bool()).default(true),
57
+ metrics: av.optional(av.bool()).default(true),
58
+ traces: av.optional(av.bool()).default(true),
59
+ }, { unknownKeys: "strip" }),
60
+ export: av.object({
61
+ flushIntervalMs: av.optional(av.int32().min(100)).default(5000),
62
+ maxBatchSize: av.optional(av.int32().min(1)).default(1000),
63
+ }, { unknownKeys: "strip" }),
64
+ resourceAttributes: av.optional(av.record(av.string())).default({}),
65
+ }, { unknownKeys: "strip" });
70
66
 
71
67
  export const Config = createConfigSchema(
72
68
  {
73
69
  name: 'observable-axiom',
74
70
  description: 'Axiom.co observability integration for logs, metrics, and traces',
75
- version: '1.0.0',
76
71
  image: './axiom-co-logo.png',
77
72
  tags: ['axiom', 'observability', 'logs', 'metrics', 'traces', 'analytics'],
78
73
  },
package/tsconfig.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "target": "ES2020",
4
- "module": "commonjs",
4
+ "module": "NodeNext",
5
5
  "lib": ["ES2020"],
6
6
  "declaration": true,
7
7
  "outDir": "./lib",
@@ -10,7 +10,7 @@
10
10
  "esModuleInterop": true,
11
11
  "skipLibCheck": true,
12
12
  "forceConsistentCasingInFileNames": true,
13
- "moduleResolution": "node",
13
+ "moduleResolution": "NodeNext",
14
14
  "resolveJsonModule": true,
15
15
  "types": ["node"]
16
16
  },