@gurulu/node 0.1.1 → 1.0.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.
Files changed (48) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +64 -31
  3. package/dist/context.d.ts +12 -0
  4. package/dist/context.d.ts.map +1 -0
  5. package/dist/core.d.ts +60 -0
  6. package/dist/core.d.ts.map +1 -0
  7. package/dist/errors.d.ts +32 -0
  8. package/dist/errors.d.ts.map +1 -0
  9. package/dist/identify.d.ts +9 -0
  10. package/dist/identify.d.ts.map +1 -0
  11. package/dist/index.d.ts +13 -12
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +947 -21
  14. package/dist/middleware/express.d.ts +25 -0
  15. package/dist/middleware/express.d.ts.map +1 -0
  16. package/dist/middleware/express.js +66 -0
  17. package/dist/middleware/fastify.d.ts +20 -0
  18. package/dist/middleware/fastify.d.ts.map +1 -0
  19. package/dist/middleware/fastify.js +68 -0
  20. package/dist/middleware/next.d.ts +10 -0
  21. package/dist/middleware/next.d.ts.map +1 -0
  22. package/dist/middleware/next.js +69 -0
  23. package/dist/queue.d.ts +20 -0
  24. package/dist/queue.d.ts.map +1 -0
  25. package/dist/track.d.ts +10 -0
  26. package/dist/track.d.ts.map +1 -0
  27. package/dist/transport.d.ts +16 -0
  28. package/dist/transport.d.ts.map +1 -0
  29. package/dist/types.d.ts +129 -43
  30. package/dist/types.d.ts.map +1 -0
  31. package/dist/webhooks/custom.d.ts +30 -0
  32. package/dist/webhooks/custom.d.ts.map +1 -0
  33. package/dist/webhooks/custom.js +123 -0
  34. package/dist/webhooks/lemonsqueezy.d.ts +30 -0
  35. package/dist/webhooks/lemonsqueezy.d.ts.map +1 -0
  36. package/dist/webhooks/lemonsqueezy.js +140 -0
  37. package/dist/webhooks/shopify.d.ts +18 -0
  38. package/dist/webhooks/shopify.d.ts.map +1 -0
  39. package/dist/webhooks/shopify.js +142 -0
  40. package/dist/webhooks/stripe.d.ts +31 -0
  41. package/dist/webhooks/stripe.d.ts.map +1 -0
  42. package/dist/webhooks/stripe.js +160 -0
  43. package/package.json +105 -11
  44. package/dist/business-events.d.ts +0 -73
  45. package/dist/business-events.js +0 -113
  46. package/dist/client.d.ts +0 -90
  47. package/dist/client.js +0 -307
  48. package/dist/types.js +0 -30
@@ -0,0 +1,25 @@
1
+ export interface ExpressReqLike {
2
+ ip?: string;
3
+ headers: Record<string, string | string[] | undefined>;
4
+ cookies?: Record<string, string>;
5
+ socket?: {
6
+ remoteAddress?: string;
7
+ };
8
+ hostname?: string;
9
+ }
10
+ export interface ExpressResLike {
11
+ setHeader: (name: string, value: string) => void;
12
+ on: (event: string, cb: () => void) => void;
13
+ }
14
+ export type NextFn = (err?: unknown) => void;
15
+ export interface ExpressMiddlewareOptions {
16
+ /** Cookie name carrying anonymous_id from browser. Default `gurulu_aid`. */
17
+ anonymousIdCookie?: string;
18
+ /** Custom header carrying anonymous_id (server-to-server). Default `x-gurulu-anonymous-id`. */
19
+ anonymousIdHeader?: string;
20
+ /** Propagate request_id to response header. Default true. */
21
+ emitResponseHeader?: boolean;
22
+ }
23
+ /** Returns Express-compatible middleware: `app.use(gurulu.express.middleware())`. */
24
+ export declare function createExpressMiddleware(options?: ExpressMiddlewareOptions): (req: ExpressReqLike, res: ExpressResLike, next: NextFn) => void;
25
+ //# sourceMappingURL=express.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../../src/middleware/express.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,cAAc;IAC7B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;CAC7C;AAED,MAAM,MAAM,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;AAE7C,MAAM,WAAW,wBAAwB;IACvC,4EAA4E;IAC5E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,+FAA+F;IAC/F,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,6DAA6D;IAC7D,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,qFAAqF;AACrF,wBAAgB,uBAAuB,CAAC,OAAO,GAAE,wBAA6B,IAM1E,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,MAAM,MAAM,KACX,IAAI,CAoBR"}
@@ -0,0 +1,66 @@
1
+ // src/context.ts
2
+ import { AsyncLocalStorage } from "node:async_hooks";
3
+ var contextStorage = new AsyncLocalStorage;
4
+ function runWithContext(ctx, fn) {
5
+ return contextStorage.run(ctx, fn);
6
+ }
7
+ function getContext() {
8
+ return contextStorage.getStore();
9
+ }
10
+ function mergeContext(explicit) {
11
+ const stored = contextStorage.getStore();
12
+ if (!stored && !explicit)
13
+ return {};
14
+ if (!stored)
15
+ return explicit ?? {};
16
+ if (!explicit)
17
+ return stored;
18
+ return {
19
+ ...stored,
20
+ ...explicit,
21
+ source_context: { ...stored.source_context, ...explicit.source_context },
22
+ consent_state: explicit.consent_state ?? stored.consent_state
23
+ };
24
+ }
25
+ function generateRequestId() {
26
+ return crypto.randomUUID();
27
+ }
28
+
29
+ // src/middleware/express.ts
30
+ function createExpressMiddleware(options = {}) {
31
+ const cookieName = options.anonymousIdCookie ?? "gurulu_aid";
32
+ const headerName = options.anonymousIdHeader ?? "x-gurulu-anonymous-id";
33
+ const emit = options.emitResponseHeader ?? true;
34
+ return function guruluExpressMiddleware(req, res, next) {
35
+ const headerVal = req.headers[headerName];
36
+ const headerAid = Array.isArray(headerVal) ? headerVal[0] : headerVal;
37
+ const cookieAid = req.cookies?.[cookieName];
38
+ const requestId = pickHeader(req.headers["x-request-id"]) ?? generateRequestId();
39
+ const traceId = pickHeader(req.headers["x-trace-id"]) ?? pickHeader(req.headers.traceparent);
40
+ const ctx = {
41
+ request_id: requestId
42
+ };
43
+ if (headerAid || cookieAid)
44
+ ctx.anonymous_id = headerAid ?? cookieAid;
45
+ if (traceId)
46
+ ctx.trace_id = traceId;
47
+ if (req.ip || req.socket?.remoteAddress)
48
+ ctx.ip = req.ip ?? req.socket?.remoteAddress;
49
+ const ua = pickHeader(req.headers["user-agent"]);
50
+ if (ua)
51
+ ctx.user_agent = ua;
52
+ if (req.hostname)
53
+ ctx.domain = req.hostname;
54
+ if (emit)
55
+ res.setHeader("x-gurulu-request-id", requestId);
56
+ runWithContext(ctx, () => next());
57
+ };
58
+ }
59
+ function pickHeader(v) {
60
+ if (Array.isArray(v))
61
+ return v[0];
62
+ return v;
63
+ }
64
+ export {
65
+ createExpressMiddleware
66
+ };
@@ -0,0 +1,20 @@
1
+ export interface FastifyReqLike {
2
+ ip?: string;
3
+ headers: Record<string, string | string[] | undefined>;
4
+ cookies?: Record<string, string>;
5
+ hostname?: string;
6
+ }
7
+ export interface FastifyReplyLike {
8
+ header: (name: string, value: string) => unknown;
9
+ }
10
+ export interface FastifyInstanceLike {
11
+ addHook: (name: 'onRequest', handler: (req: FastifyReqLike, reply: FastifyReplyLike) => Promise<void> | void) => void;
12
+ }
13
+ export interface FastifyPluginOptions {
14
+ anonymousIdCookie?: string;
15
+ anonymousIdHeader?: string;
16
+ emitResponseHeader?: boolean;
17
+ }
18
+ /** Fastify plugin (default async signature). */
19
+ export declare function createFastifyPlugin(options?: FastifyPluginOptions): (fastify: FastifyInstanceLike) => Promise<void>;
20
+ //# sourceMappingURL=fastify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fastify.d.ts","sourceRoot":"","sources":["../../src/middleware/fastify.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,cAAc;IAC7B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;CAClD;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,CACP,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,KAC5E,IAAI,CAAC;CACX;AAED,MAAM,WAAW,oBAAoB;IACnC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,gDAAgD;AAChD,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,oBAAyB,IAK1B,SAAS,mBAAmB,KAAG,OAAO,CAAC,IAAI,CAAC,CAuBvF"}
@@ -0,0 +1,68 @@
1
+ // src/context.ts
2
+ import { AsyncLocalStorage } from "node:async_hooks";
3
+ var contextStorage = new AsyncLocalStorage;
4
+ function runWithContext(ctx, fn) {
5
+ return contextStorage.run(ctx, fn);
6
+ }
7
+ function getContext() {
8
+ return contextStorage.getStore();
9
+ }
10
+ function mergeContext(explicit) {
11
+ const stored = contextStorage.getStore();
12
+ if (!stored && !explicit)
13
+ return {};
14
+ if (!stored)
15
+ return explicit ?? {};
16
+ if (!explicit)
17
+ return stored;
18
+ return {
19
+ ...stored,
20
+ ...explicit,
21
+ source_context: { ...stored.source_context, ...explicit.source_context },
22
+ consent_state: explicit.consent_state ?? stored.consent_state
23
+ };
24
+ }
25
+ function generateRequestId() {
26
+ return crypto.randomUUID();
27
+ }
28
+
29
+ // src/middleware/fastify.ts
30
+ function createFastifyPlugin(options = {}) {
31
+ const cookieName = options.anonymousIdCookie ?? "gurulu_aid";
32
+ const headerName = options.anonymousIdHeader ?? "x-gurulu-anonymous-id";
33
+ const emit = options.emitResponseHeader ?? true;
34
+ return async function guruluFastifyPlugin(fastify) {
35
+ fastify.addHook("onRequest", (req, reply) => {
36
+ return new Promise((resolve) => {
37
+ const headerVal = req.headers[headerName];
38
+ const headerAid = Array.isArray(headerVal) ? headerVal[0] : headerVal;
39
+ const cookieAid = req.cookies?.[cookieName];
40
+ const requestId = pickHeader(req.headers["x-request-id"]) ?? generateRequestId();
41
+ const traceId = pickHeader(req.headers["x-trace-id"]) ?? pickHeader(req.headers.traceparent);
42
+ const ctx = { request_id: requestId };
43
+ if (headerAid || cookieAid)
44
+ ctx.anonymous_id = headerAid ?? cookieAid;
45
+ if (traceId)
46
+ ctx.trace_id = traceId;
47
+ if (req.ip)
48
+ ctx.ip = req.ip;
49
+ const ua = pickHeader(req.headers["user-agent"]);
50
+ if (ua)
51
+ ctx.user_agent = ua;
52
+ if (req.hostname)
53
+ ctx.domain = req.hostname;
54
+ if (emit)
55
+ reply.header("x-gurulu-request-id", requestId);
56
+ runWithContext(ctx, () => resolve());
57
+ });
58
+ });
59
+ };
60
+ }
61
+ function pickHeader(v) {
62
+ if (Array.isArray(v))
63
+ return v[0];
64
+ return v;
65
+ }
66
+ export {
67
+ createFastifyPlugin
68
+ };
@@ -0,0 +1,10 @@
1
+ import type { ServerContext } from '../types.ts';
2
+ export interface NextHandlerOptions {
3
+ anonymousIdCookie?: string;
4
+ anonymousIdHeader?: string;
5
+ }
6
+ type RouteHandler<T> = (req: Request, ctx: ServerContext) => Promise<T> | T;
7
+ /** App Router wrapper — auto AsyncLocalStorage context per request. */
8
+ export declare function createNextHandler(options?: NextHandlerOptions): <T>(handler: RouteHandler<T>) => (req: Request) => Promise<T>;
9
+ export {};
10
+ //# sourceMappingURL=next.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next.d.ts","sourceRoot":"","sources":["../../src/middleware/next.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,WAAW,kBAAkB;IACjC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AAE5E,uEAAuE;AACvE,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,kBAAuB,IAI3C,CAAC,EAAE,SAAS,YAAY,CAAC,CAAC,CAAC,KAAG,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,CAuBhF"}
@@ -0,0 +1,69 @@
1
+ // src/context.ts
2
+ import { AsyncLocalStorage } from "node:async_hooks";
3
+ var contextStorage = new AsyncLocalStorage;
4
+ function runWithContext(ctx, fn) {
5
+ return contextStorage.run(ctx, fn);
6
+ }
7
+ function getContext() {
8
+ return contextStorage.getStore();
9
+ }
10
+ function mergeContext(explicit) {
11
+ const stored = contextStorage.getStore();
12
+ if (!stored && !explicit)
13
+ return {};
14
+ if (!stored)
15
+ return explicit ?? {};
16
+ if (!explicit)
17
+ return stored;
18
+ return {
19
+ ...stored,
20
+ ...explicit,
21
+ source_context: { ...stored.source_context, ...explicit.source_context },
22
+ consent_state: explicit.consent_state ?? stored.consent_state
23
+ };
24
+ }
25
+ function generateRequestId() {
26
+ return crypto.randomUUID();
27
+ }
28
+
29
+ // src/middleware/next.ts
30
+ function createNextHandler(options = {}) {
31
+ const cookieName = options.anonymousIdCookie ?? "gurulu_aid";
32
+ const headerName = options.anonymousIdHeader ?? "x-gurulu-anonymous-id";
33
+ return function wrap(handler) {
34
+ return async function nextRouteHandler(req) {
35
+ const headerAid = req.headers.get(headerName) ?? undefined;
36
+ const cookieAid = readCookie(req.headers.get("cookie"), cookieName);
37
+ const requestId = req.headers.get("x-request-id") ?? generateRequestId();
38
+ const traceId = req.headers.get("x-trace-id") ?? req.headers.get("traceparent") ?? undefined;
39
+ const ctx = { request_id: requestId };
40
+ if (headerAid || cookieAid)
41
+ ctx.anonymous_id = headerAid ?? cookieAid;
42
+ if (traceId)
43
+ ctx.trace_id = traceId;
44
+ const ip = req.headers.get("x-forwarded-for")?.split(",")[0]?.trim();
45
+ if (ip)
46
+ ctx.ip = ip;
47
+ const ua = req.headers.get("user-agent") ?? undefined;
48
+ if (ua)
49
+ ctx.user_agent = ua;
50
+ try {
51
+ ctx.domain = new URL(req.url).host;
52
+ } catch {}
53
+ return await runWithContext(ctx, async () => handler(req, ctx));
54
+ };
55
+ };
56
+ }
57
+ function readCookie(cookieHeader, name) {
58
+ if (!cookieHeader)
59
+ return;
60
+ for (const part of cookieHeader.split(";")) {
61
+ const [k, v] = part.trim().split("=", 2);
62
+ if (k === name)
63
+ return v;
64
+ }
65
+ return;
66
+ }
67
+ export {
68
+ createNextHandler
69
+ };
@@ -0,0 +1,20 @@
1
+ import type { FlushResult, OutgoingEvent, ResolvedConfig } from './types.ts';
2
+ export declare class EventQueue {
3
+ private readonly config;
4
+ private readonly buffer;
5
+ private timer;
6
+ private flushing;
7
+ private droppedTotal;
8
+ private closed;
9
+ constructor(config: ResolvedConfig);
10
+ enqueue(event: OutgoingEvent): {
11
+ queued: boolean;
12
+ dropped: number;
13
+ };
14
+ size(): number;
15
+ private scheduleFlush;
16
+ flush(): Promise<FlushResult>;
17
+ /** Graceful shutdown — flush remaining + cancel timer + max 10s timeout. */
18
+ drain(timeoutMs?: number): Promise<FlushResult>;
19
+ }
20
+ //# sourceMappingURL=queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE7E,qBAAa,UAAU;IAOT,OAAO,CAAC,QAAQ,CAAC,MAAM;IANnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAC9C,OAAO,CAAC,KAAK,CAA8C;IAC3D,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,MAAM,CAAS;gBAEM,MAAM,EAAE,cAAc;IAEnD,OAAO,CAAC,KAAK,EAAE,aAAa,GAAG;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IAuBnE,IAAI,IAAI,MAAM;IAId,OAAO,CAAC,aAAa;IAUf,KAAK,IAAI,OAAO,CAAC,WAAW,CAAC;IA6BnC,4EAA4E;IACtE,KAAK,CAAC,SAAS,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;CAwBtD"}
@@ -0,0 +1,10 @@
1
+ import type { EventClass, OutgoingEvent, ResolvedConfig, ServerContext } from './types.ts';
2
+ export interface BuildEventInput {
3
+ config: ResolvedConfig;
4
+ eventKey: string;
5
+ eventType?: EventClass;
6
+ properties?: Record<string, unknown>;
7
+ explicitContext?: ServerContext;
8
+ }
9
+ export declare function buildEvent(input: BuildEventInput): OutgoingEvent;
10
+ //# sourceMappingURL=track.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"track.d.ts","sourceRoot":"","sources":["../src/track.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAU3F,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,UAAU,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,eAAe,CAAC,EAAE,aAAa,CAAC;CACjC;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,aAAa,CA8BhE"}
@@ -0,0 +1,16 @@
1
+ import type { OutgoingEvent, OutgoingIdentify, ResolvedConfig } from './types.ts';
2
+ interface PostInput {
3
+ path: '/v1/ingest/event' | '/v1/ingest/batch' | '/v1/ingest/identify';
4
+ body: unknown;
5
+ }
6
+ interface PostResult {
7
+ ok: boolean;
8
+ status: number;
9
+ body: unknown;
10
+ }
11
+ /** Internal POST with retry. testMode'da SADECE log + skip transport (core kontrol eder). */
12
+ export declare function postWithRetry(config: ResolvedConfig, input: PostInput): Promise<PostResult>;
13
+ export declare function sendBatch(config: ResolvedConfig, events: OutgoingEvent[]): Promise<void>;
14
+ export declare function sendIdentify(config: ResolvedConfig, payload: OutgoingIdentify): Promise<PostResult>;
15
+ export {};
16
+ //# sourceMappingURL=transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAgBlF,UAAU,SAAS;IACjB,IAAI,EAAE,kBAAkB,GAAG,kBAAkB,GAAG,qBAAqB,CAAC;IACtE,IAAI,EAAE,OAAO,CAAC;CACf;AAED,UAAU,UAAU;IAClB,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;CACf;AAED,6FAA6F;AAC7F,wBAAsB,aAAa,CAAC,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CA6CjG;AAUD,wBAAsB,SAAS,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAW9F;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,CAOrB"}
package/dist/types.d.ts CHANGED
@@ -1,46 +1,132 @@
1
- /**
2
- * Node SDK public types.
3
- *
4
- * Canonical event shapes (Envelope, ServerEvent, EventTier, EventSource,
5
- * ConsentLevel, createEnvelope, normalizeLegacy, parseEnvelope) are re-exported
6
- * from @gurulu/shared-core — single source of truth per W1.2.
7
- *
8
- * The only node-sdk-specific addition is the transport config
9
- * (GuruluClientConfig) which wraps the shared ServerEvent with the knobs
10
- * needed to actually ship events to the ingest endpoint.
11
- *
12
- * Related docs: PHASE-10-ROADMAP.md §W1.2, §W4.2
13
- */
14
- import type { ServerEvent } from '@gurulu/shared-core';
15
- export * from '@gurulu/shared-core';
16
- /**
17
- * Dead-letter callback fired when a batch is permanently dropped (either
18
- * because all retries failed against a 5xx/network error, or because the
19
- * server replied 4xx).
20
- */
21
- export type DeadLetterCallback = (batch: ServerEvent[], reason: {
22
- kind: 'client_error' | 'network_error' | 'server_error';
23
- status?: number;
24
- message: string;
25
- }) => void;
26
- export type ErrorCallback = (err: Error) => void;
27
- export interface GuruluClientConfig {
28
- siteId: string;
29
- apiKey: string;
1
+ /** K17 — 4-kategori event-level consent snapshot. */
2
+ export interface ServerConsentSnapshot {
3
+ analytics: boolean;
4
+ marketing: boolean;
5
+ functional: boolean;
6
+ personalization: boolean;
7
+ captured_at?: string;
8
+ source?: 'banner' | 'settings' | 'api' | 'sdk' | 'webhook';
9
+ granular_categories?: Record<string, boolean>;
10
+ }
11
+ /** K16 producer enum (server SDK + webhook iki kanal). */
12
+ export type ServerProducer = 'sdk_server' | 'webhook';
13
+ /** Gurulu native event_type enum (K14 3-sınıf). */
14
+ export type EventClass = 'interaction' | 'intent' | 'outcome';
15
+ /** Request-scope context (AsyncLocalStorage + manuel set). */
16
+ export interface ServerContext {
17
+ /** Browser cookie'den header X-Gurulu-Anonymous-Id ile gelir. */
18
+ anonymous_id?: string;
19
+ person_id?: string;
20
+ session_id?: string;
21
+ /** request_id + trace_id auto-populated middleware tarafından. */
22
+ request_id?: string;
23
+ trace_id?: string;
24
+ /** Outcome event'ler için source preservation (UTM + click ID + referrer). */
25
+ source_context?: {
26
+ utm_source?: string;
27
+ utm_medium?: string;
28
+ utm_campaign?: string;
29
+ utm_term?: string;
30
+ utm_content?: string;
31
+ gclid?: string;
32
+ fbclid?: string;
33
+ ttclid?: string;
34
+ li_fat_id?: string;
35
+ referrer?: string;
36
+ };
37
+ ip?: string;
38
+ user_agent?: string;
39
+ domain?: string;
40
+ consent_state?: ServerConsentSnapshot;
41
+ }
42
+ /** Identify trait dictionary — email/phone hash'lenir, diğerleri raw. */
43
+ export interface IdentifyTraits {
44
+ email?: string;
45
+ phone?: string;
46
+ name?: string;
47
+ [key: string]: unknown;
48
+ }
49
+ /** Outgoing single event — queue + transport şeması. */
50
+ export interface OutgoingEvent {
51
+ anonymous_id: string;
52
+ person_id?: string;
53
+ session_id?: string;
54
+ event_id?: string;
55
+ event_key: string;
56
+ event_type: EventClass;
57
+ occurred_at: string;
58
+ producer: ServerProducer;
59
+ producer_version?: string;
60
+ properties?: Record<string, unknown>;
61
+ context?: {
62
+ url?: string;
63
+ referrer?: string;
64
+ user_agent?: string;
65
+ ip?: string;
66
+ domain?: string;
67
+ utm?: NonNullable<ServerContext['source_context']>;
68
+ request_id?: string;
69
+ trace_id?: string;
70
+ };
71
+ consent_state?: ServerConsentSnapshot;
72
+ }
73
+ /** Identify payload (M9 /v1/ingest/identify şemasıyla uyumlu). */
74
+ export interface OutgoingIdentify {
75
+ workspace_id?: string;
76
+ anonymous_id: string;
77
+ external_user_id?: string;
78
+ email?: string;
79
+ phone?: string;
80
+ traits?: Record<string, unknown>;
81
+ context?: {
82
+ domain?: string;
83
+ consent_state?: ServerConsentSnapshot;
84
+ };
85
+ }
86
+ export interface ServerSDKConfig {
87
+ /** sk_xxx (secret key) — pk_xxx kabul edilmez. */
88
+ workspaceKey: string;
30
89
  endpoint?: string;
31
- /** Periodic flush interval in ms. Default 5000. */
32
- flushInterval?: number;
33
- /** Max events per batch. Auto-flushes when queue reaches this size. Default 50. */
34
- batchSize?: number;
35
- /** Per-request HTTP timeout in ms. Default 10000. */
36
- timeout?: number;
37
- /** Fired on every transport error (retryable or not). */
38
- onError?: ErrorCallback;
39
- /** Fired when a batch is permanently dropped. */
40
- onDeadLetter?: DeadLetterCallback;
41
- /** Inject fetch for testing (defaults to globalThis.fetch). */
90
+ flushIntervalMs?: number;
91
+ maxBatchSize?: number;
92
+ maxQueueSize?: number;
93
+ retryMaxAttempts?: number;
94
+ retryBackoffBaseMs?: number;
95
+ /** true → console.log JSON, HTTP gönderim atlanır (CI / dev). */
96
+ testMode?: boolean;
97
+ defaultConsent?: ServerConsentSnapshot;
98
+ /** Custom fetch (test injection veya undici override). */
42
99
  fetchImpl?: typeof fetch;
43
- /** Suppress automatic process.on('beforeExit'/'SIGTERM') hooks. */
44
- disableAutoShutdown?: boolean;
45
- debug?: boolean;
46
100
  }
101
+ export interface ResolvedConfig {
102
+ workspaceKey: string;
103
+ endpoint: string;
104
+ flushIntervalMs: number;
105
+ maxBatchSize: number;
106
+ maxQueueSize: number;
107
+ retryMaxAttempts: number;
108
+ retryBackoffBaseMs: number;
109
+ testMode: boolean;
110
+ defaultConsent: ServerConsentSnapshot;
111
+ fetchImpl: typeof fetch;
112
+ }
113
+ export interface IdentifyResult {
114
+ ok: boolean;
115
+ status: number;
116
+ body?: unknown;
117
+ }
118
+ export interface TrackResult {
119
+ queued: boolean;
120
+ queueSize: number;
121
+ }
122
+ export interface FlushResult {
123
+ attempted: number;
124
+ succeeded: number;
125
+ dropped: number;
126
+ }
127
+ export interface HandleResult {
128
+ events_emitted: number;
129
+ vendor: 'stripe' | 'shopify' | 'lemonsqueezy' | 'custom';
130
+ event_keys: string[];
131
+ }
132
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { HandleResult, OutgoingEvent, ResolvedConfig } from '../types.ts';
2
+ export interface CustomHandleReq {
3
+ body: string;
4
+ headers: Record<string, string | string[] | undefined>;
5
+ }
6
+ export interface CustomMapResult {
7
+ event_key: string;
8
+ event_id?: string;
9
+ anonymous_id?: string;
10
+ person_id?: string;
11
+ properties?: Record<string, unknown>;
12
+ occurred_at?: string;
13
+ }
14
+ export interface CreateCustomWebhookOptions {
15
+ signatureHeader: string;
16
+ secret: string;
17
+ /**
18
+ * Signature verifier — default sha256-hex HMAC.
19
+ * Custom override için: `(rawBody, signature, secret) => boolean`.
20
+ */
21
+ verifySignature?: (rawBody: string, signature: string, secret: string) => boolean;
22
+ /** Payload → Gurulu event mapping (customer logic). */
23
+ mapPayload: (payload: unknown) => CustomMapResult | CustomMapResult[];
24
+ }
25
+ export interface CustomWebhookHandler {
26
+ verify: (rawBody: string, signature: string) => boolean;
27
+ handle: (req: CustomHandleReq) => Promise<HandleResult>;
28
+ }
29
+ export declare function createCustomWebhook(config: ResolvedConfig, enqueue: (event: OutgoingEvent) => void, options: CreateCustomWebhookOptions): CustomWebhookHandler;
30
+ //# sourceMappingURL=custom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom.d.ts","sourceRoot":"","sources":["../../src/webhooks/custom.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,cAAc,EAEf,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;CACxD;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,0BAA0B;IACzC,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAClF,uDAAuD;IACvD,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,eAAe,GAAG,eAAe,EAAE,CAAC;CACvE;AAqCD,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IACxD,MAAM,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;CACzD;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,EACvC,OAAO,EAAE,0BAA0B,GAClC,oBAAoB,CA6BtB"}