@adjedaini/clockwork-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.
Files changed (65) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +225 -0
  3. package/dist/globals.d.ts +27 -0
  4. package/dist/index.d.ts +61 -0
  5. package/dist/index.js +695 -0
  6. package/dist/public/assets/index-B2HEyS_P.css +1 -0
  7. package/dist/public/assets/index-B83PrqXa.css +1 -0
  8. package/dist/public/assets/index-CdsiP1dN.css +1 -0
  9. package/dist/public/assets/index-Df9idoqY.js +198 -0
  10. package/dist/public/assets/index-KmGT-iQM.js +198 -0
  11. package/dist/public/assets/index-znhjCgo1.js +198 -0
  12. package/dist/public/index.html +13 -0
  13. package/node_modules/@adjedaini/clockwork-core/dist/index.d.ts +53 -0
  14. package/node_modules/@adjedaini/clockwork-core/dist/index.js +192 -0
  15. package/node_modules/@adjedaini/clockwork-core/package.json +17 -0
  16. package/node_modules/@adjedaini/clockwork-core/src/index.ts +194 -0
  17. package/node_modules/@adjedaini/clockwork-core/src/ring-buffer.ts +47 -0
  18. package/node_modules/@adjedaini/clockwork-core/tsconfig.build.json +6 -0
  19. package/node_modules/@adjedaini/clockwork-core/tsconfig.json +10 -0
  20. package/node_modules/@adjedaini/clockwork-core/tsup.config.ts +13 -0
  21. package/node_modules/@adjedaini/clockwork-db-interceptor/dist/index.d.ts +33 -0
  22. package/node_modules/@adjedaini/clockwork-db-interceptor/dist/index.js +163 -0
  23. package/node_modules/@adjedaini/clockwork-db-interceptor/package.json +18 -0
  24. package/node_modules/@adjedaini/clockwork-db-interceptor/src/index.ts +28 -0
  25. package/node_modules/@adjedaini/clockwork-db-interceptor/src/mysql2.ts +84 -0
  26. package/node_modules/@adjedaini/clockwork-db-interceptor/src/pg.ts +56 -0
  27. package/node_modules/@adjedaini/clockwork-db-interceptor/tsconfig.build.json +6 -0
  28. package/node_modules/@adjedaini/clockwork-db-interceptor/tsconfig.json +10 -0
  29. package/node_modules/@adjedaini/clockwork-db-interceptor/tsup.config.ts +13 -0
  30. package/node_modules/@adjedaini/clockwork-log-interceptor/dist/index.d.ts +25 -0
  31. package/node_modules/@adjedaini/clockwork-log-interceptor/dist/index.js +153 -0
  32. package/node_modules/@adjedaini/clockwork-log-interceptor/package.json +16 -0
  33. package/node_modules/@adjedaini/clockwork-log-interceptor/src/index.ts +14 -0
  34. package/node_modules/@adjedaini/clockwork-log-interceptor/src/pino.ts +78 -0
  35. package/node_modules/@adjedaini/clockwork-log-interceptor/src/winston.ts +66 -0
  36. package/node_modules/@adjedaini/clockwork-log-interceptor/tsconfig.build.json +4 -0
  37. package/node_modules/@adjedaini/clockwork-log-interceptor/tsconfig.json +10 -0
  38. package/node_modules/@adjedaini/clockwork-log-interceptor/tsup.config.ts +13 -0
  39. package/node_modules/@adjedaini/clockwork-plugins/dist/index.d.ts +45 -0
  40. package/node_modules/@adjedaini/clockwork-plugins/dist/index.js +172 -0
  41. package/node_modules/@adjedaini/clockwork-plugins/package.json +19 -0
  42. package/node_modules/@adjedaini/clockwork-plugins/src/console.ts +70 -0
  43. package/node_modules/@adjedaini/clockwork-plugins/src/context.ts +30 -0
  44. package/node_modules/@adjedaini/clockwork-plugins/src/index.ts +50 -0
  45. package/node_modules/@adjedaini/clockwork-plugins/src/process-errors.ts +33 -0
  46. package/node_modules/@adjedaini/clockwork-plugins/tsconfig.build.json +1 -0
  47. package/node_modules/@adjedaini/clockwork-plugins/tsconfig.json +16 -0
  48. package/node_modules/@adjedaini/clockwork-plugins/tsup.config.ts +13 -0
  49. package/node_modules/@adjedaini/clockwork-shared/dist/index.d.ts +97 -0
  50. package/node_modules/@adjedaini/clockwork-shared/dist/index.js +18 -0
  51. package/node_modules/@adjedaini/clockwork-shared/package.json +14 -0
  52. package/node_modules/@adjedaini/clockwork-shared/src/index.ts +96 -0
  53. package/node_modules/@adjedaini/clockwork-shared/tsconfig.build.json +6 -0
  54. package/node_modules/@adjedaini/clockwork-shared/tsconfig.json +9 -0
  55. package/node_modules/@adjedaini/clockwork-shared/tsup.config.ts +13 -0
  56. package/node_modules/@adjedaini/clockwork-transport-http/dist/index.d.ts +75 -0
  57. package/node_modules/@adjedaini/clockwork-transport-http/dist/index.js +306 -0
  58. package/node_modules/@adjedaini/clockwork-transport-http/package.json +18 -0
  59. package/node_modules/@adjedaini/clockwork-transport-http/src/index.ts +277 -0
  60. package/node_modules/@adjedaini/clockwork-transport-http/src/sanitize.ts +92 -0
  61. package/node_modules/@adjedaini/clockwork-transport-http/src/types.ts +37 -0
  62. package/node_modules/@adjedaini/clockwork-transport-http/tsconfig.build.json +6 -0
  63. package/node_modules/@adjedaini/clockwork-transport-http/tsconfig.json +10 -0
  64. package/node_modules/@adjedaini/clockwork-transport-http/tsup.config.ts +13 -0
  65. package/package.json +69 -0
@@ -0,0 +1,277 @@
1
+ /**
2
+ * @adjedaini/clockwork-transport-http
3
+ * HTTP adapter: wraps core, exposes middleware + data handler.
4
+ * No hard dependency on Express types.
5
+ */
6
+
7
+ import type { MonitorCore } from '@adjedaini/clockwork-core';
8
+ import type {
9
+ ClockworkRequestLike,
10
+ ClockworkResponseLike,
11
+ NextLike,
12
+ } from './types';
13
+ import { sanitizeHeaders, sanitizeBody } from './sanitize';
14
+
15
+ export type { ClockworkRequestLike, ClockworkResponseLike, NextLike } from './types.js';
16
+
17
+ export type ContextRunner = (requestId: string, next: NextLike) => void;
18
+
19
+ export interface HttpAdapterOptions {
20
+ /** Base path for API and UI (e.g. "/__clockwork"). No trailing slash. */
21
+ path?: string;
22
+ /** Run the rest of the request (next) inside this context (e.g. AsyncLocalStorage.run). Enables per-request correlation. */
23
+ contextRunner?: ContextRunner;
24
+ /** Max request list returned by snapshot. */
25
+ snapshotLimit?: number;
26
+ /** Redact these keys in headers/body. */
27
+ redactKeys?: string[];
28
+ /** Max body size to capture (chars). */
29
+ maxBodySize?: number;
30
+ /** Max depth when serializing body. */
31
+ maxBodyDepth?: number;
32
+ /** Capture request body. */
33
+ captureRequestBody?: boolean;
34
+ /** Capture response body. */
35
+ captureResponseBody?: boolean;
36
+ /** Skip paths that start with any of these. */
37
+ ignoreStartsWith?: string[];
38
+ }
39
+
40
+ const DEFAULT_PATH = '/__clockwork';
41
+ const DEFAULT_REDACT_KEYS = [
42
+ 'authorization', 'cookie', 'set-cookie', 'x-api-key', 'x-auth-token',
43
+ 'password', 'passwd', 'secret', 'token', 'access_token', 'refresh_token',
44
+ ];
45
+
46
+ export interface HttpAdapter {
47
+ /** Middleware: capture request, call next(), finalize on res finish. */
48
+ middleware(
49
+ req: ClockworkRequestLike,
50
+ res: ClockworkResponseLike,
51
+ next: NextLike
52
+ ): void;
53
+ /** Handler: serve JSON API (snapshot, by id). Call for GET path, path/latest, path/:id. */
54
+ dataHandler(req: ClockworkRequestLike, res: ClockworkResponseLike): void;
55
+ }
56
+
57
+ function getPathPrefix(path: string): string {
58
+ return path.replace(/\/$/, '') || DEFAULT_PATH;
59
+ }
60
+
61
+ function getMethod(req: ClockworkRequestLike): string {
62
+ return (req.method || 'GET').toUpperCase();
63
+ }
64
+
65
+ function getUri(req: ClockworkRequestLike): string {
66
+ return req.originalUrl ?? req.url ?? req.path ?? '/';
67
+ }
68
+
69
+ function getPathname(req: ClockworkRequestLike): string {
70
+ const u = req.originalUrl ?? req.url ?? req.path ?? '/';
71
+ const q = u.indexOf('?');
72
+ return q === -1 ? u : u.slice(0, q);
73
+ }
74
+
75
+ export function createHttpAdapter(
76
+ core: MonitorCore,
77
+ options: HttpAdapterOptions = {}
78
+ ): HttpAdapter {
79
+ const pathPrefix = getPathPrefix(options.path ?? DEFAULT_PATH);
80
+ const contextRunner = options.contextRunner;
81
+ const snapshotLimit = options.snapshotLimit ?? 50;
82
+ const redactKeys = options.redactKeys ?? DEFAULT_REDACT_KEYS;
83
+ const maxBodySize = options.maxBodySize ?? 10000;
84
+ const maxBodyDepth = options.maxBodyDepth ?? 10;
85
+ const captureRequestBody = options.captureRequestBody ?? true;
86
+ const captureResponseBody = options.captureResponseBody ?? true;
87
+ const ignoreStartsWith = options.ignoreStartsWith ?? [];
88
+
89
+ const sanitizeOpts = { redactKeys, maxLength: maxBodySize, maxDepth: maxBodyDepth };
90
+
91
+ function shouldIgnore(pathname: string): boolean {
92
+ return ignoreStartsWith.some((p) => pathname.startsWith(p));
93
+ }
94
+
95
+ function isClockworkPath(pathname: string): boolean {
96
+ return pathname === pathPrefix || pathname.startsWith(pathPrefix + '/');
97
+ }
98
+
99
+ function sendJson(res: ClockworkResponseLike, body: unknown, statusCode?: number): void {
100
+ const payload = JSON.stringify(body);
101
+ if (statusCode != null && res.status) {
102
+ const r = res.status(statusCode);
103
+ if (r.json) r.json(body);
104
+ else r.end?.(payload);
105
+ } else if (res.json) {
106
+ res.json(body);
107
+ } else {
108
+ res.setHeader('Content-Type', 'application/json');
109
+ res.end?.(payload);
110
+ }
111
+ }
112
+
113
+ const dataHandler: HttpAdapter['dataHandler'] = (req, res) => {
114
+ const pathname = getPathname(req);
115
+ if (!isClockworkPath(pathname)) {
116
+ if (res.status) res.status(404).end?.('Not found');
117
+ else { res.setHeader('Content-Type', 'text/plain'); res.end?.('Not found'); }
118
+ return;
119
+ }
120
+
121
+ const relative = pathname.slice(pathPrefix.length).replace(/^\/+/, '') || 'index';
122
+ const segments = relative.split('/');
123
+
124
+ // GET /__clockwork -> snapshot (requests list)
125
+ if (segments[0] === 'index' || segments[0] === '') {
126
+ sendJson(res, core.getSnapshot(snapshotLimit));
127
+ return;
128
+ }
129
+
130
+ // GET /__clockwork/metrics -> metrics only
131
+ if (segments[0] === 'metrics') {
132
+ const snapshot = core.getSnapshot(1);
133
+ sendJson(res, snapshot.metrics ?? { timestamp: Date.now() / 1000, spans: [] });
134
+ return;
135
+ }
136
+
137
+ // GET /__clockwork/latest -> latest request
138
+ if (segments[0] === 'latest') {
139
+ const snapshot = core.getSnapshot(1);
140
+ const reqs = snapshot.requests;
141
+ if (reqs.length === 0) {
142
+ sendJson(res, { error: 'No requests found' }, 404);
143
+ return;
144
+ }
145
+ const latest = core.getRequest(reqs[0].id);
146
+ sendJson(res, latest ?? {});
147
+ return;
148
+ }
149
+
150
+ // GET /__clockwork/:id -> single request
151
+ const id = segments[0];
152
+ const request = core.getRequest(id);
153
+ if (!request) {
154
+ sendJson(res, { error: 'Request not found' }, 404);
155
+ return;
156
+ }
157
+ sendJson(res, request);
158
+ };
159
+
160
+ const middleware: HttpAdapter['middleware'] = (req, res, next) => {
161
+ const pathname = getPathname(req);
162
+ if (isClockworkPath(pathname)) {
163
+ dataHandler(req, res);
164
+ return;
165
+ }
166
+ if (shouldIgnore(pathname)) {
167
+ next();
168
+ return;
169
+ }
170
+
171
+ const headers = sanitizeHeaders(
172
+ req.headers as Record<string, unknown>,
173
+ { redactKeys, maxValueLength: 500 }
174
+ );
175
+ const getData = (req.query ?? {}) as Record<string, unknown>;
176
+ const postData =
177
+ captureRequestBody && req.body !== undefined
178
+ ? sanitizeBody(req.body, sanitizeOpts)
179
+ : undefined;
180
+ const cookies =
181
+ req.cookies !== undefined
182
+ ? sanitizeHeaders(req.cookies as Record<string, unknown>, { redactKeys })
183
+ : undefined;
184
+
185
+ const requestId = core.captureRequest({
186
+ method: getMethod(req),
187
+ uri: getUri(req),
188
+ headers,
189
+ getData: sanitizeBody(getData, sanitizeOpts) as Record<string, unknown>,
190
+ postData,
191
+ cookies,
192
+ controller: req.route?.path,
193
+ });
194
+ const startTimeMs = Date.now();
195
+ let capturedResponseBody: unknown = undefined;
196
+
197
+ const setHeader = res.setHeader.bind(res);
198
+ res.setHeader = function (name: string, value: string | number) {
199
+ if (!(res as { headersSent?: boolean }).headersSent) {
200
+ if (name.toLowerCase() === 'x-clockwork-id') {
201
+ setHeader('X-Clockwork-Id', String(value));
202
+ } else if (name.toLowerCase() === 'x-clockwork-version') {
203
+ setHeader('X-Clockwork-Version', '2.0');
204
+ } else if (name.toLowerCase() === 'x-clockwork-path') {
205
+ setHeader('X-Clockwork-Path', `${pathPrefix}/${value}`);
206
+ }
207
+ }
208
+ return setHeader(name, value);
209
+ };
210
+
211
+ const originalSend = res.send;
212
+ const originalJson = res.json;
213
+ if (originalSend) {
214
+ res.send = function (body?: unknown) {
215
+ if (!(res as { headersSent?: boolean }).headersSent) {
216
+ res.setHeader('X-Clockwork-Id', requestId);
217
+ res.setHeader('X-Clockwork-Version', '2.0');
218
+ res.setHeader('X-Clockwork-Path', `${pathPrefix}/${requestId}`);
219
+ }
220
+ if (captureResponseBody && body !== undefined) {
221
+ try {
222
+ const str = typeof body === 'string' ? body : JSON.stringify(body);
223
+ capturedResponseBody =
224
+ str.length <= maxBodySize ? (typeof body === 'string' ? body : body) : str.slice(0, maxBodySize) + '...[truncated]';
225
+ } catch {
226
+ capturedResponseBody = '[unserializable]';
227
+ }
228
+ }
229
+ return originalSend.call(this, body);
230
+ };
231
+ }
232
+ if (originalJson) {
233
+ res.json = function (body?: unknown) {
234
+ if (!(res as { headersSent?: boolean }).headersSent) {
235
+ res.setHeader('X-Clockwork-Id', requestId);
236
+ res.setHeader('X-Clockwork-Version', '2.0');
237
+ res.setHeader('X-Clockwork-Path', `${pathPrefix}/${requestId}`);
238
+ }
239
+ if (captureResponseBody && body !== undefined) {
240
+ try {
241
+ const str = JSON.stringify(body);
242
+ capturedResponseBody =
243
+ str.length <= maxBodySize ? body : str.slice(0, maxBodySize) + '...[truncated]';
244
+ } catch {
245
+ capturedResponseBody = '[unserializable]';
246
+ }
247
+ }
248
+ return originalJson.call(this, body);
249
+ };
250
+ }
251
+
252
+ res.on('finish', () => {
253
+ const statusCode =
254
+ typeof (res as { statusCode?: number }).statusCode === 'number'
255
+ ? (res as { statusCode: number }).statusCode
256
+ : 200;
257
+ const duration = Date.now() - startTimeMs;
258
+ core.finalizeRequest(requestId, {
259
+ responseStatus: statusCode,
260
+ responseDuration: duration,
261
+ responseData:
262
+ capturedResponseBody !== undefined
263
+ ? sanitizeBody(capturedResponseBody, sanitizeOpts)
264
+ : undefined,
265
+ });
266
+ });
267
+
268
+ (req as { clockworkId?: string }).clockworkId = requestId;
269
+ if (contextRunner) {
270
+ contextRunner(requestId, next);
271
+ } else {
272
+ next();
273
+ }
274
+ };
275
+
276
+ return { middleware, dataHandler };
277
+ }
@@ -0,0 +1,92 @@
1
+ /** Minimal sanitization for headers/body. No framework deps. */
2
+
3
+ const DEFAULT_REDACT_KEYS = [
4
+ 'authorization', 'cookie', 'set-cookie', 'x-api-key', 'x-auth-token',
5
+ 'password', 'passwd', 'secret', 'token', 'access_token', 'refresh_token',
6
+ 'api_key', 'apikey', 'credential', 'credentials',
7
+ ];
8
+
9
+ function redactValue(): string {
10
+ return '[REDACTED]';
11
+ }
12
+
13
+ function truncate(str: string, maxLength: number): string {
14
+ if (typeof str !== 'string') return str;
15
+ if (str.length <= maxLength) return str;
16
+ return str.slice(0, maxLength) + '...[truncated]';
17
+ }
18
+
19
+ function shouldRedact(key: string, redactKeys: string[]): boolean {
20
+ const lower = key.toLowerCase();
21
+ return redactKeys.some((k) => lower.includes(k.toLowerCase()) || k.toLowerCase().includes(lower));
22
+ }
23
+
24
+ export function sanitizeHeaders(
25
+ obj: Record<string, unknown> | undefined,
26
+ options: { redactKeys?: string[]; maxValueLength?: number } = {}
27
+ ): Record<string, unknown> {
28
+ if (!obj || typeof obj !== 'object') return {};
29
+ const keys = options.redactKeys ?? DEFAULT_REDACT_KEYS;
30
+ const maxLen = options.maxValueLength ?? 500;
31
+ const out: Record<string, unknown> = {};
32
+ for (const [k, v] of Object.entries(obj)) {
33
+ if (shouldRedact(k, keys)) {
34
+ out[k] = redactValue();
35
+ } else if (typeof v === 'string') {
36
+ out[k] = truncate(v, maxLen);
37
+ } else {
38
+ out[k] = v;
39
+ }
40
+ }
41
+ return out;
42
+ }
43
+
44
+ const DEFAULT_MAX_DEPTH = 10;
45
+ const OMITTED_DEPTH = '[depth exceeded]';
46
+
47
+ export interface SanitizeBodyOptions {
48
+ redactKeys?: string[];
49
+ maxLength?: number;
50
+ maxDepth?: number;
51
+ }
52
+
53
+ function sanitizeBodyAtDepth(
54
+ value: unknown,
55
+ options: SanitizeBodyOptions & { _depth?: number }
56
+ ): unknown {
57
+ const keys = options.redactKeys ?? DEFAULT_REDACT_KEYS;
58
+ const maxLength = options.maxLength ?? 10000;
59
+ const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;
60
+ const depth = options._depth ?? 0;
61
+
62
+ if (value === null || value === undefined) return value;
63
+ if (typeof value === 'string') return truncate(value, maxLength);
64
+ if (depth >= maxDepth) return OMITTED_DEPTH;
65
+
66
+ const nextOpts: SanitizeBodyOptions & { _depth?: number } = {
67
+ redactKeys: keys,
68
+ maxLength,
69
+ maxDepth,
70
+ _depth: depth + 1,
71
+ };
72
+
73
+ if (Array.isArray(value)) {
74
+ return value.slice(0, 50).map((item) => sanitizeBodyAtDepth(item, nextOpts));
75
+ }
76
+ if (typeof value === 'object') {
77
+ const out: Record<string, unknown> = {};
78
+ for (const [k, v] of Object.entries(value)) {
79
+ if (shouldRedact(k, keys)) out[k] = redactValue();
80
+ else out[k] = sanitizeBodyAtDepth(v, nextOpts);
81
+ }
82
+ return out;
83
+ }
84
+ return value;
85
+ }
86
+
87
+ export function sanitizeBody(value: unknown, options: SanitizeBodyOptions = {}): unknown {
88
+ const { _depth, ...opts } = options as SanitizeBodyOptions & { _depth?: number };
89
+ return sanitizeBodyAtDepth(value, opts);
90
+ }
91
+
92
+ export { DEFAULT_REDACT_KEYS };
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Minimal HTTP request/response-like types.
3
+ * No hard dependency on Express; compatible with Express, Fastify (with adapters), etc.
4
+ */
5
+
6
+ export interface ClockworkRequestLike {
7
+ method: string;
8
+ url?: string;
9
+ originalUrl?: string;
10
+ path?: string;
11
+ headers: Record<string, string | string[] | undefined>;
12
+ body?: unknown;
13
+ /** Parsed query (e.g. from ?foo=bar). */
14
+ query?: Record<string, unknown>;
15
+ /** Parsed cookies if available. */
16
+ cookies?: Record<string, unknown>;
17
+ /** Route pattern if available (e.g. "/user/:id"). */
18
+ route?: { path?: string };
19
+ }
20
+
21
+ export interface ClockworkResponseLike {
22
+ setHeader(name: string, value: string | number): void;
23
+ getHeader?(name: string): string | number | string[] | undefined;
24
+ statusCode: number;
25
+ on(event: 'finish', fn: () => void): void;
26
+ /** Set status and return chainable res (Express-style). */
27
+ status?(code: number): ClockworkResponseLike;
28
+ /** Send body (string or Buffer). */
29
+ send?(body?: unknown): unknown;
30
+ /** Send JSON. */
31
+ json?(body?: unknown): unknown;
32
+ /** End response with optional body. */
33
+ end?(body?: string): void;
34
+ headersSent?: boolean;
35
+ }
36
+
37
+ export type NextLike = (err?: unknown) => void;
@@ -0,0 +1,6 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "composite": false
5
+ }
6
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "outDir": "dist",
5
+ "rootDir": "src",
6
+ "composite": true
7
+ },
8
+ "include": ["src/**/*"],
9
+ "references": [{ "path": "../core" }, { "path": "../shared" }]
10
+ }
@@ -0,0 +1,13 @@
1
+ import path from 'path';
2
+ import { fileURLToPath } from 'url';
3
+ import { defineConfig } from 'tsup';
4
+
5
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
6
+
7
+ export default defineConfig({
8
+ entry: ['src/index.ts'],
9
+ format: ['cjs'],
10
+ dts: true,
11
+ outDir: 'dist',
12
+ tsconfig: path.join(__dirname, 'tsconfig.build.json'),
13
+ });
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "@adjedaini/clockwork-node",
3
+ "version": "0.0.1",
4
+ "description": "Clockwork Node — framework-agnostic debugging, profiling & metrics for Node.js backends",
5
+ "private": false,
6
+ "type": "module",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js",
16
+ "default": "./dist/index.js"
17
+ },
18
+ "./globals": "./dist/globals.d.ts"
19
+ },
20
+ "workspaces": [
21
+ ".",
22
+ "packages/*",
23
+ "apps/*"
24
+ ],
25
+ "scripts": {
26
+ "build": "npm run build:packages && npm run build:ui && npm run build:root && npm run build:copy-ui",
27
+ "build:packages": "node scripts/build-packages.cjs",
28
+ "build:ui": "npm run build -w @adjedaini/clockwork-ui",
29
+ "build:root": "tsup",
30
+ "build:copy-ui": "node scripts/copy-ui.cjs",
31
+ "dev:ui": "npm run dev -w @adjedaini/clockwork-ui",
32
+ "dev:example": "npm run start -w example",
33
+ "clean": "rm -rf dist packages/*/dist; true",
34
+ "test": "vitest run",
35
+ "test:watch": "vitest",
36
+ "version": "changeset version",
37
+ "release": "changeset publish",
38
+ "prepublishOnly": "npm run build"
39
+ },
40
+ "dependencies": {
41
+ "@adjedaini/clockwork-core": "*",
42
+ "@adjedaini/clockwork-transport-http": "*",
43
+ "@adjedaini/clockwork-shared": "*",
44
+ "@adjedaini/clockwork-plugins": "*",
45
+ "@adjedaini/clockwork-db-interceptor": "*",
46
+ "@adjedaini/clockwork-log-interceptor": "*"
47
+ },
48
+ "devDependencies": {
49
+ "@changesets/cli": "^2.27.0",
50
+ "tsup": "^8.0.0",
51
+ "typescript": "^5.5.0",
52
+ "vitest": "^2.0.0"
53
+ },
54
+ "engines": {
55
+ "node": ">=18.0.0"
56
+ },
57
+ "license": "MIT",
58
+ "publishConfig": {
59
+ "access": "public"
60
+ },
61
+ "bundledDependencies": [
62
+ "@adjedaini/clockwork-core",
63
+ "@adjedaini/clockwork-transport-http",
64
+ "@adjedaini/clockwork-shared",
65
+ "@adjedaini/clockwork-plugins",
66
+ "@adjedaini/clockwork-db-interceptor",
67
+ "@adjedaini/clockwork-log-interceptor"
68
+ ]
69
+ }