@stacksjs/browser-extension 0.70.65
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/LICENSE.md +21 -0
- package/README.md +3 -0
- package/dist/build.d.ts +16 -0
- package/dist/build.js +64 -0
- package/dist/config.d.ts +17 -0
- package/dist/config.js +16 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +5 -0
- package/dist/manifest.d.ts +44 -0
- package/dist/manifest.js +60 -0
- package/dist/package.d.ts +15 -0
- package/dist/package.js +21 -0
- package/dist/types.d.ts +64 -0
- package/dist/types.js +0 -0
- package/package.json +61 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Open Web Foundation
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
package/dist/build.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { BuildOptions, ExtensionConfig, ExtensionTarget } from './types';
|
|
2
|
+
/** Resolve the output directory for a target. */
|
|
3
|
+
export declare function resolveOutdir(config: ExtensionConfig, target: ExtensionTarget, override?: string): string;
|
|
4
|
+
/**
|
|
5
|
+
* Build a browser extension for one target: bundle stx pages → HTML, content +
|
|
6
|
+
* background scripts → classic IIFE bundles, copy static assets, and write the
|
|
7
|
+
* generated manifest.json. Mirrors the hand-rolled build-extension.ts every
|
|
8
|
+
* extension used to carry, now driven purely by `ExtensionConfig`.
|
|
9
|
+
*
|
|
10
|
+
* The stx page bundling is delegated to `bun-plugin-stx` (loaded lazily so the
|
|
11
|
+
* package doesn't hard-depend on it when only the manifest/packaging APIs are
|
|
12
|
+
* used).
|
|
13
|
+
*/
|
|
14
|
+
export declare function buildExtension(config: ExtensionConfig, options: BuildOptions): Promise<{ outdir: string, target: ExtensionTarget }>;
|
|
15
|
+
/** Build every configured target. */
|
|
16
|
+
export declare function buildAllTargets(config: ExtensionConfig, options: Omit<BuildOptions, 'target'>): Promise<void>;
|
package/dist/build.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { cp, mkdir, rm } from "node:fs/promises";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
|
+
import { contentScriptOut, generateManifest } from "./manifest";
|
|
5
|
+
export function resolveOutdir(config, target, override) {
|
|
6
|
+
if (override)
|
|
7
|
+
return override;
|
|
8
|
+
if (typeof config.outdir === "string")
|
|
9
|
+
return config.outdir;
|
|
10
|
+
if (config.outdir?.[target])
|
|
11
|
+
return config.outdir[target];
|
|
12
|
+
return target === "firefox" ? "dist-firefox" : "dist";
|
|
13
|
+
}
|
|
14
|
+
export async function buildExtension(config, options) {
|
|
15
|
+
const target = options.target ?? "chrome", cwd = options.cwd ?? process.cwd(), outdir = resolve(cwd, resolveOutdir(config, target, options.outdir)), minify = options.minify ?? !0;
|
|
16
|
+
await rm(outdir, { recursive: !0, force: !0 });
|
|
17
|
+
await mkdir(outdir, { recursive: !0 });
|
|
18
|
+
if (config.public) {
|
|
19
|
+
const pub = resolve(cwd, config.public);
|
|
20
|
+
if (existsSync(pub))
|
|
21
|
+
await cp(pub, outdir, { recursive: !0 });
|
|
22
|
+
}
|
|
23
|
+
const pageEntries = collectPages(config, cwd);
|
|
24
|
+
if (pageEntries.length) {
|
|
25
|
+
const { default: stxPlugin } = await import("bun-plugin-stx");
|
|
26
|
+
await Bun.build({
|
|
27
|
+
entrypoints: pageEntries,
|
|
28
|
+
outdir,
|
|
29
|
+
target: "browser",
|
|
30
|
+
minify,
|
|
31
|
+
plugins: [stxPlugin]
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
const scripts = [];
|
|
35
|
+
if (config.background)
|
|
36
|
+
scripts.push({ entry: config.background, out: "background.js" });
|
|
37
|
+
for (const cs of config.content ?? [])
|
|
38
|
+
scripts.push({ entry: cs.entry, out: contentScriptOut(cs.entry, cs.out) });
|
|
39
|
+
await Promise.all(scripts.map(async ({ entry, out }) => {
|
|
40
|
+
const result = await Bun.build({
|
|
41
|
+
entrypoints: [resolve(cwd, entry)],
|
|
42
|
+
target: "browser",
|
|
43
|
+
format: "iife",
|
|
44
|
+
minify
|
|
45
|
+
});
|
|
46
|
+
if (!result.success)
|
|
47
|
+
throw Error(`[browser-extension] failed to build ${entry}: ${result.logs.join(`
|
|
48
|
+
`)}`);
|
|
49
|
+
await Bun.write(join(outdir, out), await result.outputs[0].text());
|
|
50
|
+
}));
|
|
51
|
+
await Bun.write(join(outdir, "manifest.json"), `${JSON.stringify(generateManifest(config, { version: options.version, target }), null, 2)}
|
|
52
|
+
`);
|
|
53
|
+
return { outdir, target };
|
|
54
|
+
}
|
|
55
|
+
function collectPages(config, cwd) {
|
|
56
|
+
const p = config.pages;
|
|
57
|
+
if (!p)
|
|
58
|
+
return [];
|
|
59
|
+
return [p.popup, p.options, ...Object.values(p.extra ?? {})].filter(Boolean).map((e) => resolve(cwd, e));
|
|
60
|
+
}
|
|
61
|
+
export async function buildAllTargets(config, options) {
|
|
62
|
+
for (const target of config.targets ?? ["chrome", "firefox"])
|
|
63
|
+
await buildExtension(config, { ...options, target });
|
|
64
|
+
}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ExtensionConfig } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Identity helper for authoring `config/extension.ts` with full type-checking
|
|
4
|
+
* and editor completion:
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* // config/extension.ts
|
|
8
|
+
* import { defineExtension } from '@stacksjs/browser-extension'
|
|
9
|
+
* export default defineExtension({ name: 'My Extension', description: '…', … })
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export declare function defineExtension(config: ExtensionConfig): ExtensionConfig;
|
|
13
|
+
/**
|
|
14
|
+
* Load the project's extension config from `config/extension.ts` (default
|
|
15
|
+
* export). Returns null when the project has no extension config.
|
|
16
|
+
*/
|
|
17
|
+
export declare function loadExtensionConfig(cwd?: string): Promise<ExtensionConfig | null>;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
export function defineExtension(config) {
|
|
4
|
+
return config;
|
|
5
|
+
}
|
|
6
|
+
export async function loadExtensionConfig(cwd = process.cwd()) {
|
|
7
|
+
for (const rel of ["config/extension.ts", "extension.config.ts"]) {
|
|
8
|
+
const path = resolve(cwd, rel);
|
|
9
|
+
if (!existsSync(path))
|
|
10
|
+
continue;
|
|
11
|
+
const mod = await import(path), config = mod.default ?? mod.extension ?? mod.config;
|
|
12
|
+
if (config)
|
|
13
|
+
return config;
|
|
14
|
+
}
|
|
15
|
+
return null;
|
|
16
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @stacksjs/browser-extension
|
|
3
|
+
*
|
|
4
|
+
* Build MV3 browser extensions (Chrome + Firefox) from a single
|
|
5
|
+
* `ExtensionConfig` — manifest generation, content/background script bundling,
|
|
6
|
+
* stx pages, declarativeNetRequest rulesets, and store-ready packaging — with
|
|
7
|
+
* none of the per-project boilerplate.
|
|
8
|
+
*/
|
|
9
|
+
export * from './build';
|
|
10
|
+
export * from './config';
|
|
11
|
+
export * from './manifest';
|
|
12
|
+
export * from './package';
|
|
13
|
+
export * from './types';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ExtensionConfig, ExtensionTarget } from './types';
|
|
2
|
+
/** Output filename for a content script (explicit `out`, else entry basename). */
|
|
3
|
+
export declare function contentScriptOut(entry: string, out?: string): string;
|
|
4
|
+
/**
|
|
5
|
+
* Generate an MV3 manifest for a target from the extension config. Chrome uses
|
|
6
|
+
* a `service_worker` background + `minimum_chrome_version`; Firefox uses a
|
|
7
|
+
* `scripts` event page + `browser_specific_settings.gecko` (required by AMO).
|
|
8
|
+
*/
|
|
9
|
+
export declare function generateManifest(config: ExtensionConfig, opts: { version: string, target?: ExtensionTarget }): GeneratedManifest;
|
|
10
|
+
/** MV3 manifest shape (loose — the two targets diverge on `background`). */
|
|
11
|
+
export declare interface GeneratedManifest {
|
|
12
|
+
manifest_version: 3
|
|
13
|
+
name: string
|
|
14
|
+
description: string
|
|
15
|
+
version: string
|
|
16
|
+
minimum_chrome_version?: string
|
|
17
|
+
action?: { default_title?: string, default_popup?: string }
|
|
18
|
+
options_page?: string
|
|
19
|
+
background?: { service_worker: string, type?: 'module' } | { scripts: string[], type?: 'module' }
|
|
20
|
+
browser_specific_settings?: {
|
|
21
|
+
gecko: {
|
|
22
|
+
id: string
|
|
23
|
+
strict_min_version: string
|
|
24
|
+
data_collection_permissions: { required: ['none'] }
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
permissions?: string[]
|
|
28
|
+
optional_permissions?: string[]
|
|
29
|
+
host_permissions?: string[]
|
|
30
|
+
icons?: Record<string, string>
|
|
31
|
+
content_scripts?: Array<{
|
|
32
|
+
matches: string[]
|
|
33
|
+
js: string[]
|
|
34
|
+
run_at?: string
|
|
35
|
+
world?: string
|
|
36
|
+
all_frames?: boolean
|
|
37
|
+
match_about_blank?: boolean
|
|
38
|
+
exclude_matches?: string[]
|
|
39
|
+
}>
|
|
40
|
+
declarative_net_request?: { rule_resources: Array<{ id: string, enabled: boolean, path: string }> }
|
|
41
|
+
content_security_policy?: { extension_pages: string }
|
|
42
|
+
web_accessible_resources?: Array<{ resources: string[], matches: string[] }>
|
|
43
|
+
[key: string]: unknown
|
|
44
|
+
}
|
package/dist/manifest.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { basename } from "node:path";
|
|
2
|
+
export function contentScriptOut(entry, out) {
|
|
3
|
+
return out ?? basename(entry).replace(/\.[cm]?tsx?$/, ".js");
|
|
4
|
+
}
|
|
5
|
+
export function generateManifest(config, opts) {
|
|
6
|
+
const isFirefox = (opts.target ?? "chrome") === "firefox", m = config.manifest ?? {}, manifest = {
|
|
7
|
+
manifest_version: 3,
|
|
8
|
+
name: config.name,
|
|
9
|
+
description: config.description,
|
|
10
|
+
version: opts.version
|
|
11
|
+
};
|
|
12
|
+
if (!isFirefox && m.minimumChromeVersion)
|
|
13
|
+
manifest.minimum_chrome_version = m.minimumChromeVersion;
|
|
14
|
+
if (config.pages?.popup)
|
|
15
|
+
manifest.action = { default_title: config.name, default_popup: "popup.html" };
|
|
16
|
+
if (config.pages?.options)
|
|
17
|
+
manifest.options_page = "options.html";
|
|
18
|
+
if (config.background)
|
|
19
|
+
manifest.background = isFirefox ? { scripts: ["background.js"], type: "module" } : { service_worker: "background.js", type: "module" };
|
|
20
|
+
if (isFirefox && config.geckoId)
|
|
21
|
+
manifest.browser_specific_settings = {
|
|
22
|
+
gecko: {
|
|
23
|
+
id: config.geckoId,
|
|
24
|
+
strict_min_version: m.firefoxMinVersion ?? "128.0",
|
|
25
|
+
data_collection_permissions: { required: ["none"] }
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
if (m.permissions?.length)
|
|
29
|
+
manifest.permissions = m.permissions;
|
|
30
|
+
if (m.optionalPermissions?.length)
|
|
31
|
+
manifest.optional_permissions = m.optionalPermissions;
|
|
32
|
+
if (m.hostPermissions?.length)
|
|
33
|
+
manifest.host_permissions = m.hostPermissions;
|
|
34
|
+
if (config.icons)
|
|
35
|
+
manifest.icons = Object.fromEntries(Object.entries(config.icons).map(([size, path]) => [String(size), path]));
|
|
36
|
+
if (config.content?.length)
|
|
37
|
+
manifest.content_scripts = config.content.map((cs) => ({
|
|
38
|
+
matches: cs.matches,
|
|
39
|
+
js: [contentScriptOut(cs.entry, cs.out)],
|
|
40
|
+
...cs.runAt ? { run_at: cs.runAt } : {},
|
|
41
|
+
...cs.world ? { world: cs.world } : {},
|
|
42
|
+
...cs.allFrames ? { all_frames: !0 } : {},
|
|
43
|
+
...cs.matchAboutBlank ? { match_about_blank: !0 } : {},
|
|
44
|
+
...cs.excludeMatches ? { exclude_matches: cs.excludeMatches } : {}
|
|
45
|
+
}));
|
|
46
|
+
if (config.rules?.length)
|
|
47
|
+
manifest.declarative_net_request = {
|
|
48
|
+
rule_resources: config.rules.map((r) => ({
|
|
49
|
+
id: r.id,
|
|
50
|
+
enabled: r.enabled ?? !0,
|
|
51
|
+
path: r.path ?? `rules/${r.id}.json`
|
|
52
|
+
}))
|
|
53
|
+
};
|
|
54
|
+
manifest.content_security_policy = {
|
|
55
|
+
extension_pages: m.contentSecurityPolicy ?? "script-src 'self'; object-src 'self'"
|
|
56
|
+
};
|
|
57
|
+
if (m.webAccessibleResources?.length)
|
|
58
|
+
manifest.web_accessible_resources = m.webAccessibleResources;
|
|
59
|
+
return { ...manifest, ...m.extra ?? {} };
|
|
60
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ExtensionConfig, ExtensionTarget } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Package a built extension into a store-ready `.zip` (one per target). Builds
|
|
4
|
+
* first unless `build: false`. Uses the system `zip` (available on CI runners
|
|
5
|
+
* and dev machines) so the archive matches what the Chrome/Firefox stores
|
|
6
|
+
* expect (files at the archive root, no wrapping directory).
|
|
7
|
+
*/
|
|
8
|
+
export declare function packageExtension(config: ExtensionConfig, options: PackageOptions): Promise<string>;
|
|
9
|
+
export declare interface PackageOptions {
|
|
10
|
+
target?: ExtensionTarget
|
|
11
|
+
version: string
|
|
12
|
+
cwd?: string
|
|
13
|
+
outfile?: string
|
|
14
|
+
build?: boolean
|
|
15
|
+
}
|
package/dist/package.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { mkdir } from "node:fs/promises";
|
|
3
|
+
import { dirname, resolve } from "node:path";
|
|
4
|
+
import { buildExtension, resolveOutdir } from "./build";
|
|
5
|
+
function slug(name) {
|
|
6
|
+
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");
|
|
7
|
+
}
|
|
8
|
+
export async function packageExtension(config, options) {
|
|
9
|
+
const target = options.target ?? "chrome", cwd = options.cwd ?? process.cwd();
|
|
10
|
+
if (options.build !== !1)
|
|
11
|
+
await buildExtension(config, { target, version: options.version, cwd });
|
|
12
|
+
const outdir = resolve(cwd, resolveOutdir(config, target));
|
|
13
|
+
if (!existsSync(outdir))
|
|
14
|
+
throw Error(`[browser-extension] nothing to package: ${outdir} does not exist`);
|
|
15
|
+
const suffix = target === "firefox" ? "-firefox" : "", outfile = resolve(cwd, options.outfile ?? `${slug(config.name)}-${options.version}${suffix}.zip`);
|
|
16
|
+
await mkdir(dirname(outfile), { recursive: !0 });
|
|
17
|
+
const proc = Bun.spawn(["zip", "-r", "-q", outfile, "."], { cwd: outdir, stdout: "pipe", stderr: "pipe" }), code = await proc.exited;
|
|
18
|
+
if (code !== 0)
|
|
19
|
+
throw Error(`[browser-extension] zip failed (${code}): ${await new Response(proc.stderr).text()}`);
|
|
20
|
+
return outfile;
|
|
21
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/** A content script mapped into the manifest's `content_scripts`. */
|
|
2
|
+
export declare interface ContentScript {
|
|
3
|
+
entry: string
|
|
4
|
+
out?: string
|
|
5
|
+
matches: string[]
|
|
6
|
+
runAt?: 'document_start' | 'document_end' | 'document_idle'
|
|
7
|
+
world?: 'ISOLATED' | 'MAIN'
|
|
8
|
+
allFrames?: boolean
|
|
9
|
+
matchAboutBlank?: boolean
|
|
10
|
+
excludeMatches?: string[]
|
|
11
|
+
}
|
|
12
|
+
/** A declarativeNetRequest static ruleset. */
|
|
13
|
+
export declare interface RuleResource {
|
|
14
|
+
id: string
|
|
15
|
+
path?: string
|
|
16
|
+
enabled?: boolean
|
|
17
|
+
}
|
|
18
|
+
/** An stx page bundled to HTML (popup, options, …). */
|
|
19
|
+
export declare interface ExtensionPages {
|
|
20
|
+
popup?: string
|
|
21
|
+
options?: string
|
|
22
|
+
extra?: Record<string, string>
|
|
23
|
+
}
|
|
24
|
+
/** Overrides merged verbatim into the generated manifest, per target. */
|
|
25
|
+
export declare interface ManifestOverrides {
|
|
26
|
+
permissions?: string[]
|
|
27
|
+
hostPermissions?: string[]
|
|
28
|
+
optionalPermissions?: string[]
|
|
29
|
+
minimumChromeVersion?: string
|
|
30
|
+
firefoxMinVersion?: string
|
|
31
|
+
contentSecurityPolicy?: string
|
|
32
|
+
webAccessibleResources?: Array<{ resources: string[], matches: string[] }>
|
|
33
|
+
extra?: Record<string, unknown>
|
|
34
|
+
}
|
|
35
|
+
export declare interface ExtensionConfig {
|
|
36
|
+
name: string
|
|
37
|
+
description: string
|
|
38
|
+
geckoId?: string
|
|
39
|
+
targets?: ExtensionTarget[]
|
|
40
|
+
background?: string
|
|
41
|
+
content?: ContentScript[]
|
|
42
|
+
pages?: ExtensionPages
|
|
43
|
+
icons?: Record<number, string>
|
|
44
|
+
public?: string
|
|
45
|
+
rules?: RuleResource[]
|
|
46
|
+
manifest?: ManifestOverrides
|
|
47
|
+
outdir?: Partial<Record<ExtensionTarget, string>> | string
|
|
48
|
+
}
|
|
49
|
+
export declare interface BuildOptions {
|
|
50
|
+
target?: ExtensionTarget
|
|
51
|
+
version: string
|
|
52
|
+
outdir?: string
|
|
53
|
+
minify?: boolean
|
|
54
|
+
cwd?: string
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Config-driven MV3 browser-extension types.
|
|
58
|
+
*
|
|
59
|
+
* A consuming app declares one `ExtensionConfig` (typically in
|
|
60
|
+
* `config/extension.ts` via `defineExtension`) and the framework derives the
|
|
61
|
+
* manifest, build graph, and packaging from it — no hand-written manifest.json
|
|
62
|
+
* or per-project build script.
|
|
63
|
+
*/
|
|
64
|
+
export type ExtensionTarget = 'chrome' | 'firefox';
|
package/dist/types.js
ADDED
|
File without changes
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@stacksjs/browser-extension",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.70.65",
|
|
5
|
+
"description": "Build MV3 browser extensions (Chrome + Firefox) the Stacks way — manifest, content/background scripts, DNR rules, packaging, all config-driven.",
|
|
6
|
+
"author": "Chris Breuer",
|
|
7
|
+
"contributors": [
|
|
8
|
+
"Chris Breuer <chris@stacksjs.com>"
|
|
9
|
+
],
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"funding": "https://github.com/sponsors/chrisbbreuer",
|
|
12
|
+
"homepage": "https://github.com/stacksjs/stacks/tree/main/storage/framework/core/browser-extension#readme",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/stacksjs/stacks.git",
|
|
16
|
+
"directory": "./storage/framework/core/browser-extension"
|
|
17
|
+
},
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/stacksjs/stacks/issues"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"browser-extension",
|
|
23
|
+
"chrome-extension",
|
|
24
|
+
"firefox-extension",
|
|
25
|
+
"manifest-v3",
|
|
26
|
+
"mv3",
|
|
27
|
+
"declarativeNetRequest",
|
|
28
|
+
"bun",
|
|
29
|
+
"stacks"
|
|
30
|
+
],
|
|
31
|
+
"sideEffects": false,
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"development": "./src/index.ts",
|
|
36
|
+
"bun": "./dist/index.js",
|
|
37
|
+
"import": "./dist/index.js",
|
|
38
|
+
"default": "./dist/index.js"
|
|
39
|
+
},
|
|
40
|
+
"./*": {
|
|
41
|
+
"development": "./src/*",
|
|
42
|
+
"bun": "./dist/*",
|
|
43
|
+
"import": "./dist/*",
|
|
44
|
+
"default": "./dist/*"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"module": "dist/index.js",
|
|
48
|
+
"types": "dist/index.d.ts",
|
|
49
|
+
"files": [
|
|
50
|
+
"README.md",
|
|
51
|
+
"dist"
|
|
52
|
+
],
|
|
53
|
+
"scripts": {
|
|
54
|
+
"build": "bun build.ts",
|
|
55
|
+
"typecheck": "bun tsc --noEmit",
|
|
56
|
+
"prepublishOnly": "bun run build"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"better-dx": "^0.2.12"
|
|
60
|
+
}
|
|
61
|
+
}
|