@extension.dev/mcp 6.2.0 → 6.4.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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +103 -0
- package/README.md +12 -2
- package/bin/extension-mcp.js +1 -0
- package/dist/module.js +5094 -3216
- package/dist/src/lib/carrier.d.ts +0 -57
- package/dist/src/lib/credentials.d.ts +0 -9
- package/dist/src/lib/device-flow.d.ts +0 -6
- package/dist/src/lib/github-device.d.ts +0 -9
- package/dist/src/lib/guest-load-oracle.d.ts +0 -10
- package/dist/src/lib/login-flow.d.ts +0 -36
- package/dist/src/lib/preview-upload.d.ts +33 -0
- package/dist/src/lib/project-ignore.d.ts +10 -0
- package/dist/src/lib/publish.d.ts +0 -10
- package/dist/src/lib/registry-access.d.ts +29 -0
- package/dist/src/lib/registry.d.ts +7 -45
- package/dist/src/lib/share-record.d.ts +26 -0
- package/dist/src/lib/vendor/chrome-theme/chrome-theme-color-math.d.ts +84 -0
- package/dist/src/lib/vendor/chrome-theme/chrome-theme-reference.d.ts +270 -0
- package/dist/src/lib/vendor/chrome-theme/chrome-theme-resolve.d.ts +52 -0
- package/dist/src/tools/open.d.ts +1 -0
- package/dist/src/tools/preview-web.d.ts +76 -0
- package/dist/src/tools/release-list.d.ts +5 -0
- package/dist/src/tools/stop.d.ts +0 -1
- package/dist/src/tools/store-status.d.ts +5 -9
- package/dist/src/tools/theme-verify.d.ts +22 -0
- package/extensions/live-preview/chromium/action/index.js +9 -1
- package/extensions/live-preview/chromium/background/service_worker.js +10 -2
- package/extensions/live-preview/chromium/manifest.json +1 -0
- package/package.json +3 -3
- package/server.json +3 -3
|
@@ -1,73 +1,21 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The Extension.dev Live Preview carrier, bundled prebuilt in this package
|
|
3
|
-
* under extensions/live-preview/<engine>. extension_dev materializes it into
|
|
4
|
-
* the project's ./extensions folder (which Extension.js auto-scans and loads
|
|
5
|
-
* as a companion next to the user's extension), so the dev browser comes up
|
|
6
|
-
* carrier-equipped: web pages the carrier allowlists (inspect.extension.dev,
|
|
7
|
-
* localhost) can then watch the session's real-lane trace and pair with it.
|
|
8
|
-
*/
|
|
9
1
|
export declare const CARRIER_DIR_NAME = "extension-dev-live-preview";
|
|
10
2
|
export declare const CARRIER_EXTENSION_ID = "ibppeifnekhjjjmpjfiobccjlicbmgcb";
|
|
11
|
-
/** Where the carrier lands inside a project. */
|
|
12
3
|
export declare function carrierPath(projectPath: string): string;
|
|
13
|
-
/** True only for a directory carrying our marker, i.e. ours to delete. */
|
|
14
4
|
export declare function isManagedCarrier(projectPath: string): boolean;
|
|
15
5
|
export type CarrierRemoval = {
|
|
16
6
|
removed: boolean;
|
|
17
7
|
path: string;
|
|
18
|
-
/** Present when something was there but was NOT ours to touch. */
|
|
19
8
|
note?: string;
|
|
20
9
|
};
|
|
21
|
-
/**
|
|
22
|
-
* Remove the carrier from a project, marker-guarded.
|
|
23
|
-
*
|
|
24
|
-
* The trace swarm's most release-dangerous finding was that a debugging flag
|
|
25
|
-
* leaves a permanent companion extension in the project: it survived
|
|
26
|
-
* extension_stop, Extension.js auto-scans ./extensions, and the first
|
|
27
|
-
* `git add -A` vendors it. Nothing removed it, ever. Stop and build both call
|
|
28
|
-
* this now, and `extension_dev carrier: true` puts it back on demand.
|
|
29
|
-
*/
|
|
30
10
|
export declare function removeCarrier(projectPath: string): CarrierRemoval;
|
|
31
|
-
/**
|
|
32
|
-
* Keep the carrier out of the user's commits. The scaffolder runs `git init`
|
|
33
|
-
* with no initial commit, so the first `git add -A` in a project that ever ran
|
|
34
|
-
* with carrier: true vendors 460K of somebody else's extension.
|
|
35
|
-
* Returns the line added, or null when nothing needed doing.
|
|
36
|
-
*/
|
|
37
11
|
export declare function ensureCarrierIgnored(projectPath: string): string | null;
|
|
38
12
|
export type CarrierMaterialization = {
|
|
39
13
|
loaded: boolean;
|
|
40
14
|
path?: string;
|
|
41
15
|
note: string;
|
|
42
|
-
/** The .gitignore entry this run added, when it added one. */
|
|
43
16
|
gitignored?: string;
|
|
44
|
-
/**
|
|
45
|
-
* What the carrier lane CANNOT do, stated at the moment it is handed over.
|
|
46
|
-
* The trace swarm's top finding was that the real lane's boundaries were
|
|
47
|
-
* discoverable only by experiment: 14 personas independently filed the
|
|
48
|
-
* carrier-identity scoping as a severe bug, and 10 more expected the trace
|
|
49
|
-
* to show their own extension's calls. Both are honest constraints; neither
|
|
50
|
-
* was written down anywhere the caller would look.
|
|
51
|
-
*/
|
|
52
17
|
limitations?: string[];
|
|
53
|
-
/**
|
|
54
|
-
* The graduation path, stated next to the shared-identity limitation so the
|
|
55
|
-
* caller is not left at a dead end. The carrier lane is the SHARED real lane
|
|
56
|
-
* (calls run as the carrier); but the guest is ALREADY loaded as itself in
|
|
57
|
-
* this same session, so its OWN storage, identity and messaging are reached by
|
|
58
|
-
* driving the guest directly with the control verbs, not the carrier bridge.
|
|
59
|
-
* This is the agent-lane twin of the inspect Trace tab's "load as your own
|
|
60
|
-
* extension" affordance: here the extension is already loaded, so graduating
|
|
61
|
-
* means targeting it, not launching it.
|
|
62
|
-
*/
|
|
63
18
|
graduation?: string;
|
|
64
|
-
/**
|
|
65
|
-
* How to actually DRIVE the real lane. Seven personas reached a
|
|
66
|
-
* permanently empty trace and concluded the feature was broken, because
|
|
67
|
-
* nothing in the 33 tool schemas, this note, or the rendered page named the
|
|
68
|
-
* carrier's extension id or its message envelopes. Every persona that did
|
|
69
|
-
* reach the real lane used out-of-band knowledge of the emulator source.
|
|
70
|
-
*/
|
|
71
19
|
bridgeProtocol?: {
|
|
72
20
|
carrierExtensionId: string;
|
|
73
21
|
allowedOrigins: string;
|
|
@@ -75,9 +23,4 @@ export type CarrierMaterialization = {
|
|
|
75
23
|
example: string;
|
|
76
24
|
};
|
|
77
25
|
};
|
|
78
|
-
/**
|
|
79
|
-
* Copy the bundled carrier into <projectPath>/extensions/<CARRIER_DIR_NAME>.
|
|
80
|
-
* Refuses to touch an existing directory that lacks our marker file (it is
|
|
81
|
-
* the user's, not ours); otherwise replaces it so version updates propagate.
|
|
82
|
-
*/
|
|
83
26
|
export declare function materializeCarrier(projectPath: string, browser: string): CarrierMaterialization;
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
export interface StoredCredentials {
|
|
2
2
|
version: 1;
|
|
3
|
-
/** The HMAC access token the publish path sends as `Bearer`. */
|
|
4
3
|
token: string;
|
|
5
4
|
workspaceSlug: string;
|
|
6
5
|
projectSlug: string;
|
|
7
|
-
/** Token expiry as unix epoch seconds (0 if unknown). */
|
|
8
6
|
expiresAt: number;
|
|
9
|
-
/** Platform base URL the token was minted against. */
|
|
10
7
|
api: string;
|
|
11
|
-
/** Which device flow minted this token: extension.dev-gated or GitHub-direct. */
|
|
12
8
|
provider?: "extensiondev" | "github";
|
|
13
9
|
}
|
|
14
10
|
export declare function credentialsPath(): string;
|
|
@@ -18,9 +14,4 @@ export declare function clearCredentials(): {
|
|
|
18
14
|
cleared: boolean;
|
|
19
15
|
path: string;
|
|
20
16
|
};
|
|
21
|
-
/**
|
|
22
|
-
* Return stored credentials only if the token has not expired. Used by the
|
|
23
|
-
* publish token resolution so an expired local token falls through cleanly to
|
|
24
|
-
* "no token" instead of producing a 401 from the platform.
|
|
25
|
-
*/
|
|
26
17
|
export declare function readValidCredentials(nowSeconds?: number): StoredCredentials | null;
|
|
@@ -23,12 +23,6 @@ export type DevicePollResult = {
|
|
|
23
23
|
reason: "pending" | "denied" | "expired" | "error";
|
|
24
24
|
message?: string;
|
|
25
25
|
};
|
|
26
|
-
/**
|
|
27
|
-
* Poll the extension.dev token endpoint until approved or the budget runs out.
|
|
28
|
-
* The budget is kept under the MCP client request timeout; the tool re-invokes
|
|
29
|
-
* with the same deviceCode to keep waiting (idempotent), mirroring the GitHub
|
|
30
|
-
* poll's two-phase contract.
|
|
31
|
-
*/
|
|
32
26
|
export declare function pollDeviceToken(args: {
|
|
33
27
|
apiBase: string;
|
|
34
28
|
path: string;
|
|
@@ -2,9 +2,7 @@ export interface DeviceCodeStart {
|
|
|
2
2
|
deviceCode: string;
|
|
3
3
|
userCode: string;
|
|
4
4
|
verificationUri: string;
|
|
5
|
-
/** Minimum seconds to wait between polls. */
|
|
6
5
|
interval: number;
|
|
7
|
-
/** Seconds until the device code expires. */
|
|
8
6
|
expiresIn: number;
|
|
9
7
|
}
|
|
10
8
|
export type PollResult = {
|
|
@@ -22,13 +20,6 @@ export declare function startDeviceCode(args: {
|
|
|
22
20
|
scope?: string;
|
|
23
21
|
fetchImpl?: FetchImpl;
|
|
24
22
|
}): Promise<DeviceCodeStart>;
|
|
25
|
-
/**
|
|
26
|
-
* Poll for the access token until the budget elapses. A budget shorter than
|
|
27
|
-
* the device-code lifetime lets a caller (e.g. an MCP tool that must return
|
|
28
|
-
* promptly) poll in bounded slices and report "pending" between calls; a long
|
|
29
|
-
* budget (a blocking CLI) waits the whole time. Returns `pending` only on
|
|
30
|
-
* budget exhaustion; `expired`/`denied` are terminal.
|
|
31
|
-
*/
|
|
32
23
|
export declare function pollForToken(args: {
|
|
33
24
|
clientId: string;
|
|
34
25
|
deviceCode: string;
|
|
@@ -11,16 +11,6 @@ export type GuestLoadCheck = {
|
|
|
11
11
|
cdpPort?: number;
|
|
12
12
|
reason: string;
|
|
13
13
|
};
|
|
14
|
-
/**
|
|
15
|
-
* The BUGS_TO_FIX §83 oracle: ask the BROWSER whether the guest actually loaded,
|
|
16
|
-
* instead of trusting the engine's ready.json. Chrome refusing --load-extension
|
|
17
|
-
* is invisible to every engine surface (ready.json stamps status:ready, empty
|
|
18
|
-
* logs), so the only trustworthy "did the guest load" signal is a
|
|
19
|
-
* chrome-extension:// target in the browser's own CDP /json list. The engine's
|
|
20
|
-
* devtools companion is always present and is not the guest; a NON-companion
|
|
21
|
-
* extension target is. Never throws: an unreachable endpoint returns
|
|
22
|
-
* checked:false so callers can degrade instead of failing.
|
|
23
|
-
*/
|
|
24
14
|
export declare function verifyGuestLoaded(projectPath: string, browser: string, options?: {
|
|
25
15
|
waitMs?: number;
|
|
26
16
|
timeoutMs?: number;
|
|
@@ -1,22 +1,7 @@
|
|
|
1
1
|
import { type StoredCredentials } from "./credentials";
|
|
2
|
-
/**
|
|
3
|
-
* The platform clamps CLI token TTL to at most 7 days (server-owned; this
|
|
4
|
-
* client only states the truth). Every token surface repeats it so CI authors
|
|
5
|
-
* learn the rotation contract up front instead of from a 401 a week after
|
|
6
|
-
* wiring the pipeline. Links the console's Access tokens page when the
|
|
7
|
-
* project is known.
|
|
8
|
-
*/
|
|
9
2
|
export declare function tokenTtlNote(workspaceSlug?: string, projectSlug?: string): string;
|
|
10
3
|
type FetchImpl = typeof fetch;
|
|
11
4
|
export declare function resolveApiBase(api?: string): string;
|
|
12
|
-
/**
|
|
13
|
-
* Validate the platform base URL BEFORE we attach a bearer token to a request to
|
|
14
|
-
* it. SECURITY: the `api` arg / EXTENSION_DEV_API_URL is operator-supplied, but a
|
|
15
|
-
* hostile value (e.g. via prompt-injection in the client) could redirect the
|
|
16
|
-
* token to an attacker. The access token must never leave over plaintext or go to
|
|
17
|
-
* an arbitrary scheme, so we require https -- allowing http only for localhost
|
|
18
|
-
* dev. Returns the normalized base (no trailing slash) or an error message.
|
|
19
|
-
*/
|
|
20
5
|
export declare function safeApiBase(raw: string): {
|
|
21
6
|
ok: true;
|
|
22
7
|
base: string;
|
|
@@ -25,10 +10,6 @@ export declare function safeApiBase(raw: string): {
|
|
|
25
10
|
message: string;
|
|
26
11
|
};
|
|
27
12
|
export interface LoginConfig {
|
|
28
|
-
/**
|
|
29
|
-
* "extensiondev": the extension.dev-gated device flow (branded /device, GitHub
|
|
30
|
-
* federated server-side). "github": the legacy GitHub-direct device flow.
|
|
31
|
-
*/
|
|
32
13
|
provider: "extensiondev" | "github";
|
|
33
14
|
clientId: string;
|
|
34
15
|
scope: string;
|
|
@@ -36,29 +17,12 @@ export interface LoginConfig {
|
|
|
36
17
|
deviceTokenUrl: string;
|
|
37
18
|
verificationUri: string;
|
|
38
19
|
}
|
|
39
|
-
/**
|
|
40
|
-
* Resolve how the device flow should authenticate. The server's public config
|
|
41
|
-
* picks the provider (extension.dev-gated once its device endpoints are live,
|
|
42
|
-
* else GitHub-direct). EXTENSION_DEV_GITHUB_CLIENT_ID forces the GitHub flow
|
|
43
|
-
* (useful when pointing at a self-hosted platform).
|
|
44
|
-
*/
|
|
45
20
|
export declare function fetchLoginConfig(apiBase: string, fetchImpl?: FetchImpl): Promise<LoginConfig>;
|
|
46
|
-
/**
|
|
47
|
-
* Persist a `{ token, expiresAt, workspaceSlug, projectSlug }` response (the
|
|
48
|
-
* shape returned by BOTH the GitHub exchange endpoint and the extension.dev
|
|
49
|
-
* device/token endpoint) to the local credentials file. Records which provider
|
|
50
|
-
* minted it.
|
|
51
|
-
*/
|
|
52
21
|
export declare function persistTokenResponse(args: {
|
|
53
22
|
apiBase: string;
|
|
54
23
|
data: Record<string, unknown>;
|
|
55
24
|
provider: "extensiondev" | "github";
|
|
56
25
|
}): StoredCredentials;
|
|
57
|
-
/**
|
|
58
|
-
* Trade a verified GitHub user token for a project-scoped access token and
|
|
59
|
-
* write it to the local credentials file. Returns the stored credentials
|
|
60
|
-
* (token included for the caller's in-memory use; never logged).
|
|
61
|
-
*/
|
|
62
26
|
export declare function exchangeAndPersist(args: {
|
|
63
27
|
apiBase: string;
|
|
64
28
|
githubToken: string;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
type FetchImpl = typeof fetch;
|
|
2
|
+
export interface PreviewUploadFile {
|
|
3
|
+
path: string;
|
|
4
|
+
content: string;
|
|
5
|
+
encoding: "utf8" | "base64";
|
|
6
|
+
}
|
|
7
|
+
export interface PreviewUploadResult {
|
|
8
|
+
artifactId: string;
|
|
9
|
+
previewUrl: string;
|
|
10
|
+
zipUrl?: string;
|
|
11
|
+
revokeUrl?: string;
|
|
12
|
+
expiresAt?: string;
|
|
13
|
+
}
|
|
14
|
+
export type PreviewUploadOutcome = {
|
|
15
|
+
ok: true;
|
|
16
|
+
data: PreviewUploadResult;
|
|
17
|
+
} | {
|
|
18
|
+
ok: false;
|
|
19
|
+
error: {
|
|
20
|
+
name: string;
|
|
21
|
+
message: string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export declare function collectDistFiles(distDir: string): PreviewUploadFile[];
|
|
25
|
+
export declare function uploadPreview(options: {
|
|
26
|
+
distDir: string;
|
|
27
|
+
manifest: Record<string, unknown>;
|
|
28
|
+
browser: string;
|
|
29
|
+
api?: string;
|
|
30
|
+
token?: string;
|
|
31
|
+
fetchImpl?: FetchImpl;
|
|
32
|
+
}): Promise<PreviewUploadOutcome>;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type ProjectIgnoreState = "added" | "already-ignored" | "not-a-repo" | "failed";
|
|
2
|
+
export interface ProjectIgnoreOutcome {
|
|
3
|
+
state: ProjectIgnoreState;
|
|
4
|
+
entry: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function ensureProjectIgnored(projectPath: string, options: {
|
|
7
|
+
entry: string;
|
|
8
|
+
aliases?: string[];
|
|
9
|
+
comment: string;
|
|
10
|
+
}): ProjectIgnoreOutcome;
|
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
type FetchImpl = typeof fetch;
|
|
2
|
-
/** Resolve the access token: EXTENSION_DEV_TOKEN env first, then the login creds file. */
|
|
3
2
|
export declare function resolveToken(): string;
|
|
4
3
|
export interface PublishOptions {
|
|
5
|
-
/** Share-link lifetime in hours (1-168, platform default 24). */
|
|
6
4
|
ttlHours?: number;
|
|
7
|
-
/** Pin the share URL to a specific build sha. */
|
|
8
5
|
buildSha?: string;
|
|
9
|
-
/** Platform base URL (defaults to https://www.extension.dev or EXTENSION_DEV_API_URL). */
|
|
10
6
|
api?: string;
|
|
11
|
-
/** Explicit token; defaults to resolveToken(). */
|
|
12
7
|
token?: string;
|
|
13
8
|
fetchImpl?: FetchImpl;
|
|
14
9
|
}
|
|
@@ -22,10 +17,5 @@ export type PublishResult = {
|
|
|
22
17
|
message: string;
|
|
23
18
|
};
|
|
24
19
|
};
|
|
25
|
-
/**
|
|
26
|
-
* Publish the project the token is scoped to and return the platform
|
|
27
|
-
* response (shareUrl, visibility, ...). The publish target is identified by
|
|
28
|
-
* the token's claims (workspaceSlug/projectSlug), so no project path is sent.
|
|
29
|
-
*/
|
|
30
20
|
export declare function publish(options?: PublishOptions): Promise<PublishResult>;
|
|
31
21
|
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ProjectRef } from "./registry";
|
|
2
|
+
export type AccessGrant = {
|
|
3
|
+
status: "ok";
|
|
4
|
+
token: string;
|
|
5
|
+
expiresAt: number;
|
|
6
|
+
} | {
|
|
7
|
+
status: "public";
|
|
8
|
+
} | {
|
|
9
|
+
status: "no-credential";
|
|
10
|
+
} | {
|
|
11
|
+
status: "denied";
|
|
12
|
+
httpStatus?: number;
|
|
13
|
+
message: string;
|
|
14
|
+
};
|
|
15
|
+
export interface AccessTokenCacheOptions {
|
|
16
|
+
fetchImpl?: typeof fetch;
|
|
17
|
+
nowSeconds?: () => number;
|
|
18
|
+
}
|
|
19
|
+
export declare class RegistryAccessTokens {
|
|
20
|
+
private readonly cache;
|
|
21
|
+
private readonly fetchImpl;
|
|
22
|
+
private readonly nowSeconds;
|
|
23
|
+
constructor(options?: AccessTokenCacheOptions);
|
|
24
|
+
peek(ref: ProjectRef): string;
|
|
25
|
+
get(ref: ProjectRef, apiHint?: string): Promise<AccessGrant>;
|
|
26
|
+
private mint;
|
|
27
|
+
}
|
|
28
|
+
export declare const defaultRegistryAccessTokens: RegistryAccessTokens;
|
|
29
|
+
export declare function withAccessToken(url: string, token: string): string;
|
|
@@ -1,42 +1,20 @@
|
|
|
1
|
+
import { type RegistryAccessTokens } from "./registry-access";
|
|
1
2
|
import { type Origins } from "@extension.dev/urls/origins";
|
|
2
3
|
export declare const REGISTRY_BASE_DEFAULT: string;
|
|
3
|
-
/**
|
|
4
|
-
* Resolve the fleet origins from the MCP's env vars, once per call. Console,
|
|
5
|
-
* registry, and media all DERIVE from the platform base (`EXTENSION_DEV_API_URL`
|
|
6
|
-
* or a per-tool `api`): point that at a local stack and every dashboard link the
|
|
7
|
-
* MCP hands back follows to the dev host (`console.extension.localhost`) instead
|
|
8
|
-
* of silently pointing at prod. Explicit per-host env vars still win. Falls back
|
|
9
|
-
* to production when nothing is set. The dev-derivation lives in
|
|
10
|
-
* `@extension.dev/urls` so it stays identical to what the apps resolve.
|
|
11
|
-
*/
|
|
12
4
|
export declare function mcpOrigins(apiHint?: string): Origins;
|
|
13
|
-
/** Base origin of the console dashboard, dev-aware (no trailing slash). */
|
|
14
5
|
export declare function consoleBase(apiHint?: string): string;
|
|
15
6
|
export declare function registryBase(): string;
|
|
16
7
|
export interface ProjectRef {
|
|
17
8
|
workspace: string;
|
|
18
9
|
project: string;
|
|
19
10
|
}
|
|
20
|
-
/**
|
|
21
|
-
* Resolve which project registry reads should target: explicit overrides
|
|
22
|
-
* first, then the stored login's workspace/project slugs. Returns null when
|
|
23
|
-
* neither names a project (e.g. token came from EXTENSION_DEV_TOKEN and no
|
|
24
|
-
* login was ever stored).
|
|
25
|
-
*/
|
|
26
11
|
export declare function resolveProjectRef(overrides?: {
|
|
27
12
|
workspace?: string;
|
|
28
13
|
project?: string;
|
|
29
14
|
}): ProjectRef | null;
|
|
30
|
-
/** URL of a file under the project's `_extension-dev/` registry directory. */
|
|
31
15
|
export declare function registryFileUrl(ref: ProjectRef, file: string): string;
|
|
32
|
-
/**
|
|
33
|
-
* Console page URL for the project (builds, releases/new, stores, ...). The
|
|
34
|
-
* origin is dev-aware; the path comes from the shared route contract so a
|
|
35
|
-
* console route rename is caught in one place. Pass `apiHint` (a tool's `api`
|
|
36
|
-
* arg) so the link matches that call's environment; otherwise it follows
|
|
37
|
-
* `EXTENSION_DEV_API_URL`/`EXTENSION_DEV_CONSOLE_URL`.
|
|
38
|
-
*/
|
|
39
16
|
export declare function consoleProjectUrl(ref: ProjectRef | null, page: string, apiHint?: string): string;
|
|
17
|
+
export declare function userlandProjectUrl(ref: ProjectRef | null, page?: string, apiHint?: string): string;
|
|
40
18
|
export type RegistryFetchResult<T> = {
|
|
41
19
|
ok: true;
|
|
42
20
|
json: T;
|
|
@@ -45,27 +23,19 @@ export type RegistryFetchResult<T> = {
|
|
|
45
23
|
status?: number;
|
|
46
24
|
message: string;
|
|
47
25
|
};
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
export declare function fetchRegistryJson<T = unknown>(url: string, fetchImpl?: typeof fetch): Promise<RegistryFetchResult<T>>;
|
|
26
|
+
export declare function fetchRegistryJson<T = unknown>(url: string, fetchImpl?: typeof fetch, options?: {
|
|
27
|
+
ref?: ProjectRef | null;
|
|
28
|
+
api?: string;
|
|
29
|
+
tokens?: RegistryAccessTokens;
|
|
30
|
+
}): Promise<RegistryFetchResult<T>>;
|
|
54
31
|
export interface ChannelEntry {
|
|
55
32
|
channel: string;
|
|
56
33
|
sha: string;
|
|
57
34
|
buildId?: string;
|
|
58
35
|
version?: string;
|
|
59
|
-
/** ISO timestamp parsed from the channel row when the writer recorded one. */
|
|
60
36
|
promotedAt?: string;
|
|
61
37
|
description?: string;
|
|
62
38
|
}
|
|
63
|
-
/**
|
|
64
|
-
* Normalize the registry's channels.json (a map of channel -> row) into a
|
|
65
|
-
* list. `promotedAt` is not a first-class field in the file today; the
|
|
66
|
-
* promote workflow stamps it into the description ("Promoted from X on
|
|
67
|
-
* <ISO>"), so it is parsed back out when present.
|
|
68
|
-
*/
|
|
69
39
|
export declare function parseChannels(json: unknown): ChannelEntry[];
|
|
70
40
|
export interface BuildIndexItem {
|
|
71
41
|
sha: string;
|
|
@@ -78,13 +48,5 @@ export interface BuildIndexItem {
|
|
|
78
48
|
timestamp?: string;
|
|
79
49
|
browsers?: string[];
|
|
80
50
|
}
|
|
81
|
-
/** Normalize `_extension-dev/builds/index.json` items (schemaVersion 3). */
|
|
82
51
|
export declare function parseBuildIndex(json: unknown): BuildIndexItem[];
|
|
83
|
-
/**
|
|
84
|
-
* Derive the project mirror repo's Actions URL from any GitHub run URL the
|
|
85
|
-
* registry exposes (stores/status.json carries one from the mirror's own
|
|
86
|
-
* runs: https://github.com/extensiondev/<ownerGithubId>--<projectId>/actions/
|
|
87
|
-
* runs/<id>). Only trusts the extensiondev org so a user-source-repo run URL
|
|
88
|
-
* (build.json's runUrl) is never mistaken for the mirror.
|
|
89
|
-
*/
|
|
90
52
|
export declare function mirrorActionsUrlFromRunUrl(runUrl: unknown): string | null;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type ProjectIgnoreState } from "./project-ignore";
|
|
2
|
+
export declare const SHARE_STATE_DIR = ".extension.dev";
|
|
3
|
+
export declare const SHARE_RECORD_FILE = "shared-previews.json";
|
|
4
|
+
export interface SharedPreviewEntry {
|
|
5
|
+
sharedAt: string;
|
|
6
|
+
previewUrl: string;
|
|
7
|
+
artifactId: string;
|
|
8
|
+
revokeUrl?: string;
|
|
9
|
+
expiresAt?: string;
|
|
10
|
+
zipUrl?: string;
|
|
11
|
+
name?: string;
|
|
12
|
+
version?: string;
|
|
13
|
+
browser?: string;
|
|
14
|
+
distDir?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface ShareRecordOutcome {
|
|
17
|
+
recorded: boolean;
|
|
18
|
+
path: string;
|
|
19
|
+
entries?: number;
|
|
20
|
+
gitignored?: ProjectIgnoreState;
|
|
21
|
+
preserved?: string;
|
|
22
|
+
note: string;
|
|
23
|
+
warning?: string;
|
|
24
|
+
}
|
|
25
|
+
export declare function sharedPreviewsPath(projectPath: string): string;
|
|
26
|
+
export declare function recordSharedPreview(projectPath: string, entry: SharedPreviewEntry): ShareRecordOutcome;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exact TypeScript ports of the Chromium color math used by the browser
|
|
3
|
+
* theme pipeline (ui/gfx/color_utils.cc, refs/heads/main, cached under
|
|
4
|
+
* parity/chromium-src-cache, fetched 2026-07-04).
|
|
5
|
+
*
|
|
6
|
+
* Every function mirrors its Chromium namesake so the theme resolver can
|
|
7
|
+
* reproduce Chrome's derived colors bit-for-bit. When editing, re-read the
|
|
8
|
+
* cited source instead of "fixing" the math: several rules (HSL lightness
|
|
9
|
+
* shift in RGB space, the luminance midpoint, alpha normalization) are
|
|
10
|
+
* deliberately not the textbook versions.
|
|
11
|
+
*/
|
|
12
|
+
export interface RgbaColor {
|
|
13
|
+
r: number;
|
|
14
|
+
g: number;
|
|
15
|
+
b: number;
|
|
16
|
+
/** 0..255, like SkColor. */
|
|
17
|
+
a: number;
|
|
18
|
+
}
|
|
19
|
+
/** HSL tint triple; -1 in a channel means "leave unchanged". */
|
|
20
|
+
export interface HslTint {
|
|
21
|
+
h: number;
|
|
22
|
+
s: number;
|
|
23
|
+
l: number;
|
|
24
|
+
}
|
|
25
|
+
/** color_utils.cc:35 g_darkest_color = gfx::kGoogleGrey900. */
|
|
26
|
+
export declare const DARKEST_COLOR: RgbaColor;
|
|
27
|
+
/**
|
|
28
|
+
* color_utils.cc:40 g_luminance_midpoint: the luminance where white and
|
|
29
|
+
* kGoogleGrey900 contrast equally. IsDark() pivots here, NOT at 0.5.
|
|
30
|
+
*/
|
|
31
|
+
export declare const LUMINANCE_MIDPOINT = 0.211692036;
|
|
32
|
+
/** color_utils.cc kMinimumReadableContrastRatio. */
|
|
33
|
+
export declare const MINIMUM_READABLE_CONTRAST_RATIO = 4.5;
|
|
34
|
+
export declare function rgba(r: number, g: number, b: number, a?: number): RgbaColor;
|
|
35
|
+
export declare function parseHexColor(hex: string): RgbaColor;
|
|
36
|
+
export declare function toHexColor(color: RgbaColor): string;
|
|
37
|
+
/** base::ClampRound for the 0..255 channel domain. */
|
|
38
|
+
export declare function clampRound(value: number): number;
|
|
39
|
+
/** color_utils.cc:425 GetRelativeLuminance4f. */
|
|
40
|
+
export declare function relativeLuminance(color: RgbaColor): number;
|
|
41
|
+
/** color_utils.cc:412 GetContrastRatio (luminance form). */
|
|
42
|
+
export declare function contrastRatioFromLuminance(a: number, b: number): number;
|
|
43
|
+
/** color_utils.cc:402 GetContrastRatio. */
|
|
44
|
+
export declare function contrastRatio(a: RgbaColor, b: RgbaColor): number;
|
|
45
|
+
/** color_utils.cc:617 IsDark: luminance below the grey900/white midpoint. */
|
|
46
|
+
export declare function isDarkChromium(color: RgbaColor): boolean;
|
|
47
|
+
/** color_utils.cc:621 GetColorWithMaxContrast: white or kGoogleGrey900. */
|
|
48
|
+
export declare function getColorWithMaxContrast(color: RgbaColor): RgbaColor;
|
|
49
|
+
/** color_utils.cc:625 GetEndpointColorWithMinContrast. */
|
|
50
|
+
export declare function getEndpointColorWithMinContrast(color: RgbaColor): RgbaColor;
|
|
51
|
+
/** color_utils.cc:436 SkColorToHSL. */
|
|
52
|
+
export declare function skColorToHsl(color: RgbaColor): HslTint;
|
|
53
|
+
/** color_utils.cc:467 HSLToSkColor. */
|
|
54
|
+
export declare function hslToSkColor(hsl: HslTint, alpha: number): RgbaColor;
|
|
55
|
+
/** color_utils.cc:518 MakeHSLShiftValid: out-of-range channels become -1. */
|
|
56
|
+
export declare function makeHslShiftValid(tint: HslTint): HslTint;
|
|
57
|
+
/** A tint that leaves the color unchanged. */
|
|
58
|
+
export declare const HSL_NO_TINT: HslTint;
|
|
59
|
+
/**
|
|
60
|
+
* color_utils.cc:534 HSLShift, Chrome's tint operation. NOT a plain HSL
|
|
61
|
+
* replacement: hue is replaced, saturation is scaled around 0.5, and the
|
|
62
|
+
* lightness shift happens in RGB space ("in the style of popular image
|
|
63
|
+
* editors").
|
|
64
|
+
*/
|
|
65
|
+
export declare function hslShift(color: RgbaColor, shift: HslTint): RgbaColor;
|
|
66
|
+
/**
|
|
67
|
+
* color_utils.cc:581 AlphaBlend(float): weights each side by its own alpha
|
|
68
|
+
* times the blend factor (a foreground with alpha participates less).
|
|
69
|
+
*/
|
|
70
|
+
export declare function alphaBlend(foreground: RgbaColor, background: RgbaColor, alpha: number): RgbaColor;
|
|
71
|
+
/** color_utils.cc:612 GetResultingPaintColor: composite fg over opaque bg. */
|
|
72
|
+
export declare function getResultingPaintColor(foreground: RgbaColor, background: RgbaColor): RgbaColor;
|
|
73
|
+
export interface BlendResult {
|
|
74
|
+
alpha: number;
|
|
75
|
+
color: RgbaColor;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* color_utils.cc:647 BlendForMinContrast: binary-search the smallest blend
|
|
79
|
+
* of the target foreground into the default foreground that reaches
|
|
80
|
+
* `targetContrastRatio` against `background`.
|
|
81
|
+
*/
|
|
82
|
+
export declare function blendForMinContrast(defaultForeground: RgbaColor, background: RgbaColor, highContrastForeground?: RgbaColor, targetContrastRatio?: number): BlendResult;
|
|
83
|
+
/** browser_theme_pack.cc:605 IsColorGrayscale: channel range under 9. */
|
|
84
|
+
export declare function isColorGrayscale(color: RgbaColor): boolean;
|