@opentabs-dev/shared 0.0.22 → 0.0.24
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/dist/constants.d.ts +56 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +86 -0
- package/dist/constants.js.map +1 -0
- package/dist/cross-platform.d.ts +41 -0
- package/dist/cross-platform.d.ts.map +1 -0
- package/dist/cross-platform.js +96 -0
- package/dist/cross-platform.js.map +1 -0
- package/dist/error.d.ts +9 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +9 -0
- package/dist/error.js.map +1 -0
- package/dist/index.d.ts +17 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -3
- package/dist/index.js.map +1 -1
- package/dist/manifest.d.ts +8 -1
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +7 -9
- package/dist/manifest.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared constants for the OpenTabs platform.
|
|
3
|
+
*
|
|
4
|
+
* These values are used by multiple packages (MCP server, CLI, plugin-tools,
|
|
5
|
+
* browser-extension). Defining them once here prevents drift and duplication.
|
|
6
|
+
*/
|
|
7
|
+
/** Default port for the MCP server (HTTP + WebSocket) */
|
|
8
|
+
export declare const DEFAULT_PORT = 9515;
|
|
9
|
+
/** Filename of the bundled adapter IIFE produced by `opentabs-plugin build` */
|
|
10
|
+
export declare const ADAPTER_FILENAME = "adapter.iife.js";
|
|
11
|
+
/** Filename of the source map for the adapter IIFE */
|
|
12
|
+
export declare const ADAPTER_SOURCE_MAP_FILENAME = "adapter.iife.js.map";
|
|
13
|
+
/** Filename of the tool/resource/prompt manifest produced by `opentabs-plugin build` */
|
|
14
|
+
export declare const TOOLS_FILENAME = "tools.json";
|
|
15
|
+
/** Returns the config directory path (~/.opentabs or OPENTABS_CONFIG_DIR override).
|
|
16
|
+
* Re-evaluated on each call so test overrides via OPENTABS_CONFIG_DIR take effect. */
|
|
17
|
+
export declare const getConfigDir: () => string;
|
|
18
|
+
/** Returns the path to config.json inside the config directory. */
|
|
19
|
+
export declare const getConfigPath: () => string;
|
|
20
|
+
/** Returns the managed extension install directory (~/.opentabs/extension/). */
|
|
21
|
+
export declare const getExtensionDir: () => string;
|
|
22
|
+
/** Returns the path to the server log file (~/.opentabs/server.log). */
|
|
23
|
+
export declare const getLogFilePath: () => string;
|
|
24
|
+
/** npm scope for official first-party OpenTabs plugins */
|
|
25
|
+
export declare const OFFICIAL_SCOPE = "@opentabs-dev";
|
|
26
|
+
/** Prefix for opentabs plugin npm package names */
|
|
27
|
+
export declare const PLUGIN_PREFIX = "opentabs-plugin-";
|
|
28
|
+
/**
|
|
29
|
+
* Resolve all possible npm package names for a given plugin shorthand.
|
|
30
|
+
*
|
|
31
|
+
* Returns candidates in priority order (official first, then community unscoped).
|
|
32
|
+
* Already-qualified names (scoped or full `opentabs-plugin-*`) return as-is.
|
|
33
|
+
*
|
|
34
|
+
* Examples:
|
|
35
|
+
* "slack" → ["@opentabs-dev/opentabs-plugin-slack", "opentabs-plugin-slack"]
|
|
36
|
+
* "opentabs-plugin-slack" → ["opentabs-plugin-slack"]
|
|
37
|
+
* "@opentabs-dev/opentabs-plugin-slack"→ ["@opentabs-dev/opentabs-plugin-slack"]
|
|
38
|
+
* "@myorg/opentabs-plugin-jira" → ["@myorg/opentabs-plugin-jira"]
|
|
39
|
+
*/
|
|
40
|
+
export declare const resolvePluginPackageCandidates: (name: string) => string[];
|
|
41
|
+
/**
|
|
42
|
+
* Normalize a shorthand plugin name to its full npm package name.
|
|
43
|
+
*
|
|
44
|
+
* Shorthand names expand to the official scoped package first. Already-qualified
|
|
45
|
+
* names (scoped or prefixed with `opentabs-plugin-`) pass through unchanged.
|
|
46
|
+
*
|
|
47
|
+
* Examples:
|
|
48
|
+
* "slack" → "@opentabs-dev/opentabs-plugin-slack"
|
|
49
|
+
* "opentabs-plugin-slack" → "opentabs-plugin-slack"
|
|
50
|
+
* "@opentabs-dev/opentabs-plugin-slack" → "@opentabs-dev/opentabs-plugin-slack"
|
|
51
|
+
* "@myorg/opentabs-plugin-jira" → "@myorg/opentabs-plugin-jira"
|
|
52
|
+
*/
|
|
53
|
+
export declare const normalizePluginName: (name: string) => string;
|
|
54
|
+
/** Generate a 256-bit cryptographic random secret as a 64-character hex string. */
|
|
55
|
+
export declare const generateSecret: () => string;
|
|
56
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,yDAAyD;AACzD,eAAO,MAAM,YAAY,OAAO,CAAC;AAMjC,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,oBAAoB,CAAC;AAElD,sDAAsD;AACtD,eAAO,MAAM,2BAA2B,wBAAwB,CAAC;AAEjE,wFAAwF;AACxF,eAAO,MAAM,cAAc,eAAe,CAAC;AAM3C;uFACuF;AACvF,eAAO,MAAM,YAAY,QAAO,MAAqE,CAAC;AAEtG,mEAAmE;AACnE,eAAO,MAAM,aAAa,QAAO,MAA6C,CAAC;AAE/E,gFAAgF;AAChF,eAAO,MAAM,eAAe,QAAO,MAA2C,CAAC;AAE/E,wEAAwE;AACxE,eAAO,MAAM,cAAc,QAAO,MAA4C,CAAC;AAM/E,0DAA0D;AAC1D,eAAO,MAAM,cAAc,kBAAkB,CAAC;AAE9C,mDAAmD;AACnD,eAAO,MAAM,aAAa,qBAAqB,CAAC;AAEhD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,8BAA8B,GAAI,MAAM,MAAM,KAAG,MAAM,EAInE,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,mBAAmB,GAAI,MAAM,MAAM,KAAG,MAGlD,CAAC;AAMF,mFAAmF;AACnF,eAAO,MAAM,cAAc,QAAO,MAIjC,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared constants for the OpenTabs platform.
|
|
3
|
+
*
|
|
4
|
+
* These values are used by multiple packages (MCP server, CLI, plugin-tools,
|
|
5
|
+
* browser-extension). Defining them once here prevents drift and duplication.
|
|
6
|
+
*/
|
|
7
|
+
import { homedir } from 'node:os';
|
|
8
|
+
import { join } from 'node:path';
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Network
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
/** Default port for the MCP server (HTTP + WebSocket) */
|
|
13
|
+
export const DEFAULT_PORT = 9515;
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Plugin build artifacts
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
/** Filename of the bundled adapter IIFE produced by `opentabs-plugin build` */
|
|
18
|
+
export const ADAPTER_FILENAME = 'adapter.iife.js';
|
|
19
|
+
/** Filename of the source map for the adapter IIFE */
|
|
20
|
+
export const ADAPTER_SOURCE_MAP_FILENAME = 'adapter.iife.js.map';
|
|
21
|
+
/** Filename of the tool/resource/prompt manifest produced by `opentabs-plugin build` */
|
|
22
|
+
export const TOOLS_FILENAME = 'tools.json';
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Config directory paths
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
/** Returns the config directory path (~/.opentabs or OPENTABS_CONFIG_DIR override).
|
|
27
|
+
* Re-evaluated on each call so test overrides via OPENTABS_CONFIG_DIR take effect. */
|
|
28
|
+
export const getConfigDir = () => Bun.env.OPENTABS_CONFIG_DIR || join(homedir(), '.opentabs');
|
|
29
|
+
/** Returns the path to config.json inside the config directory. */
|
|
30
|
+
export const getConfigPath = () => join(getConfigDir(), 'config.json');
|
|
31
|
+
/** Returns the managed extension install directory (~/.opentabs/extension/). */
|
|
32
|
+
export const getExtensionDir = () => join(getConfigDir(), 'extension');
|
|
33
|
+
/** Returns the path to the server log file (~/.opentabs/server.log). */
|
|
34
|
+
export const getLogFilePath = () => join(getConfigDir(), 'server.log');
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
// Plugin naming conventions
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
/** npm scope for official first-party OpenTabs plugins */
|
|
39
|
+
export const OFFICIAL_SCOPE = '@opentabs-dev';
|
|
40
|
+
/** Prefix for opentabs plugin npm package names */
|
|
41
|
+
export const PLUGIN_PREFIX = 'opentabs-plugin-';
|
|
42
|
+
/**
|
|
43
|
+
* Resolve all possible npm package names for a given plugin shorthand.
|
|
44
|
+
*
|
|
45
|
+
* Returns candidates in priority order (official first, then community unscoped).
|
|
46
|
+
* Already-qualified names (scoped or full `opentabs-plugin-*`) return as-is.
|
|
47
|
+
*
|
|
48
|
+
* Examples:
|
|
49
|
+
* "slack" → ["@opentabs-dev/opentabs-plugin-slack", "opentabs-plugin-slack"]
|
|
50
|
+
* "opentabs-plugin-slack" → ["opentabs-plugin-slack"]
|
|
51
|
+
* "@opentabs-dev/opentabs-plugin-slack"→ ["@opentabs-dev/opentabs-plugin-slack"]
|
|
52
|
+
* "@myorg/opentabs-plugin-jira" → ["@myorg/opentabs-plugin-jira"]
|
|
53
|
+
*/
|
|
54
|
+
export const resolvePluginPackageCandidates = (name) => {
|
|
55
|
+
if (name.startsWith('@'))
|
|
56
|
+
return [name];
|
|
57
|
+
if (name.startsWith(PLUGIN_PREFIX))
|
|
58
|
+
return [name];
|
|
59
|
+
return [`${OFFICIAL_SCOPE}/${PLUGIN_PREFIX}${name}`, `${PLUGIN_PREFIX}${name}`];
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Normalize a shorthand plugin name to its full npm package name.
|
|
63
|
+
*
|
|
64
|
+
* Shorthand names expand to the official scoped package first. Already-qualified
|
|
65
|
+
* names (scoped or prefixed with `opentabs-plugin-`) pass through unchanged.
|
|
66
|
+
*
|
|
67
|
+
* Examples:
|
|
68
|
+
* "slack" → "@opentabs-dev/opentabs-plugin-slack"
|
|
69
|
+
* "opentabs-plugin-slack" → "opentabs-plugin-slack"
|
|
70
|
+
* "@opentabs-dev/opentabs-plugin-slack" → "@opentabs-dev/opentabs-plugin-slack"
|
|
71
|
+
* "@myorg/opentabs-plugin-jira" → "@myorg/opentabs-plugin-jira"
|
|
72
|
+
*/
|
|
73
|
+
export const normalizePluginName = (name) => {
|
|
74
|
+
const candidates = resolvePluginPackageCandidates(name);
|
|
75
|
+
return candidates[0] ?? `${OFFICIAL_SCOPE}/${PLUGIN_PREFIX}${name}`;
|
|
76
|
+
};
|
|
77
|
+
// ---------------------------------------------------------------------------
|
|
78
|
+
// Cryptography
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
/** Generate a 256-bit cryptographic random secret as a 64-character hex string. */
|
|
81
|
+
export const generateSecret = () => {
|
|
82
|
+
const bytes = new Uint8Array(32);
|
|
83
|
+
crypto.getRandomValues(bytes);
|
|
84
|
+
return Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');
|
|
85
|
+
};
|
|
86
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,yDAAyD;AACzD,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC;AAEjC,8EAA8E;AAC9E,yBAAyB;AACzB,8EAA8E;AAE9E,+EAA+E;AAC/E,MAAM,CAAC,MAAM,gBAAgB,GAAG,iBAAiB,CAAC;AAElD,sDAAsD;AACtD,MAAM,CAAC,MAAM,2BAA2B,GAAG,qBAAqB,CAAC;AAEjE,wFAAwF;AACxF,MAAM,CAAC,MAAM,cAAc,GAAG,YAAY,CAAC;AAE3C,8EAA8E;AAC9E,yBAAyB;AACzB,8EAA8E;AAE9E;uFACuF;AACvF,MAAM,CAAC,MAAM,YAAY,GAAG,GAAW,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,mBAAmB,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC;AAEtG,mEAAmE;AACnE,MAAM,CAAC,MAAM,aAAa,GAAG,GAAW,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,aAAa,CAAC,CAAC;AAE/E,gFAAgF;AAChF,MAAM,CAAC,MAAM,eAAe,GAAG,GAAW,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,WAAW,CAAC,CAAC;AAE/E,wEAAwE;AACxE,MAAM,CAAC,MAAM,cAAc,GAAG,GAAW,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,YAAY,CAAC,CAAC;AAE/E,8EAA8E;AAC9E,4BAA4B;AAC5B,8EAA8E;AAE9E,0DAA0D;AAC1D,MAAM,CAAC,MAAM,cAAc,GAAG,eAAe,CAAC;AAE9C,mDAAmD;AACnD,MAAM,CAAC,MAAM,aAAa,GAAG,kBAAkB,CAAC;AAEhD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,IAAY,EAAY,EAAE;IACvE,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,IAAI,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,cAAc,IAAI,aAAa,GAAG,IAAI,EAAE,EAAE,GAAG,aAAa,GAAG,IAAI,EAAE,CAAC,CAAC;AAClF,CAAC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,IAAY,EAAU,EAAE;IAC1D,MAAM,UAAU,GAAG,8BAA8B,CAAC,IAAI,CAAC,CAAC;IACxD,OAAO,UAAU,CAAC,CAAC,CAAC,IAAI,GAAG,cAAc,IAAI,aAAa,GAAG,IAAI,EAAE,CAAC;AACtE,CAAC,CAAC;AAEF,8EAA8E;AAC9E,eAAe;AACf,8EAA8E;AAE9E,mFAAmF;AACnF,MAAM,CAAC,MAAM,cAAc,GAAG,GAAW,EAAE;IACzC,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IACjC,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAC9B,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC1E,CAAC,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-platform utilities for the OpenTabs platform.
|
|
3
|
+
*
|
|
4
|
+
* Provides portable abstractions for file operations, process spawning,
|
|
5
|
+
* and platform detection that work correctly on macOS, Linux, and Windows.
|
|
6
|
+
*/
|
|
7
|
+
/** Returns true when running on Windows (process.platform === 'win32'). */
|
|
8
|
+
export declare const isWindows: () => boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Resolves a bare command name for the current platform.
|
|
11
|
+
*
|
|
12
|
+
* On Windows, npm is distributed as `npm.cmd` (a cmd wrapper) and bun as
|
|
13
|
+
* `bun.exe`. Bun.spawn requires the full name on Windows because it does
|
|
14
|
+
* not search PATHEXT the way cmd.exe does.
|
|
15
|
+
*
|
|
16
|
+
* On Unix, the command name is returned unchanged.
|
|
17
|
+
*/
|
|
18
|
+
export declare const platformExec: (cmd: string) => string;
|
|
19
|
+
/**
|
|
20
|
+
* Write a file atomically: write to a temporary file in the same directory,
|
|
21
|
+
* optionally set restrictive permissions, then rename over the target.
|
|
22
|
+
*
|
|
23
|
+
* On POSIX, `rename(2)` is atomic — readers never see a partially-written file.
|
|
24
|
+
* On Windows (NTFS), `rename` fails when the target already exists. The
|
|
25
|
+
* fallback deletes the target first, then renames. This creates a brief window
|
|
26
|
+
* where the file does not exist; callers that read this file should retry on
|
|
27
|
+
* ENOENT.
|
|
28
|
+
*
|
|
29
|
+
* @param filePath — absolute path to the destination file
|
|
30
|
+
* @param content — file content to write
|
|
31
|
+
* @param mode — optional POSIX permission mode (e.g., 0o600). Silently
|
|
32
|
+
* skipped on Windows with a debug-level warning.
|
|
33
|
+
*/
|
|
34
|
+
export declare const atomicWrite: (filePath: string, content: string, mode?: number) => Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Set file permissions, silently succeeding on Windows where POSIX chmod
|
|
37
|
+
* is not supported. Logs a warning if chmod fails on a platform that
|
|
38
|
+
* supports it (i.e., on POSIX systems).
|
|
39
|
+
*/
|
|
40
|
+
export declare const safeChmod: (filePath: string, mode: number) => Promise<void>;
|
|
41
|
+
//# sourceMappingURL=cross-platform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cross-platform.d.ts","sourceRoot":"","sources":["../src/cross-platform.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,2EAA2E;AAC3E,eAAO,MAAM,SAAS,QAAO,OAAuC,CAAC;AAMrE;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,KAAG,MAY1C,CAAC;AAMF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,WAAW,GAAU,UAAU,MAAM,EAAE,SAAS,MAAM,EAAE,OAAO,MAAM,KAAG,OAAO,CAAC,IAAI,CAsBhG,CAAC;AAMF;;;;GAIG;AACH,eAAO,MAAM,SAAS,GAAU,UAAU,MAAM,EAAE,MAAM,MAAM,KAAG,OAAO,CAAC,IAAI,CAW5E,CAAC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-platform utilities for the OpenTabs platform.
|
|
3
|
+
*
|
|
4
|
+
* Provides portable abstractions for file operations, process spawning,
|
|
5
|
+
* and platform detection that work correctly on macOS, Linux, and Windows.
|
|
6
|
+
*/
|
|
7
|
+
import { toErrorMessage } from './error.js';
|
|
8
|
+
import { chmod, rename, unlink } from 'node:fs/promises';
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Platform detection
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
/** Returns true when running on Windows (process.platform === 'win32'). */
|
|
13
|
+
export const isWindows = () => process.platform === 'win32';
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Command resolution for Bun.spawn / Bun.spawnSync
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
/**
|
|
18
|
+
* Resolves a bare command name for the current platform.
|
|
19
|
+
*
|
|
20
|
+
* On Windows, npm is distributed as `npm.cmd` (a cmd wrapper) and bun as
|
|
21
|
+
* `bun.exe`. Bun.spawn requires the full name on Windows because it does
|
|
22
|
+
* not search PATHEXT the way cmd.exe does.
|
|
23
|
+
*
|
|
24
|
+
* On Unix, the command name is returned unchanged.
|
|
25
|
+
*/
|
|
26
|
+
export const platformExec = (cmd) => {
|
|
27
|
+
if (!isWindows())
|
|
28
|
+
return cmd;
|
|
29
|
+
switch (cmd) {
|
|
30
|
+
case 'npm':
|
|
31
|
+
case 'npx':
|
|
32
|
+
return `${cmd}.cmd`;
|
|
33
|
+
case 'bun':
|
|
34
|
+
case 'bunx':
|
|
35
|
+
return `${cmd}.exe`;
|
|
36
|
+
default:
|
|
37
|
+
return cmd;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// Atomic file writes
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
/**
|
|
44
|
+
* Write a file atomically: write to a temporary file in the same directory,
|
|
45
|
+
* optionally set restrictive permissions, then rename over the target.
|
|
46
|
+
*
|
|
47
|
+
* On POSIX, `rename(2)` is atomic — readers never see a partially-written file.
|
|
48
|
+
* On Windows (NTFS), `rename` fails when the target already exists. The
|
|
49
|
+
* fallback deletes the target first, then renames. This creates a brief window
|
|
50
|
+
* where the file does not exist; callers that read this file should retry on
|
|
51
|
+
* ENOENT.
|
|
52
|
+
*
|
|
53
|
+
* @param filePath — absolute path to the destination file
|
|
54
|
+
* @param content — file content to write
|
|
55
|
+
* @param mode — optional POSIX permission mode (e.g., 0o600). Silently
|
|
56
|
+
* skipped on Windows with a debug-level warning.
|
|
57
|
+
*/
|
|
58
|
+
export const atomicWrite = async (filePath, content, mode) => {
|
|
59
|
+
const tmpPath = filePath + '.tmp';
|
|
60
|
+
try {
|
|
61
|
+
await Bun.write(tmpPath, content);
|
|
62
|
+
if (mode !== undefined) {
|
|
63
|
+
await safeChmod(tmpPath, mode);
|
|
64
|
+
}
|
|
65
|
+
if (isWindows()) {
|
|
66
|
+
// NTFS rename does not atomically replace an existing file. Remove the
|
|
67
|
+
// target first, then rename. The unlink may fail with ENOENT if the
|
|
68
|
+
// target does not exist yet — that is fine.
|
|
69
|
+
await unlink(filePath).catch(() => { });
|
|
70
|
+
}
|
|
71
|
+
await rename(tmpPath, filePath);
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
// Clean up the temporary file on any failure.
|
|
75
|
+
await unlink(tmpPath).catch(() => { });
|
|
76
|
+
throw err;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
// Permission helpers
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
/**
|
|
83
|
+
* Set file permissions, silently succeeding on Windows where POSIX chmod
|
|
84
|
+
* is not supported. Logs a warning if chmod fails on a platform that
|
|
85
|
+
* supports it (i.e., on POSIX systems).
|
|
86
|
+
*/
|
|
87
|
+
export const safeChmod = async (filePath, mode) => {
|
|
88
|
+
if (isWindows()) {
|
|
89
|
+
// Windows does not support POSIX file permissions.
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
await chmod(filePath, mode).catch((err) => {
|
|
93
|
+
console.warn(`Warning: Could not set file permissions on ${filePath}: ${toErrorMessage(err)}. The file may be readable by other users.`);
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
//# sourceMappingURL=cross-platform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cross-platform.js","sourceRoot":"","sources":["../src/cross-platform.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAEzD,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E,2EAA2E;AAC3E,MAAM,CAAC,MAAM,SAAS,GAAG,GAAY,EAAE,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC;AAErE,8EAA8E;AAC9E,mDAAmD;AACnD,8EAA8E;AAE9E;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAW,EAAU,EAAE;IAClD,IAAI,CAAC,SAAS,EAAE;QAAE,OAAO,GAAG,CAAC;IAC7B,QAAQ,GAAG,EAAE,CAAC;QACZ,KAAK,KAAK,CAAC;QACX,KAAK,KAAK;YACR,OAAO,GAAG,GAAG,MAAM,CAAC;QACtB,KAAK,KAAK,CAAC;QACX,KAAK,MAAM;YACT,OAAO,GAAG,GAAG,MAAM,CAAC;QACtB;YACE,OAAO,GAAG,CAAC;IACf,CAAC;AACH,CAAC,CAAC;AAEF,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,QAAgB,EAAE,OAAe,EAAE,IAAa,EAAiB,EAAE;IACnG,MAAM,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IAClC,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAElC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,MAAM,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACjC,CAAC;QAED,IAAI,SAAS,EAAE,EAAE,CAAC;YAChB,uEAAuE;YACvE,oEAAoE;YACpE,4CAA4C;YAC5C,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACzC,CAAC;QAED,MAAM,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,8CAA8C;QAC9C,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACtC,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC,CAAC;AAEF,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAAE,QAAgB,EAAE,IAAY,EAAiB,EAAE;IAC/E,IAAI,SAAS,EAAE,EAAE,CAAC;QAChB,mDAAmD;QACnD,OAAO;IACT,CAAC;IAED,MAAM,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;QACjD,OAAO,CAAC,IAAI,CACV,8CAA8C,QAAQ,KAAK,cAAc,CAAC,GAAG,CAAC,4CAA4C,CAC3H,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC"}
|
package/dist/error.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract a human-readable message from an unknown thrown value.
|
|
3
|
+
*
|
|
4
|
+
* Returns `err.message` for Error instances and `String(err)` for everything
|
|
5
|
+
* else. This replaces the repetitive `err instanceof Error ? err.message : String(err)`
|
|
6
|
+
* pattern used across the platform.
|
|
7
|
+
*/
|
|
8
|
+
export declare const toErrorMessage: (err: unknown) => string;
|
|
9
|
+
//# sourceMappingURL=error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,GAAI,KAAK,OAAO,KAAG,MAA4D,CAAC"}
|
package/dist/error.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract a human-readable message from an unknown thrown value.
|
|
3
|
+
*
|
|
4
|
+
* Returns `err.message` for Error instances and `String(err)` for everything
|
|
5
|
+
* else. This replaces the repetitive `err instanceof Error ? err.message : String(err)`
|
|
6
|
+
* pattern used across the platform.
|
|
7
|
+
*/
|
|
8
|
+
export const toErrorMessage = (err) => (err instanceof Error ? err.message : String(err));
|
|
9
|
+
//# sourceMappingURL=error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.js","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,GAAY,EAAU,EAAE,CAAC,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,8 +5,11 @@
|
|
|
5
5
|
* to provide compile-time safety for the JSON-RPC wire protocol and shared
|
|
6
6
|
* domain concepts.
|
|
7
7
|
*/
|
|
8
|
+
export { atomicWrite, isWindows, platformExec, safeChmod } from './cross-platform.js';
|
|
9
|
+
export { toErrorMessage } from './error.js';
|
|
10
|
+
export { DEFAULT_PORT, ADAPTER_FILENAME, ADAPTER_SOURCE_MAP_FILENAME, TOOLS_FILENAME, getConfigDir, getConfigPath, getExtensionDir, getLogFilePath, generateSecret, OFFICIAL_SCOPE, PLUGIN_PREFIX, normalizePluginName, resolvePluginPackageCandidates, } from './constants.js';
|
|
8
11
|
export { type Ok, type Err, type Result, ok, err, isOk, isErr, unwrap, unwrapOr, mapResult } from './result.js';
|
|
9
|
-
export { parsePluginPackageJson } from './manifest.js';
|
|
12
|
+
export { parsePluginPackageJson, isValidPluginPackageName } from './manifest.js';
|
|
10
13
|
export type { PluginOpentabsField, PluginPackageJson } from './manifest.js';
|
|
11
14
|
/** Tab state for a plugin */
|
|
12
15
|
export type TabState = 'closed' | 'unavailable' | 'ready';
|
|
@@ -184,6 +187,11 @@ export interface ConfigStatePlugin {
|
|
|
184
187
|
iconSvg?: string;
|
|
185
188
|
/** Optional SVG icon for the inactive state */
|
|
186
189
|
iconInactiveSvg?: string;
|
|
190
|
+
/** Present when a newer version of this plugin is available on npm */
|
|
191
|
+
update?: {
|
|
192
|
+
latestVersion: string;
|
|
193
|
+
updateCommand: string;
|
|
194
|
+
};
|
|
187
195
|
}
|
|
188
196
|
/** A plugin that failed discovery, sent to the side panel for display */
|
|
189
197
|
export interface ConfigStateFailedPlugin {
|
|
@@ -194,12 +202,6 @@ export interface ConfigStateFailedPlugin {
|
|
|
194
202
|
export interface ConfigStateResult {
|
|
195
203
|
plugins: ConfigStatePlugin[];
|
|
196
204
|
failedPlugins: ConfigStateFailedPlugin[];
|
|
197
|
-
outdatedPlugins: Array<{
|
|
198
|
-
name: string;
|
|
199
|
-
currentVersion: string;
|
|
200
|
-
latestVersion: string;
|
|
201
|
-
updateCommand: string;
|
|
202
|
-
}>;
|
|
203
205
|
}
|
|
204
206
|
/** config.setToolEnabled request params */
|
|
205
207
|
export interface ConfigSetToolEnabledParams {
|
|
@@ -241,7 +243,14 @@ export interface PluginUninstallParams {
|
|
|
241
243
|
export declare const BLOCKED_URL_SCHEMES: readonly string[];
|
|
242
244
|
/** Check if a URL uses a blocked scheme. Returns true if the URL is dangerous or unparseable. */
|
|
243
245
|
export declare const isBlockedUrlScheme: (url: string) => boolean;
|
|
244
|
-
/**
|
|
246
|
+
/**
|
|
247
|
+
* Matches paths to exclude when copying the browser extension to ~/.opentabs/extension/.
|
|
248
|
+
*
|
|
249
|
+
* Excluded categories:
|
|
250
|
+
* - Directories: node_modules, src, .git, .storybook, storybook-static
|
|
251
|
+
* - File patterns: tsconfig*, build-*.ts
|
|
252
|
+
* - Root-level metadata: package.json, CLAUDE.md
|
|
253
|
+
*/
|
|
245
254
|
export declare const EXTENSION_COPY_EXCLUDE_PATTERN: RegExp;
|
|
246
255
|
/** Regex for valid plugin names: lowercase alphanumeric with hyphens */
|
|
247
256
|
export declare const NAME_REGEX: RegExp;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,GAAG,EAAE,KAAK,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAMhH,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAMtF,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAM5C,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,2BAA2B,EAC3B,cAAc,EACd,YAAY,EACZ,aAAa,EACb,eAAe,EACf,cAAc,EACd,cAAc,EACd,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,8BAA8B,GAC/B,MAAM,gBAAgB,CAAC;AAMxB,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,GAAG,EAAE,KAAK,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAMhH,OAAO,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACjF,YAAY,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAM5E,6BAA6B;AAC7B,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,aAAa,GAAG,OAAO,CAAC;AAE1D,8BAA8B;AAC9B,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,OAAO,CAAC;AAE3D,2DAA2D;AAC3D,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,8FAA8F;IAC9F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC/B,OAAO,CAAC,EAAE,cAAc,EAAE,CAAC;IAC3B,oFAAoF;IACpF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,sDAAsD;AACtD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,4FAA4F;AAC5F,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,0DAA0D;AAC1D,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,0FAA0F;AAC1F,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,sBAAsB,EAAE,CAAC;CACtC;AAED,gFAAgF;AAChF,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACjD;AAMD,+DAA+D;AAC/D,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,KAAK,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,wDAAwD;AACxD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;CACrB;AAED,oCAAoC;AACpC,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,KAAK,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;CACrB;AAED,mFAAmF;AACnF,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC;IACzE,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;CAC5B;AAUD,wEAAwE;AACxE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,qEAAqE;AACrE,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,0EAA0E;AAC1E,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,iBAAiB,EAAE,CAAC;CAC9B;AAED,gDAAgD;AAChD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,mFAAmF;AACnF,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,iFAAiF;AACjF,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,iFAAiF;AACjF,MAAM,MAAM,kBAAkB,GAAG,iBAAiB,CAAC;AAEnD,wDAAwD;AACxD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,QAAQ,CAAC;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB;AAED,mDAAmD;AACnD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,QAAQ,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;CACrF;AAED,uCAAuC;AACvC,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,EAAE,KAAK,GAAG,OAAO,CAAC;IACxB,QAAQ,EAAE,QAAQ,CAAC;IACnB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,0FAA0F;IAC1F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sEAAsE;IACtE,MAAM,CAAC,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3D;AAED,yEAAyE;AACzE,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,6BAA6B;AAC7B,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,aAAa,EAAE,uBAAuB,EAAE,CAAC;CAC1C;AAED,2CAA2C;AAC3C,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,+CAA+C;AAC/C,MAAM,WAAW,8BAA8B;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,sEAAsE;AACtE,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAE1D,qCAAqC;AACrC,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;CACb;AAED,yCAAyC;AACzC,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,sCAAsC;AACtC,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;CACf;AAED,2CAA2C;AAC3C,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,uFAAuF;IACvF,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,sCAAsC;AACtC,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;CACd;AAMD,sFAAsF;AACtF,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAOhD,CAAC;AAEF,iGAAiG;AACjG,eAAO,MAAM,kBAAkB,GAAI,KAAK,MAAM,KAAG,OAOhD,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,8BAA8B,QACgJ,CAAC;AAM5L,wEAAwE;AACxE,eAAO,MAAM,UAAU,QAA6B,CAAC;AAErD,yDAAyD;AACzD,eAAO,MAAM,cAAc,aASzB,CAAC;AAEH,iFAAiF;AACjF,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,KAAG,MAAM,GAAG,IAM1D,CAAC;AAMF;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,GAAI,SAAS,MAAM,KAAG,MAAM,GAAG,IAsC7D,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -6,13 +6,25 @@
|
|
|
6
6
|
* domain concepts.
|
|
7
7
|
*/
|
|
8
8
|
// ---------------------------------------------------------------------------
|
|
9
|
+
// Cross-platform utilities
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
export { atomicWrite, isWindows, platformExec, safeChmod } from './cross-platform.js';
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
// Error utilities
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
export { toErrorMessage } from './error.js';
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Shared constants — port, filenames, config paths, crypto
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
export { DEFAULT_PORT, ADAPTER_FILENAME, ADAPTER_SOURCE_MAP_FILENAME, TOOLS_FILENAME, getConfigDir, getConfigPath, getExtensionDir, getLogFilePath, generateSecret, OFFICIAL_SCOPE, PLUGIN_PREFIX, normalizePluginName, resolvePluginPackageCandidates, } from './constants.js';
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
9
21
|
// Result type — structured error handling
|
|
10
22
|
// ---------------------------------------------------------------------------
|
|
11
23
|
export { ok, err, isOk, isErr, unwrap, unwrapOr, mapResult } from './result.js';
|
|
12
24
|
// ---------------------------------------------------------------------------
|
|
13
25
|
// Plugin package.json manifest — new plugin metadata format
|
|
14
26
|
// ---------------------------------------------------------------------------
|
|
15
|
-
export { parsePluginPackageJson } from './manifest.js';
|
|
27
|
+
export { parsePluginPackageJson, isValidPluginPackageName } from './manifest.js';
|
|
16
28
|
// ---------------------------------------------------------------------------
|
|
17
29
|
// Security constants — shared between MCP server and Chrome extension
|
|
18
30
|
// ---------------------------------------------------------------------------
|
|
@@ -35,8 +47,15 @@ export const isBlockedUrlScheme = (url) => {
|
|
|
35
47
|
return true;
|
|
36
48
|
}
|
|
37
49
|
};
|
|
38
|
-
/**
|
|
39
|
-
|
|
50
|
+
/**
|
|
51
|
+
* Matches paths to exclude when copying the browser extension to ~/.opentabs/extension/.
|
|
52
|
+
*
|
|
53
|
+
* Excluded categories:
|
|
54
|
+
* - Directories: node_modules, src, .git, .storybook, storybook-static
|
|
55
|
+
* - File patterns: tsconfig*, build-*.ts
|
|
56
|
+
* - Root-level metadata: package.json, CLAUDE.md
|
|
57
|
+
*/
|
|
58
|
+
export const EXTENSION_COPY_EXCLUDE_PATTERN = /(?:^|[\\/])(?:node_modules|src|\.git|\.storybook|storybook-static)(?:[\\/]|$)|(?:^|[\\/])tsconfig[^/\\]*|(?:^|[\\/])build-[^/\\]*\.ts$|(?:^|[\\/])package\.json$|(?:^|[\\/])CLAUDE\.md$/;
|
|
40
59
|
// ---------------------------------------------------------------------------
|
|
41
60
|
// Plugin name validation
|
|
42
61
|
// ---------------------------------------------------------------------------
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,8EAA8E;AAC9E,0CAA0C;AAC1C,8EAA8E;AAE9E,OAAO,EAAkC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAEhH,8EAA8E;AAC9E,4DAA4D;AAC5D,8EAA8E;AAE9E,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/manifest.d.ts
CHANGED
|
@@ -19,6 +19,13 @@ interface PluginPackageJson {
|
|
|
19
19
|
readonly main: string;
|
|
20
20
|
readonly opentabs: PluginOpentabsField;
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Validate that a package name matches the opentabs plugin naming convention.
|
|
24
|
+
*
|
|
25
|
+
* Accepts `opentabs-plugin-<name>` (unscoped) and `@scope/opentabs-plugin-<name>` (scoped).
|
|
26
|
+
* The name portion after the prefix must be non-empty.
|
|
27
|
+
*/
|
|
28
|
+
declare const isValidPluginPackageName: (name: string) => boolean;
|
|
22
29
|
/**
|
|
23
30
|
* Parse and validate a raw JSON object as a PluginPackageJson.
|
|
24
31
|
*
|
|
@@ -27,6 +34,6 @@ interface PluginPackageJson {
|
|
|
27
34
|
* Returns a Result with the validated PluginPackageJson or a descriptive error.
|
|
28
35
|
*/
|
|
29
36
|
declare const parsePluginPackageJson: (json: unknown, sourcePath: string) => Result<PluginPackageJson, string>;
|
|
30
|
-
export { parsePluginPackageJson };
|
|
37
|
+
export { parsePluginPackageJson, isValidPluginPackageName };
|
|
31
38
|
export type { PluginOpentabsField, PluginPackageJson };
|
|
32
39
|
//# sourceMappingURL=manifest.d.ts.map
|
package/dist/manifest.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,uEAAuE;AACvE,UAAU,mBAAmB;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;CAChC;AAED,iEAAiE;AACjE,UAAU,iBAAiB;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;CACxC;
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,uEAAuE;AACvE,UAAU,mBAAmB;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;CAChC;AAED,iEAAiE;AACjE,UAAU,iBAAiB;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;CACxC;AAED;;;;;GAKG;AACH,QAAA,MAAM,wBAAwB,GAAI,MAAM,MAAM,KAAG,OAKhD,CAAC;AAEF;;;;;;GAMG;AACH,QAAA,MAAM,sBAAsB,GAAI,MAAM,OAAO,EAAE,YAAY,MAAM,KAAG,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAoEnG,CAAC;AAEF,OAAO,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,CAAC;AAC5D,YAAY,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,CAAC"}
|
package/dist/manifest.js
CHANGED
|
@@ -7,18 +7,16 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { err, ok } from './result.js';
|
|
9
9
|
/**
|
|
10
|
-
* Validate a
|
|
11
|
-
*
|
|
10
|
+
* Validate that a package name matches the opentabs plugin naming convention.
|
|
11
|
+
*
|
|
12
|
+
* Accepts `opentabs-plugin-<name>` (unscoped) and `@scope/opentabs-plugin-<name>` (scoped).
|
|
13
|
+
* The name portion after the prefix must be non-empty.
|
|
12
14
|
*/
|
|
13
15
|
const isValidPluginPackageName = (name) => {
|
|
14
|
-
if (name.startsWith('opentabs-plugin-'))
|
|
15
|
-
return true;
|
|
16
16
|
if (name.startsWith('@')) {
|
|
17
|
-
|
|
18
|
-
if (parts.length === 2 && (parts[1] ?? '').startsWith('opentabs-plugin-'))
|
|
19
|
-
return true;
|
|
17
|
+
return /^@[^/]+\/opentabs-plugin-.+$/.test(name);
|
|
20
18
|
}
|
|
21
|
-
return
|
|
19
|
+
return name.startsWith('opentabs-plugin-') && name.length > 'opentabs-plugin-'.length;
|
|
22
20
|
};
|
|
23
21
|
/**
|
|
24
22
|
* Parse and validate a raw JSON object as a PluginPackageJson.
|
|
@@ -84,5 +82,5 @@ const parsePluginPackageJson = (json, sourcePath) => {
|
|
|
84
82
|
},
|
|
85
83
|
});
|
|
86
84
|
};
|
|
87
|
-
export { parsePluginPackageJson };
|
|
85
|
+
export { parsePluginPackageJson, isValidPluginPackageName };
|
|
88
86
|
//# sourceMappingURL=manifest.js.map
|
package/dist/manifest.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAkBtC
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"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"}
|