@appmachina/node 0.0.1 → 2.2.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.
@@ -0,0 +1,59 @@
1
+ import "./persistence-ChBsyTkr.js";
2
+ import { o as AppMachinaNode } from "./express-D5w2Pl15.js";
3
+
4
+ //#region src/nextjs.d.ts
5
+ interface RequestContext {
6
+ distinctId: string;
7
+ properties: Record<string, unknown>;
8
+ }
9
+ /**
10
+ * Extract attribution parameters from a URL string.
11
+ *
12
+ * Parses the query string and returns any recognized click ID or UTM
13
+ * parameters, prefixed with `$url_` to avoid collisions with user properties.
14
+ */
15
+ declare function extractUrlParamsFromUrl(url: string): Record<string, string>;
16
+ /**
17
+ * Run a callback with a AppMachina request context.
18
+ * Inside the callback, `getAppMachinaContext()` returns the context.
19
+ *
20
+ * Usage in Next.js middleware or API routes:
21
+ * withAppMachinaContext({ distinctId: userId }, async () => {
22
+ * // ... handler code
23
+ * sdk.track(getAppMachinaContext()!.distinctId, 'page_view', { path });
24
+ * });
25
+ */
26
+ declare function withAppMachinaContext<T>(context: RequestContext, fn: () => T): T;
27
+ /**
28
+ * Create a AppMachina request context from a Next.js request URL, automatically
29
+ * extracting attribution URL parameters and merging them into the context
30
+ * properties.
31
+ *
32
+ * Usage:
33
+ * withAppMachinaRequestContext({ distinctId: userId, url: req.url }, async () => {
34
+ * trackServerPageView(sdk, '/dashboard');
35
+ * });
36
+ */
37
+ declare function withAppMachinaRequestContext<T>(options: {
38
+ distinctId: string;
39
+ url?: string;
40
+ properties?: Record<string, unknown>;
41
+ }, fn: () => T): T;
42
+ /**
43
+ * Get the current AppMachina request context (set by withAppMachinaContext).
44
+ * Returns undefined if called outside a context.
45
+ */
46
+ declare function getAppMachinaContext(): RequestContext | undefined;
47
+ /**
48
+ * Track a server-side page view in Next.js.
49
+ * Resolves the distinctId from the current AsyncLocalStorage context
50
+ * or falls back to the provided distinctId.
51
+ */
52
+ declare function trackServerPageView(sdk: AppMachinaNode, path: string, distinctId?: string): void;
53
+ /**
54
+ * Track a Next.js Server Action invocation.
55
+ */
56
+ declare function trackServerAction(sdk: AppMachinaNode, actionName: string, properties?: Record<string, unknown>, distinctId?: string): void;
57
+ //#endregion
58
+ export { RequestContext, extractUrlParamsFromUrl, getAppMachinaContext, trackServerAction, trackServerPageView, withAppMachinaContext, withAppMachinaRequestContext };
59
+ //# sourceMappingURL=nextjs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nextjs.d.ts","names":[],"sources":["../src/nextjs.ts"],"sourcesContent":[],"mappings":";;;;UAkBiB,cAAA;;cAEH;AAFd;AAaA;AA+BA;;;;;AAcgB,iBA7CA,uBAAA,CA6C4B,GAAA,EAAA,MAAA,CAAA,EA7CU,MA6CV,CAAA,MAAA,EAAA,MAAA,CAAA;;;;;AAgB5C;AASA;AAcA;;;;iBArDgB,kCAAkC,0BAA0B,IAAI;;;;;;;;;;;iBAchE;;;eAC4C;aAChD,IACT;;;;;iBAaa,oBAAA,CAAA,GAAwB;;;;;;iBASxB,mBAAA,MAAyB;;;;iBAczB,iBAAA,MACT,iDAEQ"}
package/dist/nextjs.js ADDED
@@ -0,0 +1,112 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+
3
+ //#region src/nextjs.ts
4
+ /** Attribution URL parameters captured from Next.js request URLs. */
5
+ const CLICK_ID_PARAMS = [
6
+ "fbclid",
7
+ "gclid",
8
+ "gbraid",
9
+ "wbraid",
10
+ "ttclid",
11
+ "msclkid",
12
+ "rclid"
13
+ ];
14
+ const UTM_PARAMS = [
15
+ "utm_source",
16
+ "utm_medium",
17
+ "utm_campaign",
18
+ "utm_content",
19
+ "utm_term"
20
+ ];
21
+ const ALL_ATTRIBUTION_PARAMS = [...CLICK_ID_PARAMS, ...UTM_PARAMS];
22
+ const storage = new AsyncLocalStorage();
23
+ /**
24
+ * Extract attribution parameters from a URL string.
25
+ *
26
+ * Parses the query string and returns any recognized click ID or UTM
27
+ * parameters, prefixed with `$url_` to avoid collisions with user properties.
28
+ */
29
+ function extractUrlParamsFromUrl(url) {
30
+ const params = {};
31
+ try {
32
+ const queryStart = url.indexOf("?");
33
+ if (queryStart === -1) return params;
34
+ const searchParams = new URLSearchParams(url.slice(queryStart));
35
+ for (const param of ALL_ATTRIBUTION_PARAMS) {
36
+ const value = searchParams.get(param);
37
+ if (value) params[`$url_${param}`] = value;
38
+ }
39
+ } catch {}
40
+ return params;
41
+ }
42
+ /**
43
+ * Run a callback with a AppMachina request context.
44
+ * Inside the callback, `getAppMachinaContext()` returns the context.
45
+ *
46
+ * Usage in Next.js middleware or API routes:
47
+ * withAppMachinaContext({ distinctId: userId }, async () => {
48
+ * // ... handler code
49
+ * sdk.track(getAppMachinaContext()!.distinctId, 'page_view', { path });
50
+ * });
51
+ */
52
+ function withAppMachinaContext(context, fn) {
53
+ return storage.run(context, fn);
54
+ }
55
+ /**
56
+ * Create a AppMachina request context from a Next.js request URL, automatically
57
+ * extracting attribution URL parameters and merging them into the context
58
+ * properties.
59
+ *
60
+ * Usage:
61
+ * withAppMachinaRequestContext({ distinctId: userId, url: req.url }, async () => {
62
+ * trackServerPageView(sdk, '/dashboard');
63
+ * });
64
+ */
65
+ function withAppMachinaRequestContext(options, fn) {
66
+ const urlParams = options.url ? extractUrlParamsFromUrl(options.url) : {};
67
+ const context = {
68
+ distinctId: options.distinctId,
69
+ properties: {
70
+ ...urlParams,
71
+ ...options.properties
72
+ }
73
+ };
74
+ return storage.run(context, fn);
75
+ }
76
+ /**
77
+ * Get the current AppMachina request context (set by withAppMachinaContext).
78
+ * Returns undefined if called outside a context.
79
+ */
80
+ function getAppMachinaContext() {
81
+ return storage.getStore();
82
+ }
83
+ /**
84
+ * Track a server-side page view in Next.js.
85
+ * Resolves the distinctId from the current AsyncLocalStorage context
86
+ * or falls back to the provided distinctId.
87
+ */
88
+ function trackServerPageView(sdk, path, distinctId) {
89
+ const ctx = getAppMachinaContext();
90
+ const resolvedId = distinctId ?? ctx?.distinctId ?? "anonymous";
91
+ sdk.track(resolvedId, "page_view", {
92
+ path,
93
+ ...ctx?.properties,
94
+ server_rendered: true
95
+ });
96
+ }
97
+ /**
98
+ * Track a Next.js Server Action invocation.
99
+ */
100
+ function trackServerAction(sdk, actionName, properties, distinctId) {
101
+ const ctx = getAppMachinaContext();
102
+ const resolvedId = distinctId ?? ctx?.distinctId ?? "anonymous";
103
+ sdk.track(resolvedId, "server_action", {
104
+ action_name: actionName,
105
+ ...properties,
106
+ ...ctx?.properties
107
+ });
108
+ }
109
+
110
+ //#endregion
111
+ export { extractUrlParamsFromUrl, getAppMachinaContext, trackServerAction, trackServerPageView, withAppMachinaContext, withAppMachinaRequestContext };
112
+ //# sourceMappingURL=nextjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nextjs.js","names":["params: Record<string, string>","context: RequestContext"],"sources":["../src/nextjs.ts"],"sourcesContent":["// @appmachina/node/nextjs — Next.js integration with AsyncLocalStorage for request context.\nimport { AsyncLocalStorage } from 'node:async_hooks';\n\nimport type { AppMachinaNode } from './index.js';\n\n/** Attribution URL parameters captured from Next.js request URLs. */\nconst CLICK_ID_PARAMS = [\n 'fbclid',\n 'gclid',\n 'gbraid',\n 'wbraid',\n 'ttclid',\n 'msclkid',\n 'rclid'\n] as const;\nconst UTM_PARAMS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'] as const;\nconst ALL_ATTRIBUTION_PARAMS = [...CLICK_ID_PARAMS, ...UTM_PARAMS] as const;\n\nexport interface RequestContext {\n distinctId: string;\n properties: Record<string, unknown>;\n}\n\nconst storage = new AsyncLocalStorage<RequestContext>();\n\n/**\n * Extract attribution parameters from a URL string.\n *\n * Parses the query string and returns any recognized click ID or UTM\n * parameters, prefixed with `$url_` to avoid collisions with user properties.\n */\nexport function extractUrlParamsFromUrl(url: string): Record<string, string> {\n const params: Record<string, string> = {};\n\n try {\n const queryStart = url.indexOf('?');\n if (queryStart === -1) return params;\n\n const searchParams = new URLSearchParams(url.slice(queryStart));\n for (const param of ALL_ATTRIBUTION_PARAMS) {\n const value = searchParams.get(param);\n if (value) {\n params[`$url_${param}`] = value;\n }\n }\n } catch {\n // URL parsing failed — return empty\n }\n\n return params;\n}\n\n/**\n * Run a callback with a AppMachina request context.\n * Inside the callback, `getAppMachinaContext()` returns the context.\n *\n * Usage in Next.js middleware or API routes:\n * withAppMachinaContext({ distinctId: userId }, async () => {\n * // ... handler code\n * sdk.track(getAppMachinaContext()!.distinctId, 'page_view', { path });\n * });\n */\nexport function withAppMachinaContext<T>(context: RequestContext, fn: () => T): T {\n return storage.run(context, fn);\n}\n\n/**\n * Create a AppMachina request context from a Next.js request URL, automatically\n * extracting attribution URL parameters and merging them into the context\n * properties.\n *\n * Usage:\n * withAppMachinaRequestContext({ distinctId: userId, url: req.url }, async () => {\n * trackServerPageView(sdk, '/dashboard');\n * });\n */\nexport function withAppMachinaRequestContext<T>(\n options: { distinctId: string; url?: string; properties?: Record<string, unknown> },\n fn: () => T\n): T {\n const urlParams = options.url ? extractUrlParamsFromUrl(options.url) : {};\n const context: RequestContext = {\n distinctId: options.distinctId,\n properties: { ...urlParams, ...options.properties }\n };\n return storage.run(context, fn);\n}\n\n/**\n * Get the current AppMachina request context (set by withAppMachinaContext).\n * Returns undefined if called outside a context.\n */\nexport function getAppMachinaContext(): RequestContext | undefined {\n return storage.getStore();\n}\n\n/**\n * Track a server-side page view in Next.js.\n * Resolves the distinctId from the current AsyncLocalStorage context\n * or falls back to the provided distinctId.\n */\nexport function trackServerPageView(sdk: AppMachinaNode, path: string, distinctId?: string): void {\n const ctx = getAppMachinaContext();\n const resolvedId = distinctId ?? ctx?.distinctId ?? 'anonymous';\n\n sdk.track(resolvedId, 'page_view', {\n path,\n ...ctx?.properties,\n server_rendered: true\n });\n}\n\n/**\n * Track a Next.js Server Action invocation.\n */\nexport function trackServerAction(\n sdk: AppMachinaNode,\n actionName: string,\n properties?: Record<string, unknown>,\n distinctId?: string\n): void {\n const ctx = getAppMachinaContext();\n const resolvedId = distinctId ?? ctx?.distinctId ?? 'anonymous';\n\n sdk.track(resolvedId, 'server_action', {\n action_name: actionName,\n ...properties,\n ...ctx?.properties\n });\n}\n"],"mappings":";;;;AAMA,MAAM,kBAAkB;CACtB;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AACD,MAAM,aAAa;CAAC;CAAc;CAAc;CAAgB;CAAe;CAAW;AAC1F,MAAM,yBAAyB,CAAC,GAAG,iBAAiB,GAAG,WAAW;AAOlE,MAAM,UAAU,IAAI,mBAAmC;;;;;;;AAQvD,SAAgB,wBAAwB,KAAqC;CAC3E,MAAMA,SAAiC,EAAE;AAEzC,KAAI;EACF,MAAM,aAAa,IAAI,QAAQ,IAAI;AACnC,MAAI,eAAe,GAAI,QAAO;EAE9B,MAAM,eAAe,IAAI,gBAAgB,IAAI,MAAM,WAAW,CAAC;AAC/D,OAAK,MAAM,SAAS,wBAAwB;GAC1C,MAAM,QAAQ,aAAa,IAAI,MAAM;AACrC,OAAI,MACF,QAAO,QAAQ,WAAW;;SAGxB;AAIR,QAAO;;;;;;;;;;;;AAaT,SAAgB,sBAAyB,SAAyB,IAAgB;AAChF,QAAO,QAAQ,IAAI,SAAS,GAAG;;;;;;;;;;;;AAajC,SAAgB,6BACd,SACA,IACG;CACH,MAAM,YAAY,QAAQ,MAAM,wBAAwB,QAAQ,IAAI,GAAG,EAAE;CACzE,MAAMC,UAA0B;EAC9B,YAAY,QAAQ;EACpB,YAAY;GAAE,GAAG;GAAW,GAAG,QAAQ;GAAY;EACpD;AACD,QAAO,QAAQ,IAAI,SAAS,GAAG;;;;;;AAOjC,SAAgB,uBAAmD;AACjE,QAAO,QAAQ,UAAU;;;;;;;AAQ3B,SAAgB,oBAAoB,KAAqB,MAAc,YAA2B;CAChG,MAAM,MAAM,sBAAsB;CAClC,MAAM,aAAa,cAAc,KAAK,cAAc;AAEpD,KAAI,MAAM,YAAY,aAAa;EACjC;EACA,GAAG,KAAK;EACR,iBAAiB;EAClB,CAAC;;;;;AAMJ,SAAgB,kBACd,KACA,YACA,YACA,YACM;CACN,MAAM,MAAM,sBAAsB;CAClC,MAAM,aAAa,cAAc,KAAK,cAAc;AAEpD,KAAI,MAAM,YAAY,iBAAiB;EACrC,aAAa;EACb,GAAG;EACH,GAAG,KAAK;EACT,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { PersistenceBackend } from "@appmachina/core-wasm";
2
+
3
+ //#region src/persistence.d.ts
4
+
5
+ /**
6
+ * File-system-backed persistence for Node.js environments.
7
+ *
8
+ * Stores each key as a separate file in a directory scoped by appId.
9
+ * Uses synchronous fs APIs so writes are guaranteed before the call returns
10
+ * (important for SIGTERM / graceful-shutdown scenarios).
11
+ */
12
+ declare class FilePersistence implements PersistenceBackend {
13
+ private readonly dir;
14
+ constructor(appId: string, baseDir?: string);
15
+ write(key: string, data: Uint8Array): void;
16
+ read(key: string): Uint8Array | null;
17
+ delete(key: string): void;
18
+ listKeys(prefix: string): string[];
19
+ }
20
+ //#endregion
21
+ export { FilePersistence as t };
22
+ //# sourceMappingURL=persistence-ChBsyTkr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistence-ChBsyTkr.d.ts","names":[],"sources":["../src/persistence.ts"],"sourcesContent":[],"mappings":";;;;;;AAoBA;;;;;cAAa,eAAA,YAA2B;;;2BAUb;qBAKN"}
@@ -0,0 +1,47 @@
1
+ import { existsSync, mkdirSync, readFileSync, readdirSync, unlinkSync, writeFileSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+
5
+ //#region src/persistence.ts
6
+ /**
7
+ * File-system-backed persistence for Node.js environments.
8
+ *
9
+ * Stores each key as a separate file in a directory scoped by appId.
10
+ * Uses synchronous fs APIs so writes are guaranteed before the call returns
11
+ * (important for SIGTERM / graceful-shutdown scenarios).
12
+ */
13
+ var FilePersistence = class {
14
+ dir;
15
+ constructor(appId, baseDir) {
16
+ this.dir = join(baseDir ?? tmpdir(), "appmachina-sdk", appId);
17
+ if (!existsSync(this.dir)) mkdirSync(this.dir, { recursive: true });
18
+ }
19
+ write(key, data) {
20
+ writeFileSync(join(this.dir, encodeURIComponent(key)), Buffer.from(data));
21
+ }
22
+ read(key) {
23
+ const path = join(this.dir, encodeURIComponent(key));
24
+ try {
25
+ return new Uint8Array(readFileSync(path));
26
+ } catch {
27
+ return null;
28
+ }
29
+ }
30
+ delete(key) {
31
+ const path = join(this.dir, encodeURIComponent(key));
32
+ try {
33
+ unlinkSync(path);
34
+ } catch {}
35
+ }
36
+ listKeys(prefix) {
37
+ try {
38
+ return readdirSync(this.dir).map((f) => decodeURIComponent(f)).filter((k) => k.startsWith(prefix));
39
+ } catch {
40
+ return [];
41
+ }
42
+ }
43
+ };
44
+
45
+ //#endregion
46
+ export { FilePersistence as t };
47
+ //# sourceMappingURL=persistence-D_zFNklE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistence-D_zFNklE.js","names":[],"sources":["../src/persistence.ts"],"sourcesContent":["import {\n existsSync,\n mkdirSync,\n readFileSync,\n readdirSync,\n unlinkSync,\n writeFileSync\n} from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\n\nimport type { PersistenceBackend } from '@appmachina/core-wasm';\n\n/**\n * File-system-backed persistence for Node.js environments.\n *\n * Stores each key as a separate file in a directory scoped by appId.\n * Uses synchronous fs APIs so writes are guaranteed before the call returns\n * (important for SIGTERM / graceful-shutdown scenarios).\n */\nexport class FilePersistence implements PersistenceBackend {\n private readonly dir: string;\n\n constructor(appId: string, baseDir?: string) {\n this.dir = join(baseDir ?? tmpdir(), 'appmachina-sdk', appId);\n if (!existsSync(this.dir)) {\n mkdirSync(this.dir, { recursive: true });\n }\n }\n\n write(key: string, data: Uint8Array): void {\n const path = join(this.dir, encodeURIComponent(key));\n writeFileSync(path, Buffer.from(data));\n }\n\n read(key: string): Uint8Array | null {\n const path = join(this.dir, encodeURIComponent(key));\n try {\n return new Uint8Array(readFileSync(path));\n } catch {\n return null;\n }\n }\n\n delete(key: string): void {\n const path = join(this.dir, encodeURIComponent(key));\n try {\n unlinkSync(path);\n } catch {\n // File may not exist — ignore\n }\n }\n\n listKeys(prefix: string): string[] {\n try {\n return readdirSync(this.dir)\n .map((f) => decodeURIComponent(f))\n .filter((k) => k.startsWith(prefix));\n } catch {\n return [];\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;AAoBA,IAAa,kBAAb,MAA2D;CACzD,AAAiB;CAEjB,YAAY,OAAe,SAAkB;AAC3C,OAAK,MAAM,KAAK,WAAW,QAAQ,EAAE,kBAAkB,MAAM;AAC7D,MAAI,CAAC,WAAW,KAAK,IAAI,CACvB,WAAU,KAAK,KAAK,EAAE,WAAW,MAAM,CAAC;;CAI5C,MAAM,KAAa,MAAwB;AAEzC,gBADa,KAAK,KAAK,KAAK,mBAAmB,IAAI,CAAC,EAChC,OAAO,KAAK,KAAK,CAAC;;CAGxC,KAAK,KAAgC;EACnC,MAAM,OAAO,KAAK,KAAK,KAAK,mBAAmB,IAAI,CAAC;AACpD,MAAI;AACF,UAAO,IAAI,WAAW,aAAa,KAAK,CAAC;UACnC;AACN,UAAO;;;CAIX,OAAO,KAAmB;EACxB,MAAM,OAAO,KAAK,KAAK,KAAK,mBAAmB,IAAI,CAAC;AACpD,MAAI;AACF,cAAW,KAAK;UACV;;CAKV,SAAS,QAA0B;AACjC,MAAI;AACF,UAAO,YAAY,KAAK,IAAI,CACzB,KAAK,MAAM,mBAAmB,EAAE,CAAC,CACjC,QAAQ,MAAM,EAAE,WAAW,OAAO,CAAC;UAChC;AACN,UAAO,EAAE"}
@@ -0,0 +1,2 @@
1
+ import { t as FilePersistence } from "./persistence-ChBsyTkr.js";
2
+ export { FilePersistence };
@@ -0,0 +1,3 @@
1
+ import { t as FilePersistence } from "./persistence-D_zFNklE.js";
2
+
3
+ export { FilePersistence };
package/package.json CHANGED
@@ -1,7 +1,54 @@
1
1
  {
2
2
  "name": "@appmachina/node",
3
- "version": "0.0.1",
4
- "description": "AppMachina SDK - node (placeholder)",
5
- "main": "index.js",
6
- "access": "public"
7
- }
3
+ "version": "2.2.0",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
7
+ "description": "AppMachina Analytics Node.js SDK — thin wrapper over Rust core via WASM",
8
+ "license": "MIT",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://github.com/appmachina/sdks.git",
12
+ "directory": "packages/node"
13
+ },
14
+ "author": "AppMachina Team",
15
+ "type": "module",
16
+ "main": "./dist/index.js",
17
+ "module": "./dist/index.js",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "default": "./dist/index.js"
22
+ },
23
+ "./express": {
24
+ "types": "./dist/express.d.ts",
25
+ "default": "./dist/express.js"
26
+ },
27
+ "./nextjs": {
28
+ "types": "./dist/nextjs.d.ts",
29
+ "default": "./dist/nextjs.js"
30
+ }
31
+ },
32
+ "files": [
33
+ "dist"
34
+ ],
35
+ "dependencies": {
36
+ "@appmachina/core-wasm": "2.2.0"
37
+ },
38
+ "keywords": [
39
+ "appmachina",
40
+ "analytics",
41
+ "sdk",
42
+ "node",
43
+ "server"
44
+ ],
45
+ "types": "./dist/index.d.ts",
46
+ "sideEffects": false,
47
+ "engines": {
48
+ "node": ">=18"
49
+ },
50
+ "scripts": {
51
+ "build": "tsdown src/index.ts src/express.ts src/nextjs.ts src/persistence.ts --format esm --dts",
52
+ "test": "vitest run"
53
+ }
54
+ }
package/index.js DELETED
@@ -1 +0,0 @@
1
- module.exports = {};