@proj-airi/cap-vite 0.9.0-alpha.9 → 0.9.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -14
- package/dist/bin/run.mjs +35 -31
- package/dist/bin/run.mjs.map +1 -1
- package/dist/index.d.mts +14 -5
- package/dist/index.mjs +94 -141
- package/dist/index.mjs.map +1 -1
- package/dist/native-hZ5d7ukC.mjs +125 -0
- package/dist/native-hZ5d7ukC.mjs.map +1 -0
- package/dist/vite-plugin.d.mts +10 -0
- package/dist/vite-plugin.mjs +146 -0
- package/dist/vite-plugin.mjs.map +1 -0
- package/dist/vite-wrapper-config.d.mts +7 -0
- package/dist/vite-wrapper-config.mjs +23 -0
- package/dist/vite-wrapper-config.mjs.map +1 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -5,25 +5,33 @@ CLI for [Capacitor](https://capacitorjs.com/) live-reload development using Vite
|
|
|
5
5
|
## Usage
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
9
|
-
pnpm cap-vite android --target <DEVICE_ID_OR_SIMULATOR_NAME>
|
|
10
|
-
pnpm cap-vite ios --target <DEVICE_ID_OR_SIMULATOR_NAME> -- --scheme AIRI
|
|
11
|
-
pnpm cap-vite android --target <DEVICE_ID_OR_SIMULATOR_NAME> -- --flavor release
|
|
12
|
-
# Or
|
|
13
|
-
CAPACITOR_DEVICE_ID=<DEVICE_ID_OR_SIMULATOR_NAME> pnpm cap-vite ios
|
|
14
|
-
CAPACITOR_DEVICE_ID=<DEVICE_ID_OR_SIMULATOR_NAME> pnpm cap-vite android
|
|
8
|
+
cap-vite [vite args...] -- <ios|android> [cap run args...]
|
|
15
9
|
```
|
|
16
10
|
|
|
17
|
-
|
|
11
|
+
Examples:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pnpm exec cap-vite -- ios --target <DEVICE_ID_OR_SIMULATOR_NAME>
|
|
15
|
+
pnpm exec cap-vite -- --host 0.0.0.0 --port 5173 -- android --target <DEVICE_ID_OR_SIMULATOR_NAME> --flavor release
|
|
16
|
+
CAPACITOR_DEVICE_ID_IOS=<DEVICE_ID_OR_SIMULATOR_NAME> pnpm exec cap-vite -- ios
|
|
17
|
+
pnpm -F @proj-airi/stage-pocket run dev:ios -- --target <DEVICE_ID_OR_SIMULATOR_NAME>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
- Arguments before `--` are forwarded to `vite`.
|
|
21
|
+
- Arguments after `--` are forwarded to `cap run`.
|
|
22
|
+
- If the platform-specific env is set (`CAPACITOR_DEVICE_ID_IOS` or `CAPACITOR_DEVICE_ID_ANDROID`) and `cap run` args do not contain `--target`, `cap-vite` injects `--target` with that value automatically.
|
|
23
|
+
- `cap-vite` always launches the Vite dev server. Do not pass `vite dev` or `vite serve` as extra args.
|
|
24
|
+
- After the dev server starts, press `R` in the terminal to re-run `cap run` without restarting Vite.
|
|
18
25
|
|
|
19
26
|
You can see the list of available devices and simulators by running `pnpm exec cap run ios --list` or `pnpm exec cap run android --list`.
|
|
20
27
|
|
|
21
28
|
## Capacitor Configuration
|
|
22
29
|
|
|
23
|
-
You need to set `server.url` in `capacitor.config.ts` to the env variable `CAPACITOR_DEV_SERVER_URL
|
|
30
|
+
You need to set `server.url` in `capacitor.config.ts` to the env variable `CAPACITOR_DEV_SERVER_URL`, then the cli will handle rest for you.
|
|
24
31
|
|
|
25
32
|
```ts
|
|
26
33
|
const serverURL = env.CAPACITOR_DEV_SERVER_URL
|
|
34
|
+
const isCleartext = serverURL?.startsWith('http://') ?? false
|
|
27
35
|
|
|
28
36
|
const config: CapacitorConfig = {
|
|
29
37
|
appId: 'com.example.app',
|
|
@@ -32,7 +40,7 @@ const config: CapacitorConfig = {
|
|
|
32
40
|
server: serverURL
|
|
33
41
|
? {
|
|
34
42
|
url: serverURL,
|
|
35
|
-
cleartext:
|
|
43
|
+
cleartext: isCleartext,
|
|
36
44
|
}
|
|
37
45
|
: undefined,
|
|
38
46
|
}
|
|
@@ -40,8 +48,16 @@ const config: CapacitorConfig = {
|
|
|
40
48
|
export default config
|
|
41
49
|
```
|
|
42
50
|
|
|
43
|
-
##
|
|
51
|
+
## Why we need this?
|
|
52
|
+
|
|
53
|
+
- No need to care what `server.url` should be, it will be automatically set to the correct value.
|
|
54
|
+
- Rerun native app when native code changes, you won't forget to start it.
|
|
55
|
+
- Rerun `cap run` on demand from the same terminal when you need a clean native relaunch.
|
|
56
|
+
- No need to open two terminals to run the project, you can run it with one command.
|
|
57
|
+
|
|
58
|
+
## Architecture Notes
|
|
44
59
|
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
-
|
|
60
|
+
- Vite arguments are left to the real Vite CLI instead of being reimplemented inside `cap-vite`.
|
|
61
|
+
- `cap-vite` injects a wrapper config so it can append its own Vite plugin without editing the user's existing `vite.config.*`.
|
|
62
|
+
- The injected plugin reads `server.resolvedUrls`, starts `cap run`, and restarts it when files under the native platform directory change or when you press `R` in the terminal.
|
|
63
|
+
- `cap-vite` only splits the two argument groups and passes the `cap run` arguments into the injected plugin through environment variables.
|
package/dist/bin/run.mjs
CHANGED
|
@@ -1,51 +1,55 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { runCapVite } from "../index.mjs";
|
|
3
3
|
import process from "node:process";
|
|
4
|
-
import { cac } from "cac";
|
|
5
|
-
|
|
6
4
|
//#region src/cli.ts
|
|
7
|
-
const usage = "cap-vite <ios|android> [
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
const usage = "cap-vite [vite args...] -- <ios|android> [cap run args...]";
|
|
6
|
+
const helpText = [
|
|
7
|
+
"Run a Vite dev server and forward a second argument group to `cap run`.",
|
|
8
|
+
"",
|
|
9
|
+
"Usage:",
|
|
10
|
+
` ${usage}`,
|
|
11
|
+
"",
|
|
12
|
+
"Examples:",
|
|
13
|
+
" cap-vite -- ios --target \"iPhone 16 Pro\"",
|
|
14
|
+
" cap-vite --host 0.0.0.0 --port 5173 -- android --target emulator-5554 --flavor release",
|
|
15
|
+
"",
|
|
16
|
+
"Notes:",
|
|
17
|
+
" Arguments before `--` are forwarded to Vite.",
|
|
18
|
+
" Arguments after `--` are forwarded to `cap run`.",
|
|
19
|
+
" After the dev server starts, press `R` to re-run `cap run`."
|
|
20
|
+
].join("\n");
|
|
21
|
+
function getCapViteCliHelpText() {
|
|
22
|
+
return helpText;
|
|
13
23
|
}
|
|
14
|
-
function parseCapViteCliArgs(argv
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
if (cli.options.help) return null;
|
|
22
|
-
cli.matchedCommand?.checkUnknownOptions();
|
|
23
|
-
cli.matchedCommand?.checkOptionValue();
|
|
24
|
-
cli.matchedCommand?.checkRequiredArgs();
|
|
25
|
-
if (parsed.args.length > 1) throw new Error(usage);
|
|
26
|
-
const platform = parsed.args[0];
|
|
24
|
+
function parseCapViteCliArgs(argv) {
|
|
25
|
+
if (argv.length === 1 && (argv[0] === "--help" || argv[0] === "-h")) return null;
|
|
26
|
+
const separatorIndex = argv.indexOf("--");
|
|
27
|
+
if (separatorIndex === -1) throw new Error(usage);
|
|
28
|
+
const capArgs = argv.slice(separatorIndex + 1);
|
|
29
|
+
if (capArgs.length === 0) throw new Error(usage);
|
|
30
|
+
const platform = capArgs[0];
|
|
27
31
|
if (platform !== "android" && platform !== "ios") throw new Error(usage);
|
|
28
|
-
const target = typeof parsed.options.target === "string" ? parsed.options.target : env.CAPACITOR_DEVICE_ID;
|
|
29
|
-
if (!target) throw new Error(usage);
|
|
30
32
|
return {
|
|
31
|
-
capArgs
|
|
32
|
-
|
|
33
|
-
target
|
|
33
|
+
capArgs,
|
|
34
|
+
viteArgs: argv.slice(0, separatorIndex)
|
|
34
35
|
};
|
|
35
36
|
}
|
|
36
|
-
|
|
37
37
|
//#endregion
|
|
38
38
|
//#region src/bin/run.ts
|
|
39
39
|
async function main() {
|
|
40
40
|
const parsed = parseCapViteCliArgs(process.argv.slice(2));
|
|
41
|
-
if (!parsed)
|
|
42
|
-
|
|
41
|
+
if (!parsed) {
|
|
42
|
+
process.stdout.write(`${getCapViteCliHelpText()}\n`);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const result = await runCapVite(parsed.viteArgs, parsed.capArgs);
|
|
46
|
+
if (typeof result.exitCode === "number") process.exitCode = result.exitCode;
|
|
43
47
|
}
|
|
44
48
|
main().catch((error) => {
|
|
45
49
|
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
46
50
|
process.exit(1);
|
|
47
51
|
});
|
|
48
|
-
|
|
49
52
|
//#endregion
|
|
50
|
-
export {
|
|
53
|
+
export {};
|
|
54
|
+
|
|
51
55
|
//# sourceMappingURL=run.mjs.map
|
package/dist/bin/run.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.mjs","names":[],"sources":["../../src/cli.ts","../../src/bin/run.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"run.mjs","names":[],"sources":["../../src/cli.ts","../../src/bin/run.ts"],"sourcesContent":["const usage = 'cap-vite [vite args...] -- <ios|android> [cap run args...]'\n\nconst helpText = [\n 'Run a Vite dev server and forward a second argument group to `cap run`.',\n '',\n 'Usage:',\n ` ${usage}`,\n '',\n 'Examples:',\n ' cap-vite -- ios --target \"iPhone 16 Pro\"',\n ' cap-vite --host 0.0.0.0 --port 5173 -- android --target emulator-5554 --flavor release',\n '',\n 'Notes:',\n ' Arguments before `--` are forwarded to Vite.',\n ' Arguments after `--` are forwarded to `cap run`.',\n ' After the dev server starts, press `R` to re-run `cap run`.',\n].join('\\n')\n\nexport interface ParsedCapViteCliArgs {\n capArgs: string[]\n viteArgs: string[]\n}\n\nexport function getCapViteCliHelpText(): string {\n return helpText\n}\n\nexport function getCapViteCliUsage(): string {\n return usage\n}\n\n// TODO: CLI and `cap run` argument handling are hand-rolled (see also `resolveCapRunArgs` /\n// `hasCapacitorTargetArg` in native.ts). If parsing rules keep growing, adopt a dedicated argv\n// library (cac is already a dependency—consider subcommands or a small wrapper) so flags like\n// `--target` / `--target=`, env-based defaults, and validation stay in one maintainable layer.\n\nexport function parseCapViteCliArgs(argv: string[]): ParsedCapViteCliArgs | null {\n if (argv.length === 1 && (argv[0] === '--help' || argv[0] === '-h')) {\n return null\n }\n\n const separatorIndex = argv.indexOf('--')\n if (separatorIndex === -1) {\n throw new Error(usage)\n }\n\n const capArgs = argv.slice(separatorIndex + 1)\n if (capArgs.length === 0) {\n throw new Error(usage)\n }\n\n const platform = capArgs[0]\n if (platform !== 'android' && platform !== 'ios') {\n throw new Error(usage)\n }\n\n return {\n capArgs,\n viteArgs: argv.slice(0, separatorIndex),\n }\n}\n","#!/usr/bin/env node\n\nimport process from 'node:process'\n\nimport { runCapVite } from '..'\nimport { getCapViteCliHelpText, parseCapViteCliArgs } from '../cli'\n\nasync function main() {\n const parsed = parseCapViteCliArgs(process.argv.slice(2))\n if (!parsed) {\n process.stdout.write(`${getCapViteCliHelpText()}\\n`)\n return\n }\n\n const result = await runCapVite(parsed.viteArgs, parsed.capArgs)\n if (typeof result.exitCode === 'number') {\n process.exitCode = result.exitCode\n }\n}\n\nvoid main().catch((error) => {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`)\n process.exit(1)\n})\n"],"mappings":";;;;AAAA,MAAM,QAAQ;AAEd,MAAM,WAAW;CACf;CACA;CACA;CACA,KAAK;CACL;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC,KAAK,KAAK;AAOZ,SAAgB,wBAAgC;AAC9C,QAAO;;AAYT,SAAgB,oBAAoB,MAA6C;AAC/E,KAAI,KAAK,WAAW,MAAM,KAAK,OAAO,YAAY,KAAK,OAAO,MAC5D,QAAO;CAGT,MAAM,iBAAiB,KAAK,QAAQ,KAAK;AACzC,KAAI,mBAAmB,GACrB,OAAM,IAAI,MAAM,MAAM;CAGxB,MAAM,UAAU,KAAK,MAAM,iBAAiB,EAAE;AAC9C,KAAI,QAAQ,WAAW,EACrB,OAAM,IAAI,MAAM,MAAM;CAGxB,MAAM,WAAW,QAAQ;AACzB,KAAI,aAAa,aAAa,aAAa,MACzC,OAAM,IAAI,MAAM,MAAM;AAGxB,QAAO;EACL;EACA,UAAU,KAAK,MAAM,GAAG,eAAe;EACxC;;;;ACpDH,eAAe,OAAO;CACpB,MAAM,SAAS,oBAAoB,QAAQ,KAAK,MAAM,EAAE,CAAC;AACzD,KAAI,CAAC,QAAQ;AACX,UAAQ,OAAO,MAAM,GAAG,uBAAuB,CAAC,IAAI;AACpD;;CAGF,MAAM,SAAS,MAAM,WAAW,OAAO,UAAU,OAAO,QAAQ;AAChE,KAAI,OAAO,OAAO,aAAa,SAC7B,SAAQ,WAAW,OAAO;;AAIzB,MAAM,CAAC,OAAO,UAAU;AAC3B,SAAQ,OAAO,MAAM,GAAG,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC,IAAI;AACnF,SAAQ,KAAK,EAAE;EACf"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
import { Output } from "tinyexec";
|
|
2
|
+
//#region src/native.d.ts
|
|
2
3
|
type CapacitorPlatform = 'android' | 'ios';
|
|
4
|
+
//#endregion
|
|
5
|
+
//#region src/index.d.ts
|
|
3
6
|
interface RunCapViteOptions {
|
|
4
|
-
capArgs?: string[];
|
|
5
7
|
cwd?: string;
|
|
6
|
-
debounceMs?: number;
|
|
7
8
|
}
|
|
8
|
-
|
|
9
|
+
interface PreparedViteLaunch {
|
|
10
|
+
baseConfigFile?: string;
|
|
11
|
+
configLoader?: 'bundle' | 'native' | 'runner';
|
|
12
|
+
projectRoot: string;
|
|
13
|
+
viteArgs: string[];
|
|
14
|
+
wrapperConfigFile: string;
|
|
15
|
+
}
|
|
16
|
+
declare function prepareCapViteLaunch(viteArgs: string[], cwd?: string): PreparedViteLaunch;
|
|
17
|
+
declare function runCapVite(viteArgs: string[], capArgs: string[], options?: RunCapViteOptions): Promise<Output>;
|
|
9
18
|
//#endregion
|
|
10
|
-
export { CapacitorPlatform, RunCapViteOptions, runCapVite };
|
|
19
|
+
export { type CapacitorPlatform, RunCapViteOptions, prepareCapViteLaunch, runCapVite };
|
|
11
20
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
CHANGED
|
@@ -1,156 +1,109 @@
|
|
|
1
|
+
import { t as parseCapacitorPlatform } from "./native-hZ5d7ukC.mjs";
|
|
1
2
|
import process from "node:process";
|
|
2
|
-
import {
|
|
3
|
+
import { extname, resolve } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
3
5
|
import { x } from "tinyexec";
|
|
4
|
-
import { createServer } from "vite";
|
|
5
|
-
|
|
6
6
|
//#region src/index.ts
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
".mm",
|
|
14
|
-
".pbxproj",
|
|
15
|
-
".plist",
|
|
16
|
-
".storyboard",
|
|
17
|
-
".strings",
|
|
18
|
-
".swift",
|
|
19
|
-
".xcodeproj",
|
|
20
|
-
".xcconfig",
|
|
21
|
-
".xcscheme",
|
|
22
|
-
".xib"
|
|
23
|
-
]),
|
|
24
|
-
android: new Set([
|
|
25
|
-
".gradle",
|
|
26
|
-
".java",
|
|
27
|
-
".json",
|
|
28
|
-
".kts",
|
|
29
|
-
".kt",
|
|
30
|
-
".properties",
|
|
31
|
-
".xml"
|
|
32
|
-
])
|
|
33
|
-
};
|
|
34
|
-
const nativeNamesByPlatform = {
|
|
35
|
-
ios: new Set([
|
|
36
|
-
"Podfile",
|
|
37
|
-
"Podfile.lock",
|
|
38
|
-
"project.pbxproj"
|
|
39
|
-
]),
|
|
40
|
-
android: new Set([
|
|
41
|
-
"AndroidManifest.xml",
|
|
42
|
-
"build.gradle",
|
|
43
|
-
"build.gradle.kts",
|
|
44
|
-
"gradle.properties",
|
|
45
|
-
"settings.gradle",
|
|
46
|
-
"settings.gradle.kts"
|
|
47
|
-
])
|
|
48
|
-
};
|
|
49
|
-
const ignoredNames = new Set(["capacitor.config.json"]);
|
|
50
|
-
const ignoredPathSegments = new Set([
|
|
51
|
-
".gradle",
|
|
52
|
-
"DerivedData",
|
|
53
|
-
"Pods",
|
|
54
|
-
"build",
|
|
55
|
-
"xcuserdata"
|
|
56
|
-
]);
|
|
57
|
-
const ignoredPathPrefixesByPlatform = {
|
|
58
|
-
ios: [["App", "CapApp-SPM"]],
|
|
59
|
-
android: []
|
|
60
|
-
};
|
|
61
|
-
function pickServerUrl(server) {
|
|
62
|
-
const url = server.resolvedUrls?.network?.[0] ?? server.resolvedUrls?.local?.[0];
|
|
63
|
-
if (!url) throw new Error("Vite did not expose a reachable dev server URL.");
|
|
64
|
-
return new URL(url);
|
|
7
|
+
function resolveWrapperConfigFile() {
|
|
8
|
+
const wrapperExtension = extname(fileURLToPath(import.meta.url)) === ".ts" ? ".ts" : ".mjs";
|
|
9
|
+
return fileURLToPath(new URL(`./vite-wrapper-config${wrapperExtension}`, import.meta.url));
|
|
10
|
+
}
|
|
11
|
+
function parseViteConfigLoader(value) {
|
|
12
|
+
if (value === "bundle" || value === "native" || value === "runner") return value;
|
|
65
13
|
}
|
|
66
|
-
function
|
|
67
|
-
|
|
68
|
-
const platformRoot = resolve(cwd, platform);
|
|
69
|
-
if (!absoluteFile.startsWith(`${platformRoot}${sep}`) && absoluteFile !== platformRoot) return false;
|
|
70
|
-
const fileName = basename(absoluteFile);
|
|
71
|
-
if (ignoredNames.has(fileName)) return false;
|
|
72
|
-
if (absoluteFile.split(sep).some((segment) => ignoredPathSegments.has(segment))) return false;
|
|
73
|
-
const relativeSegments = relative(platformRoot, absoluteFile).split(sep).filter(Boolean);
|
|
74
|
-
if (ignoredPathPrefixesByPlatform[platform].some((prefix) => prefix.every((segment, index) => relativeSegments[index] === segment))) return false;
|
|
75
|
-
if (nativeNamesByPlatform[platform].has(fileName)) return true;
|
|
76
|
-
return nativeExtensionsByPlatform[platform].has(extname(fileName).toLowerCase());
|
|
14
|
+
function resolveConfigPath(cwd, value) {
|
|
15
|
+
return resolve(cwd, value);
|
|
77
16
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
await current;
|
|
83
|
-
} catch {}
|
|
17
|
+
function readRequiredOptionValue(viteArgs, index, optionName) {
|
|
18
|
+
const value = viteArgs[index + 1];
|
|
19
|
+
if (!value) throw new Error(`Missing value for \`${optionName}\`.`);
|
|
20
|
+
return value;
|
|
84
21
|
}
|
|
85
|
-
function
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
22
|
+
function parseConfigArg(viteArgs, index, cwd) {
|
|
23
|
+
const arg = viteArgs[index];
|
|
24
|
+
if (arg === "--config" || arg === "-c") return {
|
|
25
|
+
baseConfigFile: resolveConfigPath(cwd, readRequiredOptionValue(viteArgs, index, "--config")),
|
|
26
|
+
consumedArgs: 2,
|
|
27
|
+
forwardedArgs: []
|
|
28
|
+
};
|
|
29
|
+
if (arg.startsWith("--config=")) return {
|
|
30
|
+
baseConfigFile: resolveConfigPath(cwd, arg.slice(9)),
|
|
31
|
+
consumedArgs: 1,
|
|
32
|
+
forwardedArgs: []
|
|
33
|
+
};
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
function parseConfigLoaderArg(viteArgs, index) {
|
|
37
|
+
const arg = viteArgs[index];
|
|
38
|
+
if (arg === "--configLoader") {
|
|
39
|
+
const value = readRequiredOptionValue(viteArgs, index, "--configLoader");
|
|
40
|
+
return {
|
|
41
|
+
configLoader: parseViteConfigLoader(value),
|
|
42
|
+
consumedArgs: 2,
|
|
43
|
+
forwardedArgs: [arg, value]
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
if (arg.startsWith("--configLoader=")) return {
|
|
47
|
+
configLoader: parseViteConfigLoader(arg.slice(15)),
|
|
48
|
+
consumedArgs: 1,
|
|
49
|
+
forwardedArgs: [arg]
|
|
50
|
+
};
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
function parseViteArg(viteArgs, index, cwd) {
|
|
54
|
+
return parseConfigArg(viteArgs, index, cwd) ?? parseConfigLoaderArg(viteArgs, index) ?? {
|
|
55
|
+
consumedArgs: 1,
|
|
56
|
+
forwardedArgs: [viteArgs[index]]
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function resolveProjectRoot(viteArgs, cwd) {
|
|
60
|
+
const firstArg = viteArgs[0];
|
|
61
|
+
return firstArg && !firstArg.startsWith("-") ? resolve(cwd, firstArg) : cwd;
|
|
62
|
+
}
|
|
63
|
+
function prepareCapViteLaunch(viteArgs, cwd = process.cwd()) {
|
|
64
|
+
const resolvedCwd = resolve(cwd);
|
|
65
|
+
const projectRoot = resolveProjectRoot(viteArgs, resolvedCwd);
|
|
66
|
+
let baseConfigFile;
|
|
67
|
+
let configLoader;
|
|
68
|
+
const forwardedViteArgs = [];
|
|
69
|
+
for (let index = 0; index < viteArgs.length;) {
|
|
70
|
+
const parsedArg = parseViteArg(viteArgs, index, resolvedCwd);
|
|
71
|
+
baseConfigFile = parsedArg.baseConfigFile ?? baseConfigFile;
|
|
72
|
+
configLoader = parsedArg.configLoader ?? configLoader;
|
|
73
|
+
forwardedViteArgs.push(...parsedArg.forwardedArgs);
|
|
74
|
+
index += parsedArg.consumedArgs;
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
baseConfigFile,
|
|
78
|
+
configLoader,
|
|
79
|
+
projectRoot,
|
|
80
|
+
viteArgs: forwardedViteArgs,
|
|
81
|
+
wrapperConfigFile: resolveWrapperConfigFile()
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
async function runCapVite(viteArgs, capArgs, options = {}) {
|
|
85
|
+
if (!parseCapacitorPlatform(capArgs[0])) throw new Error("The first `cap run` argument must be `ios` or `android`.");
|
|
86
|
+
const cwd = resolve(options.cwd ?? process.cwd());
|
|
87
|
+
const prepared = prepareCapViteLaunch(viteArgs, cwd);
|
|
88
|
+
return await x("vite", [
|
|
89
|
+
"--config",
|
|
90
|
+
prepared.wrapperConfigFile,
|
|
91
|
+
...prepared.viteArgs
|
|
94
92
|
], {
|
|
95
|
-
persist: true,
|
|
96
93
|
throwOnError: false,
|
|
97
94
|
nodeOptions: {
|
|
98
95
|
cwd,
|
|
99
|
-
|
|
100
|
-
|
|
96
|
+
env: {
|
|
97
|
+
CAP_VITE_BASE_CONFIG: prepared.baseConfigFile ?? "",
|
|
98
|
+
CAP_VITE_CAP_ARGS_JSON: JSON.stringify(capArgs),
|
|
99
|
+
CAP_VITE_CONFIG_LOADER: prepared.configLoader ?? "",
|
|
100
|
+
CAP_VITE_ROOT: prepared.projectRoot
|
|
101
|
+
},
|
|
102
|
+
stdio: "inherit"
|
|
101
103
|
}
|
|
102
104
|
});
|
|
103
105
|
}
|
|
104
|
-
async function runCapVite(platform, target, options = {}) {
|
|
105
|
-
const capArgs = options.capArgs ?? [];
|
|
106
|
-
const cwd = resolve(options.cwd ?? process.cwd());
|
|
107
|
-
const debounceMs = options.debounceMs ?? 300;
|
|
108
|
-
const server = await createServer({
|
|
109
|
-
clearScreen: false,
|
|
110
|
-
root: cwd
|
|
111
|
-
});
|
|
112
|
-
await server.listen();
|
|
113
|
-
server.printUrls();
|
|
114
|
-
const url = pickServerUrl(server);
|
|
115
|
-
const logger = server.config.logger;
|
|
116
|
-
let currentCapProcess = startCapProcess(cwd, platform, target, url, capArgs);
|
|
117
|
-
let restartTimer;
|
|
118
|
-
let shuttingDown = false;
|
|
119
|
-
async function restartCapProcess(reason) {
|
|
120
|
-
if (shuttingDown) return;
|
|
121
|
-
logger.info(`[cap-vite] ${reason}. Re-running cap run ${platform}.`);
|
|
122
|
-
const previous = currentCapProcess;
|
|
123
|
-
currentCapProcess = void 0;
|
|
124
|
-
await stopCapProcess(previous);
|
|
125
|
-
currentCapProcess = startCapProcess(cwd, platform, target, url, capArgs);
|
|
126
|
-
}
|
|
127
|
-
const onWatcherEvent = (_event, file) => {
|
|
128
|
-
if (!shouldRestartForNativeChange(file, platform, cwd)) return;
|
|
129
|
-
clearTimeout(restartTimer);
|
|
130
|
-
restartTimer = setTimeout(() => {
|
|
131
|
-
restartCapProcess(`native file changed: ${resolve(cwd, file)}`);
|
|
132
|
-
}, debounceMs);
|
|
133
|
-
};
|
|
134
|
-
const shutdown = async (exitCode) => {
|
|
135
|
-
if (shuttingDown) return;
|
|
136
|
-
shuttingDown = true;
|
|
137
|
-
clearTimeout(restartTimer);
|
|
138
|
-
server.watcher.off("all", onWatcherEvent);
|
|
139
|
-
await server.watcher.unwatch(platform);
|
|
140
|
-
await server.close();
|
|
141
|
-
await stopCapProcess(currentCapProcess);
|
|
142
|
-
process.exit(exitCode);
|
|
143
|
-
};
|
|
144
|
-
server.watcher.add(platform);
|
|
145
|
-
server.watcher.on("all", onWatcherEvent);
|
|
146
|
-
process.once("SIGINT", () => {
|
|
147
|
-
shutdown(0);
|
|
148
|
-
});
|
|
149
|
-
process.once("SIGTERM", () => {
|
|
150
|
-
shutdown(0);
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
|
|
154
106
|
//#endregion
|
|
155
|
-
export { runCapVite };
|
|
107
|
+
export { prepareCapViteLaunch, runCapVite };
|
|
108
|
+
|
|
156
109
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { Output } from 'tinyexec'\n\nimport process from 'node:process'\n\nimport { extname, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nimport { x } from 'tinyexec'\n\nimport { parseCapacitorPlatform } from './native'\n\nexport type { CapacitorPlatform } from './native'\n\nexport interface RunCapViteOptions {\n cwd?: string\n}\n\ninterface PreparedViteLaunch {\n baseConfigFile?: string\n configLoader?: 'bundle' | 'native' | 'runner'\n projectRoot: string\n viteArgs: string[]\n wrapperConfigFile: string\n}\n\ninterface ParsedViteArg {\n baseConfigFile?: string\n configLoader?: 'bundle' | 'native' | 'runner'\n consumedArgs: number\n forwardedArgs: string[]\n}\n\nfunction resolveWrapperConfigFile(): string {\n const currentModulePath = fileURLToPath(import.meta.url)\n const wrapperExtension = extname(currentModulePath) === '.ts' ? '.ts' : '.mjs'\n return fileURLToPath(new URL(`./vite-wrapper-config${wrapperExtension}`, import.meta.url))\n}\n\nfunction parseViteConfigLoader(value: string | undefined): 'bundle' | 'native' | 'runner' | undefined {\n if (value === 'bundle' || value === 'native' || value === 'runner') {\n return value\n }\n\n return undefined\n}\n\nfunction resolveConfigPath(cwd: string, value: string): string {\n return resolve(cwd, value)\n}\n\nfunction readRequiredOptionValue(viteArgs: string[], index: number, optionName: string): string {\n const value = viteArgs[index + 1]\n if (!value) {\n throw new Error(`Missing value for \\`${optionName}\\`.`)\n }\n\n return value\n}\n\nfunction parseConfigArg(viteArgs: string[], index: number, cwd: string): ParsedViteArg | null {\n const arg = viteArgs[index]\n\n // NOTICE: Vite only accepts one `--config` entrypoint. cap-vite consumes that slot\n // for its wrapper config, then loads the user config from inside the wrapper.\n if (arg === '--config' || arg === '-c') {\n return {\n baseConfigFile: resolveConfigPath(cwd, readRequiredOptionValue(viteArgs, index, '--config')),\n consumedArgs: 2,\n forwardedArgs: [],\n }\n }\n\n if (arg.startsWith('--config=')) {\n return {\n baseConfigFile: resolveConfigPath(cwd, arg.slice('--config='.length)),\n consumedArgs: 1,\n forwardedArgs: [],\n }\n }\n\n return null\n}\n\nfunction parseConfigLoaderArg(viteArgs: string[], index: number): ParsedViteArg | null {\n const arg = viteArgs[index]\n\n if (arg === '--configLoader') {\n const value = readRequiredOptionValue(viteArgs, index, '--configLoader')\n\n return {\n configLoader: parseViteConfigLoader(value),\n consumedArgs: 2,\n forwardedArgs: [arg, value],\n }\n }\n\n if (arg.startsWith('--configLoader=')) {\n return {\n configLoader: parseViteConfigLoader(arg.slice('--configLoader='.length)),\n consumedArgs: 1,\n forwardedArgs: [arg],\n }\n }\n\n return null\n}\n\nfunction parseViteArg(viteArgs: string[], index: number, cwd: string): ParsedViteArg {\n return parseConfigArg(viteArgs, index, cwd)\n ?? parseConfigLoaderArg(viteArgs, index)\n ?? {\n consumedArgs: 1,\n forwardedArgs: [viteArgs[index]],\n }\n}\n\nfunction resolveProjectRoot(viteArgs: string[], cwd: string): string {\n const firstArg = viteArgs[0]\n\n return firstArg && !firstArg.startsWith('-')\n ? resolve(cwd, firstArg)\n : cwd\n}\n\nexport function prepareCapViteLaunch(viteArgs: string[], cwd: string = process.cwd()): PreparedViteLaunch {\n const resolvedCwd = resolve(cwd)\n const projectRoot = resolveProjectRoot(viteArgs, resolvedCwd)\n\n let baseConfigFile: string | undefined\n let configLoader: 'bundle' | 'native' | 'runner' | undefined\n const forwardedViteArgs: string[] = []\n\n for (let index = 0; index < viteArgs.length;) {\n const parsedArg = parseViteArg(viteArgs, index, resolvedCwd)\n\n baseConfigFile = parsedArg.baseConfigFile ?? baseConfigFile\n configLoader = parsedArg.configLoader ?? configLoader\n forwardedViteArgs.push(...parsedArg.forwardedArgs)\n index += parsedArg.consumedArgs\n }\n\n return {\n baseConfigFile,\n configLoader,\n projectRoot,\n viteArgs: forwardedViteArgs,\n wrapperConfigFile: resolveWrapperConfigFile(),\n }\n}\n\nexport async function runCapVite(\n viteArgs: string[],\n capArgs: string[],\n options: RunCapViteOptions = {},\n): Promise<Output> {\n if (!parseCapacitorPlatform(capArgs[0])) {\n throw new Error('The first `cap run` argument must be `ios` or `android`.')\n }\n\n const cwd = resolve(options.cwd ?? process.cwd())\n const prepared = prepareCapViteLaunch(viteArgs, cwd)\n\n return await x('vite', ['--config', prepared.wrapperConfigFile, ...prepared.viteArgs], {\n throwOnError: false,\n nodeOptions: {\n cwd,\n env: {\n CAP_VITE_BASE_CONFIG: prepared.baseConfigFile ?? '',\n CAP_VITE_CAP_ARGS_JSON: JSON.stringify(capArgs),\n CAP_VITE_CONFIG_LOADER: prepared.configLoader ?? '',\n CAP_VITE_ROOT: prepared.projectRoot,\n },\n stdio: 'inherit',\n },\n })\n}\n"],"mappings":";;;;;;AAgCA,SAAS,2BAAmC;CAE1C,MAAM,mBAAmB,QADC,cAAc,OAAO,KAAK,IAAI,CACL,KAAK,QAAQ,QAAQ;AACxE,QAAO,cAAc,IAAI,IAAI,wBAAwB,oBAAoB,OAAO,KAAK,IAAI,CAAC;;AAG5F,SAAS,sBAAsB,OAAuE;AACpG,KAAI,UAAU,YAAY,UAAU,YAAY,UAAU,SACxD,QAAO;;AAMX,SAAS,kBAAkB,KAAa,OAAuB;AAC7D,QAAO,QAAQ,KAAK,MAAM;;AAG5B,SAAS,wBAAwB,UAAoB,OAAe,YAA4B;CAC9F,MAAM,QAAQ,SAAS,QAAQ;AAC/B,KAAI,CAAC,MACH,OAAM,IAAI,MAAM,uBAAuB,WAAW,KAAK;AAGzD,QAAO;;AAGT,SAAS,eAAe,UAAoB,OAAe,KAAmC;CAC5F,MAAM,MAAM,SAAS;AAIrB,KAAI,QAAQ,cAAc,QAAQ,KAChC,QAAO;EACL,gBAAgB,kBAAkB,KAAK,wBAAwB,UAAU,OAAO,WAAW,CAAC;EAC5F,cAAc;EACd,eAAe,EAAE;EAClB;AAGH,KAAI,IAAI,WAAW,YAAY,CAC7B,QAAO;EACL,gBAAgB,kBAAkB,KAAK,IAAI,MAAM,EAAmB,CAAC;EACrE,cAAc;EACd,eAAe,EAAE;EAClB;AAGH,QAAO;;AAGT,SAAS,qBAAqB,UAAoB,OAAqC;CACrF,MAAM,MAAM,SAAS;AAErB,KAAI,QAAQ,kBAAkB;EAC5B,MAAM,QAAQ,wBAAwB,UAAU,OAAO,iBAAiB;AAExE,SAAO;GACL,cAAc,sBAAsB,MAAM;GAC1C,cAAc;GACd,eAAe,CAAC,KAAK,MAAM;GAC5B;;AAGH,KAAI,IAAI,WAAW,kBAAkB,CACnC,QAAO;EACL,cAAc,sBAAsB,IAAI,MAAM,GAAyB,CAAC;EACxE,cAAc;EACd,eAAe,CAAC,IAAI;EACrB;AAGH,QAAO;;AAGT,SAAS,aAAa,UAAoB,OAAe,KAA4B;AACnF,QAAO,eAAe,UAAU,OAAO,IAAI,IACtC,qBAAqB,UAAU,MAAM,IACrC;EACD,cAAc;EACd,eAAe,CAAC,SAAS,OAAO;EACjC;;AAGL,SAAS,mBAAmB,UAAoB,KAAqB;CACnE,MAAM,WAAW,SAAS;AAE1B,QAAO,YAAY,CAAC,SAAS,WAAW,IAAI,GACxC,QAAQ,KAAK,SAAS,GACtB;;AAGN,SAAgB,qBAAqB,UAAoB,MAAc,QAAQ,KAAK,EAAsB;CACxG,MAAM,cAAc,QAAQ,IAAI;CAChC,MAAM,cAAc,mBAAmB,UAAU,YAAY;CAE7D,IAAI;CACJ,IAAI;CACJ,MAAM,oBAA8B,EAAE;AAEtC,MAAK,IAAI,QAAQ,GAAG,QAAQ,SAAS,SAAS;EAC5C,MAAM,YAAY,aAAa,UAAU,OAAO,YAAY;AAE5D,mBAAiB,UAAU,kBAAkB;AAC7C,iBAAe,UAAU,gBAAgB;AACzC,oBAAkB,KAAK,GAAG,UAAU,cAAc;AAClD,WAAS,UAAU;;AAGrB,QAAO;EACL;EACA;EACA;EACA,UAAU;EACV,mBAAmB,0BAA0B;EAC9C;;AAGH,eAAsB,WACpB,UACA,SACA,UAA6B,EAAE,EACd;AACjB,KAAI,CAAC,uBAAuB,QAAQ,GAAG,CACrC,OAAM,IAAI,MAAM,2DAA2D;CAG7E,MAAM,MAAM,QAAQ,QAAQ,OAAO,QAAQ,KAAK,CAAC;CACjD,MAAM,WAAW,qBAAqB,UAAU,IAAI;AAEpD,QAAO,MAAM,EAAE,QAAQ;EAAC;EAAY,SAAS;EAAmB,GAAG,SAAS;EAAS,EAAE;EACrF,cAAc;EACd,aAAa;GACX;GACA,KAAK;IACH,sBAAsB,SAAS,kBAAkB;IACjD,wBAAwB,KAAK,UAAU,QAAQ;IAC/C,wBAAwB,SAAS,gBAAgB;IACjD,eAAe,SAAS;IACzB;GACD,OAAO;GACR;EACF,CAAC"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
import { basename, extname, relative, resolve, sep } from "node:path";
|
|
3
|
+
//#region src/native.ts
|
|
4
|
+
const nativeExtensionsByPlatform = {
|
|
5
|
+
ios: new Set([
|
|
6
|
+
".entitlements",
|
|
7
|
+
".h",
|
|
8
|
+
".hpp",
|
|
9
|
+
".m",
|
|
10
|
+
".mm",
|
|
11
|
+
".pbxproj",
|
|
12
|
+
".plist",
|
|
13
|
+
".storyboard",
|
|
14
|
+
".strings",
|
|
15
|
+
".swift",
|
|
16
|
+
".xcodeproj",
|
|
17
|
+
".xcconfig",
|
|
18
|
+
".xcscheme",
|
|
19
|
+
".xib"
|
|
20
|
+
]),
|
|
21
|
+
android: new Set([
|
|
22
|
+
".gradle",
|
|
23
|
+
".java",
|
|
24
|
+
".json",
|
|
25
|
+
".kts",
|
|
26
|
+
".kt",
|
|
27
|
+
".properties",
|
|
28
|
+
".xml"
|
|
29
|
+
])
|
|
30
|
+
};
|
|
31
|
+
const nativeNamesByPlatform = {
|
|
32
|
+
ios: new Set([
|
|
33
|
+
"Podfile",
|
|
34
|
+
"Podfile.lock",
|
|
35
|
+
"project.pbxproj"
|
|
36
|
+
]),
|
|
37
|
+
android: new Set([
|
|
38
|
+
"AndroidManifest.xml",
|
|
39
|
+
"build.gradle",
|
|
40
|
+
"build.gradle.kts",
|
|
41
|
+
"gradle.properties",
|
|
42
|
+
"settings.gradle",
|
|
43
|
+
"settings.gradle.kts"
|
|
44
|
+
])
|
|
45
|
+
};
|
|
46
|
+
const ignoredNames = new Set(["capacitor.config.json"]);
|
|
47
|
+
const ignoredPathSegments = new Set([
|
|
48
|
+
".gradle",
|
|
49
|
+
"DerivedData",
|
|
50
|
+
"Pods",
|
|
51
|
+
"build",
|
|
52
|
+
"xcuserdata"
|
|
53
|
+
]);
|
|
54
|
+
const ignoredPathPrefixesByPlatform = {
|
|
55
|
+
ios: [["App", "CapApp-SPM"]],
|
|
56
|
+
android: [
|
|
57
|
+
[
|
|
58
|
+
"app",
|
|
59
|
+
"src",
|
|
60
|
+
"main",
|
|
61
|
+
"assets",
|
|
62
|
+
"public"
|
|
63
|
+
],
|
|
64
|
+
[
|
|
65
|
+
"app",
|
|
66
|
+
"src",
|
|
67
|
+
"main",
|
|
68
|
+
"assets",
|
|
69
|
+
"capacitor.plugins.json"
|
|
70
|
+
],
|
|
71
|
+
[
|
|
72
|
+
"app",
|
|
73
|
+
"src",
|
|
74
|
+
"main",
|
|
75
|
+
"res",
|
|
76
|
+
"xml",
|
|
77
|
+
"config.xml"
|
|
78
|
+
],
|
|
79
|
+
["app", "capacitor.build.gradle"],
|
|
80
|
+
["capacitor-cordova-android-plugins"],
|
|
81
|
+
["capacitor.settings.gradle"]
|
|
82
|
+
]
|
|
83
|
+
};
|
|
84
|
+
function parseCapacitorPlatform(value) {
|
|
85
|
+
return value === "android" || value === "ios" ? value : null;
|
|
86
|
+
}
|
|
87
|
+
function hasCapacitorTargetArg(capArgs) {
|
|
88
|
+
return capArgs.some((arg, index) => arg === "--target" || index > 0 && arg.startsWith("--target="));
|
|
89
|
+
}
|
|
90
|
+
function resolveCapRunArgs(capArgs, env = process.env) {
|
|
91
|
+
if (capArgs.length === 0 || hasCapacitorTargetArg(capArgs)) return capArgs;
|
|
92
|
+
const [platformArg, ...rest] = capArgs;
|
|
93
|
+
const platform = parseCapacitorPlatform(platformArg);
|
|
94
|
+
let target;
|
|
95
|
+
if (platform === "ios") target = env.CAPACITOR_DEVICE_ID_IOS;
|
|
96
|
+
else if (platform === "android") target = env.CAPACITOR_DEVICE_ID_ANDROID;
|
|
97
|
+
if (!target) return capArgs;
|
|
98
|
+
return [
|
|
99
|
+
platformArg,
|
|
100
|
+
"--target",
|
|
101
|
+
target,
|
|
102
|
+
...rest
|
|
103
|
+
];
|
|
104
|
+
}
|
|
105
|
+
function pickServerUrl(server) {
|
|
106
|
+
const url = server.resolvedUrls?.network?.[0] ?? server.resolvedUrls?.local?.[0];
|
|
107
|
+
if (!url) throw new Error("Vite did not expose a reachable dev server URL.");
|
|
108
|
+
return new URL(url);
|
|
109
|
+
}
|
|
110
|
+
function shouldRestartForNativeChange(file, platform, cwd) {
|
|
111
|
+
const absoluteFile = resolve(cwd, file);
|
|
112
|
+
const platformRoot = resolve(cwd, platform);
|
|
113
|
+
if (!absoluteFile.startsWith(`${platformRoot}${sep}`) && absoluteFile !== platformRoot) return false;
|
|
114
|
+
const fileName = basename(absoluteFile);
|
|
115
|
+
if (ignoredNames.has(fileName)) return false;
|
|
116
|
+
if (absoluteFile.split(sep).some((segment) => ignoredPathSegments.has(segment))) return false;
|
|
117
|
+
const relativeSegments = relative(platformRoot, absoluteFile).split(sep).filter(Boolean);
|
|
118
|
+
if (ignoredPathPrefixesByPlatform[platform].some((prefix) => prefix.every((segment, index) => relativeSegments[index] === segment))) return false;
|
|
119
|
+
if (nativeNamesByPlatform[platform].has(fileName)) return true;
|
|
120
|
+
return nativeExtensionsByPlatform[platform].has(extname(fileName).toLowerCase());
|
|
121
|
+
}
|
|
122
|
+
//#endregion
|
|
123
|
+
export { shouldRestartForNativeChange as i, pickServerUrl as n, resolveCapRunArgs as r, parseCapacitorPlatform as t };
|
|
124
|
+
|
|
125
|
+
//# sourceMappingURL=native-hZ5d7ukC.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-hZ5d7ukC.mjs","names":[],"sources":["../src/native.ts"],"sourcesContent":["import type { ViteDevServer } from 'vite'\n\nimport process from 'node:process'\n\nimport { basename, extname, relative, resolve, sep } from 'node:path'\n\nexport type CapacitorPlatform = 'android' | 'ios'\n\nconst nativeExtensionsByPlatform: Record<CapacitorPlatform, Set<string>> = {\n ios: new Set([\n '.entitlements',\n '.h',\n '.hpp',\n '.m',\n '.mm',\n '.pbxproj',\n '.plist',\n '.storyboard',\n '.strings',\n '.swift',\n '.xcodeproj',\n '.xcconfig',\n '.xcscheme',\n '.xib',\n ]),\n android: new Set([\n '.gradle',\n '.java',\n '.json',\n '.kts',\n '.kt',\n '.properties',\n '.xml',\n ]),\n}\n\nconst nativeNamesByPlatform: Record<CapacitorPlatform, Set<string>> = {\n ios: new Set([\n 'Podfile',\n 'Podfile.lock',\n 'project.pbxproj',\n ]),\n android: new Set([\n 'AndroidManifest.xml',\n 'build.gradle',\n 'build.gradle.kts',\n 'gradle.properties',\n 'settings.gradle',\n 'settings.gradle.kts',\n ]),\n}\n\nconst ignoredNames = new Set([\n 'capacitor.config.json',\n])\n\nconst ignoredPathSegments = new Set([\n '.gradle',\n 'DerivedData',\n 'Pods',\n 'build',\n 'xcuserdata',\n])\n\nconst ignoredPathPrefixesByPlatform: Record<CapacitorPlatform, string[][]> = {\n ios: [\n ['App', 'CapApp-SPM'],\n ],\n android: [\n ['app', 'src', 'main', 'assets', 'public'],\n ['app', 'src', 'main', 'assets', 'capacitor.plugins.json'],\n ['app', 'src', 'main', 'res', 'xml', 'config.xml'],\n ['app', 'capacitor.build.gradle'],\n ['capacitor-cordova-android-plugins'],\n ['capacitor.settings.gradle'],\n ],\n}\n\nexport function parseCapacitorPlatform(value: string | undefined): CapacitorPlatform | null {\n return value === 'android' || value === 'ios' ? value : null\n}\n\nexport function hasCapacitorTargetArg(capArgs: string[]): boolean {\n return capArgs.some((arg, index) => arg === '--target' || (index > 0 && arg.startsWith('--target=')))\n}\n\nexport function resolveCapRunArgs(capArgs: string[], env: NodeJS.ProcessEnv = process.env): string[] {\n if (capArgs.length === 0 || hasCapacitorTargetArg(capArgs)) {\n return capArgs\n }\n\n const [platformArg, ...rest] = capArgs\n const platform = parseCapacitorPlatform(platformArg)\n let target: string | undefined\n if (platform === 'ios') {\n target = env.CAPACITOR_DEVICE_ID_IOS\n }\n else if (platform === 'android') {\n target = env.CAPACITOR_DEVICE_ID_ANDROID\n }\n\n if (!target) {\n return capArgs\n }\n\n return [platformArg, '--target', target, ...rest]\n}\n\nexport function pickServerUrl(server: Pick<ViteDevServer, 'resolvedUrls'>): URL {\n const url = server.resolvedUrls?.network?.[0] ?? server.resolvedUrls?.local?.[0]\n\n if (!url) {\n throw new Error('Vite did not expose a reachable dev server URL.')\n }\n\n return new URL(url)\n}\n\nexport function shouldRestartForNativeChange(file: string, platform: CapacitorPlatform, cwd: string): boolean {\n const absoluteFile = resolve(cwd, file)\n const platformRoot = resolve(cwd, platform)\n\n if (!absoluteFile.startsWith(`${platformRoot}${sep}`) && absoluteFile !== platformRoot) {\n return false\n }\n\n const fileName = basename(absoluteFile)\n\n if (ignoredNames.has(fileName)) {\n return false\n }\n\n const segments = absoluteFile.split(sep)\n if (segments.some(segment => ignoredPathSegments.has(segment))) {\n return false\n }\n\n const relativeFile = relative(platformRoot, absoluteFile)\n const relativeSegments = relativeFile.split(sep).filter(Boolean)\n\n if (ignoredPathPrefixesByPlatform[platform].some(prefix =>\n prefix.every((segment, index) => relativeSegments[index] === segment),\n )) {\n // NOTICE: Capacitor regenerates ios/App/CapApp-SPM/Package.swift during `cap run`.\n // It also rewrites several generated Android files and plugin trees during `cap update`.\n // Treating those generated outputs as native source changes causes an infinite restart loop.\n return false\n }\n\n if (nativeNamesByPlatform[platform].has(fileName)) {\n return true\n }\n\n return nativeExtensionsByPlatform[platform].has(extname(fileName).toLowerCase())\n}\n"],"mappings":";;;AAQA,MAAM,6BAAqE;CACzE,KAAK,IAAI,IAAI;EACX;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAAC;CACF,SAAS,IAAI,IAAI;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAAC;CACH;AAED,MAAM,wBAAgE;CACpE,KAAK,IAAI,IAAI;EACX;EACA;EACA;EACD,CAAC;CACF,SAAS,IAAI,IAAI;EACf;EACA;EACA;EACA;EACA;EACA;EACD,CAAC;CACH;AAED,MAAM,eAAe,IAAI,IAAI,CAC3B,wBACD,CAAC;AAEF,MAAM,sBAAsB,IAAI,IAAI;CAClC;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAM,gCAAuE;CAC3E,KAAK,CACH,CAAC,OAAO,aAAa,CACtB;CACD,SAAS;EACP;GAAC;GAAO;GAAO;GAAQ;GAAU;GAAS;EAC1C;GAAC;GAAO;GAAO;GAAQ;GAAU;GAAyB;EAC1D;GAAC;GAAO;GAAO;GAAQ;GAAO;GAAO;GAAa;EAClD,CAAC,OAAO,yBAAyB;EACjC,CAAC,oCAAoC;EACrC,CAAC,4BAA4B;EAC9B;CACF;AAED,SAAgB,uBAAuB,OAAqD;AAC1F,QAAO,UAAU,aAAa,UAAU,QAAQ,QAAQ;;AAG1D,SAAgB,sBAAsB,SAA4B;AAChE,QAAO,QAAQ,MAAM,KAAK,UAAU,QAAQ,cAAe,QAAQ,KAAK,IAAI,WAAW,YAAY,CAAE;;AAGvG,SAAgB,kBAAkB,SAAmB,MAAyB,QAAQ,KAAe;AACnG,KAAI,QAAQ,WAAW,KAAK,sBAAsB,QAAQ,CACxD,QAAO;CAGT,MAAM,CAAC,aAAa,GAAG,QAAQ;CAC/B,MAAM,WAAW,uBAAuB,YAAY;CACpD,IAAI;AACJ,KAAI,aAAa,MACf,UAAS,IAAI;UAEN,aAAa,UACpB,UAAS,IAAI;AAGf,KAAI,CAAC,OACH,QAAO;AAGT,QAAO;EAAC;EAAa;EAAY;EAAQ,GAAG;EAAK;;AAGnD,SAAgB,cAAc,QAAkD;CAC9E,MAAM,MAAM,OAAO,cAAc,UAAU,MAAM,OAAO,cAAc,QAAQ;AAE9E,KAAI,CAAC,IACH,OAAM,IAAI,MAAM,kDAAkD;AAGpE,QAAO,IAAI,IAAI,IAAI;;AAGrB,SAAgB,6BAA6B,MAAc,UAA6B,KAAsB;CAC5G,MAAM,eAAe,QAAQ,KAAK,KAAK;CACvC,MAAM,eAAe,QAAQ,KAAK,SAAS;AAE3C,KAAI,CAAC,aAAa,WAAW,GAAG,eAAe,MAAM,IAAI,iBAAiB,aACxE,QAAO;CAGT,MAAM,WAAW,SAAS,aAAa;AAEvC,KAAI,aAAa,IAAI,SAAS,CAC5B,QAAO;AAIT,KADiB,aAAa,MAAM,IAAI,CAC3B,MAAK,YAAW,oBAAoB,IAAI,QAAQ,CAAC,CAC5D,QAAO;CAIT,MAAM,mBADe,SAAS,cAAc,aAAa,CACnB,MAAM,IAAI,CAAC,OAAO,QAAQ;AAEhE,KAAI,8BAA8B,UAAU,MAAK,WAC/C,OAAO,OAAO,SAAS,UAAU,iBAAiB,WAAW,QAAQ,CACtE,CAIC,QAAO;AAGT,KAAI,sBAAsB,UAAU,IAAI,SAAS,CAC/C,QAAO;AAGT,QAAO,2BAA2B,UAAU,IAAI,QAAQ,SAAS,CAAC,aAAa,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Plugin } from "vite";
|
|
2
|
+
|
|
3
|
+
//#region src/vite-plugin.d.ts
|
|
4
|
+
interface CapVitePluginOptions {
|
|
5
|
+
capArgs: string[];
|
|
6
|
+
}
|
|
7
|
+
declare function capVitePlugin(options: CapVitePluginOptions): Plugin;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { CapVitePluginOptions, capVitePlugin };
|
|
10
|
+
//# sourceMappingURL=vite-plugin.d.mts.map
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { i as shouldRestartForNativeChange, n as pickServerUrl, r as resolveCapRunArgs, t as parseCapacitorPlatform } from "./native-hZ5d7ukC.mjs";
|
|
2
|
+
import process from "node:process";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
import { x } from "tinyexec";
|
|
5
|
+
import * as readline from "node:readline";
|
|
6
|
+
//#region src/vite-plugin.ts
|
|
7
|
+
async function stopCapProcess(current) {
|
|
8
|
+
if (!current) return;
|
|
9
|
+
current.kill("SIGINT");
|
|
10
|
+
try {
|
|
11
|
+
await current;
|
|
12
|
+
} catch {}
|
|
13
|
+
}
|
|
14
|
+
function startCapProcess(cwd, capArgs, url) {
|
|
15
|
+
return x("cap", ["run", ...capArgs], {
|
|
16
|
+
throwOnError: false,
|
|
17
|
+
nodeOptions: {
|
|
18
|
+
cwd,
|
|
19
|
+
env: { CAPACITOR_DEV_SERVER_URL: url.toString() },
|
|
20
|
+
stdio: [
|
|
21
|
+
"ignore",
|
|
22
|
+
"inherit",
|
|
23
|
+
"inherit"
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function bindCapViteShortcuts(onRestart, onShutdown) {
|
|
29
|
+
if (!process.stdin.isTTY || typeof process.stdin.setRawMode !== "function") return () => {};
|
|
30
|
+
process.stdin.resume();
|
|
31
|
+
process.stdin.setEncoding("utf8");
|
|
32
|
+
readline.emitKeypressEvents(process.stdin);
|
|
33
|
+
const shouldRestoreRawMode = !process.stdin.isRaw;
|
|
34
|
+
if (shouldRestoreRawMode) process.stdin.setRawMode(true);
|
|
35
|
+
async function shutdownFromShortcut() {
|
|
36
|
+
try {
|
|
37
|
+
await onShutdown();
|
|
38
|
+
} finally {
|
|
39
|
+
if (shouldRestoreRawMode) process.stdin.setRawMode(false);
|
|
40
|
+
process.kill(process.pid, "SIGINT");
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const onKeyPress = (input, key) => {
|
|
44
|
+
if (key.ctrl && key.name === "c") {
|
|
45
|
+
shutdownFromShortcut();
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const keyName = key.name?.toLowerCase() ?? input.toLowerCase();
|
|
49
|
+
if (!key.ctrl && !key.meta && keyName === "r") onRestart();
|
|
50
|
+
};
|
|
51
|
+
process.stdin.on("keypress", onKeyPress);
|
|
52
|
+
return () => {
|
|
53
|
+
process.stdin.off("keypress", onKeyPress);
|
|
54
|
+
if (shouldRestoreRawMode) process.stdin.setRawMode(false);
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function capVitePlugin(options) {
|
|
58
|
+
const resolvedCapArgs = resolveCapRunArgs(options.capArgs);
|
|
59
|
+
const platform = parseCapacitorPlatform(resolvedCapArgs[0]);
|
|
60
|
+
if (!platform) throw new Error("The first `cap run` argument must be `ios` or `android`.");
|
|
61
|
+
const resolvedPlatform = platform;
|
|
62
|
+
return {
|
|
63
|
+
apply: "serve",
|
|
64
|
+
name: "cap-vite:run-capacitor",
|
|
65
|
+
configureServer(server) {
|
|
66
|
+
const cwd = resolve(server.config.root);
|
|
67
|
+
const platformRoot = resolve(cwd, resolvedPlatform);
|
|
68
|
+
const debounceMs = 300;
|
|
69
|
+
const logger = server.config.logger;
|
|
70
|
+
let currentCapProcess;
|
|
71
|
+
let restartTask;
|
|
72
|
+
let queuedRestartReason;
|
|
73
|
+
let disposeShortcut;
|
|
74
|
+
let shuttingDown = false;
|
|
75
|
+
let restartTimer;
|
|
76
|
+
function launchCapProcess() {
|
|
77
|
+
currentCapProcess = startCapProcess(cwd, resolvedCapArgs, pickServerUrl(server));
|
|
78
|
+
currentCapProcess.then(() => {
|
|
79
|
+
logger.info(`[cap-vite] Ran "cap run ${resolvedCapArgs.join(" ")}". Press R to re-run. Press Ctrl+C to exit.`);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
function requestRestart(reason) {
|
|
83
|
+
if (shuttingDown) return;
|
|
84
|
+
queuedRestartReason = reason;
|
|
85
|
+
if (!restartTask) restartTask = flushPendingRestarts();
|
|
86
|
+
}
|
|
87
|
+
async function flushPendingRestarts() {
|
|
88
|
+
try {
|
|
89
|
+
while (queuedRestartReason) {
|
|
90
|
+
const activeReason = queuedRestartReason;
|
|
91
|
+
queuedRestartReason = void 0;
|
|
92
|
+
if (shuttingDown) return;
|
|
93
|
+
logger.info(`[cap-vite] ${activeReason}. Re-running "cap run ${resolvedCapArgs.join(" ")}".`);
|
|
94
|
+
const previous = currentCapProcess;
|
|
95
|
+
currentCapProcess = void 0;
|
|
96
|
+
await stopCapProcess(previous);
|
|
97
|
+
if (shuttingDown) return;
|
|
98
|
+
launchCapProcess();
|
|
99
|
+
}
|
|
100
|
+
} catch (error) {
|
|
101
|
+
logger.error(`[cap-vite] ${error instanceof Error ? error.message : String(error)}`);
|
|
102
|
+
await shutdown();
|
|
103
|
+
} finally {
|
|
104
|
+
restartTask = void 0;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function onWatcherEvent(_event, file) {
|
|
108
|
+
if (!shouldRestartForNativeChange(file, resolvedPlatform, cwd)) return;
|
|
109
|
+
clearTimeout(restartTimer);
|
|
110
|
+
restartTimer = setTimeout(() => {
|
|
111
|
+
requestRestart(`native file changed: ${resolve(cwd, file)}`);
|
|
112
|
+
}, debounceMs);
|
|
113
|
+
}
|
|
114
|
+
function handleShutdownRequest() {
|
|
115
|
+
shutdown();
|
|
116
|
+
}
|
|
117
|
+
async function shutdown() {
|
|
118
|
+
if (shuttingDown) return;
|
|
119
|
+
shuttingDown = true;
|
|
120
|
+
clearTimeout(restartTimer);
|
|
121
|
+
queuedRestartReason = void 0;
|
|
122
|
+
const disposeBoundShortcut = disposeShortcut;
|
|
123
|
+
disposeShortcut = void 0;
|
|
124
|
+
disposeBoundShortcut?.();
|
|
125
|
+
server.watcher.off("all", onWatcherEvent);
|
|
126
|
+
process.off("SIGINT", handleShutdownRequest);
|
|
127
|
+
process.off("SIGTERM", handleShutdownRequest);
|
|
128
|
+
await server.watcher.unwatch(platformRoot);
|
|
129
|
+
await stopCapProcess(currentCapProcess);
|
|
130
|
+
}
|
|
131
|
+
server.watcher.add(platformRoot);
|
|
132
|
+
server.watcher.on("all", onWatcherEvent);
|
|
133
|
+
server.httpServer?.once("listening", () => {
|
|
134
|
+
launchCapProcess();
|
|
135
|
+
disposeShortcut = bindCapViteShortcuts(() => requestRestart("manual restart requested"), shutdown);
|
|
136
|
+
});
|
|
137
|
+
server.httpServer?.once("close", handleShutdownRequest);
|
|
138
|
+
process.once("SIGINT", handleShutdownRequest);
|
|
139
|
+
process.once("SIGTERM", handleShutdownRequest);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
//#endregion
|
|
144
|
+
export { capVitePlugin };
|
|
145
|
+
|
|
146
|
+
//# sourceMappingURL=vite-plugin.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vite-plugin.mjs","names":[],"sources":["../src/vite-plugin.ts"],"sourcesContent":["import type { Result } from 'tinyexec'\nimport type { Plugin } from 'vite'\n\nimport type { CapacitorPlatform } from './native'\n\nimport process from 'node:process'\n\nimport { resolve } from 'node:path'\n\nimport * as readline from 'node:readline'\n\nimport { x } from 'tinyexec'\n\nimport { parseCapacitorPlatform, pickServerUrl, resolveCapRunArgs, shouldRestartForNativeChange } from './native'\n\nexport interface CapVitePluginOptions {\n capArgs: string[]\n}\n\nasync function stopCapProcess(current: Result | undefined) {\n if (!current) {\n return\n }\n\n current.kill('SIGINT')\n\n try {\n await current\n }\n catch {\n // tinyexec rejects when a process is stopped during a restart.\n }\n}\n\nfunction startCapProcess(cwd: string, capArgs: string[], url: URL) {\n return x('cap', ['run', ...capArgs], {\n throwOnError: false,\n nodeOptions: {\n cwd,\n env: {\n CAPACITOR_DEV_SERVER_URL: url.toString(),\n },\n // NOTICE: cap-vite owns the terminal shortcuts, so cap run should not\n // consume stdin while still mirroring its stdout/stderr to the console.\n stdio: ['ignore', 'inherit', 'inherit'],\n },\n })\n}\n\nfunction bindCapViteShortcuts(\n onRestart: () => void,\n onShutdown: () => Promise<void>,\n) {\n if (!process.stdin.isTTY || typeof process.stdin.setRawMode !== 'function') {\n return () => {}\n }\n\n process.stdin.resume()\n process.stdin.setEncoding('utf8')\n readline.emitKeypressEvents(process.stdin)\n\n const shouldRestoreRawMode = !process.stdin.isRaw\n if (shouldRestoreRawMode) {\n process.stdin.setRawMode(true)\n }\n\n async function shutdownFromShortcut() {\n try {\n await onShutdown()\n }\n finally {\n if (shouldRestoreRawMode) {\n process.stdin.setRawMode(false)\n }\n\n process.kill(process.pid, 'SIGINT')\n }\n }\n\n const onKeyPress = (input: string, key: readline.Key) => {\n if (key.ctrl && key.name === 'c') {\n void shutdownFromShortcut()\n return\n }\n\n const keyName = key.name?.toLowerCase() ?? input.toLowerCase()\n if (!key.ctrl && !key.meta && keyName === 'r') {\n onRestart()\n }\n }\n\n process.stdin.on('keypress', onKeyPress)\n\n return () => {\n process.stdin.off('keypress', onKeyPress)\n\n if (shouldRestoreRawMode) {\n process.stdin.setRawMode(false)\n }\n }\n}\n\nexport function capVitePlugin(options: CapVitePluginOptions): Plugin {\n const resolvedCapArgs = resolveCapRunArgs(options.capArgs)\n const platform = parseCapacitorPlatform(resolvedCapArgs[0])\n if (!platform) {\n throw new Error('The first `cap run` argument must be `ios` or `android`.')\n }\n const resolvedPlatform: CapacitorPlatform = platform\n\n return {\n apply: 'serve',\n name: 'cap-vite:run-capacitor',\n configureServer(server) {\n const cwd = resolve(server.config.root)\n const platformRoot = resolve(cwd, resolvedPlatform)\n const debounceMs = 300\n const logger = server.config.logger\n\n let currentCapProcess: Result | undefined\n let restartTask: Promise<void> | undefined\n let queuedRestartReason: string | undefined\n let disposeShortcut: (() => void) | undefined\n let shuttingDown = false\n let restartTimer: NodeJS.Timeout | undefined\n\n function launchCapProcess() {\n const url = pickServerUrl(server)\n currentCapProcess = startCapProcess(cwd, resolvedCapArgs, url)\n currentCapProcess.then(() => {\n logger.info(`[cap-vite] Ran \"cap run ${resolvedCapArgs.join(' ')}\". Press R to re-run. Press Ctrl+C to exit.`)\n })\n }\n\n function requestRestart(reason: string) {\n if (shuttingDown) {\n return\n }\n\n queuedRestartReason = reason\n if (!restartTask) {\n restartTask = flushPendingRestarts()\n }\n }\n\n async function flushPendingRestarts() {\n try {\n while (queuedRestartReason) {\n const activeReason = queuedRestartReason\n queuedRestartReason = undefined\n\n if (shuttingDown) {\n return\n }\n\n logger.info(`[cap-vite] ${activeReason}. Re-running \"cap run ${resolvedCapArgs.join(' ')}\".`)\n const previous = currentCapProcess\n currentCapProcess = undefined\n await stopCapProcess(previous)\n\n if (shuttingDown) {\n return\n }\n\n launchCapProcess()\n }\n }\n catch (error) {\n logger.error(`[cap-vite] ${error instanceof Error ? error.message : String(error)}`)\n await shutdown()\n }\n finally {\n restartTask = undefined\n }\n }\n\n function onWatcherEvent(_event, file) {\n if (!shouldRestartForNativeChange(file, resolvedPlatform, cwd)) {\n return\n }\n\n clearTimeout(restartTimer)\n restartTimer = setTimeout(() => {\n requestRestart(`native file changed: ${resolve(cwd, file)}`)\n }, debounceMs)\n }\n\n function handleShutdownRequest() {\n void shutdown()\n }\n\n async function shutdown() {\n if (shuttingDown) {\n return\n }\n\n shuttingDown = true\n clearTimeout(restartTimer)\n queuedRestartReason = undefined\n const disposeBoundShortcut = disposeShortcut\n disposeShortcut = undefined\n disposeBoundShortcut?.()\n server.watcher.off('all', onWatcherEvent)\n process.off('SIGINT', handleShutdownRequest)\n process.off('SIGTERM', handleShutdownRequest)\n await server.watcher.unwatch(platformRoot)\n await stopCapProcess(currentCapProcess)\n }\n\n server.watcher.add(platformRoot)\n server.watcher.on('all', onWatcherEvent)\n\n server.httpServer?.once('listening', () => {\n launchCapProcess()\n disposeShortcut = bindCapViteShortcuts(() => requestRestart('manual restart requested'), shutdown)\n })\n server.httpServer?.once('close', handleShutdownRequest)\n process.once('SIGINT', handleShutdownRequest)\n process.once('SIGTERM', handleShutdownRequest)\n },\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { capVitePlugin } from "./vite-plugin.mjs";
|
|
2
|
+
import process from "node:process";
|
|
3
|
+
import { defineConfig, loadConfigFromFile, mergeConfig } from "vite";
|
|
4
|
+
//#region src/vite-wrapper-config.ts
|
|
5
|
+
function parseCapArgs() {
|
|
6
|
+
const value = process.env.CAP_VITE_CAP_ARGS_JSON;
|
|
7
|
+
if (!value) return [];
|
|
8
|
+
const parsed = JSON.parse(value);
|
|
9
|
+
if (!Array.isArray(parsed) || parsed.some((arg) => typeof arg !== "string")) throw new Error("CAP_VITE_CAP_ARGS_JSON must be a JSON string array.");
|
|
10
|
+
return parsed;
|
|
11
|
+
}
|
|
12
|
+
function parseConfigLoader() {
|
|
13
|
+
const value = process.env.CAP_VITE_CONFIG_LOADER;
|
|
14
|
+
if (value === "bundle" || value === "native" || value === "runner") return value;
|
|
15
|
+
}
|
|
16
|
+
var vite_wrapper_config_default = defineConfig(async (env) => {
|
|
17
|
+
const root = process.env.CAP_VITE_ROOT ?? process.cwd();
|
|
18
|
+
return mergeConfig((await loadConfigFromFile(env, process.env.CAP_VITE_BASE_CONFIG || void 0, root, void 0, void 0, parseConfigLoader()))?.config ?? {}, { plugins: [capVitePlugin({ capArgs: parseCapArgs() })] });
|
|
19
|
+
});
|
|
20
|
+
//#endregion
|
|
21
|
+
export { vite_wrapper_config_default as default };
|
|
22
|
+
|
|
23
|
+
//# sourceMappingURL=vite-wrapper-config.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vite-wrapper-config.mjs","names":[],"sources":["../src/vite-wrapper-config.ts"],"sourcesContent":["import process from 'node:process'\n\nimport { defineConfig, loadConfigFromFile, mergeConfig } from 'vite'\n\nimport { capVitePlugin } from './vite-plugin'\n\nfunction parseCapArgs(): string[] {\n const value = process.env.CAP_VITE_CAP_ARGS_JSON\n if (!value) {\n return []\n }\n\n const parsed = JSON.parse(value)\n if (!Array.isArray(parsed) || parsed.some(arg => typeof arg !== 'string')) {\n throw new Error('CAP_VITE_CAP_ARGS_JSON must be a JSON string array.')\n }\n\n return parsed\n}\n\nfunction parseConfigLoader(): 'bundle' | 'native' | 'runner' | undefined {\n const value = process.env.CAP_VITE_CONFIG_LOADER\n if (value === 'bundle' || value === 'native' || value === 'runner') {\n return value\n }\n\n return undefined\n}\n\nexport default defineConfig(async (env) => {\n const root = process.env.CAP_VITE_ROOT ?? process.cwd()\n const baseConfigFile = process.env.CAP_VITE_BASE_CONFIG || undefined\n const configLoader = parseConfigLoader()\n\n const loaded = await loadConfigFromFile(\n env,\n baseConfigFile,\n root,\n undefined,\n undefined,\n configLoader,\n )\n\n return mergeConfig(loaded?.config ?? {}, {\n plugins: [\n capVitePlugin({\n capArgs: parseCapArgs(),\n }),\n ],\n })\n})\n"],"mappings":";;;;AAMA,SAAS,eAAyB;CAChC,MAAM,QAAQ,QAAQ,IAAI;AAC1B,KAAI,CAAC,MACH,QAAO,EAAE;CAGX,MAAM,SAAS,KAAK,MAAM,MAAM;AAChC,KAAI,CAAC,MAAM,QAAQ,OAAO,IAAI,OAAO,MAAK,QAAO,OAAO,QAAQ,SAAS,CACvE,OAAM,IAAI,MAAM,sDAAsD;AAGxE,QAAO;;AAGT,SAAS,oBAAgE;CACvE,MAAM,QAAQ,QAAQ,IAAI;AAC1B,KAAI,UAAU,YAAY,UAAU,YAAY,UAAU,SACxD,QAAO;;AAMX,IAAA,8BAAe,aAAa,OAAO,QAAQ;CACzC,MAAM,OAAO,QAAQ,IAAI,iBAAiB,QAAQ,KAAK;AAavD,QAAO,aATQ,MAAM,mBACnB,KAJqB,QAAQ,IAAI,wBAAwB,KAAA,GAMzD,MACA,KAAA,GACA,KAAA,GAPmB,mBAAmB,CASvC,GAE0B,UAAU,EAAE,EAAE,EACvC,SAAS,CACP,cAAc,EACZ,SAAS,cAAc,EACxB,CAAC,CACH,EACF,CAAC;EACF"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@proj-airi/cap-vite",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.9.0-
|
|
4
|
+
"version": "0.9.0-beta.1",
|
|
5
5
|
"description": "CLI that starts a Vite dev server and runs Capacitor live reload",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Moeru AI Project AIRI Team",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"vite": "^7.0.0 || ^8.0.0-beta.0"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"cac": "^
|
|
39
|
-
"tinyexec": "^1.0.
|
|
38
|
+
"cac": "^7.0.0",
|
|
39
|
+
"tinyexec": "^1.0.4"
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|
|
42
42
|
"build": "tsdown",
|