@crxjs/vite-plugin 1.0.1 → 1.0.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # @crxjs/vite-plugin
2
2
 
3
+ ## 1.0.2
4
+
5
+ ### Patch Changes
6
+
7
+ - be8a1de: Remove unused code that throws when web accessible resources contains
8
+ an HTML file.
9
+
3
10
  ## 1.0.1
4
11
 
5
12
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -2545,6 +2545,216 @@ const pluginHtmlAuditor = () => {
2545
2545
  };
2546
2546
  };
2547
2547
 
2548
+ const pluginManifest = (_manifest) => () => {
2549
+ let manifest;
2550
+ let plugins;
2551
+ let refId;
2552
+ let config;
2553
+ return [
2554
+ {
2555
+ name: "crx:manifest-init",
2556
+ enforce: "pre",
2557
+ async config(config2, env) {
2558
+ manifest = await (typeof _manifest === "function" ? _manifest(env) : _manifest);
2559
+ if (manifest.manifest_version !== 3)
2560
+ throw new Error(`Manifest v${manifest.manifest_version} is currently unsupported, please use manifest v3`);
2561
+ if (env.command === "serve") {
2562
+ const {
2563
+ contentScripts: js,
2564
+ background: sw,
2565
+ html
2566
+ } = await manifestFiles(manifest);
2567
+ let { entries = [] } = config2.optimizeDeps ?? {};
2568
+ entries = [entries].flat();
2569
+ const set = new Set(entries);
2570
+ for (const x of [...js, ...sw, ...html])
2571
+ set.add(x);
2572
+ return {
2573
+ ...config2,
2574
+ optimizeDeps: {
2575
+ ...config2.optimizeDeps,
2576
+ entries: [...set]
2577
+ }
2578
+ };
2579
+ }
2580
+ },
2581
+ buildStart(options) {
2582
+ if (options.plugins)
2583
+ plugins = options.plugins;
2584
+ }
2585
+ },
2586
+ {
2587
+ name: "crx:manifest-loader",
2588
+ apply: "build",
2589
+ enforce: "pre",
2590
+ buildStart() {
2591
+ refId = this.emitFile({
2592
+ type: "chunk",
2593
+ id: manifestId,
2594
+ name: "crx-manifest.js",
2595
+ preserveSignature: "strict"
2596
+ });
2597
+ },
2598
+ resolveId(source) {
2599
+ if (source === manifestId)
2600
+ return manifestId;
2601
+ return null;
2602
+ },
2603
+ load(id) {
2604
+ if (id === manifestId)
2605
+ return encodeManifest(manifest);
2606
+ return null;
2607
+ }
2608
+ },
2609
+ {
2610
+ name: "crx:stub-input",
2611
+ apply: "build",
2612
+ enforce: "pre",
2613
+ options({ input, ...options }) {
2614
+ return {
2615
+ input: isString(input) && input.endsWith("index.html") ? stubId : input,
2616
+ ...options
2617
+ };
2618
+ },
2619
+ resolveId(source) {
2620
+ if (source === stubId)
2621
+ return stubId;
2622
+ return null;
2623
+ },
2624
+ load(id) {
2625
+ if (id === stubId)
2626
+ return `console.log('stub')`;
2627
+ return null;
2628
+ },
2629
+ generateBundle(options, bundle) {
2630
+ for (const [key, chunk] of Object.entries(bundle)) {
2631
+ if (chunk.type === "chunk" && chunk.facadeModuleId === stubId) {
2632
+ delete bundle[key];
2633
+ break;
2634
+ }
2635
+ }
2636
+ }
2637
+ },
2638
+ {
2639
+ name: "crx:manifest-post",
2640
+ apply: "build",
2641
+ enforce: "post",
2642
+ configResolved(_config) {
2643
+ config = _config;
2644
+ const plugins2 = config.plugins;
2645
+ const crx = plugins2.findIndex(({ name }) => name === "crx:manifest-post");
2646
+ const [plugin] = plugins2.splice(crx, 1);
2647
+ plugins2.push(plugin);
2648
+ },
2649
+ async transform(code, id) {
2650
+ if (id !== manifestId)
2651
+ return;
2652
+ let manifest2 = decodeManifest.call(this, code);
2653
+ for (const plugin of plugins) {
2654
+ try {
2655
+ const m = structuredClone(manifest2);
2656
+ const result = await plugin.transformCrxManifest?.call(this, m);
2657
+ manifest2 = result ?? manifest2;
2658
+ } catch (error) {
2659
+ if (error instanceof Error)
2660
+ error.message = `[${plugin.name}] ${error.message}`;
2661
+ throw error;
2662
+ }
2663
+ }
2664
+ if (manifest2.content_scripts?.length) {
2665
+ manifest2.content_scripts = manifest2.content_scripts.map(({ js = [], ...rest }) => {
2666
+ const refJS = js.map((file) => this.emitFile({
2667
+ type: "chunk",
2668
+ id: file,
2669
+ name: basename(file)
2670
+ }));
2671
+ return { js: refJS, ...rest };
2672
+ });
2673
+ }
2674
+ if (!this.meta.watchMode) {
2675
+ if (manifest2.background?.service_worker) {
2676
+ const file = manifest2.background.service_worker;
2677
+ const refId2 = this.emitFile({
2678
+ type: "chunk",
2679
+ id: file,
2680
+ name: basename(file)
2681
+ });
2682
+ manifest2.background.service_worker = refId2;
2683
+ }
2684
+ for (const file of htmlFiles(manifest2)) {
2685
+ this.emitFile({
2686
+ type: "chunk",
2687
+ id: file,
2688
+ name: basename(file)
2689
+ });
2690
+ }
2691
+ }
2692
+ const encoded = encodeManifest(manifest2);
2693
+ return encoded;
2694
+ },
2695
+ async generateBundle(options, bundle) {
2696
+ const manifestName = this.getFileName(refId);
2697
+ const manifestJs = bundle[manifestName];
2698
+ let manifest2 = decodeManifest.call(this, manifestJs.code);
2699
+ if (manifest2.background?.service_worker && !this.meta.watchMode) {
2700
+ const ref = manifest2.background.service_worker;
2701
+ const name = this.getFileName(ref);
2702
+ manifest2.background.service_worker = name;
2703
+ }
2704
+ manifest2.content_scripts = manifest2.content_scripts?.map(({ js = [], ...rest }) => {
2705
+ const refJS = js.map((ref) => this.getFileName(ref));
2706
+ return { js: refJS, ...rest };
2707
+ });
2708
+ for (const plugin of plugins) {
2709
+ try {
2710
+ const m = structuredClone(manifest2);
2711
+ const result = await plugin.renderCrxManifest?.call(this, m, bundle);
2712
+ manifest2 = result ?? manifest2;
2713
+ } catch (error) {
2714
+ const name = `[${plugin.name}]`;
2715
+ let message = error;
2716
+ if (error instanceof Error) {
2717
+ message = colors__default["default"].red(`${name} ${error.stack ? error.stack : error.message}`);
2718
+ } else if (typeof error === "string") {
2719
+ message = colors__default["default"].red(`${name} ${error}`);
2720
+ }
2721
+ console.log(message);
2722
+ throw new Error(`Error in ${plugin.name}.renderCrxManifest`);
2723
+ }
2724
+ }
2725
+ const assetTypes = [
2726
+ "icons",
2727
+ "locales",
2728
+ "rulesets",
2729
+ "webAccessibleResources"
2730
+ ];
2731
+ const files = await manifestFiles(manifest2);
2732
+ await Promise.all(assetTypes.map((k) => files[k]).flat().map(async (f) => {
2733
+ if (typeof bundle[f] === "undefined") {
2734
+ const filename = join(config.root, f);
2735
+ this.emitFile({
2736
+ type: "asset",
2737
+ fileName: f,
2738
+ source: await fsExtra.readFile(filename)
2739
+ });
2740
+ }
2741
+ }));
2742
+ const manifestJson = bundle["manifest.json"];
2743
+ if (typeof manifestJson === "undefined") {
2744
+ this.emitFile({
2745
+ type: "asset",
2746
+ fileName: "manifest.json",
2747
+ source: JSON.stringify(manifest2, null, 2)
2748
+ });
2749
+ } else {
2750
+ manifestJson.source = JSON.stringify(manifest2, null, 2);
2751
+ }
2752
+ delete bundle[manifestName];
2753
+ }
2754
+ }
2755
+ ];
2756
+ };
2757
+
2548
2758
  var contentHmrPort = "function isCrxHMRPayload(x) {\n return x.type === \"custom\" && x.event.startsWith(\"crx:\");\n}\nclass HMRPort {\n port;\n callbacks = /* @__PURE__ */ new Map();\n constructor() {\n setInterval(() => {\n try {\n this.port?.postMessage({ data: \"ping\" });\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"Extension context invalidated.\")) {\n location.reload();\n } else\n throw error;\n }\n }, __CRX_HMR_TIMEOUT__);\n setInterval(this.initPort, 5 * 60 * 1e3);\n this.initPort();\n }\n initPort = () => {\n this.port?.disconnect();\n this.port = chrome.runtime.connect({ name: \"@crx/client\" });\n this.port.onDisconnect.addListener(this.handleDisconnect.bind(this));\n this.port.onMessage.addListener(this.handleMessage.bind(this));\n this.port.postMessage({ type: \"connected\" });\n };\n handleDisconnect = () => {\n if (this.callbacks.has(\"close\"))\n for (const cb of this.callbacks.get(\"close\")) {\n cb({ wasClean: true });\n }\n };\n handleMessage = (message) => {\n const forward = (data) => {\n if (this.callbacks.has(\"message\"))\n for (const cb of this.callbacks.get(\"message\")) {\n cb({ data });\n }\n };\n const payload = JSON.parse(message.data);\n if (isCrxHMRPayload(payload)) {\n if (payload.event === \"crx:runtime-reload\") {\n console.log(\"[crx] runtime reload\");\n setTimeout(() => location.reload(), 500);\n } else {\n forward(JSON.stringify(payload.data));\n }\n } else {\n forward(message.data);\n }\n };\n addEventListener = (event, callback) => {\n const cbs = this.callbacks.get(event) ?? /* @__PURE__ */ new Set();\n cbs.add(callback);\n this.callbacks.set(event, cbs);\n };\n send = (data) => {\n if (this.port)\n this.port.postMessage({ data });\n else\n throw new Error(\"HMRPort is not initialized\");\n };\n}\n\nexport { HMRPort };\n";
2549
2759
 
2550
2760
  var contentDevLoader = "(function () {\n 'use strict';\n\n (async () => {\n if (__PREAMBLE__)\n await import(\n /* @vite-ignore */\n chrome.runtime.getURL(__PREAMBLE__)\n );\n await import(\n /* @vite-ignore */\n chrome.runtime.getURL(__CLIENT__)\n );\n await import(\n /* @vite-ignore */\n chrome.runtime.getURL(__SCRIPT__)\n );\n })().catch(console.error);\n\n})();\n";
@@ -2983,220 +3193,6 @@ const pluginResources = ({ contentScripts = {} }) => {
2983
3193
  ];
2984
3194
  };
2985
3195
 
2986
- const pluginManifest = (_manifest) => () => {
2987
- let manifest;
2988
- let plugins;
2989
- let refId;
2990
- let config;
2991
- return [
2992
- {
2993
- name: "crx:manifest-init",
2994
- enforce: "pre",
2995
- async config(config2, env) {
2996
- manifest = await (typeof _manifest === "function" ? _manifest(env) : _manifest);
2997
- if (manifest.manifest_version !== 3)
2998
- throw new Error(`Manifest v${manifest.manifest_version} is currently unsupported, please use manifest v3`);
2999
- if (env.command === "serve") {
3000
- const {
3001
- contentScripts: js,
3002
- background: sw,
3003
- html
3004
- } = await manifestFiles(manifest);
3005
- let { entries = [] } = config2.optimizeDeps ?? {};
3006
- entries = [entries].flat();
3007
- const set = new Set(entries);
3008
- for (const x of [...js, ...sw, ...html])
3009
- set.add(x);
3010
- return {
3011
- ...config2,
3012
- optimizeDeps: {
3013
- ...config2.optimizeDeps,
3014
- entries: [...set]
3015
- }
3016
- };
3017
- }
3018
- },
3019
- buildStart(options) {
3020
- if (options.plugins)
3021
- plugins = options.plugins;
3022
- }
3023
- },
3024
- {
3025
- name: "crx:manifest-loader",
3026
- apply: "build",
3027
- enforce: "pre",
3028
- buildStart() {
3029
- refId = this.emitFile({
3030
- type: "chunk",
3031
- id: manifestId,
3032
- name: "crx-manifest.js",
3033
- preserveSignature: "strict"
3034
- });
3035
- },
3036
- resolveId(source) {
3037
- if (source === manifestId)
3038
- return manifestId;
3039
- return null;
3040
- },
3041
- load(id) {
3042
- if (id === manifestId)
3043
- return encodeManifest(manifest);
3044
- return null;
3045
- }
3046
- },
3047
- {
3048
- name: "crx:stub-input",
3049
- apply: "build",
3050
- enforce: "pre",
3051
- options({ input, ...options }) {
3052
- return {
3053
- input: isString(input) && input.endsWith("index.html") ? stubId : input,
3054
- ...options
3055
- };
3056
- },
3057
- resolveId(source) {
3058
- if (source === stubId)
3059
- return stubId;
3060
- return null;
3061
- },
3062
- load(id) {
3063
- if (id === stubId)
3064
- return `console.log('stub')`;
3065
- return null;
3066
- },
3067
- generateBundle(options, bundle) {
3068
- for (const [key, chunk] of Object.entries(bundle)) {
3069
- if (chunk.type === "chunk" && chunk.facadeModuleId === stubId) {
3070
- delete bundle[key];
3071
- break;
3072
- }
3073
- }
3074
- }
3075
- },
3076
- {
3077
- name: "crx:manifest-post",
3078
- apply: "build",
3079
- enforce: "post",
3080
- configResolved(_config) {
3081
- config = _config;
3082
- const plugins2 = config.plugins;
3083
- const crx = plugins2.findIndex(({ name }) => name === "crx:manifest-post");
3084
- const [plugin] = plugins2.splice(crx, 1);
3085
- plugins2.push(plugin);
3086
- },
3087
- async transform(code, id) {
3088
- if (id !== manifestId)
3089
- return;
3090
- let manifest2 = decodeManifest.call(this, code);
3091
- for (const plugin of plugins) {
3092
- try {
3093
- const m = structuredClone(manifest2);
3094
- const result = await plugin.transformCrxManifest?.call(this, m);
3095
- manifest2 = result ?? manifest2;
3096
- } catch (error) {
3097
- if (error instanceof Error)
3098
- error.message = `[${plugin.name}] ${error.message}`;
3099
- throw error;
3100
- }
3101
- }
3102
- if (manifest2.content_scripts?.length) {
3103
- manifest2.content_scripts = manifest2.content_scripts.map(({ js = [], ...rest }) => {
3104
- const refJS = js.map((file) => this.emitFile({
3105
- type: "chunk",
3106
- id: file,
3107
- name: basename(file)
3108
- }));
3109
- return { js: refJS, ...rest };
3110
- });
3111
- }
3112
- if (!this.meta.watchMode) {
3113
- if (manifest2.background?.service_worker) {
3114
- const file = manifest2.background.service_worker;
3115
- const refId2 = this.emitFile({
3116
- type: "chunk",
3117
- id: file,
3118
- name: basename(file)
3119
- });
3120
- manifest2.background.service_worker = refId2;
3121
- }
3122
- for (const file of htmlFiles(manifest2)) {
3123
- this.emitFile({
3124
- type: "chunk",
3125
- id: file,
3126
- name: basename(file)
3127
- });
3128
- }
3129
- }
3130
- const encoded = encodeManifest(manifest2);
3131
- return encoded;
3132
- },
3133
- async generateBundle(options, bundle) {
3134
- const manifestName = this.getFileName(refId);
3135
- const manifestJs = bundle[manifestName];
3136
- let manifest2 = decodeManifest.call(this, manifestJs.code);
3137
- if (manifest2.background?.service_worker && !this.meta.watchMode) {
3138
- const ref = manifest2.background.service_worker;
3139
- const name = this.getFileName(ref);
3140
- manifest2.background.service_worker = name;
3141
- }
3142
- manifest2.content_scripts = manifest2.content_scripts?.map(({ js = [], ...rest }) => {
3143
- const refJS = js.map((ref) => this.getFileName(ref));
3144
- return { js: refJS, ...rest };
3145
- });
3146
- manifest2.web_accessible_resources = manifest2.web_accessible_resources?.map(({ resources, ...rest }) => ({
3147
- resources: resources.map((r) => fg__default["default"].isDynamicPattern(r) || r === dynamicResourcesName ? r : this.getFileName(r)),
3148
- ...rest
3149
- }));
3150
- for (const plugin of plugins) {
3151
- try {
3152
- const m = structuredClone(manifest2);
3153
- const result = await plugin.renderCrxManifest?.call(this, m, bundle);
3154
- manifest2 = result ?? manifest2;
3155
- } catch (error) {
3156
- const name = `[${plugin.name}]`;
3157
- let message = error;
3158
- if (error instanceof Error) {
3159
- message = colors__default["default"].red(`${name} ${error.stack ? error.stack : error.message}`);
3160
- } else if (typeof error === "string") {
3161
- message = colors__default["default"].red(`${name} ${error}`);
3162
- }
3163
- console.log(message);
3164
- throw new Error(`Error in ${plugin.name}.renderCrxManifest`);
3165
- }
3166
- }
3167
- const assetTypes = [
3168
- "icons",
3169
- "locales",
3170
- "rulesets",
3171
- "webAccessibleResources"
3172
- ];
3173
- const files = await manifestFiles(manifest2);
3174
- await Promise.all(assetTypes.map((k) => files[k]).flat().map(async (f) => {
3175
- if (typeof bundle[f] === "undefined") {
3176
- const filename = join(config.root, f);
3177
- this.emitFile({
3178
- type: "asset",
3179
- fileName: f,
3180
- source: await fsExtra.readFile(filename)
3181
- });
3182
- }
3183
- }));
3184
- const manifestJson = bundle["manifest.json"];
3185
- if (typeof manifestJson === "undefined") {
3186
- this.emitFile({
3187
- type: "asset",
3188
- fileName: "manifest.json",
3189
- source: JSON.stringify(manifest2, null, 2)
3190
- });
3191
- } else {
3192
- manifestJson.source = JSON.stringify(manifest2, null, 2);
3193
- }
3194
- delete bundle[manifestName];
3195
- }
3196
- }
3197
- ];
3198
- };
3199
-
3200
3196
  var workerHmrClient = "const ownOrigin = new URL(chrome.runtime.getURL(\"/\")).origin;\nself.addEventListener(\"fetch\", (fetchEvent) => {\n const url = new URL(fetchEvent.request.url);\n if (url.origin === ownOrigin) {\n fetchEvent.respondWith(sendToServer(url));\n }\n});\nasync function sendToServer(url) {\n url.protocol = \"http:\";\n url.host = \"localhost\";\n url.port = __SERVER_PORT__;\n url.searchParams.set(\"t\", Date.now().toString());\n const response = await fetch(url.href.replace(/=$|=(?=&)/g, \"\"));\n return new Response(response.body, {\n headers: {\n \"Content-Type\": response.headers.get(\"Content-Type\") ?? \"text/javascript\"\n }\n });\n}\nconst ports = /* @__PURE__ */ new Set();\nchrome.runtime.onConnect.addListener((port) => {\n if (port.name === \"@crx/client\") {\n ports.add(port);\n port.onDisconnect.addListener((port2) => ports.delete(port2));\n port.onMessage.addListener((message) => {\n });\n port.postMessage({ data: JSON.stringify({ type: \"connected\" }) });\n }\n});\nfunction notifyContentScripts(payload) {\n const data = JSON.stringify(payload);\n for (const port of ports)\n port.postMessage({ data });\n}\nconsole.log(\"[vite] connecting...\");\nconst socketProtocol = __HMR_PROTOCOL__ || (location.protocol === \"https:\" ? \"wss\" : \"ws\");\nconst socketHost = `${__HMR_HOSTNAME__ || location.hostname}:${__HMR_PORT__}`;\nconst socket = new WebSocket(`${socketProtocol}://${socketHost}`, \"vite-hmr\");\nconst base = __BASE__ || \"/\";\nsocket.addEventListener(\"message\", async ({ data }) => {\n handleSocketMessage(JSON.parse(data));\n});\nfunction isCrxHmrPayload(x) {\n return x.type === \"custom\" && x.event.startsWith(\"crx:\");\n}\nfunction handleSocketMessage(payload) {\n if (isCrxHmrPayload(payload)) {\n handleCrxHmrPayload(payload);\n } else if (payload.type === \"connected\") {\n console.log(`[vite] connected.`);\n const interval = setInterval(() => socket.send(\"ping\"), __HMR_TIMEOUT__);\n socket.addEventListener(\"close\", () => clearInterval(interval));\n }\n}\nfunction handleCrxHmrPayload(payload) {\n notifyContentScripts(payload);\n switch (payload.event) {\n case \"crx:runtime-reload\":\n console.log(\"[crx] runtime reload\");\n chrome.runtime.reload();\n break;\n }\n}\nasync function waitForSuccessfulPing(ms = 1e3) {\n while (true) {\n try {\n await fetch(`${base}__vite_ping`);\n break;\n } catch (e) {\n await new Promise((resolve) => setTimeout(resolve, ms));\n }\n }\n}\nsocket.addEventListener(\"close\", async ({ wasClean }) => {\n if (wasClean)\n return;\n console.log(`[vite] server connection lost. polling for restart...`);\n await waitForSuccessfulPing();\n chrome.runtime.reload();\n});\n";
3201
3197
 
3202
3198
  function defineClientValues(code, config) {
package/dist/index.mjs CHANGED
@@ -2512,6 +2512,216 @@ const pluginHtmlAuditor = () => {
2512
2512
  };
2513
2513
  };
2514
2514
 
2515
+ const pluginManifest = (_manifest) => () => {
2516
+ let manifest;
2517
+ let plugins;
2518
+ let refId;
2519
+ let config;
2520
+ return [
2521
+ {
2522
+ name: "crx:manifest-init",
2523
+ enforce: "pre",
2524
+ async config(config2, env) {
2525
+ manifest = await (typeof _manifest === "function" ? _manifest(env) : _manifest);
2526
+ if (manifest.manifest_version !== 3)
2527
+ throw new Error(`Manifest v${manifest.manifest_version} is currently unsupported, please use manifest v3`);
2528
+ if (env.command === "serve") {
2529
+ const {
2530
+ contentScripts: js,
2531
+ background: sw,
2532
+ html
2533
+ } = await manifestFiles(manifest);
2534
+ let { entries = [] } = config2.optimizeDeps ?? {};
2535
+ entries = [entries].flat();
2536
+ const set = new Set(entries);
2537
+ for (const x of [...js, ...sw, ...html])
2538
+ set.add(x);
2539
+ return {
2540
+ ...config2,
2541
+ optimizeDeps: {
2542
+ ...config2.optimizeDeps,
2543
+ entries: [...set]
2544
+ }
2545
+ };
2546
+ }
2547
+ },
2548
+ buildStart(options) {
2549
+ if (options.plugins)
2550
+ plugins = options.plugins;
2551
+ }
2552
+ },
2553
+ {
2554
+ name: "crx:manifest-loader",
2555
+ apply: "build",
2556
+ enforce: "pre",
2557
+ buildStart() {
2558
+ refId = this.emitFile({
2559
+ type: "chunk",
2560
+ id: manifestId,
2561
+ name: "crx-manifest.js",
2562
+ preserveSignature: "strict"
2563
+ });
2564
+ },
2565
+ resolveId(source) {
2566
+ if (source === manifestId)
2567
+ return manifestId;
2568
+ return null;
2569
+ },
2570
+ load(id) {
2571
+ if (id === manifestId)
2572
+ return encodeManifest(manifest);
2573
+ return null;
2574
+ }
2575
+ },
2576
+ {
2577
+ name: "crx:stub-input",
2578
+ apply: "build",
2579
+ enforce: "pre",
2580
+ options({ input, ...options }) {
2581
+ return {
2582
+ input: isString(input) && input.endsWith("index.html") ? stubId : input,
2583
+ ...options
2584
+ };
2585
+ },
2586
+ resolveId(source) {
2587
+ if (source === stubId)
2588
+ return stubId;
2589
+ return null;
2590
+ },
2591
+ load(id) {
2592
+ if (id === stubId)
2593
+ return `console.log('stub')`;
2594
+ return null;
2595
+ },
2596
+ generateBundle(options, bundle) {
2597
+ for (const [key, chunk] of Object.entries(bundle)) {
2598
+ if (chunk.type === "chunk" && chunk.facadeModuleId === stubId) {
2599
+ delete bundle[key];
2600
+ break;
2601
+ }
2602
+ }
2603
+ }
2604
+ },
2605
+ {
2606
+ name: "crx:manifest-post",
2607
+ apply: "build",
2608
+ enforce: "post",
2609
+ configResolved(_config) {
2610
+ config = _config;
2611
+ const plugins2 = config.plugins;
2612
+ const crx = plugins2.findIndex(({ name }) => name === "crx:manifest-post");
2613
+ const [plugin] = plugins2.splice(crx, 1);
2614
+ plugins2.push(plugin);
2615
+ },
2616
+ async transform(code, id) {
2617
+ if (id !== manifestId)
2618
+ return;
2619
+ let manifest2 = decodeManifest.call(this, code);
2620
+ for (const plugin of plugins) {
2621
+ try {
2622
+ const m = structuredClone(manifest2);
2623
+ const result = await plugin.transformCrxManifest?.call(this, m);
2624
+ manifest2 = result ?? manifest2;
2625
+ } catch (error) {
2626
+ if (error instanceof Error)
2627
+ error.message = `[${plugin.name}] ${error.message}`;
2628
+ throw error;
2629
+ }
2630
+ }
2631
+ if (manifest2.content_scripts?.length) {
2632
+ manifest2.content_scripts = manifest2.content_scripts.map(({ js = [], ...rest }) => {
2633
+ const refJS = js.map((file) => this.emitFile({
2634
+ type: "chunk",
2635
+ id: file,
2636
+ name: basename(file)
2637
+ }));
2638
+ return { js: refJS, ...rest };
2639
+ });
2640
+ }
2641
+ if (!this.meta.watchMode) {
2642
+ if (manifest2.background?.service_worker) {
2643
+ const file = manifest2.background.service_worker;
2644
+ const refId2 = this.emitFile({
2645
+ type: "chunk",
2646
+ id: file,
2647
+ name: basename(file)
2648
+ });
2649
+ manifest2.background.service_worker = refId2;
2650
+ }
2651
+ for (const file of htmlFiles(manifest2)) {
2652
+ this.emitFile({
2653
+ type: "chunk",
2654
+ id: file,
2655
+ name: basename(file)
2656
+ });
2657
+ }
2658
+ }
2659
+ const encoded = encodeManifest(manifest2);
2660
+ return encoded;
2661
+ },
2662
+ async generateBundle(options, bundle) {
2663
+ const manifestName = this.getFileName(refId);
2664
+ const manifestJs = bundle[manifestName];
2665
+ let manifest2 = decodeManifest.call(this, manifestJs.code);
2666
+ if (manifest2.background?.service_worker && !this.meta.watchMode) {
2667
+ const ref = manifest2.background.service_worker;
2668
+ const name = this.getFileName(ref);
2669
+ manifest2.background.service_worker = name;
2670
+ }
2671
+ manifest2.content_scripts = manifest2.content_scripts?.map(({ js = [], ...rest }) => {
2672
+ const refJS = js.map((ref) => this.getFileName(ref));
2673
+ return { js: refJS, ...rest };
2674
+ });
2675
+ for (const plugin of plugins) {
2676
+ try {
2677
+ const m = structuredClone(manifest2);
2678
+ const result = await plugin.renderCrxManifest?.call(this, m, bundle);
2679
+ manifest2 = result ?? manifest2;
2680
+ } catch (error) {
2681
+ const name = `[${plugin.name}]`;
2682
+ let message = error;
2683
+ if (error instanceof Error) {
2684
+ message = colors.red(`${name} ${error.stack ? error.stack : error.message}`);
2685
+ } else if (typeof error === "string") {
2686
+ message = colors.red(`${name} ${error}`);
2687
+ }
2688
+ console.log(message);
2689
+ throw new Error(`Error in ${plugin.name}.renderCrxManifest`);
2690
+ }
2691
+ }
2692
+ const assetTypes = [
2693
+ "icons",
2694
+ "locales",
2695
+ "rulesets",
2696
+ "webAccessibleResources"
2697
+ ];
2698
+ const files = await manifestFiles(manifest2);
2699
+ await Promise.all(assetTypes.map((k) => files[k]).flat().map(async (f) => {
2700
+ if (typeof bundle[f] === "undefined") {
2701
+ const filename = join(config.root, f);
2702
+ this.emitFile({
2703
+ type: "asset",
2704
+ fileName: f,
2705
+ source: await readFile(filename)
2706
+ });
2707
+ }
2708
+ }));
2709
+ const manifestJson = bundle["manifest.json"];
2710
+ if (typeof manifestJson === "undefined") {
2711
+ this.emitFile({
2712
+ type: "asset",
2713
+ fileName: "manifest.json",
2714
+ source: JSON.stringify(manifest2, null, 2)
2715
+ });
2716
+ } else {
2717
+ manifestJson.source = JSON.stringify(manifest2, null, 2);
2718
+ }
2719
+ delete bundle[manifestName];
2720
+ }
2721
+ }
2722
+ ];
2723
+ };
2724
+
2515
2725
  var contentHmrPort = "function isCrxHMRPayload(x) {\n return x.type === \"custom\" && x.event.startsWith(\"crx:\");\n}\nclass HMRPort {\n port;\n callbacks = /* @__PURE__ */ new Map();\n constructor() {\n setInterval(() => {\n try {\n this.port?.postMessage({ data: \"ping\" });\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"Extension context invalidated.\")) {\n location.reload();\n } else\n throw error;\n }\n }, __CRX_HMR_TIMEOUT__);\n setInterval(this.initPort, 5 * 60 * 1e3);\n this.initPort();\n }\n initPort = () => {\n this.port?.disconnect();\n this.port = chrome.runtime.connect({ name: \"@crx/client\" });\n this.port.onDisconnect.addListener(this.handleDisconnect.bind(this));\n this.port.onMessage.addListener(this.handleMessage.bind(this));\n this.port.postMessage({ type: \"connected\" });\n };\n handleDisconnect = () => {\n if (this.callbacks.has(\"close\"))\n for (const cb of this.callbacks.get(\"close\")) {\n cb({ wasClean: true });\n }\n };\n handleMessage = (message) => {\n const forward = (data) => {\n if (this.callbacks.has(\"message\"))\n for (const cb of this.callbacks.get(\"message\")) {\n cb({ data });\n }\n };\n const payload = JSON.parse(message.data);\n if (isCrxHMRPayload(payload)) {\n if (payload.event === \"crx:runtime-reload\") {\n console.log(\"[crx] runtime reload\");\n setTimeout(() => location.reload(), 500);\n } else {\n forward(JSON.stringify(payload.data));\n }\n } else {\n forward(message.data);\n }\n };\n addEventListener = (event, callback) => {\n const cbs = this.callbacks.get(event) ?? /* @__PURE__ */ new Set();\n cbs.add(callback);\n this.callbacks.set(event, cbs);\n };\n send = (data) => {\n if (this.port)\n this.port.postMessage({ data });\n else\n throw new Error(\"HMRPort is not initialized\");\n };\n}\n\nexport { HMRPort };\n";
2516
2726
 
2517
2727
  var contentDevLoader = "(function () {\n 'use strict';\n\n (async () => {\n if (__PREAMBLE__)\n await import(\n /* @vite-ignore */\n chrome.runtime.getURL(__PREAMBLE__)\n );\n await import(\n /* @vite-ignore */\n chrome.runtime.getURL(__CLIENT__)\n );\n await import(\n /* @vite-ignore */\n chrome.runtime.getURL(__SCRIPT__)\n );\n })().catch(console.error);\n\n})();\n";
@@ -2950,220 +3160,6 @@ const pluginResources = ({ contentScripts = {} }) => {
2950
3160
  ];
2951
3161
  };
2952
3162
 
2953
- const pluginManifest = (_manifest) => () => {
2954
- let manifest;
2955
- let plugins;
2956
- let refId;
2957
- let config;
2958
- return [
2959
- {
2960
- name: "crx:manifest-init",
2961
- enforce: "pre",
2962
- async config(config2, env) {
2963
- manifest = await (typeof _manifest === "function" ? _manifest(env) : _manifest);
2964
- if (manifest.manifest_version !== 3)
2965
- throw new Error(`Manifest v${manifest.manifest_version} is currently unsupported, please use manifest v3`);
2966
- if (env.command === "serve") {
2967
- const {
2968
- contentScripts: js,
2969
- background: sw,
2970
- html
2971
- } = await manifestFiles(manifest);
2972
- let { entries = [] } = config2.optimizeDeps ?? {};
2973
- entries = [entries].flat();
2974
- const set = new Set(entries);
2975
- for (const x of [...js, ...sw, ...html])
2976
- set.add(x);
2977
- return {
2978
- ...config2,
2979
- optimizeDeps: {
2980
- ...config2.optimizeDeps,
2981
- entries: [...set]
2982
- }
2983
- };
2984
- }
2985
- },
2986
- buildStart(options) {
2987
- if (options.plugins)
2988
- plugins = options.plugins;
2989
- }
2990
- },
2991
- {
2992
- name: "crx:manifest-loader",
2993
- apply: "build",
2994
- enforce: "pre",
2995
- buildStart() {
2996
- refId = this.emitFile({
2997
- type: "chunk",
2998
- id: manifestId,
2999
- name: "crx-manifest.js",
3000
- preserveSignature: "strict"
3001
- });
3002
- },
3003
- resolveId(source) {
3004
- if (source === manifestId)
3005
- return manifestId;
3006
- return null;
3007
- },
3008
- load(id) {
3009
- if (id === manifestId)
3010
- return encodeManifest(manifest);
3011
- return null;
3012
- }
3013
- },
3014
- {
3015
- name: "crx:stub-input",
3016
- apply: "build",
3017
- enforce: "pre",
3018
- options({ input, ...options }) {
3019
- return {
3020
- input: isString(input) && input.endsWith("index.html") ? stubId : input,
3021
- ...options
3022
- };
3023
- },
3024
- resolveId(source) {
3025
- if (source === stubId)
3026
- return stubId;
3027
- return null;
3028
- },
3029
- load(id) {
3030
- if (id === stubId)
3031
- return `console.log('stub')`;
3032
- return null;
3033
- },
3034
- generateBundle(options, bundle) {
3035
- for (const [key, chunk] of Object.entries(bundle)) {
3036
- if (chunk.type === "chunk" && chunk.facadeModuleId === stubId) {
3037
- delete bundle[key];
3038
- break;
3039
- }
3040
- }
3041
- }
3042
- },
3043
- {
3044
- name: "crx:manifest-post",
3045
- apply: "build",
3046
- enforce: "post",
3047
- configResolved(_config) {
3048
- config = _config;
3049
- const plugins2 = config.plugins;
3050
- const crx = plugins2.findIndex(({ name }) => name === "crx:manifest-post");
3051
- const [plugin] = plugins2.splice(crx, 1);
3052
- plugins2.push(plugin);
3053
- },
3054
- async transform(code, id) {
3055
- if (id !== manifestId)
3056
- return;
3057
- let manifest2 = decodeManifest.call(this, code);
3058
- for (const plugin of plugins) {
3059
- try {
3060
- const m = structuredClone(manifest2);
3061
- const result = await plugin.transformCrxManifest?.call(this, m);
3062
- manifest2 = result ?? manifest2;
3063
- } catch (error) {
3064
- if (error instanceof Error)
3065
- error.message = `[${plugin.name}] ${error.message}`;
3066
- throw error;
3067
- }
3068
- }
3069
- if (manifest2.content_scripts?.length) {
3070
- manifest2.content_scripts = manifest2.content_scripts.map(({ js = [], ...rest }) => {
3071
- const refJS = js.map((file) => this.emitFile({
3072
- type: "chunk",
3073
- id: file,
3074
- name: basename(file)
3075
- }));
3076
- return { js: refJS, ...rest };
3077
- });
3078
- }
3079
- if (!this.meta.watchMode) {
3080
- if (manifest2.background?.service_worker) {
3081
- const file = manifest2.background.service_worker;
3082
- const refId2 = this.emitFile({
3083
- type: "chunk",
3084
- id: file,
3085
- name: basename(file)
3086
- });
3087
- manifest2.background.service_worker = refId2;
3088
- }
3089
- for (const file of htmlFiles(manifest2)) {
3090
- this.emitFile({
3091
- type: "chunk",
3092
- id: file,
3093
- name: basename(file)
3094
- });
3095
- }
3096
- }
3097
- const encoded = encodeManifest(manifest2);
3098
- return encoded;
3099
- },
3100
- async generateBundle(options, bundle) {
3101
- const manifestName = this.getFileName(refId);
3102
- const manifestJs = bundle[manifestName];
3103
- let manifest2 = decodeManifest.call(this, manifestJs.code);
3104
- if (manifest2.background?.service_worker && !this.meta.watchMode) {
3105
- const ref = manifest2.background.service_worker;
3106
- const name = this.getFileName(ref);
3107
- manifest2.background.service_worker = name;
3108
- }
3109
- manifest2.content_scripts = manifest2.content_scripts?.map(({ js = [], ...rest }) => {
3110
- const refJS = js.map((ref) => this.getFileName(ref));
3111
- return { js: refJS, ...rest };
3112
- });
3113
- manifest2.web_accessible_resources = manifest2.web_accessible_resources?.map(({ resources, ...rest }) => ({
3114
- resources: resources.map((r) => fg.isDynamicPattern(r) || r === dynamicResourcesName ? r : this.getFileName(r)),
3115
- ...rest
3116
- }));
3117
- for (const plugin of plugins) {
3118
- try {
3119
- const m = structuredClone(manifest2);
3120
- const result = await plugin.renderCrxManifest?.call(this, m, bundle);
3121
- manifest2 = result ?? manifest2;
3122
- } catch (error) {
3123
- const name = `[${plugin.name}]`;
3124
- let message = error;
3125
- if (error instanceof Error) {
3126
- message = colors.red(`${name} ${error.stack ? error.stack : error.message}`);
3127
- } else if (typeof error === "string") {
3128
- message = colors.red(`${name} ${error}`);
3129
- }
3130
- console.log(message);
3131
- throw new Error(`Error in ${plugin.name}.renderCrxManifest`);
3132
- }
3133
- }
3134
- const assetTypes = [
3135
- "icons",
3136
- "locales",
3137
- "rulesets",
3138
- "webAccessibleResources"
3139
- ];
3140
- const files = await manifestFiles(manifest2);
3141
- await Promise.all(assetTypes.map((k) => files[k]).flat().map(async (f) => {
3142
- if (typeof bundle[f] === "undefined") {
3143
- const filename = join(config.root, f);
3144
- this.emitFile({
3145
- type: "asset",
3146
- fileName: f,
3147
- source: await readFile(filename)
3148
- });
3149
- }
3150
- }));
3151
- const manifestJson = bundle["manifest.json"];
3152
- if (typeof manifestJson === "undefined") {
3153
- this.emitFile({
3154
- type: "asset",
3155
- fileName: "manifest.json",
3156
- source: JSON.stringify(manifest2, null, 2)
3157
- });
3158
- } else {
3159
- manifestJson.source = JSON.stringify(manifest2, null, 2);
3160
- }
3161
- delete bundle[manifestName];
3162
- }
3163
- }
3164
- ];
3165
- };
3166
-
3167
3163
  var workerHmrClient = "const ownOrigin = new URL(chrome.runtime.getURL(\"/\")).origin;\nself.addEventListener(\"fetch\", (fetchEvent) => {\n const url = new URL(fetchEvent.request.url);\n if (url.origin === ownOrigin) {\n fetchEvent.respondWith(sendToServer(url));\n }\n});\nasync function sendToServer(url) {\n url.protocol = \"http:\";\n url.host = \"localhost\";\n url.port = __SERVER_PORT__;\n url.searchParams.set(\"t\", Date.now().toString());\n const response = await fetch(url.href.replace(/=$|=(?=&)/g, \"\"));\n return new Response(response.body, {\n headers: {\n \"Content-Type\": response.headers.get(\"Content-Type\") ?? \"text/javascript\"\n }\n });\n}\nconst ports = /* @__PURE__ */ new Set();\nchrome.runtime.onConnect.addListener((port) => {\n if (port.name === \"@crx/client\") {\n ports.add(port);\n port.onDisconnect.addListener((port2) => ports.delete(port2));\n port.onMessage.addListener((message) => {\n });\n port.postMessage({ data: JSON.stringify({ type: \"connected\" }) });\n }\n});\nfunction notifyContentScripts(payload) {\n const data = JSON.stringify(payload);\n for (const port of ports)\n port.postMessage({ data });\n}\nconsole.log(\"[vite] connecting...\");\nconst socketProtocol = __HMR_PROTOCOL__ || (location.protocol === \"https:\" ? \"wss\" : \"ws\");\nconst socketHost = `${__HMR_HOSTNAME__ || location.hostname}:${__HMR_PORT__}`;\nconst socket = new WebSocket(`${socketProtocol}://${socketHost}`, \"vite-hmr\");\nconst base = __BASE__ || \"/\";\nsocket.addEventListener(\"message\", async ({ data }) => {\n handleSocketMessage(JSON.parse(data));\n});\nfunction isCrxHmrPayload(x) {\n return x.type === \"custom\" && x.event.startsWith(\"crx:\");\n}\nfunction handleSocketMessage(payload) {\n if (isCrxHmrPayload(payload)) {\n handleCrxHmrPayload(payload);\n } else if (payload.type === \"connected\") {\n console.log(`[vite] connected.`);\n const interval = setInterval(() => socket.send(\"ping\"), __HMR_TIMEOUT__);\n socket.addEventListener(\"close\", () => clearInterval(interval));\n }\n}\nfunction handleCrxHmrPayload(payload) {\n notifyContentScripts(payload);\n switch (payload.event) {\n case \"crx:runtime-reload\":\n console.log(\"[crx] runtime reload\");\n chrome.runtime.reload();\n break;\n }\n}\nasync function waitForSuccessfulPing(ms = 1e3) {\n while (true) {\n try {\n await fetch(`${base}__vite_ping`);\n break;\n } catch (e) {\n await new Promise((resolve) => setTimeout(resolve, ms));\n }\n }\n}\nsocket.addEventListener(\"close\", async ({ wasClean }) => {\n if (wasClean)\n return;\n console.log(`[vite] server connection lost. polling for restart...`);\n await waitForSuccessfulPing();\n chrome.runtime.reload();\n});\n";
3168
3164
 
3169
3165
  function defineClientValues(code, config) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crxjs/vite-plugin",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Build Chrome Extensions with this Vite plugin.",
5
5
  "keywords": [
6
6
  "rollup-plugin",
@@ -72,7 +72,7 @@
72
72
  "jsesc": "^3.0.2",
73
73
  "magic-string": "^0.26.0",
74
74
  "picocolors": "^1.0.0",
75
- "react-refresh": "^0.12.0",
75
+ "react-refresh": "^0.13.0",
76
76
  "rollup": "^2.70.2"
77
77
  },
78
78
  "devDependencies": {
@@ -95,11 +95,9 @@
95
95
  "@typescript-eslint/parser": "5.21.0",
96
96
  "@vitejs/plugin-react": "1.3.1",
97
97
  "@vitejs/plugin-vue": "2.3.1",
98
- "@vue/compiler-sfc": "3.2.33",
99
- "@vueuse/core": "8.3.1",
100
- "@vueuse/router": "8.2.6",
101
98
  "esbuild": "0.14.38",
102
99
  "esbuild-runner": "2.2.1",
100
+ "eslint": "^8.14.0",
103
101
  "jest": "27.5.1",
104
102
  "jest-image-snapshot": "4.5.1",
105
103
  "playwright-chromium": "1.21.1",
@@ -109,7 +107,6 @@
109
107
  "rollup-plugin-dts": "^4.2.0",
110
108
  "rollup-plugin-esbuild": "4.9.1",
111
109
  "rxjs": "7.5.5",
112
- "typescript": "4.6.3",
113
110
  "vite": "^2.9.5",
114
111
  "vite-plugin-inspect": "0.5.0",
115
112
  "vue": "3.2.33"