@nextop-os/browser-node 0.0.8

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.
package/README.md ADDED
@@ -0,0 +1,18 @@
1
+ # @nextop-os/browser-node
2
+
3
+ Reusable Workbench Browser Node capability for Electron desktop hosts.
4
+
5
+ The package owns browser-node mechanics such as URL normalization, session
6
+ partitioning, renderer state, React surfaces, webview security, and Electron
7
+ guest lifecycle coordination. Product hosts own business bridge methods,
8
+ diagnostics policy, preview route policy, and daemon or server clients.
9
+
10
+ The first version supports ordinary HTTP and HTTPS browser navigation. Runtime
11
+ preview proxy interfaces are present for host integration but are intentionally
12
+ inert until a later phase.
13
+
14
+ For Workbench hosts, the package also exposes a dock helper through
15
+ `@nextop-os/browser-node/workbench`. `createBrowserDockEntry(...)` wires the
16
+ default Browser dock icon and label, matches Browser nodes back to the dock
17
+ entry, and restores popup title, URL subtitle, and preview capture from the
18
+ Browser runtime state.
@@ -0,0 +1,15 @@
1
+ import { f as BrowserNodeBridgeResult, d as BrowserNodeBridgeMeta, e as BrowserNodeBridgeMethodDescriptor, b as BrowserNodeBridgeCallable, B as BrowserNodeBridgeApiTree } from '../types-Bmzz1Q84.js';
2
+ export { a as BrowserNodeBridgeCallPayload, c as BrowserNodeBridgeError } from '../types-Bmzz1Q84.js';
3
+
4
+ declare function buildBrowserNodeBridgeApiTree({ call, currentUrl, meta, methods, namespace, wrapCallable }: {
5
+ call: (method: string, args: unknown) => Promise<BrowserNodeBridgeResult<unknown>>;
6
+ currentUrl: string;
7
+ meta?: BrowserNodeBridgeMeta;
8
+ methods: readonly BrowserNodeBridgeMethodDescriptor[];
9
+ namespace: string;
10
+ wrapCallable?: (methodName: string, callable: BrowserNodeBridgeCallable) => BrowserNodeBridgeCallable;
11
+ }): BrowserNodeBridgeApiTree;
12
+
13
+ declare function isBrowserNodeBridgeHostAllowed(url: string, hostPatterns: readonly string[]): boolean;
14
+
15
+ export { BrowserNodeBridgeApiTree, BrowserNodeBridgeCallable, BrowserNodeBridgeMeta, BrowserNodeBridgeMethodDescriptor, BrowserNodeBridgeResult, buildBrowserNodeBridgeApiTree, isBrowserNodeBridgeHostAllowed };
@@ -0,0 +1,9 @@
1
+ import {
2
+ buildBrowserNodeBridgeApiTree,
3
+ isBrowserNodeBridgeHostAllowed
4
+ } from "../chunk-IO5AJ2R5.js";
5
+ export {
6
+ buildBrowserNodeBridgeApiTree,
7
+ isBrowserNodeBridgeHostAllowed
8
+ };
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,66 @@
1
+ // src/core/url.ts
2
+ var allowedBrowserProtocols = /* @__PURE__ */ new Set(["http:", "https:"]);
3
+ var likelyHostPattern = /^(localhost|(\d{1,3}\.){3}\d{1,3}|(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,})(?::\d{1,5})?(?:[/?#][^\s]*)?$/i;
4
+ var explicitProtocolPattern = /^[a-zA-Z][a-zA-Z\d+\-.]*:\/\//;
5
+ var loopbackHostPattern = /^(localhost|127(?:\.\d{1,3}){3})(?::\d{1,5})?(?:[/?#][^\s]*)?$/i;
6
+ function defaultSchemeForHostInput(value) {
7
+ return loopbackHostPattern.test(value) ? "http" : "https";
8
+ }
9
+ function resolveBrowserNavigationUrl(rawUrl) {
10
+ const trimmed = rawUrl.trim();
11
+ if (trimmed.length === 0) {
12
+ return { errorCode: null, url: null };
13
+ }
14
+ if (explicitProtocolPattern.test(trimmed)) {
15
+ try {
16
+ const parsed = new URL(trimmed);
17
+ if (!allowedBrowserProtocols.has(parsed.protocol)) {
18
+ return {
19
+ errorCode: "unsupported-protocol",
20
+ errorParams: { protocol: parsed.protocol },
21
+ url: null
22
+ };
23
+ }
24
+ return { errorCode: null, url: parsed.toString() };
25
+ } catch {
26
+ return { errorCode: "invalid-url", url: null };
27
+ }
28
+ }
29
+ if (!likelyHostPattern.test(trimmed)) {
30
+ return { errorCode: "invalid-url", url: null };
31
+ }
32
+ try {
33
+ const parsed = new URL(
34
+ `${defaultSchemeForHostInput(trimmed)}://${trimmed}`
35
+ );
36
+ return { errorCode: null, url: parsed.toString() };
37
+ } catch {
38
+ return { errorCode: "invalid-url", url: null };
39
+ }
40
+ }
41
+ function resolveBrowserAddressInput(rawInput, options = {}) {
42
+ const trimmed = rawInput.trim();
43
+ if (trimmed.length === 0) {
44
+ return { errorCode: null, url: null };
45
+ }
46
+ const navigation = resolveBrowserNavigationUrl(trimmed);
47
+ if (navigation.url) {
48
+ return navigation;
49
+ }
50
+ const searchUrl = options.resolveSearchUrl?.(trimmed);
51
+ if (!searchUrl) {
52
+ return navigation;
53
+ }
54
+ return resolveBrowserNavigationUrl(searchUrl);
55
+ }
56
+ function normalizeBrowserComparableUrl(rawUrl) {
57
+ const resolved = resolveBrowserNavigationUrl(rawUrl);
58
+ return resolved.errorCode === null ? resolved.url : null;
59
+ }
60
+
61
+ export {
62
+ resolveBrowserNavigationUrl,
63
+ resolveBrowserAddressInput,
64
+ normalizeBrowserComparableUrl
65
+ };
66
+ //# sourceMappingURL=chunk-2ZAMKGGP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/url.ts"],"sourcesContent":["const allowedBrowserProtocols = new Set([\"http:\", \"https:\"]);\nconst likelyHostPattern =\n /^(localhost|(\\d{1,3}\\.){3}\\d{1,3}|(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,})(?::\\d{1,5})?(?:[/?#][^\\s]*)?$/i;\nconst explicitProtocolPattern = /^[a-zA-Z][a-zA-Z\\d+\\-.]*:\\/\\//;\nconst loopbackHostPattern =\n /^(localhost|127(?:\\.\\d{1,3}){3})(?::\\d{1,5})?(?:[/?#][^\\s]*)?$/i;\n\nfunction defaultSchemeForHostInput(value: string): \"http\" | \"https\" {\n return loopbackHostPattern.test(value) ? \"http\" : \"https\";\n}\n\nexport type BrowserNavigationUrlErrorCode =\n | \"invalid-url\"\n | \"unsupported-protocol\";\n\nexport interface BrowserNavigationUrlResolution {\n errorCode: BrowserNavigationUrlErrorCode | null;\n errorParams?: Record<string, string>;\n url: string | null;\n}\n\nexport type BrowserSearchUrlResolver = (query: string) => string | null;\n\nexport function resolveBrowserNavigationUrl(\n rawUrl: string\n): BrowserNavigationUrlResolution {\n const trimmed = rawUrl.trim();\n if (trimmed.length === 0) {\n return { errorCode: null, url: null };\n }\n\n if (explicitProtocolPattern.test(trimmed)) {\n try {\n const parsed = new URL(trimmed);\n if (!allowedBrowserProtocols.has(parsed.protocol)) {\n return {\n errorCode: \"unsupported-protocol\",\n errorParams: { protocol: parsed.protocol },\n url: null\n };\n }\n\n return { errorCode: null, url: parsed.toString() };\n } catch {\n return { errorCode: \"invalid-url\", url: null };\n }\n }\n\n if (!likelyHostPattern.test(trimmed)) {\n return { errorCode: \"invalid-url\", url: null };\n }\n\n try {\n const parsed = new URL(\n `${defaultSchemeForHostInput(trimmed)}://${trimmed}`\n );\n return { errorCode: null, url: parsed.toString() };\n } catch {\n return { errorCode: \"invalid-url\", url: null };\n }\n}\n\nexport type BrowserAddressInputResolution = BrowserNavigationUrlResolution;\n\nexport function resolveBrowserAddressInput(\n rawInput: string,\n options: {\n resolveSearchUrl?: BrowserSearchUrlResolver;\n } = {}\n): BrowserAddressInputResolution {\n const trimmed = rawInput.trim();\n if (trimmed.length === 0) {\n return { errorCode: null, url: null };\n }\n\n const navigation = resolveBrowserNavigationUrl(trimmed);\n if (navigation.url) {\n return navigation;\n }\n\n const searchUrl = options.resolveSearchUrl?.(trimmed);\n if (!searchUrl) {\n return navigation;\n }\n\n return resolveBrowserNavigationUrl(searchUrl);\n}\n\nexport function normalizeBrowserComparableUrl(rawUrl: string): string | null {\n const resolved = resolveBrowserNavigationUrl(rawUrl);\n return resolved.errorCode === null ? resolved.url : null;\n}\n"],"mappings":";AAAA,IAAM,0BAA0B,oBAAI,IAAI,CAAC,SAAS,QAAQ,CAAC;AAC3D,IAAM,oBACJ;AACF,IAAM,0BAA0B;AAChC,IAAM,sBACJ;AAEF,SAAS,0BAA0B,OAAiC;AAClE,SAAO,oBAAoB,KAAK,KAAK,IAAI,SAAS;AACpD;AAcO,SAAS,4BACd,QACgC;AAChC,QAAM,UAAU,OAAO,KAAK;AAC5B,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO,EAAE,WAAW,MAAM,KAAK,KAAK;AAAA,EACtC;AAEA,MAAI,wBAAwB,KAAK,OAAO,GAAG;AACzC,QAAI;AACF,YAAM,SAAS,IAAI,IAAI,OAAO;AAC9B,UAAI,CAAC,wBAAwB,IAAI,OAAO,QAAQ,GAAG;AACjD,eAAO;AAAA,UACL,WAAW;AAAA,UACX,aAAa,EAAE,UAAU,OAAO,SAAS;AAAA,UACzC,KAAK;AAAA,QACP;AAAA,MACF;AAEA,aAAO,EAAE,WAAW,MAAM,KAAK,OAAO,SAAS,EAAE;AAAA,IACnD,QAAQ;AACN,aAAO,EAAE,WAAW,eAAe,KAAK,KAAK;AAAA,IAC/C;AAAA,EACF;AAEA,MAAI,CAAC,kBAAkB,KAAK,OAAO,GAAG;AACpC,WAAO,EAAE,WAAW,eAAe,KAAK,KAAK;AAAA,EAC/C;AAEA,MAAI;AACF,UAAM,SAAS,IAAI;AAAA,MACjB,GAAG,0BAA0B,OAAO,CAAC,MAAM,OAAO;AAAA,IACpD;AACA,WAAO,EAAE,WAAW,MAAM,KAAK,OAAO,SAAS,EAAE;AAAA,EACnD,QAAQ;AACN,WAAO,EAAE,WAAW,eAAe,KAAK,KAAK;AAAA,EAC/C;AACF;AAIO,SAAS,2BACd,UACA,UAEI,CAAC,GAC0B;AAC/B,QAAM,UAAU,SAAS,KAAK;AAC9B,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO,EAAE,WAAW,MAAM,KAAK,KAAK;AAAA,EACtC;AAEA,QAAM,aAAa,4BAA4B,OAAO;AACtD,MAAI,WAAW,KAAK;AAClB,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,QAAQ,mBAAmB,OAAO;AACpD,MAAI,CAAC,WAAW;AACd,WAAO;AAAA,EACT;AAEA,SAAO,4BAA4B,SAAS;AAC9C;AAEO,SAAS,8BAA8B,QAA+B;AAC3E,QAAM,WAAW,4BAA4B,MAAM;AACnD,SAAO,SAAS,cAAc,OAAO,SAAS,MAAM;AACtD;","names":[]}
@@ -0,0 +1,111 @@
1
+ // src/bridge/hostPolicy.ts
2
+ function normalizeHostPattern(pattern) {
3
+ const trimmed = pattern.trim().toLowerCase();
4
+ return trimmed.length > 0 ? trimmed : null;
5
+ }
6
+ function matchesHostPattern(host, pattern) {
7
+ const normalizedPattern = normalizeHostPattern(pattern);
8
+ if (!normalizedPattern) {
9
+ return false;
10
+ }
11
+ if (normalizedPattern === "*") {
12
+ return true;
13
+ }
14
+ if (normalizedPattern.startsWith("*.")) {
15
+ const suffix = normalizedPattern.slice(1);
16
+ return host.endsWith(suffix) && host.length > suffix.length;
17
+ }
18
+ if (normalizedPattern.endsWith(".*")) {
19
+ return host.startsWith(normalizedPattern.slice(0, -1));
20
+ }
21
+ return host === normalizedPattern;
22
+ }
23
+ function isBrowserNodeBridgeHostAllowed(url, hostPatterns) {
24
+ let parsed;
25
+ try {
26
+ parsed = new URL(url);
27
+ } catch {
28
+ return false;
29
+ }
30
+ const host = parsed.hostname.trim().toLowerCase();
31
+ if (host.length === 0) {
32
+ return false;
33
+ }
34
+ return hostPatterns.some((pattern) => matchesHostPattern(host, pattern));
35
+ }
36
+
37
+ // src/bridge/buildApiTree.ts
38
+ var reservedBridgeSegments = /* @__PURE__ */ new Set([
39
+ "__proto__",
40
+ "constructor",
41
+ "prototype"
42
+ ]);
43
+ var safeBridgePropertyPattern = /^[A-Za-z_$][\w$-]*$/;
44
+ function createBridgeBranch() {
45
+ return /* @__PURE__ */ Object.create(null);
46
+ }
47
+ function assertSafeBridgeSegment(segment) {
48
+ if (reservedBridgeSegments.has(segment) || !safeBridgePropertyPattern.test(segment)) {
49
+ throw new Error(`Unsafe Browser Node bridge path segment: ${segment}`);
50
+ }
51
+ }
52
+ function ensureBranch(root, keys) {
53
+ let cursor = root;
54
+ for (const key of keys) {
55
+ assertSafeBridgeSegment(key);
56
+ if (!cursor[key] || typeof cursor[key] !== "object") {
57
+ cursor[key] = createBridgeBranch();
58
+ }
59
+ cursor = cursor[key];
60
+ }
61
+ return cursor;
62
+ }
63
+ function assignMethod({
64
+ call,
65
+ method,
66
+ root,
67
+ wrapCallable
68
+ }) {
69
+ const parts = method.name.split(".").map((part) => part.trim()).filter(Boolean);
70
+ if (parts.length === 0) {
71
+ return;
72
+ }
73
+ const methodName = parts.join(".");
74
+ const leaf = parts.pop();
75
+ if (!leaf) {
76
+ return;
77
+ }
78
+ assertSafeBridgeSegment(leaf);
79
+ const branch = ensureBranch(root, parts);
80
+ const callable = async (args) => await call(methodName, args ?? null);
81
+ branch[leaf] = wrapCallable ? wrapCallable(methodName, callable) : callable;
82
+ }
83
+ function buildBrowserNodeBridgeApiTree({
84
+ call,
85
+ currentUrl,
86
+ meta,
87
+ methods,
88
+ namespace,
89
+ wrapCallable
90
+ }) {
91
+ const normalizedNamespace = namespace.trim();
92
+ if (normalizedNamespace.length === 0) {
93
+ throw new Error("Browser Node bridge namespace is required");
94
+ }
95
+ assertSafeBridgeSegment(normalizedNamespace);
96
+ const api = createBridgeBranch();
97
+ api.meta = meta ?? { runtime: "electron", version: "1" };
98
+ for (const method of methods) {
99
+ if (!isBrowserNodeBridgeHostAllowed(currentUrl, method.hostPatterns)) {
100
+ continue;
101
+ }
102
+ assignMethod({ call, method, root: api, wrapCallable });
103
+ }
104
+ return api;
105
+ }
106
+
107
+ export {
108
+ isBrowserNodeBridgeHostAllowed,
109
+ buildBrowserNodeBridgeApiTree
110
+ };
111
+ //# sourceMappingURL=chunk-IO5AJ2R5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/bridge/hostPolicy.ts","../src/bridge/buildApiTree.ts"],"sourcesContent":["function normalizeHostPattern(pattern: string): string | null {\n const trimmed = pattern.trim().toLowerCase();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction matchesHostPattern(host: string, pattern: string): boolean {\n const normalizedPattern = normalizeHostPattern(pattern);\n if (!normalizedPattern) {\n return false;\n }\n\n if (normalizedPattern === \"*\") {\n return true;\n }\n\n if (normalizedPattern.startsWith(\"*.\")) {\n const suffix = normalizedPattern.slice(1);\n return host.endsWith(suffix) && host.length > suffix.length;\n }\n\n if (normalizedPattern.endsWith(\".*\")) {\n return host.startsWith(normalizedPattern.slice(0, -1));\n }\n\n return host === normalizedPattern;\n}\n\nexport function isBrowserNodeBridgeHostAllowed(\n url: string,\n hostPatterns: readonly string[]\n): boolean {\n let parsed: URL;\n\n try {\n parsed = new URL(url);\n } catch {\n return false;\n }\n\n const host = parsed.hostname.trim().toLowerCase();\n if (host.length === 0) {\n return false;\n }\n\n return hostPatterns.some((pattern) => matchesHostPattern(host, pattern));\n}\n","import { isBrowserNodeBridgeHostAllowed } from \"./hostPolicy.ts\";\nimport type {\n BrowserNodeBridgeApiTree,\n BrowserNodeBridgeCallable,\n BrowserNodeBridgeMeta,\n BrowserNodeBridgeMethodDescriptor,\n BrowserNodeBridgeResult\n} from \"./types.ts\";\n\ntype BridgeBranch = Record<string, unknown>;\nconst reservedBridgeSegments = new Set([\n \"__proto__\",\n \"constructor\",\n \"prototype\"\n]);\nconst safeBridgePropertyPattern = /^[A-Za-z_$][\\w$-]*$/;\n\nfunction createBridgeBranch(): BridgeBranch {\n return Object.create(null) as BridgeBranch;\n}\n\nfunction assertSafeBridgeSegment(segment: string): void {\n if (\n reservedBridgeSegments.has(segment) ||\n !safeBridgePropertyPattern.test(segment)\n ) {\n throw new Error(`Unsafe Browser Node bridge path segment: ${segment}`);\n }\n}\n\nfunction ensureBranch(root: BridgeBranch, keys: string[]): BridgeBranch {\n let cursor = root;\n for (const key of keys) {\n assertSafeBridgeSegment(key);\n if (!cursor[key] || typeof cursor[key] !== \"object\") {\n cursor[key] = createBridgeBranch();\n }\n cursor = cursor[key] as BridgeBranch;\n }\n return cursor;\n}\n\nfunction assignMethod({\n call,\n method,\n root,\n wrapCallable\n}: {\n call: (\n method: string,\n args: unknown\n ) => Promise<BrowserNodeBridgeResult<unknown>>;\n method: BrowserNodeBridgeMethodDescriptor;\n root: BridgeBranch;\n wrapCallable?: (\n methodName: string,\n callable: BrowserNodeBridgeCallable\n ) => BrowserNodeBridgeCallable;\n}): void {\n const parts = method.name\n .split(\".\")\n .map((part) => part.trim())\n .filter(Boolean);\n if (parts.length === 0) {\n return;\n }\n\n const methodName = parts.join(\".\");\n const leaf = parts.pop();\n if (!leaf) {\n return;\n }\n assertSafeBridgeSegment(leaf);\n\n const branch = ensureBranch(root, parts);\n const callable: BrowserNodeBridgeCallable = async (args?: unknown) =>\n await call(methodName, args ?? null);\n branch[leaf] = wrapCallable ? wrapCallable(methodName, callable) : callable;\n}\n\nexport function buildBrowserNodeBridgeApiTree({\n call,\n currentUrl,\n meta,\n methods,\n namespace,\n wrapCallable\n}: {\n call: (\n method: string,\n args: unknown\n ) => Promise<BrowserNodeBridgeResult<unknown>>;\n currentUrl: string;\n meta?: BrowserNodeBridgeMeta;\n methods: readonly BrowserNodeBridgeMethodDescriptor[];\n namespace: string;\n wrapCallable?: (\n methodName: string,\n callable: BrowserNodeBridgeCallable\n ) => BrowserNodeBridgeCallable;\n}): BrowserNodeBridgeApiTree {\n const normalizedNamespace = namespace.trim();\n if (normalizedNamespace.length === 0) {\n throw new Error(\"Browser Node bridge namespace is required\");\n }\n assertSafeBridgeSegment(normalizedNamespace);\n\n const api: BridgeBranch = createBridgeBranch();\n api.meta = meta ?? { runtime: \"electron\", version: \"1\" };\n\n for (const method of methods) {\n if (!isBrowserNodeBridgeHostAllowed(currentUrl, method.hostPatterns)) {\n continue;\n }\n assignMethod({ call, method, root: api, wrapCallable });\n }\n\n return api as BrowserNodeBridgeApiTree;\n}\n"],"mappings":";AAAA,SAAS,qBAAqB,SAAgC;AAC5D,QAAM,UAAU,QAAQ,KAAK,EAAE,YAAY;AAC3C,SAAO,QAAQ,SAAS,IAAI,UAAU;AACxC;AAEA,SAAS,mBAAmB,MAAc,SAA0B;AAClE,QAAM,oBAAoB,qBAAqB,OAAO;AACtD,MAAI,CAAC,mBAAmB;AACtB,WAAO;AAAA,EACT;AAEA,MAAI,sBAAsB,KAAK;AAC7B,WAAO;AAAA,EACT;AAEA,MAAI,kBAAkB,WAAW,IAAI,GAAG;AACtC,UAAM,SAAS,kBAAkB,MAAM,CAAC;AACxC,WAAO,KAAK,SAAS,MAAM,KAAK,KAAK,SAAS,OAAO;AAAA,EACvD;AAEA,MAAI,kBAAkB,SAAS,IAAI,GAAG;AACpC,WAAO,KAAK,WAAW,kBAAkB,MAAM,GAAG,EAAE,CAAC;AAAA,EACvD;AAEA,SAAO,SAAS;AAClB;AAEO,SAAS,+BACd,KACA,cACS;AACT,MAAI;AAEJ,MAAI;AACF,aAAS,IAAI,IAAI,GAAG;AAAA,EACtB,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,OAAO,SAAS,KAAK,EAAE,YAAY;AAChD,MAAI,KAAK,WAAW,GAAG;AACrB,WAAO;AAAA,EACT;AAEA,SAAO,aAAa,KAAK,CAAC,YAAY,mBAAmB,MAAM,OAAO,CAAC;AACzE;;;ACnCA,IAAM,yBAAyB,oBAAI,IAAI;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACD,IAAM,4BAA4B;AAElC,SAAS,qBAAmC;AAC1C,SAAO,uBAAO,OAAO,IAAI;AAC3B;AAEA,SAAS,wBAAwB,SAAuB;AACtD,MACE,uBAAuB,IAAI,OAAO,KAClC,CAAC,0BAA0B,KAAK,OAAO,GACvC;AACA,UAAM,IAAI,MAAM,4CAA4C,OAAO,EAAE;AAAA,EACvE;AACF;AAEA,SAAS,aAAa,MAAoB,MAA8B;AACtE,MAAI,SAAS;AACb,aAAW,OAAO,MAAM;AACtB,4BAAwB,GAAG;AAC3B,QAAI,CAAC,OAAO,GAAG,KAAK,OAAO,OAAO,GAAG,MAAM,UAAU;AACnD,aAAO,GAAG,IAAI,mBAAmB;AAAA,IACnC;AACA,aAAS,OAAO,GAAG;AAAA,EACrB;AACA,SAAO;AACT;AAEA,SAAS,aAAa;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAWS;AACP,QAAM,QAAQ,OAAO,KAClB,MAAM,GAAG,EACT,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC,EACzB,OAAO,OAAO;AACjB,MAAI,MAAM,WAAW,GAAG;AACtB;AAAA,EACF;AAEA,QAAM,aAAa,MAAM,KAAK,GAAG;AACjC,QAAM,OAAO,MAAM,IAAI;AACvB,MAAI,CAAC,MAAM;AACT;AAAA,EACF;AACA,0BAAwB,IAAI;AAE5B,QAAM,SAAS,aAAa,MAAM,KAAK;AACvC,QAAM,WAAsC,OAAO,SACjD,MAAM,KAAK,YAAY,QAAQ,IAAI;AACrC,SAAO,IAAI,IAAI,eAAe,aAAa,YAAY,QAAQ,IAAI;AACrE;AAEO,SAAS,8BAA8B;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAa6B;AAC3B,QAAM,sBAAsB,UAAU,KAAK;AAC3C,MAAI,oBAAoB,WAAW,GAAG;AACpC,UAAM,IAAI,MAAM,2CAA2C;AAAA,EAC7D;AACA,0BAAwB,mBAAmB;AAE3C,QAAM,MAAoB,mBAAmB;AAC7C,MAAI,OAAO,QAAQ,EAAE,SAAS,YAAY,SAAS,IAAI;AAEvD,aAAW,UAAU,SAAS;AAC5B,QAAI,CAAC,+BAA+B,YAAY,OAAO,YAAY,GAAG;AACpE;AAAA,IACF;AACA,iBAAa,EAAE,MAAM,QAAQ,MAAM,KAAK,aAAa,CAAC;AAAA,EACxD;AAEA,SAAO;AACT;","names":[]}
@@ -0,0 +1,83 @@
1
+ // src/i18n/browserNodeI18n.ts
2
+ import {
3
+ createI18nRuntime,
4
+ createScopedI18nRuntime,
5
+ createScopedLocaleObjectsI18nModuleManifest
6
+ } from "@nextop-os/ui-i18n-runtime";
7
+ var browserNodeI18nNamespace = "browserNode";
8
+ var browserNodeI18nModule = createScopedLocaleObjectsI18nModuleManifest({
9
+ localeObjectByLocale: {
10
+ en: "browserNodeEn",
11
+ "zh-CN": "browserNodeZhCN"
12
+ },
13
+ name: "browser-node",
14
+ namespace: "browserNode",
15
+ sourceRoot: "packages/browser/workbench-node/src"
16
+ });
17
+ var browserNodeEn = {
18
+ actions: {
19
+ back: "Back",
20
+ forward: "Forward",
21
+ reload: "Reload"
22
+ },
23
+ addressLabel: "Address",
24
+ addressPlaceholder: "Search or enter address",
25
+ coldStatus: "Sleeping",
26
+ dockLabel: "Browser",
27
+ errors: {
28
+ invalidUrl: "Enter a valid web address.",
29
+ navigationFailed: "The page could not be loaded.",
30
+ unsupportedProtocol: "This address type is not supported.",
31
+ unsupportedUrl: "This page cannot be opened."
32
+ },
33
+ loadFailed: "Page load failed",
34
+ title: "Browser"
35
+ };
36
+ var browserNodeZhCN = {
37
+ actions: {
38
+ back: "\u540E\u9000",
39
+ forward: "\u524D\u8FDB",
40
+ reload: "\u91CD\u65B0\u52A0\u8F7D"
41
+ },
42
+ addressLabel: "\u5730\u5740",
43
+ addressPlaceholder: "\u641C\u7D22\u6216\u8F93\u5165\u5730\u5740",
44
+ coldStatus: "\u4F11\u7720\u4E2D",
45
+ dockLabel: "\u6D4F\u89C8\u5668",
46
+ errors: {
47
+ invalidUrl: "\u8BF7\u8F93\u5165\u6709\u6548\u7684\u7F51\u5740\u3002",
48
+ navigationFailed: "\u9875\u9762\u65E0\u6CD5\u52A0\u8F7D\u3002",
49
+ unsupportedProtocol: "\u4E0D\u652F\u6301\u6B64\u5730\u5740\u7C7B\u578B\u3002",
50
+ unsupportedUrl: "\u65E0\u6CD5\u6253\u5F00\u6B64\u9875\u9762\u3002"
51
+ },
52
+ loadFailed: "\u9875\u9762\u52A0\u8F7D\u5931\u8D25",
53
+ title: "\u6D4F\u89C8\u5668"
54
+ };
55
+ var browserNodeDefaults = {
56
+ en: browserNodeEn,
57
+ "zh-CN": browserNodeZhCN
58
+ };
59
+ var browserNodeI18nResources = {
60
+ en: {
61
+ [browserNodeI18nNamespace]: browserNodeDefaults.en
62
+ },
63
+ "zh-CN": {
64
+ [browserNodeI18nNamespace]: browserNodeDefaults["zh-CN"]
65
+ }
66
+ };
67
+ var defaultBrowserNodeI18n = createI18nRuntime({
68
+ dictionaries: [browserNodeI18nResources.en]
69
+ });
70
+ function createBrowserNodeI18nRuntime(runtime) {
71
+ return createScopedI18nRuntime(
72
+ runtime ?? defaultBrowserNodeI18n,
73
+ browserNodeI18nNamespace
74
+ );
75
+ }
76
+
77
+ export {
78
+ browserNodeI18nNamespace,
79
+ browserNodeI18nModule,
80
+ browserNodeI18nResources,
81
+ createBrowserNodeI18nRuntime
82
+ };
83
+ //# sourceMappingURL=chunk-JRJTAIK5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/i18n/browserNodeI18n.ts"],"sourcesContent":["import {\n createI18nRuntime,\n createScopedI18nRuntime,\n createScopedLocaleObjectsI18nModuleManifest,\n type I18nDictionary,\n type I18nRuntime\n} from \"@nextop-os/ui-i18n-runtime\";\n\ntype BrowserNodeI18nLocale = \"en\" | \"zh-CN\";\nexport const browserNodeI18nNamespace = \"browserNode\";\nexport const browserNodeI18nModule =\n createScopedLocaleObjectsI18nModuleManifest({\n localeObjectByLocale: {\n en: \"browserNodeEn\",\n \"zh-CN\": \"browserNodeZhCN\"\n },\n name: \"browser-node\",\n namespace: \"browserNode\",\n sourceRoot: \"packages/browser/workbench-node/src\"\n });\n\nconst browserNodeEn = {\n actions: {\n back: \"Back\",\n forward: \"Forward\",\n reload: \"Reload\"\n },\n addressLabel: \"Address\",\n addressPlaceholder: \"Search or enter address\",\n coldStatus: \"Sleeping\",\n dockLabel: \"Browser\",\n errors: {\n invalidUrl: \"Enter a valid web address.\",\n navigationFailed: \"The page could not be loaded.\",\n unsupportedProtocol: \"This address type is not supported.\",\n unsupportedUrl: \"This page cannot be opened.\"\n },\n loadFailed: \"Page load failed\",\n title: \"Browser\"\n} as const satisfies I18nDictionary;\n\nconst browserNodeZhCN = {\n actions: {\n back: \"后退\",\n forward: \"前进\",\n reload: \"重新加载\"\n },\n addressLabel: \"地址\",\n addressPlaceholder: \"搜索或输入地址\",\n coldStatus: \"休眠中\",\n dockLabel: \"浏览器\",\n errors: {\n invalidUrl: \"请输入有效的网址。\",\n navigationFailed: \"页面无法加载。\",\n unsupportedProtocol: \"不支持此地址类型。\",\n unsupportedUrl: \"无法打开此页面。\"\n },\n loadFailed: \"页面加载失败\",\n title: \"浏览器\"\n} as const satisfies I18nDictionary;\n\nexport type BrowserNodeI18nKey =\n | \"actions.back\"\n | \"actions.forward\"\n | \"actions.reload\"\n | \"addressLabel\"\n | \"addressPlaceholder\"\n | \"coldStatus\"\n | \"dockLabel\"\n | \"errors.invalidUrl\"\n | \"errors.navigationFailed\"\n | \"errors.unsupportedProtocol\"\n | \"errors.unsupportedUrl\"\n | \"loadFailed\"\n | \"title\";\n\nexport type BrowserNodeI18nRuntime = I18nRuntime<BrowserNodeI18nKey>;\n\nconst browserNodeDefaults: Record<BrowserNodeI18nLocale, I18nDictionary> = {\n en: browserNodeEn,\n \"zh-CN\": browserNodeZhCN\n};\n\nexport const browserNodeI18nResources = {\n en: {\n [browserNodeI18nNamespace]: browserNodeDefaults.en\n },\n \"zh-CN\": {\n [browserNodeI18nNamespace]: browserNodeDefaults[\"zh-CN\"]\n }\n} as const satisfies Record<BrowserNodeI18nLocale, I18nDictionary>;\n\nconst defaultBrowserNodeI18n = createI18nRuntime({\n dictionaries: [browserNodeI18nResources.en]\n});\n\nexport function createBrowserNodeI18nRuntime(\n runtime: I18nRuntime<string> | undefined\n): BrowserNodeI18nRuntime {\n return createScopedI18nRuntime<BrowserNodeI18nKey>(\n runtime ?? defaultBrowserNodeI18n,\n browserNodeI18nNamespace\n );\n}\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AAGA,IAAM,2BAA2B;AACjC,IAAM,wBACX,4CAA4C;AAAA,EAC1C,sBAAsB;AAAA,IACpB,IAAI;AAAA,IACJ,SAAS;AAAA,EACX;AAAA,EACA,MAAM;AAAA,EACN,WAAW;AAAA,EACX,YAAY;AACd,CAAC;AAEH,IAAM,gBAAgB;AAAA,EACpB,SAAS;AAAA,IACP,MAAM;AAAA,IACN,SAAS;AAAA,IACT,QAAQ;AAAA,EACV;AAAA,EACA,cAAc;AAAA,EACd,oBAAoB;AAAA,EACpB,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,QAAQ;AAAA,IACN,YAAY;AAAA,IACZ,kBAAkB;AAAA,IAClB,qBAAqB;AAAA,IACrB,gBAAgB;AAAA,EAClB;AAAA,EACA,YAAY;AAAA,EACZ,OAAO;AACT;AAEA,IAAM,kBAAkB;AAAA,EACtB,SAAS;AAAA,IACP,MAAM;AAAA,IACN,SAAS;AAAA,IACT,QAAQ;AAAA,EACV;AAAA,EACA,cAAc;AAAA,EACd,oBAAoB;AAAA,EACpB,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,QAAQ;AAAA,IACN,YAAY;AAAA,IACZ,kBAAkB;AAAA,IAClB,qBAAqB;AAAA,IACrB,gBAAgB;AAAA,EAClB;AAAA,EACA,YAAY;AAAA,EACZ,OAAO;AACT;AAmBA,IAAM,sBAAqE;AAAA,EACzE,IAAI;AAAA,EACJ,SAAS;AACX;AAEO,IAAM,2BAA2B;AAAA,EACtC,IAAI;AAAA,IACF,CAAC,wBAAwB,GAAG,oBAAoB;AAAA,EAClD;AAAA,EACA,SAAS;AAAA,IACP,CAAC,wBAAwB,GAAG,oBAAoB,OAAO;AAAA,EACzD;AACF;AAEA,IAAM,yBAAyB,kBAAkB;AAAA,EAC/C,cAAc,CAAC,yBAAyB,EAAE;AAC5C,CAAC;AAEM,SAAS,6BACd,SACwB;AACxB,SAAO;AAAA,IACL,WAAW;AAAA,IACX;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,27 @@
1
+ // src/core/session.ts
2
+ var browserSharedPartition = "persist:browser-node-shared";
3
+ var browserIncognitoPartition = "browser-node-incognito";
4
+ var browserProfilePartitionPrefix = "persist:browser-node-profile-";
5
+ function resolveBrowserSessionPartition({
6
+ profileId,
7
+ sessionMode
8
+ }) {
9
+ if (sessionMode === "incognito") {
10
+ return browserIncognitoPartition;
11
+ }
12
+ const normalizedProfileId = profileId?.trim() ?? "";
13
+ if (sessionMode === "profile" && normalizedProfileId.length > 0) {
14
+ return `${browserProfilePartitionPrefix}${normalizedProfileId}`;
15
+ }
16
+ return browserSharedPartition;
17
+ }
18
+ function isBrowserSessionPartitionAllowed(value) {
19
+ const partition = value?.trim() ?? "";
20
+ return partition === browserIncognitoPartition || partition === browserSharedPartition || partition.startsWith(browserProfilePartitionPrefix);
21
+ }
22
+
23
+ export {
24
+ resolveBrowserSessionPartition,
25
+ isBrowserSessionPartitionAllowed
26
+ };
27
+ //# sourceMappingURL=chunk-OTK5YBCK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/session.ts"],"sourcesContent":["import type { BrowserNodeSessionMode } from \"./types.ts\";\n\nconst browserSharedPartition = \"persist:browser-node-shared\";\nconst browserIncognitoPartition = \"browser-node-incognito\";\nconst browserProfilePartitionPrefix = \"persist:browser-node-profile-\";\n\nexport function resolveBrowserSessionPartition({\n profileId,\n sessionMode\n}: BrowserNodeSessionPartitionInput): string {\n if (sessionMode === \"incognito\") {\n return browserIncognitoPartition;\n }\n\n const normalizedProfileId = profileId?.trim() ?? \"\";\n if (sessionMode === \"profile\" && normalizedProfileId.length > 0) {\n return `${browserProfilePartitionPrefix}${normalizedProfileId}`;\n }\n\n return browserSharedPartition;\n}\n\nexport interface BrowserNodeSessionPartitionInput {\n profileId: string | null;\n sessionMode: BrowserNodeSessionMode;\n}\n\nexport function isBrowserSessionPartitionAllowed(\n value: string | undefined\n): boolean {\n const partition = value?.trim() ?? \"\";\n return (\n partition === browserIncognitoPartition ||\n partition === browserSharedPartition ||\n partition.startsWith(browserProfilePartitionPrefix)\n );\n}\n"],"mappings":";AAEA,IAAM,yBAAyB;AAC/B,IAAM,4BAA4B;AAClC,IAAM,gCAAgC;AAE/B,SAAS,+BAA+B;AAAA,EAC7C;AAAA,EACA;AACF,GAA6C;AAC3C,MAAI,gBAAgB,aAAa;AAC/B,WAAO;AAAA,EACT;AAEA,QAAM,sBAAsB,WAAW,KAAK,KAAK;AACjD,MAAI,gBAAgB,aAAa,oBAAoB,SAAS,GAAG;AAC/D,WAAO,GAAG,6BAA6B,GAAG,mBAAmB;AAAA,EAC/D;AAEA,SAAO;AACT;AAOO,SAAS,iCACd,OACS;AACT,QAAM,YAAY,OAAO,KAAK,KAAK;AACnC,SACE,cAAc,6BACd,cAAc,0BACd,UAAU,WAAW,6BAA6B;AAEtD;","names":[]}