@smarthivelabs-devs/observe-expo 0.0.0-stage → 26.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.
@@ -0,0 +1,130 @@
1
+ type Level = "debug" | "info" | "warn" | "error" | "fatal";
2
+ interface ObserveUser {
3
+ id: string;
4
+ email?: string;
5
+ username?: string;
6
+ ipAddress?: string;
7
+ }
8
+ interface Breadcrumb {
9
+ timestamp?: number;
10
+ category: string;
11
+ message?: string;
12
+ level?: Level;
13
+ data?: Record<string, unknown>;
14
+ }
15
+ interface TraceContext {
16
+ traceId: string;
17
+ spanId: string;
18
+ parentSpanId?: string;
19
+ sampled?: boolean;
20
+ }
21
+ interface ObserveEvent {
22
+ eventId: string;
23
+ type: "error" | "log" | "transaction" | "span" | "performance" | "session";
24
+ timestamp: number;
25
+ platform: "expo";
26
+ message?: string;
27
+ level?: Level;
28
+ user?: ObserveUser;
29
+ tags?: Record<string, string>;
30
+ contexts?: Record<string, unknown>;
31
+ breadcrumbs?: Breadcrumb[];
32
+ trace?: TraceContext;
33
+ metadata?: Record<string, unknown>;
34
+ [key: string]: unknown;
35
+ }
36
+ type BeforeSend = (event: ObserveEvent) => ObserveEvent | null | Promise<ObserveEvent | null>;
37
+ interface SmartObserveConfig {
38
+ dsn?: string;
39
+ environment?: string;
40
+ release?: string;
41
+ dist?: string;
42
+ enabled?: boolean;
43
+ debug?: boolean;
44
+ sampleRate?: number;
45
+ tracesSampleRate?: number;
46
+ errorSampleRate?: number;
47
+ sendDefaultPii?: boolean;
48
+ maxBreadcrumbs?: number;
49
+ maxQueueSize?: number;
50
+ flushIntervalMs?: number;
51
+ beforeSend?: BeforeSend;
52
+ redactKeys?: string[];
53
+ allowTracePropagationTargets?: Array<string | RegExp>;
54
+ trackNetwork?: boolean;
55
+ trackLifecycle?: boolean;
56
+ }
57
+ interface SpanOptions {
58
+ name: string;
59
+ operation: string;
60
+ attributes?: Record<string, string | number | boolean>;
61
+ parent?: TraceContext;
62
+ sampled?: boolean;
63
+ }
64
+ interface ObserveSpan {
65
+ traceId: string;
66
+ spanId: string;
67
+ setAttribute(key: string, value: string | number | boolean): void;
68
+ setStatus(status: "ok" | "error" | "cancelled" | "unknown"): void;
69
+ recordException(error: unknown): void;
70
+ end(): void;
71
+ }
72
+
73
+ declare class SmartObserveExpoClient {
74
+ private config;
75
+ private transport?;
76
+ private user?;
77
+ private tags;
78
+ private contexts;
79
+ private breadcrumbs;
80
+ private trace?;
81
+ private beforeSendHook?;
82
+ private cleanups;
83
+ private sessionId;
84
+ private sessionStarted;
85
+ constructor(input?: SmartObserveConfig);
86
+ captureException(error: unknown, hint?: Record<string, unknown>): `${string}-${string}-${string}-${string}-${string}`;
87
+ captureMessage(message: string, level?: Level, metadata?: Record<string, unknown>): `${string}-${string}-${string}-${string}-${string}`;
88
+ log: {
89
+ debug: (m: string, d?: Record<string, unknown>) => `${string}-${string}-${string}-${string}-${string}`;
90
+ info: (m: string, d?: Record<string, unknown>) => `${string}-${string}-${string}-${string}-${string}`;
91
+ warn: (m: string, d?: Record<string, unknown>) => `${string}-${string}-${string}-${string}-${string}`;
92
+ error: (m: string, d?: Record<string, unknown>) => `${string}-${string}-${string}-${string}-${string}`;
93
+ };
94
+ addBreadcrumb(value: Breadcrumb): void;
95
+ setUser(value: ObserveUser | null): void;
96
+ setTag(key: string, value: string | null): void;
97
+ setContext(key: string, value: Record<string, unknown> | null): void;
98
+ beforeSend(callback: BeforeSend): void;
99
+ startSpan<T>(options: SpanOptions, callback: (span: ObserveSpan) => T | Promise<T>): T | Promise<T>;
100
+ flush(): Promise<void>;
101
+ close(): Promise<void>;
102
+ trackScreen(name: string, params?: Record<string, unknown>): void;
103
+ private base;
104
+ private capture;
105
+ private setup;
106
+ private patchFetch;
107
+ }
108
+
109
+ declare const SmartObserve: {
110
+ init(config?: SmartObserveConfig): SmartObserveExpoClient;
111
+ captureException(error: unknown, hint?: Record<string, unknown>): `${string}-${string}-${string}-${string}-${string}`;
112
+ captureMessage(message: string, level?: Level, metadata?: Record<string, unknown>): `${string}-${string}-${string}-${string}-${string}`;
113
+ addBreadcrumb(value: Breadcrumb): void;
114
+ setUser(value: ObserveUser | null): void;
115
+ setTag(key: string, value: string | null): void;
116
+ setContext(key: string, value: Record<string, unknown> | null): void;
117
+ startSpan<T>(options: SpanOptions, callback: (span: ObserveSpan) => T | Promise<T>): T | Promise<T>;
118
+ trackScreen(name: string, params?: Record<string, unknown>): void;
119
+ beforeSend(callback: BeforeSend): void;
120
+ flush(): Promise<void>;
121
+ close(): Promise<void>;
122
+ readonly log: {
123
+ debug: (m: string, d?: Record<string, unknown>) => `${string}-${string}-${string}-${string}-${string}`;
124
+ info: (m: string, d?: Record<string, unknown>) => `${string}-${string}-${string}-${string}-${string}`;
125
+ warn: (m: string, d?: Record<string, unknown>) => `${string}-${string}-${string}-${string}-${string}`;
126
+ error: (m: string, d?: Record<string, unknown>) => `${string}-${string}-${string}-${string}-${string}`;
127
+ };
128
+ };
129
+
130
+ export { type BeforeSend, type Breadcrumb, type Level, type ObserveEvent, type ObserveSpan, type ObserveUser, SmartObserve, type SmartObserveConfig, SmartObserveExpoClient, type SpanOptions, type TraceContext };
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ import {
2
+ SmartObserve,
3
+ SmartObserveExpoClient
4
+ } from "./chunk-HNIEV66S.js";
5
+ export {
6
+ SmartObserve,
7
+ SmartObserveExpoClient
8
+ };
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/plugin.ts
21
+ var plugin_exports = {};
22
+ __export(plugin_exports, {
23
+ default: () => plugin_default,
24
+ uploadSourcemaps: () => uploadSourcemaps
25
+ });
26
+ module.exports = __toCommonJS(plugin_exports);
27
+ var import_config_plugins = require("@expo/config-plugins");
28
+
29
+ // src/upload-sourcemaps.ts
30
+ var import_promises = require("fs/promises");
31
+ var import_node_path = require("path");
32
+ async function uploadSourcemaps(projectRoot, options = {}) {
33
+ const token = process.env.SMARTOBSERVE_AUTH_TOKEN ?? process.env.SMARTOBSERVE_RELEASE_TOKEN;
34
+ if (!token) {
35
+ if (options.requireUpload) throw new Error("SMARTOBSERVE_AUTH_TOKEN is required to upload Expo source maps.");
36
+ return { uploaded: 0, skipped: "missing_token" };
37
+ }
38
+ const dsn = options.dsn ?? process.env.SMARTOBSERVE_DSN;
39
+ if (!dsn) {
40
+ if (options.requireUpload) throw new Error("SmartObserve DSN is required to upload Expo source maps.");
41
+ return { uploaded: 0, skipped: "missing_dsn" };
42
+ }
43
+ const parsed = new URL(dsn);
44
+ const endpoint = `${parsed.protocol}//${parsed.host}/api/v1/releases/artifacts`;
45
+ const release = options.release ?? process.env.SMARTOBSERVE_RELEASE ?? "unspecified";
46
+ const environment = options.environment ?? process.env.SMARTOBSERVE_ENVIRONMENT ?? "production";
47
+ const maps = await findMaps((0, import_node_path.join)(projectRoot, "dist"));
48
+ let uploaded = 0;
49
+ for (const file of maps) {
50
+ const body = await (0, import_promises.readFile)(file);
51
+ const response = await fetch(endpoint, {
52
+ method: "POST",
53
+ headers: {
54
+ "content-type": "application/json",
55
+ "x-smartobserve-release-token": token,
56
+ "x-environment": environment,
57
+ "x-release": release,
58
+ "x-file-size": String(body.byteLength)
59
+ },
60
+ body
61
+ });
62
+ if (!response.ok && options.requireUpload) throw new Error(`Source map upload failed with HTTP ${response.status}`);
63
+ if (response.ok) uploaded += 1;
64
+ }
65
+ await (0, import_promises.writeFile)((0, import_node_path.join)(projectRoot, ".smartobserve-expo.json"), JSON.stringify({ configured: true, requireUpload: options.requireUpload ?? false, uploaded, release, environment }, null, 2));
66
+ return { uploaded, skipped: uploaded ? "" : "no_maps" };
67
+ }
68
+ async function findMaps(root) {
69
+ try {
70
+ await (0, import_promises.stat)(root);
71
+ } catch {
72
+ return [];
73
+ }
74
+ const found = [];
75
+ const walk = async (dir) => {
76
+ for (const entry of await (0, import_promises.readdir)(dir, { withFileTypes: true })) {
77
+ const path = (0, import_node_path.join)(dir, entry.name);
78
+ if (entry.isDirectory()) await walk(path);
79
+ else if (entry.name.endsWith(".map")) found.push(path);
80
+ }
81
+ };
82
+ await walk(root);
83
+ return found;
84
+ }
85
+
86
+ // src/plugin.ts
87
+ var withSmartObserve = (config, options = {}) => {
88
+ config.extra = { ...config.extra, smartObserve: { dsn: options.dsn, environment: options.environment, release: options.release } };
89
+ return (0, import_config_plugins.withDangerousMod)(config, ["ios", async (value) => {
90
+ await uploadSourcemaps(value.modRequest.projectRoot, options);
91
+ return value;
92
+ }]);
93
+ };
94
+ var plugin_default = withSmartObserve;
95
+ // Annotate the CommonJS export names for ESM import in node:
96
+ 0 && (module.exports = {
97
+ uploadSourcemaps
98
+ });
99
+ //# sourceMappingURL=plugin.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/plugin.ts","../src/upload-sourcemaps.ts"],"sourcesContent":["import { type ConfigPlugin, withDangerousMod } from \"@expo/config-plugins\";\nimport { uploadSourcemaps, type SourcemapUploadOptions } from \"./upload-sourcemaps.js\";\n\nexport type SmartObservePluginOptions = SourcemapUploadOptions;\nexport { uploadSourcemaps };\n\nconst withSmartObserve: ConfigPlugin<SmartObservePluginOptions> = (config, options = {}) => {\n config.extra = { ...config.extra, smartObserve: { dsn: options.dsn, environment: options.environment, release: options.release } };\n return withDangerousMod(config, [\"ios\", async (value) => {\n await uploadSourcemaps(value.modRequest.projectRoot, options);\n return value;\n }]);\n};\n\nexport default withSmartObserve;\n","import { readdir, readFile, stat, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport interface SourcemapUploadOptions {\n dsn?: string;\n environment?: string;\n release?: string;\n requireUpload?: boolean;\n}\n\nexport async function uploadSourcemaps(projectRoot: string, options: SourcemapUploadOptions = {}): Promise<{ uploaded: number; skipped: string }> {\n const token = process.env.SMARTOBSERVE_AUTH_TOKEN ?? process.env.SMARTOBSERVE_RELEASE_TOKEN;\n if (!token) {\n if (options.requireUpload) throw new Error(\"SMARTOBSERVE_AUTH_TOKEN is required to upload Expo source maps.\");\n return { uploaded: 0, skipped: \"missing_token\" };\n }\n const dsn = options.dsn ?? process.env.SMARTOBSERVE_DSN;\n if (!dsn) {\n if (options.requireUpload) throw new Error(\"SmartObserve DSN is required to upload Expo source maps.\");\n return { uploaded: 0, skipped: \"missing_dsn\" };\n }\n const parsed = new URL(dsn);\n const endpoint = `${parsed.protocol}//${parsed.host}/api/v1/releases/artifacts`;\n const release = options.release ?? process.env.SMARTOBSERVE_RELEASE ?? \"unspecified\";\n const environment = options.environment ?? process.env.SMARTOBSERVE_ENVIRONMENT ?? \"production\";\n const maps = await findMaps(join(projectRoot, \"dist\"));\n let uploaded = 0;\n for (const file of maps) {\n const body = await readFile(file);\n const response = await fetch(endpoint, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"x-smartobserve-release-token\": token,\n \"x-environment\": environment,\n \"x-release\": release,\n \"x-file-size\": String(body.byteLength),\n },\n body,\n });\n if (!response.ok && options.requireUpload) throw new Error(`Source map upload failed with HTTP ${response.status}`);\n if (response.ok) uploaded += 1;\n }\n await writeFile(join(projectRoot, \".smartobserve-expo.json\"), JSON.stringify({ configured: true, requireUpload: options.requireUpload ?? false, uploaded, release, environment }, null, 2));\n return { uploaded, skipped: uploaded ? \"\" : \"no_maps\" };\n}\n\nasync function findMaps(root: string): Promise<string[]> {\n try { await stat(root); } catch { return []; }\n const found: string[] = [];\n const walk = async (dir: string) => {\n for (const entry of await readdir(dir, { withFileTypes: true })) {\n const path = join(dir, entry.name);\n if (entry.isDirectory()) await walk(path);\n else if (entry.name.endsWith(\".map\")) found.push(path);\n }\n };\n await walk(root);\n return found;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAAoD;;;ACApD,sBAAmD;AACnD,uBAAqB;AASrB,eAAsB,iBAAiB,aAAqB,UAAkC,CAAC,GAAmD;AAChJ,QAAM,QAAQ,QAAQ,IAAI,2BAA2B,QAAQ,IAAI;AACjE,MAAI,CAAC,OAAO;AACV,QAAI,QAAQ,cAAe,OAAM,IAAI,MAAM,iEAAiE;AAC5G,WAAO,EAAE,UAAU,GAAG,SAAS,gBAAgB;AAAA,EACjD;AACA,QAAM,MAAM,QAAQ,OAAO,QAAQ,IAAI;AACvC,MAAI,CAAC,KAAK;AACR,QAAI,QAAQ,cAAe,OAAM,IAAI,MAAM,0DAA0D;AACrG,WAAO,EAAE,UAAU,GAAG,SAAS,cAAc;AAAA,EAC/C;AACA,QAAM,SAAS,IAAI,IAAI,GAAG;AAC1B,QAAM,WAAW,GAAG,OAAO,QAAQ,KAAK,OAAO,IAAI;AACnD,QAAM,UAAU,QAAQ,WAAW,QAAQ,IAAI,wBAAwB;AACvE,QAAM,cAAc,QAAQ,eAAe,QAAQ,IAAI,4BAA4B;AACnF,QAAM,OAAO,MAAM,aAAS,uBAAK,aAAa,MAAM,CAAC;AACrD,MAAI,WAAW;AACf,aAAW,QAAQ,MAAM;AACvB,UAAM,OAAO,UAAM,0BAAS,IAAI;AAChC,UAAM,WAAW,MAAM,MAAM,UAAU;AAAA,MACrC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,gCAAgC;AAAA,QAChC,iBAAiB;AAAA,QACjB,aAAa;AAAA,QACb,eAAe,OAAO,KAAK,UAAU;AAAA,MACvC;AAAA,MACA;AAAA,IACF,CAAC;AACD,QAAI,CAAC,SAAS,MAAM,QAAQ,cAAe,OAAM,IAAI,MAAM,sCAAsC,SAAS,MAAM,EAAE;AAClH,QAAI,SAAS,GAAI,aAAY;AAAA,EAC/B;AACA,YAAM,+BAAU,uBAAK,aAAa,yBAAyB,GAAG,KAAK,UAAU,EAAE,YAAY,MAAM,eAAe,QAAQ,iBAAiB,OAAO,UAAU,SAAS,YAAY,GAAG,MAAM,CAAC,CAAC;AAC1L,SAAO,EAAE,UAAU,SAAS,WAAW,KAAK,UAAU;AACxD;AAEA,eAAe,SAAS,MAAiC;AACvD,MAAI;AAAE,cAAM,sBAAK,IAAI;AAAA,EAAG,QAAQ;AAAE,WAAO,CAAC;AAAA,EAAG;AAC7C,QAAM,QAAkB,CAAC;AACzB,QAAM,OAAO,OAAO,QAAgB;AAClC,eAAW,SAAS,UAAM,yBAAQ,KAAK,EAAE,eAAe,KAAK,CAAC,GAAG;AAC/D,YAAM,WAAO,uBAAK,KAAK,MAAM,IAAI;AACjC,UAAI,MAAM,YAAY,EAAG,OAAM,KAAK,IAAI;AAAA,eAC/B,MAAM,KAAK,SAAS,MAAM,EAAG,OAAM,KAAK,IAAI;AAAA,IACvD;AAAA,EACF;AACA,QAAM,KAAK,IAAI;AACf,SAAO;AACT;;;ADrDA,IAAM,mBAA4D,CAAC,QAAQ,UAAU,CAAC,MAAM;AAC1F,SAAO,QAAQ,EAAE,GAAG,OAAO,OAAO,cAAc,EAAE,KAAK,QAAQ,KAAK,aAAa,QAAQ,aAAa,SAAS,QAAQ,QAAQ,EAAE;AACjI,aAAO,wCAAiB,QAAQ,CAAC,OAAO,OAAO,UAAU;AACvD,UAAM,iBAAiB,MAAM,WAAW,aAAa,OAAO;AAC5D,WAAO;AAAA,EACT,CAAC,CAAC;AACJ;AAEA,IAAO,iBAAQ;","names":[]}
@@ -0,0 +1,18 @@
1
+ import { ConfigPlugin } from '@expo/config-plugins';
2
+
3
+ interface SourcemapUploadOptions {
4
+ dsn?: string;
5
+ environment?: string;
6
+ release?: string;
7
+ requireUpload?: boolean;
8
+ }
9
+ declare function uploadSourcemaps(projectRoot: string, options?: SourcemapUploadOptions): Promise<{
10
+ uploaded: number;
11
+ skipped: string;
12
+ }>;
13
+
14
+ type SmartObservePluginOptions = SourcemapUploadOptions;
15
+
16
+ declare const withSmartObserve: ConfigPlugin<SmartObservePluginOptions>;
17
+
18
+ export { type SmartObservePluginOptions, withSmartObserve as default, uploadSourcemaps };
@@ -0,0 +1,18 @@
1
+ import { ConfigPlugin } from '@expo/config-plugins';
2
+
3
+ interface SourcemapUploadOptions {
4
+ dsn?: string;
5
+ environment?: string;
6
+ release?: string;
7
+ requireUpload?: boolean;
8
+ }
9
+ declare function uploadSourcemaps(projectRoot: string, options?: SourcemapUploadOptions): Promise<{
10
+ uploaded: number;
11
+ skipped: string;
12
+ }>;
13
+
14
+ type SmartObservePluginOptions = SourcemapUploadOptions;
15
+
16
+ declare const withSmartObserve: ConfigPlugin<SmartObservePluginOptions>;
17
+
18
+ export { type SmartObservePluginOptions, withSmartObserve as default, uploadSourcemaps };
package/dist/plugin.js ADDED
@@ -0,0 +1,74 @@
1
+ // src/plugin.ts
2
+ import { withDangerousMod } from "@expo/config-plugins";
3
+
4
+ // src/upload-sourcemaps.ts
5
+ import { readdir, readFile, stat, writeFile } from "fs/promises";
6
+ import { join } from "path";
7
+ async function uploadSourcemaps(projectRoot, options = {}) {
8
+ const token = process.env.SMARTOBSERVE_AUTH_TOKEN ?? process.env.SMARTOBSERVE_RELEASE_TOKEN;
9
+ if (!token) {
10
+ if (options.requireUpload) throw new Error("SMARTOBSERVE_AUTH_TOKEN is required to upload Expo source maps.");
11
+ return { uploaded: 0, skipped: "missing_token" };
12
+ }
13
+ const dsn = options.dsn ?? process.env.SMARTOBSERVE_DSN;
14
+ if (!dsn) {
15
+ if (options.requireUpload) throw new Error("SmartObserve DSN is required to upload Expo source maps.");
16
+ return { uploaded: 0, skipped: "missing_dsn" };
17
+ }
18
+ const parsed = new URL(dsn);
19
+ const endpoint = `${parsed.protocol}//${parsed.host}/api/v1/releases/artifacts`;
20
+ const release = options.release ?? process.env.SMARTOBSERVE_RELEASE ?? "unspecified";
21
+ const environment = options.environment ?? process.env.SMARTOBSERVE_ENVIRONMENT ?? "production";
22
+ const maps = await findMaps(join(projectRoot, "dist"));
23
+ let uploaded = 0;
24
+ for (const file of maps) {
25
+ const body = await readFile(file);
26
+ const response = await fetch(endpoint, {
27
+ method: "POST",
28
+ headers: {
29
+ "content-type": "application/json",
30
+ "x-smartobserve-release-token": token,
31
+ "x-environment": environment,
32
+ "x-release": release,
33
+ "x-file-size": String(body.byteLength)
34
+ },
35
+ body
36
+ });
37
+ if (!response.ok && options.requireUpload) throw new Error(`Source map upload failed with HTTP ${response.status}`);
38
+ if (response.ok) uploaded += 1;
39
+ }
40
+ await writeFile(join(projectRoot, ".smartobserve-expo.json"), JSON.stringify({ configured: true, requireUpload: options.requireUpload ?? false, uploaded, release, environment }, null, 2));
41
+ return { uploaded, skipped: uploaded ? "" : "no_maps" };
42
+ }
43
+ async function findMaps(root) {
44
+ try {
45
+ await stat(root);
46
+ } catch {
47
+ return [];
48
+ }
49
+ const found = [];
50
+ const walk = async (dir) => {
51
+ for (const entry of await readdir(dir, { withFileTypes: true })) {
52
+ const path = join(dir, entry.name);
53
+ if (entry.isDirectory()) await walk(path);
54
+ else if (entry.name.endsWith(".map")) found.push(path);
55
+ }
56
+ };
57
+ await walk(root);
58
+ return found;
59
+ }
60
+
61
+ // src/plugin.ts
62
+ var withSmartObserve = (config, options = {}) => {
63
+ config.extra = { ...config.extra, smartObserve: { dsn: options.dsn, environment: options.environment, release: options.release } };
64
+ return withDangerousMod(config, ["ios", async (value) => {
65
+ await uploadSourcemaps(value.modRequest.projectRoot, options);
66
+ return value;
67
+ }]);
68
+ };
69
+ var plugin_default = withSmartObserve;
70
+ export {
71
+ plugin_default as default,
72
+ uploadSourcemaps
73
+ };
74
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/plugin.ts","../src/upload-sourcemaps.ts"],"sourcesContent":["import { type ConfigPlugin, withDangerousMod } from \"@expo/config-plugins\";\nimport { uploadSourcemaps, type SourcemapUploadOptions } from \"./upload-sourcemaps.js\";\n\nexport type SmartObservePluginOptions = SourcemapUploadOptions;\nexport { uploadSourcemaps };\n\nconst withSmartObserve: ConfigPlugin<SmartObservePluginOptions> = (config, options = {}) => {\n config.extra = { ...config.extra, smartObserve: { dsn: options.dsn, environment: options.environment, release: options.release } };\n return withDangerousMod(config, [\"ios\", async (value) => {\n await uploadSourcemaps(value.modRequest.projectRoot, options);\n return value;\n }]);\n};\n\nexport default withSmartObserve;\n","import { readdir, readFile, stat, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport interface SourcemapUploadOptions {\n dsn?: string;\n environment?: string;\n release?: string;\n requireUpload?: boolean;\n}\n\nexport async function uploadSourcemaps(projectRoot: string, options: SourcemapUploadOptions = {}): Promise<{ uploaded: number; skipped: string }> {\n const token = process.env.SMARTOBSERVE_AUTH_TOKEN ?? process.env.SMARTOBSERVE_RELEASE_TOKEN;\n if (!token) {\n if (options.requireUpload) throw new Error(\"SMARTOBSERVE_AUTH_TOKEN is required to upload Expo source maps.\");\n return { uploaded: 0, skipped: \"missing_token\" };\n }\n const dsn = options.dsn ?? process.env.SMARTOBSERVE_DSN;\n if (!dsn) {\n if (options.requireUpload) throw new Error(\"SmartObserve DSN is required to upload Expo source maps.\");\n return { uploaded: 0, skipped: \"missing_dsn\" };\n }\n const parsed = new URL(dsn);\n const endpoint = `${parsed.protocol}//${parsed.host}/api/v1/releases/artifacts`;\n const release = options.release ?? process.env.SMARTOBSERVE_RELEASE ?? \"unspecified\";\n const environment = options.environment ?? process.env.SMARTOBSERVE_ENVIRONMENT ?? \"production\";\n const maps = await findMaps(join(projectRoot, \"dist\"));\n let uploaded = 0;\n for (const file of maps) {\n const body = await readFile(file);\n const response = await fetch(endpoint, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n \"x-smartobserve-release-token\": token,\n \"x-environment\": environment,\n \"x-release\": release,\n \"x-file-size\": String(body.byteLength),\n },\n body,\n });\n if (!response.ok && options.requireUpload) throw new Error(`Source map upload failed with HTTP ${response.status}`);\n if (response.ok) uploaded += 1;\n }\n await writeFile(join(projectRoot, \".smartobserve-expo.json\"), JSON.stringify({ configured: true, requireUpload: options.requireUpload ?? false, uploaded, release, environment }, null, 2));\n return { uploaded, skipped: uploaded ? \"\" : \"no_maps\" };\n}\n\nasync function findMaps(root: string): Promise<string[]> {\n try { await stat(root); } catch { return []; }\n const found: string[] = [];\n const walk = async (dir: string) => {\n for (const entry of await readdir(dir, { withFileTypes: true })) {\n const path = join(dir, entry.name);\n if (entry.isDirectory()) await walk(path);\n else if (entry.name.endsWith(\".map\")) found.push(path);\n }\n };\n await walk(root);\n return found;\n}\n"],"mappings":";AAAA,SAA4B,wBAAwB;;;ACApD,SAAS,SAAS,UAAU,MAAM,iBAAiB;AACnD,SAAS,YAAY;AASrB,eAAsB,iBAAiB,aAAqB,UAAkC,CAAC,GAAmD;AAChJ,QAAM,QAAQ,QAAQ,IAAI,2BAA2B,QAAQ,IAAI;AACjE,MAAI,CAAC,OAAO;AACV,QAAI,QAAQ,cAAe,OAAM,IAAI,MAAM,iEAAiE;AAC5G,WAAO,EAAE,UAAU,GAAG,SAAS,gBAAgB;AAAA,EACjD;AACA,QAAM,MAAM,QAAQ,OAAO,QAAQ,IAAI;AACvC,MAAI,CAAC,KAAK;AACR,QAAI,QAAQ,cAAe,OAAM,IAAI,MAAM,0DAA0D;AACrG,WAAO,EAAE,UAAU,GAAG,SAAS,cAAc;AAAA,EAC/C;AACA,QAAM,SAAS,IAAI,IAAI,GAAG;AAC1B,QAAM,WAAW,GAAG,OAAO,QAAQ,KAAK,OAAO,IAAI;AACnD,QAAM,UAAU,QAAQ,WAAW,QAAQ,IAAI,wBAAwB;AACvE,QAAM,cAAc,QAAQ,eAAe,QAAQ,IAAI,4BAA4B;AACnF,QAAM,OAAO,MAAM,SAAS,KAAK,aAAa,MAAM,CAAC;AACrD,MAAI,WAAW;AACf,aAAW,QAAQ,MAAM;AACvB,UAAM,OAAO,MAAM,SAAS,IAAI;AAChC,UAAM,WAAW,MAAM,MAAM,UAAU;AAAA,MACrC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,gCAAgC;AAAA,QAChC,iBAAiB;AAAA,QACjB,aAAa;AAAA,QACb,eAAe,OAAO,KAAK,UAAU;AAAA,MACvC;AAAA,MACA;AAAA,IACF,CAAC;AACD,QAAI,CAAC,SAAS,MAAM,QAAQ,cAAe,OAAM,IAAI,MAAM,sCAAsC,SAAS,MAAM,EAAE;AAClH,QAAI,SAAS,GAAI,aAAY;AAAA,EAC/B;AACA,QAAM,UAAU,KAAK,aAAa,yBAAyB,GAAG,KAAK,UAAU,EAAE,YAAY,MAAM,eAAe,QAAQ,iBAAiB,OAAO,UAAU,SAAS,YAAY,GAAG,MAAM,CAAC,CAAC;AAC1L,SAAO,EAAE,UAAU,SAAS,WAAW,KAAK,UAAU;AACxD;AAEA,eAAe,SAAS,MAAiC;AACvD,MAAI;AAAE,UAAM,KAAK,IAAI;AAAA,EAAG,QAAQ;AAAE,WAAO,CAAC;AAAA,EAAG;AAC7C,QAAM,QAAkB,CAAC;AACzB,QAAM,OAAO,OAAO,QAAgB;AAClC,eAAW,SAAS,MAAM,QAAQ,KAAK,EAAE,eAAe,KAAK,CAAC,GAAG;AAC/D,YAAM,OAAO,KAAK,KAAK,MAAM,IAAI;AACjC,UAAI,MAAM,YAAY,EAAG,OAAM,KAAK,IAAI;AAAA,eAC/B,MAAM,KAAK,SAAS,MAAM,EAAG,OAAM,KAAK,IAAI;AAAA,IACvD;AAAA,EACF;AACA,QAAM,KAAK,IAAI;AACf,SAAO;AACT;;;ADrDA,IAAM,mBAA4D,CAAC,QAAQ,UAAU,CAAC,MAAM;AAC1F,SAAO,QAAQ,EAAE,GAAG,OAAO,OAAO,cAAc,EAAE,KAAK,QAAQ,KAAK,aAAa,QAAQ,aAAa,SAAS,QAAQ,QAAQ,EAAE;AACjI,SAAO,iBAAiB,QAAQ,CAAC,OAAO,OAAO,UAAU;AACvD,UAAM,iBAAiB,MAAM,WAAW,aAAa,OAAO;AAC5D,WAAO;AAAA,EACT,CAAC,CAAC;AACJ;AAEA,IAAO,iBAAQ;","names":[]}