@logscopeai/logscope 0.1.0-beta.2

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.
Files changed (72) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +341 -0
  3. package/dist/client/create-logscope-client.d.ts +23 -0
  4. package/dist/client/create-logscope-client.js +112 -0
  5. package/dist/client/create-logscope-client.js.map +1 -0
  6. package/dist/client/log-methods.d.ts +3 -0
  7. package/dist/client/log-methods.js +27 -0
  8. package/dist/client/log-methods.js.map +1 -0
  9. package/dist/config/config-guards.d.ts +31 -0
  10. package/dist/config/config-guards.js +128 -0
  11. package/dist/config/config-guards.js.map +1 -0
  12. package/dist/config/runtime-config.d.ts +17 -0
  13. package/dist/config/runtime-config.js +41 -0
  14. package/dist/config/runtime-config.js.map +1 -0
  15. package/dist/console/capture-console.d.ts +16 -0
  16. package/dist/console/capture-console.js +117 -0
  17. package/dist/console/capture-console.js.map +1 -0
  18. package/dist/constants.d.ts +7 -0
  19. package/dist/constants.js +17 -0
  20. package/dist/constants.js.map +1 -0
  21. package/dist/filter/level-filter.d.ts +3 -0
  22. package/dist/filter/level-filter.js +16 -0
  23. package/dist/filter/level-filter.js.map +1 -0
  24. package/dist/index.d.ts +5 -0
  25. package/dist/index.js +26 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/logscope.d.ts +11 -0
  28. package/dist/logscope.js +61 -0
  29. package/dist/logscope.js.map +1 -0
  30. package/dist/normalization/normalize-log.d.ts +12 -0
  31. package/dist/normalization/normalize-log.js +140 -0
  32. package/dist/normalization/normalize-log.js.map +1 -0
  33. package/dist/pino/map-pino-level.d.ts +2 -0
  34. package/dist/pino/map-pino-level.js +40 -0
  35. package/dist/pino/map-pino-level.js.map +1 -0
  36. package/dist/pino/transport.d.ts +20 -0
  37. package/dist/pino/transport.js +185 -0
  38. package/dist/pino/transport.js.map +1 -0
  39. package/dist/pino.d.ts +4 -0
  40. package/dist/pino.js +11 -0
  41. package/dist/pino.js.map +1 -0
  42. package/dist/pipeline/batch-queue.d.ts +9 -0
  43. package/dist/pipeline/batch-queue.js +29 -0
  44. package/dist/pipeline/batch-queue.js.map +1 -0
  45. package/dist/pipeline/delivery-runner.d.ts +12 -0
  46. package/dist/pipeline/delivery-runner.js +63 -0
  47. package/dist/pipeline/delivery-runner.js.map +1 -0
  48. package/dist/pipeline/flush-scheduler.d.ts +14 -0
  49. package/dist/pipeline/flush-scheduler.js +39 -0
  50. package/dist/pipeline/flush-scheduler.js.map +1 -0
  51. package/dist/pipeline/pipeline-ingress.d.ts +19 -0
  52. package/dist/pipeline/pipeline-ingress.js +37 -0
  53. package/dist/pipeline/pipeline-ingress.js.map +1 -0
  54. package/dist/pipeline/pipeline.d.ts +21 -0
  55. package/dist/pipeline/pipeline.js +109 -0
  56. package/dist/pipeline/pipeline.js.map +1 -0
  57. package/dist/retry/backoff.d.ts +2 -0
  58. package/dist/retry/backoff.js +16 -0
  59. package/dist/retry/backoff.js.map +1 -0
  60. package/dist/retry/retry-policy.d.ts +7 -0
  61. package/dist/retry/retry-policy.js +26 -0
  62. package/dist/retry/retry-policy.js.map +1 -0
  63. package/dist/transport/send-ingestion-request.d.ts +4 -0
  64. package/dist/transport/send-ingestion-request.js +75 -0
  65. package/dist/transport/send-ingestion-request.js.map +1 -0
  66. package/dist/transport/transport-types.d.ts +39 -0
  67. package/dist/transport/transport-types.js +3 -0
  68. package/dist/transport/transport-types.js.map +1 -0
  69. package/dist/types.d.ts +69 -0
  70. package/dist/types.js +3 -0
  71. package/dist/types.js.map +1 -0
  72. package/package.json +62 -0
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createPipelineIngress = void 0;
4
+ const level_filter_1 = require("../filter/level-filter");
5
+ const normalize_log_1 = require("../normalization/normalize-log");
6
+ const runSafe = (callback) => {
7
+ try {
8
+ callback();
9
+ }
10
+ catch {
11
+ // Never throw into user code.
12
+ }
13
+ };
14
+ const createPipelineIngress = (input) => {
15
+ const allowsLevel = (0, level_filter_1.createLevelFilterEvaluator)(input.logFilter);
16
+ return {
17
+ dispatch(log) {
18
+ if (!allowsLevel(log.level)) {
19
+ return;
20
+ }
21
+ runSafe(() => {
22
+ const normalizedLog = (0, normalize_log_1.normalizeLog)({
23
+ source: input.source,
24
+ level: log.level,
25
+ message: log.message,
26
+ metadata: log.metadata,
27
+ timestamp: log.timestamp,
28
+ }, {
29
+ now: input.now,
30
+ });
31
+ input.pipeline.enqueue(normalizedLog);
32
+ });
33
+ },
34
+ };
35
+ };
36
+ exports.createPipelineIngress = createPipelineIngress;
37
+ //# sourceMappingURL=pipeline-ingress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-ingress.js","sourceRoot":"","sources":["../../src/pipeline/pipeline-ingress.ts"],"names":[],"mappings":";;;AAAA,yDAAoE;AACpE,kEAA8D;AAuB9D,MAAM,OAAO,GAAG,CAAC,QAAoB,EAAQ,EAAE;IAC7C,IAAI,CAAC;QACH,QAAQ,EAAE,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACP,8BAA8B;IAChC,CAAC;AACH,CAAC,CAAC;AAEK,MAAM,qBAAqB,GAAG,CAAC,KAAiC,EAAmB,EAAE;IAC1F,MAAM,WAAW,GAAG,IAAA,yCAA0B,EAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAEhE,OAAO;QACL,QAAQ,CAAC,GAA4B;YACnC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC5B,OAAO;YACT,CAAC;YAED,OAAO,CAAC,GAAG,EAAE;gBACX,MAAM,aAAa,GAAG,IAAA,4BAAY,EAChC;oBACE,MAAM,EAAE,KAAK,CAAC,MAAM;oBACpB,KAAK,EAAE,GAAG,CAAC,KAAK;oBAChB,OAAO,EAAE,GAAG,CAAC,OAAO;oBACpB,QAAQ,EAAE,GAAG,CAAC,QAAQ;oBACtB,SAAS,EAAE,GAAG,CAAC,SAAS;iBACzB,EACD;oBACE,GAAG,EAAE,KAAK,CAAC,GAAG;iBACf,CACF,CAAC;gBAEF,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;YACxC,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC,CAAC;AA3BW,QAAA,qBAAqB,yBA2BhC"}
@@ -0,0 +1,21 @@
1
+ import { DEFAULT_FLUSH_INTERVAL_MS } from '../config/runtime-config';
2
+ import type { RetryPolicy } from '../retry/retry-policy';
3
+ import type { IngestionRequestResult, SendIngestionRequestInput } from '../transport/transport-types';
4
+ import type { IngestionLogEntry } from '../types';
5
+ export declare const MAX_BATCH_SIZE = 50;
6
+ export { DEFAULT_FLUSH_INTERVAL_MS };
7
+ export interface BatchingPipeline {
8
+ enqueue(log: IngestionLogEntry): void;
9
+ flushNow(): Promise<void>;
10
+ stop(): Promise<void>;
11
+ }
12
+ export interface CreateBatchingPipelineInput {
13
+ endpoint: string;
14
+ apiKey: string;
15
+ sendBatch: (input: SendIngestionRequestInput) => Promise<IngestionRequestResult>;
16
+ onBatchResult?: (result: IngestionRequestResult) => void;
17
+ maxBatchSize?: number;
18
+ flushIntervalMs?: number;
19
+ retryPolicy?: Partial<RetryPolicy>;
20
+ }
21
+ export declare const createBatchingPipeline: (input: CreateBatchingPipelineInput) => BatchingPipeline;
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createBatchingPipeline = exports.DEFAULT_FLUSH_INTERVAL_MS = exports.MAX_BATCH_SIZE = void 0;
4
+ const runtime_config_1 = require("../config/runtime-config");
5
+ Object.defineProperty(exports, "DEFAULT_FLUSH_INTERVAL_MS", { enumerable: true, get: function () { return runtime_config_1.DEFAULT_FLUSH_INTERVAL_MS; } });
6
+ const batch_queue_1 = require("./batch-queue");
7
+ const delivery_runner_1 = require("./delivery-runner");
8
+ const flush_scheduler_1 = require("./flush-scheduler");
9
+ exports.MAX_BATCH_SIZE = runtime_config_1.DEFAULT_MAX_BATCH_SIZE;
10
+ const runSafe = (callback) => {
11
+ try {
12
+ callback();
13
+ }
14
+ catch {
15
+ // Internal callbacks must not surface to user code.
16
+ }
17
+ };
18
+ const createBatchingPipeline = (input) => {
19
+ const runtimeConfig = (0, runtime_config_1.resolveRuntimeConfig)({
20
+ maxBatchSize: input.maxBatchSize,
21
+ flushIntervalMs: input.flushIntervalMs,
22
+ maxRetries: input.retryPolicy?.maxRetries,
23
+ retryBaseDelayMs: input.retryPolicy?.baseDelayMs,
24
+ retryMaxDelayMs: input.retryPolicy?.maxDelayMs,
25
+ });
26
+ const queue = (0, batch_queue_1.createBatchQueue)();
27
+ let activeFlushPromise = null;
28
+ let isStopped = false;
29
+ const emitBatchResult = (result) => {
30
+ if (input.onBatchResult === undefined) {
31
+ return;
32
+ }
33
+ runSafe(() => input.onBatchResult?.(result));
34
+ };
35
+ const scheduler = (0, flush_scheduler_1.createFlushScheduler)({
36
+ intervalMs: runtimeConfig.flushIntervalMs,
37
+ onFlush: () => {
38
+ if (isStopped || queue.isEmpty()) {
39
+ return;
40
+ }
41
+ void flushInternal();
42
+ },
43
+ });
44
+ const flushInternal = () => {
45
+ if (activeFlushPromise !== null) {
46
+ return activeFlushPromise;
47
+ }
48
+ activeFlushPromise = (async () => {
49
+ scheduler.cancel();
50
+ while (!queue.isEmpty()) {
51
+ const batch = queue.dequeueBatch(runtimeConfig.maxBatchSize);
52
+ if (batch.length === 0) {
53
+ break;
54
+ }
55
+ try {
56
+ const result = await (0, delivery_runner_1.runBatchDelivery)({
57
+ endpoint: input.endpoint,
58
+ apiKey: input.apiKey,
59
+ sendBatch: input.sendBatch,
60
+ logs: batch,
61
+ retryPolicy: runtimeConfig.retryPolicy,
62
+ });
63
+ emitBatchResult(result);
64
+ }
65
+ catch {
66
+ // Never throw into user code.
67
+ }
68
+ }
69
+ })().finally(() => {
70
+ activeFlushPromise = null;
71
+ if (isStopped || queue.isEmpty()) {
72
+ scheduler.cancel();
73
+ return;
74
+ }
75
+ scheduler.schedule();
76
+ });
77
+ return activeFlushPromise;
78
+ };
79
+ return {
80
+ enqueue(log) {
81
+ if (isStopped) {
82
+ return;
83
+ }
84
+ queue.enqueue(log);
85
+ if (queue.size() >= runtimeConfig.maxBatchSize) {
86
+ void flushInternal();
87
+ return;
88
+ }
89
+ scheduler.schedule();
90
+ },
91
+ async flushNow() {
92
+ if (isStopped || queue.isEmpty()) {
93
+ return;
94
+ }
95
+ await flushInternal();
96
+ },
97
+ async stop() {
98
+ if (isStopped) {
99
+ return;
100
+ }
101
+ isStopped = true;
102
+ scheduler.cancel();
103
+ await flushInternal();
104
+ queue.clear();
105
+ },
106
+ };
107
+ };
108
+ exports.createBatchingPipeline = createBatchingPipeline;
109
+ //# sourceMappingURL=pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../src/pipeline/pipeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { RetryPolicy } from './retry-policy';
2
+ export declare const calculateRetryDelayMs: (attempt: number, policy: RetryPolicy) => number;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.calculateRetryDelayMs = void 0;
4
+ const calculateRetryDelayMs = (attempt, policy) => {
5
+ if (attempt <= 0 || policy.baseDelayMs === 0 || policy.maxDelayMs === 0) {
6
+ return 0;
7
+ }
8
+ const growthFactor = 2 ** (attempt - 1);
9
+ const rawDelay = policy.baseDelayMs * growthFactor;
10
+ if (!Number.isFinite(rawDelay)) {
11
+ return policy.maxDelayMs;
12
+ }
13
+ return Math.min(policy.maxDelayMs, Math.trunc(rawDelay));
14
+ };
15
+ exports.calculateRetryDelayMs = calculateRetryDelayMs;
16
+ //# sourceMappingURL=backoff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backoff.js","sourceRoot":"","sources":["../../src/retry/backoff.ts"],"names":[],"mappings":";;;AAEO,MAAM,qBAAqB,GAAG,CAAC,OAAe,EAAE,MAAmB,EAAU,EAAE;IACpF,IAAI,OAAO,IAAI,CAAC,IAAI,MAAM,CAAC,WAAW,KAAK,CAAC,IAAI,MAAM,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;QACxE,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,YAAY,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,GAAG,YAAY,CAAC;IAEnD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/B,OAAO,MAAM,CAAC,UAAU,CAAC;IAC3B,CAAC;IAED,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC3D,CAAC,CAAC;AAbW,QAAA,qBAAqB,yBAahC"}
@@ -0,0 +1,7 @@
1
+ export interface RetryPolicy {
2
+ maxRetries: number;
3
+ baseDelayMs: number;
4
+ maxDelayMs: number;
5
+ }
6
+ export declare const DEFAULT_RETRY_POLICY: RetryPolicy;
7
+ export declare const resolveRetryPolicy: (policy?: Partial<RetryPolicy>) => RetryPolicy;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveRetryPolicy = exports.DEFAULT_RETRY_POLICY = void 0;
4
+ exports.DEFAULT_RETRY_POLICY = {
5
+ maxRetries: 3,
6
+ baseDelayMs: 250,
7
+ maxDelayMs: 2_000,
8
+ };
9
+ const normalizeNonNegativeInteger = (value, fallback) => {
10
+ if (value === undefined || !Number.isFinite(value) || value < 0) {
11
+ return fallback;
12
+ }
13
+ return Math.trunc(value);
14
+ };
15
+ const resolveRetryPolicy = (policy) => {
16
+ const maxRetries = normalizeNonNegativeInteger(policy?.maxRetries, exports.DEFAULT_RETRY_POLICY.maxRetries);
17
+ const baseDelayMs = normalizeNonNegativeInteger(policy?.baseDelayMs, exports.DEFAULT_RETRY_POLICY.baseDelayMs);
18
+ const maxDelayMs = normalizeNonNegativeInteger(policy?.maxDelayMs, exports.DEFAULT_RETRY_POLICY.maxDelayMs);
19
+ return {
20
+ maxRetries,
21
+ baseDelayMs,
22
+ maxDelayMs: Math.max(baseDelayMs, maxDelayMs),
23
+ };
24
+ };
25
+ exports.resolveRetryPolicy = resolveRetryPolicy;
26
+ //# sourceMappingURL=retry-policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry-policy.js","sourceRoot":"","sources":["../../src/retry/retry-policy.ts"],"names":[],"mappings":";;;AAMa,QAAA,oBAAoB,GAAgB;IAC/C,UAAU,EAAE,CAAC;IACb,WAAW,EAAE,GAAG;IAChB,UAAU,EAAE,KAAK;CAClB,CAAC;AAEF,MAAM,2BAA2B,GAAG,CAAC,KAAyB,EAAE,QAAgB,EAAU,EAAE;IAC1F,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QAChE,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC,CAAC;AAEK,MAAM,kBAAkB,GAAG,CAAC,MAA6B,EAAe,EAAE;IAC/E,MAAM,UAAU,GAAG,2BAA2B,CAC5C,MAAM,EAAE,UAAU,EAClB,4BAAoB,CAAC,UAAU,CAChC,CAAC;IACF,MAAM,WAAW,GAAG,2BAA2B,CAC7C,MAAM,EAAE,WAAW,EACnB,4BAAoB,CAAC,WAAW,CACjC,CAAC;IACF,MAAM,UAAU,GAAG,2BAA2B,CAC5C,MAAM,EAAE,UAAU,EAClB,4BAAoB,CAAC,UAAU,CAChC,CAAC;IAEF,OAAO;QACL,UAAU;QACV,WAAW;QACX,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,UAAU,CAAC;KAC9C,CAAC;AACJ,CAAC,CAAC;AAnBW,QAAA,kBAAkB,sBAmB7B"}
@@ -0,0 +1,4 @@
1
+ import type { FetchLike, IngestionRequestResult, SendIngestionRequestInput } from './transport-types';
2
+ export declare const sendIngestionRequest: (input: SendIngestionRequestInput, dependencies?: {
3
+ fetch: FetchLike;
4
+ }) => Promise<IngestionRequestResult>;
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sendIngestionRequest = void 0;
4
+ const INGESTION_PATH = '/api/logs/ingest';
5
+ // Explicit status classification for ingestion delivery behavior.
6
+ const classifyIngestionStatus = (status) => {
7
+ switch (status) {
8
+ case 202:
9
+ return 'success';
10
+ case 400:
11
+ case 413:
12
+ return 'drop';
13
+ case 401:
14
+ return 'unauthorized';
15
+ case 429:
16
+ case 500:
17
+ return 'retry';
18
+ default:
19
+ return status >= 500 ? 'retry' : 'drop';
20
+ }
21
+ };
22
+ const buildIngestionUrl = (endpoint) => {
23
+ return new URL(INGESTION_PATH, endpoint).toString();
24
+ };
25
+ const buildRequestInit = (input) => {
26
+ return {
27
+ method: 'POST',
28
+ headers: {
29
+ 'x-api-key': input.apiKey,
30
+ 'Content-Type': 'application/json',
31
+ },
32
+ body: JSON.stringify({
33
+ logs: input.logs,
34
+ }),
35
+ };
36
+ };
37
+ const sendIngestionRequest = async (input, dependencies = { fetch: globalThis.fetch }) => {
38
+ let requestUrl;
39
+ try {
40
+ requestUrl = buildIngestionUrl(input.endpoint);
41
+ }
42
+ catch {
43
+ return {
44
+ action: 'drop',
45
+ shouldWarnUnauthorized: false,
46
+ errorKind: 'invalid_endpoint',
47
+ };
48
+ }
49
+ try {
50
+ console.log(`[logscope] Sending logs batch to ${requestUrl}`);
51
+ const response = await dependencies.fetch(requestUrl, buildRequestInit(input));
52
+ const action = classifyIngestionStatus(response.status);
53
+ if (action === 'unauthorized') {
54
+ return {
55
+ action,
56
+ status: response.status,
57
+ shouldWarnUnauthorized: true,
58
+ };
59
+ }
60
+ return {
61
+ action,
62
+ status: response.status,
63
+ shouldWarnUnauthorized: false,
64
+ };
65
+ }
66
+ catch {
67
+ return {
68
+ action: 'retry',
69
+ shouldWarnUnauthorized: false,
70
+ errorKind: 'network_error',
71
+ };
72
+ }
73
+ };
74
+ exports.sendIngestionRequest = sendIngestionRequest;
75
+ //# sourceMappingURL=send-ingestion-request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send-ingestion-request.js","sourceRoot":"","sources":["../../src/transport/send-ingestion-request.ts"],"names":[],"mappings":";;;AAQA,MAAM,cAAc,GAAG,kBAAkB,CAAC;AAE1C,kEAAkE;AAClE,MAAM,uBAAuB,GAAG,CAAC,MAAc,EAA0B,EAAE;IACzE,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,GAAG;YACN,OAAO,SAAS,CAAC;QACnB,KAAK,GAAG,CAAC;QACT,KAAK,GAAG;YACN,OAAO,MAAM,CAAC;QAChB,KAAK,GAAG;YACN,OAAO,cAAc,CAAC;QACxB,KAAK,GAAG,CAAC;QACT,KAAK,GAAG;YACN,OAAO,OAAO,CAAC;QACjB;YACE,OAAO,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;IAC5C,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,QAAgB,EAAU,EAAE;IACrD,OAAO,IAAI,GAAG,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAAC;AACtD,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,CAAC,KAAgC,EAAoB,EAAE;IAC9E,OAAO;QACL,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,WAAW,EAAE,KAAK,CAAC,MAAM;YACzB,cAAc,EAAE,kBAAkB;SACnC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,IAAI,EAAE,KAAK,CAAC,IAAI;SACjB,CAAC;KACH,CAAC;AACJ,CAAC,CAAC;AAEK,MAAM,oBAAoB,GAAG,KAAK,EACvC,KAAgC,EAChC,eAAqC,EAAE,KAAK,EAAE,UAAU,CAAC,KAA6B,EAAE,EACvD,EAAE;IACnC,IAAI,UAAkB,CAAC;IAEvB,IAAI,CAAC;QACH,UAAU,GAAG,iBAAiB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,MAAM,EAAE,MAAM;YACd,sBAAsB,EAAE,KAAK;YAC7B,SAAS,EAAE,kBAAkB;SAC9B,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,oCAAoC,UAAU,EAAE,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,UAAU,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC;QAC/E,MAAM,MAAM,GAAG,uBAAuB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAExD,IAAI,MAAM,KAAK,cAAc,EAAE,CAAC;YAC9B,OAAO;gBACL,MAAM;gBACN,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,sBAAsB,EAAE,IAAI;aAC7B,CAAC;QACJ,CAAC;QAED,OAAO;YACL,MAAM;YACN,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,sBAAsB,EAAE,KAAK;SAC9B,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,MAAM,EAAE,OAAO;YACf,sBAAsB,EAAE,KAAK;YAC7B,SAAS,EAAE,eAAe;SAC3B,CAAC;IACJ,CAAC;AACH,CAAC,CAAC;AAzCW,QAAA,oBAAoB,wBAyC/B"}
@@ -0,0 +1,39 @@
1
+ import type { IngestionLogEntry } from '../types';
2
+ export type IngestionRequestAction = 'success' | 'drop' | 'retry' | 'unauthorized';
3
+ export type IngestionDropErrorKind = 'invalid_endpoint' | 'max_retries_exceeded';
4
+ export type IngestionRetryErrorKind = 'network_error';
5
+ export type IngestionRequestResult = {
6
+ action: 'success';
7
+ status?: number;
8
+ shouldWarnUnauthorized: false;
9
+ errorKind?: never;
10
+ } | {
11
+ action: 'drop';
12
+ status?: number;
13
+ shouldWarnUnauthorized: false;
14
+ errorKind?: IngestionDropErrorKind;
15
+ } | {
16
+ action: 'retry';
17
+ status?: number;
18
+ shouldWarnUnauthorized: false;
19
+ errorKind?: IngestionRetryErrorKind;
20
+ } | {
21
+ action: 'unauthorized';
22
+ status?: number;
23
+ shouldWarnUnauthorized: true;
24
+ errorKind?: never;
25
+ };
26
+ export interface SendIngestionRequestInput {
27
+ endpoint: string;
28
+ apiKey: string;
29
+ logs: IngestionLogEntry[];
30
+ }
31
+ export interface FetchRequestInit {
32
+ method: 'POST';
33
+ headers: Record<string, string>;
34
+ body: string;
35
+ }
36
+ export interface FetchResponseLike {
37
+ status: number;
38
+ }
39
+ export type FetchLike = (url: string, init: FetchRequestInit) => Promise<FetchResponseLike>;
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=transport-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport-types.js","sourceRoot":"","sources":["../../src/transport/transport-types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,69 @@
1
+ export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';
2
+ export interface LogFilterConfig {
3
+ levels?: LogLevel[];
4
+ }
5
+ export interface LogscopeRuntimeConfig {
6
+ maxBatchSize?: number;
7
+ flushIntervalMs?: number;
8
+ maxRetries?: number;
9
+ retryBaseDelayMs?: number;
10
+ retryMaxDelayMs?: number;
11
+ }
12
+ interface LogscopeConfigBase {
13
+ apiKey: string;
14
+ captureConsole?: boolean;
15
+ context?: {
16
+ /**
17
+ * @deprecated Source input is optional and falls back safely when omitted.
18
+ */
19
+ source?: string;
20
+ };
21
+ logFilter?: LogFilterConfig;
22
+ runtime?: LogscopeRuntimeConfig;
23
+ }
24
+ export interface LogscopeInitConfig {
25
+ apiKey: string;
26
+ ingestionBaseUrl?: string;
27
+ /**
28
+ * @deprecated Use ingestionBaseUrl instead.
29
+ */
30
+ endpoint?: string;
31
+ captureConsole?: boolean;
32
+ context?: {
33
+ /**
34
+ * @deprecated Source input is optional and falls back safely when omitted.
35
+ */
36
+ source?: string;
37
+ };
38
+ logFilter?: LogFilterConfig;
39
+ runtime?: LogscopeRuntimeConfig;
40
+ }
41
+ interface LogscopeIngestionTarget {
42
+ ingestionBaseUrl?: string;
43
+ /**
44
+ * @deprecated Use ingestionBaseUrl instead.
45
+ */
46
+ endpoint?: string;
47
+ }
48
+ export type LogscopeConfig = LogscopeConfigBase & LogscopeIngestionTarget;
49
+ export interface LogscopeClient {
50
+ trace(message: string, metadata?: unknown): void;
51
+ debug(message: string, metadata?: unknown): void;
52
+ info(message: string, metadata?: unknown): void;
53
+ warn(message: string, metadata?: unknown): void;
54
+ error(message: string, metadata?: unknown): void;
55
+ fatal(message: string, metadata?: unknown): void;
56
+ }
57
+ export type JsonSafePrimitive = string | number | boolean | null;
58
+ export type JsonSafeValue = JsonSafePrimitive | JsonSafeObject | JsonSafeValue[];
59
+ export interface JsonSafeObject {
60
+ [key: string]: JsonSafeValue;
61
+ }
62
+ export interface IngestionLogEntry {
63
+ source: string;
64
+ level: LogLevel;
65
+ timestamp: string;
66
+ message: string;
67
+ metadata?: Record<string, unknown>;
68
+ }
69
+ export {};
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@logscopeai/logscope",
3
+ "version": "0.1.0-beta.2",
4
+ "description": "`logscope` is the official Node.js client SDK for Logscope.",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "default": "./dist/index.js"
11
+ },
12
+ "./pino": {
13
+ "types": "./dist/pino.d.ts",
14
+ "default": "./dist/pino.js"
15
+ },
16
+ "./package.json": "./package.json"
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "README.md",
21
+ "LICENSE"
22
+ ],
23
+ "scripts": {
24
+ "build": "tsc -p tsconfig.json",
25
+ "prepublishOnly": "npm run build",
26
+ "test": "vitest run --coverage",
27
+ "test:coverage": "vitest run --coverage",
28
+ "test:watch": "vitest",
29
+ "format": "prettier --config .prettierrc --write .",
30
+ "format:check": "prettier --config .prettierrc --check ."
31
+ },
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "git+https://github.com/logscopeai/logscope.git"
35
+ },
36
+ "keywords": [
37
+ "logscope",
38
+ "logging",
39
+ "sdk",
40
+ "nodejs"
41
+ ],
42
+ "author": "",
43
+ "license": "MIT",
44
+ "bugs": {
45
+ "url": "https://github.com/logscopeai/logscope/issues"
46
+ },
47
+ "homepage": "https://github.com/logscopeai/logscope#readme",
48
+ "devDependencies": {
49
+ "@types/node": "^22.10.2",
50
+ "@vitest/coverage-v8": "^2.1.8",
51
+ "lint-staged": "^15.4.3",
52
+ "prettier": "^3.4.2",
53
+ "typescript": "^5.7.2",
54
+ "vitest": "^2.1.8"
55
+ },
56
+ "lint-staged": {
57
+ "*.{ts,js,tsx,jsx,html,css,scss,json,md}": "npx prettier --config .prettierrc --write"
58
+ },
59
+ "engines": {
60
+ "node": ">=20"
61
+ }
62
+ }