@youssoufcherif/signals-node 0.0.1

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 Youssouf Cherif Hamed
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,27 @@
1
+ # @youssoufcherif/signals-node
2
+
3
+ > ⚠️ **Pre-alpha (`0.0.x`)** — built in the open, APIs change without notice.
4
+ > Not yet supported for use outside the author's projects. See the
5
+ > [repo README](https://github.com/yhcherif/signals#readme).
6
+
7
+ Lightweight console provider for
8
+ [Signals](https://github.com/yhcherif/signals): spans, logs, and metrics as
9
+ structured JSON lines on stdout. No OpenTelemetry dependency — ideal for local
10
+ development or simple services that ship logs from stdout.
11
+
12
+ ```bash
13
+ pnpm add @youssoufcherif/signals-node
14
+ ```
15
+
16
+ ```ts
17
+ import { createNodeSignals } from '@youssoufcherif/signals-node';
18
+
19
+ const signals = createNodeSignals({ pretty: true }); // options optional
20
+
21
+ await signals.trace.run('checkout.process', async (ctx) => {
22
+ ctx.log.info('processing checkout'); // JSON line, correlated to the span
23
+ });
24
+ await signals.shutdown();
25
+ ```
26
+
27
+ MIT © Youssouf Cherif Hamed
@@ -0,0 +1,3 @@
1
+ export { createNodeSignals, makeNodePort } from './make-node-port.js';
2
+ export type { NodePortOptions } from './make-node-port.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACtE,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { createNodeSignals, makeNodePort } from './make-node-port.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { AttrRecord } from '@youssoufcherif/signals-core';
2
+ /**
3
+ * `instanceof Error` here is normal JS error normalization, not a vendor
4
+ * telemetry type crossing a port boundary — the ADR-0001 restriction is
5
+ * about vendor SDK objects (Span, Resource, ...) never requiring a
6
+ * business-code `instanceof` check to use. Kept in `internal/` anyway to
7
+ * stay on the conservative side of that line.
8
+ */
9
+ export declare function errorToAttrs(err: unknown): AttrRecord;
10
+ //# sourceMappingURL=error-to-attrs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-to-attrs.d.ts","sourceRoot":"","sources":["../../src/internal/error-to-attrs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE/D;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,UAAU,CAKrD"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * `instanceof Error` here is normal JS error normalization, not a vendor
3
+ * telemetry type crossing a port boundary — the ADR-0001 restriction is
4
+ * about vendor SDK objects (Span, Resource, ...) never requiring a
5
+ * business-code `instanceof` check to use. Kept in `internal/` anyway to
6
+ * stay on the conservative side of that line.
7
+ */
8
+ export function errorToAttrs(err) {
9
+ if (err instanceof Error) {
10
+ return { errorName: err.name, errorMessage: err.message, errorStack: err.stack ?? '' };
11
+ }
12
+ return { errorMessage: String(err) };
13
+ }
14
+ //# sourceMappingURL=error-to-attrs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-to-attrs.js","sourceRoot":"","sources":["../../src/internal/error-to-attrs.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,GAAY;IACvC,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;QACzB,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,IAAI,EAAE,YAAY,EAAE,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;IACzF,CAAC;IACD,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;AACvC,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { Signals, SignalsPort } from '@youssoufcherif/signals-core';
2
+ export type NodePortOptions = {
3
+ /** Pretty-print JSON output. Defaults to false (one line per event). */
4
+ pretty?: boolean;
5
+ /** Injectable for testing; defaults to the real console. */
6
+ write?: (line: string) => void;
7
+ };
8
+ /**
9
+ * The node strategy: a real, working provider backed by `console` and
10
+ * `performance.now()` — nothing from `@opentelemetry/*`. Useful for CLIs,
11
+ * scripts, and any context where pulling in the OTel SDK isn't worth the
12
+ * dependency weight or cold-start cost, but structured output is still
13
+ * wanted over silence.
14
+ */
15
+ export declare function makeNodePort(options?: NodePortOptions): SignalsPort;
16
+ export declare function createNodeSignals(options?: NodePortOptions): Signals;
17
+ //# sourceMappingURL=make-node-port.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"make-node-port.d.ts","sourceRoot":"","sources":["../src/make-node-port.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAc,OAAO,EAAE,WAAW,EAAc,MAAM,8BAA8B,CAAC;AAGjG,MAAM,MAAM,eAAe,GAAG;IAC5B,wEAAwE;IACxE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC,CAAC;AAMF;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,eAAoB,GAAG,WAAW,CAsEvE;AAED,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAEpE"}
@@ -0,0 +1,61 @@
1
+ import { createSignals } from '@youssoufcherif/signals-core';
2
+ import { errorToAttrs } from './internal/error-to-attrs.js';
3
+ function serialize(payload, pretty) {
4
+ return pretty ? JSON.stringify(payload, null, 2) : JSON.stringify(payload);
5
+ }
6
+ /**
7
+ * The node strategy: a real, working provider backed by `console` and
8
+ * `performance.now()` — nothing from `@opentelemetry/*`. Useful for CLIs,
9
+ * scripts, and any context where pulling in the OTel SDK isn't worth the
10
+ * dependency weight or cold-start cost, but structured output is still
11
+ * wanted over silence.
12
+ */
13
+ export function makeNodePort(options = {}) {
14
+ const write = options.write ?? ((line) => console.log(line));
15
+ let spanCounter = 0;
16
+ const startSpan = (name, parent, attrs) => {
17
+ const id = `span-${++spanCounter}`;
18
+ const parentSpanId = parent?.getCorrelation()['spanId'];
19
+ const startedAt = performance.now();
20
+ const attributes = { ...attrs };
21
+ write(serialize({ evt: 'span.start', span: name, id, parentId: parentSpanId, attributes }, options.pretty));
22
+ const handle = {
23
+ setAttribute: (key, value) => {
24
+ attributes[key] = value;
25
+ },
26
+ addEvent: (eventName, eventAttrs) => {
27
+ write(serialize({ evt: 'span.event', span: name, id, name: eventName, attrs: eventAttrs }, options.pretty));
28
+ },
29
+ recordException: (err) => {
30
+ write(serialize({ evt: 'span.exception', span: name, id, error: errorToAttrs(err) }, options.pretty));
31
+ },
32
+ end: () => {
33
+ write(serialize({
34
+ evt: 'span.end',
35
+ span: name,
36
+ id,
37
+ durationMs: performance.now() - startedAt,
38
+ attributes,
39
+ }, options.pretty));
40
+ },
41
+ getCorrelation: () => ({ traceId: 'node-trace', spanId: id }),
42
+ };
43
+ return handle;
44
+ };
45
+ const log = (level, message, attrs) => {
46
+ write(serialize({ evt: 'log', level, message, ...attrs }, options.pretty));
47
+ };
48
+ const recordMetric = (kind, name, value, attrs) => {
49
+ write(serialize({ evt: 'metric', kind, name, value, ...attrs }, options.pretty));
50
+ };
51
+ return {
52
+ startSpan,
53
+ log,
54
+ recordMetric,
55
+ flush: async () => { },
56
+ };
57
+ }
58
+ export function createNodeSignals(options) {
59
+ return createSignals(makeNodePort(options));
60
+ }
61
+ //# sourceMappingURL=make-node-port.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"make-node-port.js","sourceRoot":"","sources":["../src/make-node-port.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAS5D,SAAS,SAAS,CAAC,OAAgC,EAAE,MAA2B;IAC9E,OAAO,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;AAC7E,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,UAA2B,EAAE;IACxD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IACrE,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,MAAM,SAAS,GAA6B,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;QAClE,MAAM,EAAE,GAAG,QAAQ,EAAE,WAAW,EAAE,CAAC;QACnC,MAAM,YAAY,GAAG,MAAM,EAAE,cAAc,EAAE,CAAC,QAAQ,CAAC,CAAC;QACxD,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QACpC,MAAM,UAAU,GAAe,EAAE,GAAG,KAAK,EAAE,CAAC;QAE5C,KAAK,CACH,SAAS,CACP,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,EACzE,OAAO,CAAC,MAAM,CACf,CACF,CAAC;QAEF,MAAM,MAAM,GAAe;YACzB,YAAY,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;gBAC3B,UAAU,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YAC1B,CAAC;YACD,QAAQ,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,EAAE;gBAClC,KAAK,CACH,SAAS,CACP,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,EACzE,OAAO,CAAC,MAAM,CACf,CACF,CAAC;YACJ,CAAC;YACD,eAAe,EAAE,CAAC,GAAG,EAAE,EAAE;gBACvB,KAAK,CACH,SAAS,CACP,EAAE,GAAG,EAAE,gBAAgB,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,YAAY,CAAC,GAAG,CAAC,EAAE,EACnE,OAAO,CAAC,MAAM,CACf,CACF,CAAC;YACJ,CAAC;YACD,GAAG,EAAE,GAAG,EAAE;gBACR,KAAK,CACH,SAAS,CACP;oBACE,GAAG,EAAE,UAAU;oBACf,IAAI,EAAE,IAAI;oBACV,EAAE;oBACF,UAAU,EAAE,WAAW,CAAC,GAAG,EAAE,GAAG,SAAS;oBACzC,UAAU;iBACX,EACD,OAAO,CAAC,MAAM,CACf,CACF,CAAC;YACJ,CAAC;YACD,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;SAC9D,CAAC;QACF,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IAEF,MAAM,GAAG,GAAuB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACxD,KAAK,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7E,CAAC,CAAC;IAEF,MAAM,YAAY,GAAgC,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QAC7E,KAAK,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IACnF,CAAC,CAAC;IAEF,OAAO;QACL,SAAS;QACT,GAAG;QACH,YAAY;QACZ,KAAK,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;KACtB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAyB;IACzD,OAAO,aAAa,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;AAC9C,CAAC"}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@youssoufcherif/signals-node",
3
+ "version": "0.0.1",
4
+ "description": "Lightweight console-based Signals provider - no OpenTelemetry dependency.",
5
+ "license": "MIT",
6
+ "author": "Youssouf Cherif Hamed <youssouf.cherif.hamed@gmail.com>",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/yhcherif/signals.git",
10
+ "directory": "packages/node"
11
+ },
12
+ "homepage": "https://github.com/yhcherif/signals/tree/main/packages/node#readme",
13
+ "bugs": "https://github.com/yhcherif/signals/issues",
14
+ "keywords": [
15
+ "telemetry",
16
+ "observability",
17
+ "signals",
18
+ "console",
19
+ "structured-logging"
20
+ ],
21
+ "type": "module",
22
+ "sideEffects": false,
23
+ "engines": {
24
+ "node": ">=20"
25
+ },
26
+ "main": "./dist/index.js",
27
+ "types": "./dist/index.d.ts",
28
+ "exports": {
29
+ ".": {
30
+ "types": "./dist/index.d.ts",
31
+ "import": "./dist/index.js"
32
+ }
33
+ },
34
+ "files": [
35
+ "dist",
36
+ "LICENSE"
37
+ ],
38
+ "publishConfig": {
39
+ "access": "public",
40
+ "provenance": true
41
+ },
42
+ "dependencies": {
43
+ "@youssoufcherif/signals-core": "0.0.1"
44
+ },
45
+ "devDependencies": {
46
+ "typescript": "^5.6.0",
47
+ "vitest": "^2.1.0",
48
+ "@types/node": "^22.0.0"
49
+ },
50
+ "scripts": {
51
+ "build": "tsc -p tsconfig.json",
52
+ "test": "vitest run"
53
+ }
54
+ }