bundo-appgen 0.0.1-beta.7
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 +253 -0
- package/bin.mjs +21 -0
- package/lib/bin/bin.mjs +1141 -0
- package/lib/bin/plugin-sandbox-runner.mjs +105 -0
- package/lib/commonjs/index.js +125 -0
- package/lib/module/chunk-bhc5nymd.js +12 -0
- package/lib/module/chunk-dvyy3g4j.js +25 -0
- package/lib/module/chunk-ynqw05p0.js +70 -0
- package/lib/module/config/apple/create-osx-appiconset.js +6 -0
- package/lib/module/config/apple/index.js +7 -0
- package/lib/module/config/index.js +8 -0
- package/lib/module/index.js +8 -0
- package/lib/typescript/config/apple/asset-catalog-format/app-icon/index.d.ts +3 -0
- package/lib/typescript/config/apple/asset-catalog-format/app-icon/index.d.ts.map +1 -0
- package/lib/typescript/config/apple/asset-catalog-format/app-icon/set-type.d.ts +42 -0
- package/lib/typescript/config/apple/asset-catalog-format/app-icon/set-type.d.ts.map +1 -0
- package/lib/typescript/config/apple/asset-catalog-format/app-icon/size.d.ts +21 -0
- package/lib/typescript/config/apple/asset-catalog-format/app-icon/size.d.ts.map +1 -0
- package/lib/typescript/config/apple/asset-catalog-format/appearances.d.ts +13 -0
- package/lib/typescript/config/apple/asset-catalog-format/appearances.d.ts.map +1 -0
- package/lib/typescript/config/apple/asset-catalog-format/idiom.d.ts +5 -0
- package/lib/typescript/config/apple/asset-catalog-format/idiom.d.ts.map +1 -0
- package/lib/typescript/config/apple/asset-catalog-format/image/color-space.d.ts +2 -0
- package/lib/typescript/config/apple/asset-catalog-format/image/color-space.d.ts.map +1 -0
- package/lib/typescript/config/apple/asset-catalog-format/image/compression-type.d.ts +2 -0
- package/lib/typescript/config/apple/asset-catalog-format/image/compression-type.d.ts.map +1 -0
- package/lib/typescript/config/apple/asset-catalog-format/image/display-gamut.d.ts +2 -0
- package/lib/typescript/config/apple/asset-catalog-format/image/display-gamut.d.ts.map +1 -0
- package/lib/typescript/config/apple/asset-catalog-format/image/index.d.ts +6 -0
- package/lib/typescript/config/apple/asset-catalog-format/image/index.d.ts.map +1 -0
- package/lib/typescript/config/apple/asset-catalog-format/image/language-direction.d.ts +2 -0
- package/lib/typescript/config/apple/asset-catalog-format/image/language-direction.d.ts.map +1 -0
- package/lib/typescript/config/apple/asset-catalog-format/image/scale.d.ts +9 -0
- package/lib/typescript/config/apple/asset-catalog-format/image/scale.d.ts.map +1 -0
- package/lib/typescript/config/apple/asset-catalog-format/image/set-type.d.ts +58 -0
- package/lib/typescript/config/apple/asset-catalog-format/image/set-type.d.ts.map +1 -0
- package/lib/typescript/config/apple/asset-catalog-format/index.d.ts +5 -0
- package/lib/typescript/config/apple/asset-catalog-format/index.d.ts.map +1 -0
- package/lib/typescript/config/apple/asset-catalogs-namespaced.d.ts +5 -0
- package/lib/typescript/config/apple/asset-catalogs-namespaced.d.ts.map +1 -0
- package/lib/typescript/config/apple/asset-catalogs.d.ts +73 -0
- package/lib/typescript/config/apple/asset-catalogs.d.ts.map +1 -0
- package/lib/typescript/config/apple/create-osx-appiconset.d.mts +72 -0
- package/lib/typescript/config/apple/create-osx-appiconset.d.mts.map +1 -0
- package/lib/typescript/config/apple/data.d.ts +103 -0
- package/lib/typescript/config/apple/data.d.ts.map +1 -0
- package/lib/typescript/config/apple/index.d.mts +8 -0
- package/lib/typescript/config/apple/index.d.mts.map +1 -0
- package/lib/typescript/config/apple/info-plist-value.d.ts +8 -0
- package/lib/typescript/config/apple/info-plist-value.d.ts.map +1 -0
- package/lib/typescript/config/apple/info-plist.d.ts +4 -0
- package/lib/typescript/config/apple/info-plist.d.ts.map +1 -0
- package/lib/typescript/config/apple/string-catalog.d.ts +2 -0
- package/lib/typescript/config/apple/string-catalog.d.ts.map +1 -0
- package/lib/typescript/config/data.d.ts +50 -0
- package/lib/typescript/config/data.d.ts.map +1 -0
- package/lib/typescript/config/index.d.mts +5 -0
- package/lib/typescript/config/index.d.mts.map +1 -0
- package/lib/typescript/config/plugin-item.d.ts +2 -0
- package/lib/typescript/config/plugin-item.d.ts.map +1 -0
- package/lib/typescript/config/plugin-registry.d.ts +3 -0
- package/lib/typescript/config/plugin-registry.d.ts.map +1 -0
- package/lib/typescript/index.d.mts +3 -0
- package/lib/typescript/index.d.mts.map +1 -0
- package/lib/typescript/plugin/apple/context.d.ts +28 -0
- package/lib/typescript/plugin/apple/context.d.ts.map +1 -0
- package/lib/typescript/plugin/apple/files.d.ts +7 -0
- package/lib/typescript/plugin/apple/files.d.ts.map +1 -0
- package/lib/typescript/plugin/apple/index.d.ts +6 -0
- package/lib/typescript/plugin/apple/index.d.ts.map +1 -0
- package/lib/typescript/plugin/apple/pod-spec-source-from-cocoapods.d.ts +5 -0
- package/lib/typescript/plugin/apple/pod-spec-source-from-cocoapods.d.ts.map +1 -0
- package/lib/typescript/plugin/apple/pod-spec-source-from-git.d.ts +11 -0
- package/lib/typescript/plugin/apple/pod-spec-source-from-git.d.ts.map +1 -0
- package/lib/typescript/plugin/apple/pod-spec-source-from-local.d.ts +7 -0
- package/lib/typescript/plugin/apple/pod-spec-source-from-local.d.ts.map +1 -0
- package/lib/typescript/plugin/context.d.ts +9 -0
- package/lib/typescript/plugin/context.d.ts.map +1 -0
- package/lib/typescript/plugin/index.d.ts +3 -0
- package/lib/typescript/plugin/index.d.ts.map +1 -0
- package/package.json +49 -0
- package/src/_bin/_global-vars/_global-vars.mts +47 -0
- package/src/_bin/_global-vars/index.mts +30 -0
- package/src/_bin/_main/_check-config-validity.mts +94 -0
- package/src/_bin/_main/_evaluate-plugin-registry.mts +181 -0
- package/src/_bin/_main/_exec-plugin-runner/_spawn-plugin-sandbox-runner.mts +149 -0
- package/src/_bin/_main/_exec-plugin-runner/exec-plugin-runner.mts +92 -0
- package/src/_bin/_main/_exec-plugin-runner/index.mts +1 -0
- package/src/_bin/_main/_get-config.mts +64 -0
- package/src/_bin/_main/_helpers/config/get-name.mts +24 -0
- package/src/_bin/_main/_helpers/config/get-project-name.mts +27 -0
- package/src/_bin/_main/_helpers/config/index.mts +2 -0
- package/src/_bin/_main/_helpers/index.mts +2 -0
- package/src/_bin/_main/_helpers/platform/compatibility-error.mts +7 -0
- package/src/_bin/_main/_helpers/platform/data.ts +9 -0
- package/src/_bin/_main/_helpers/platform/get-data.mts +48 -0
- package/src/_bin/_main/_helpers/platform/index.mts +4 -0
- package/src/_bin/_main/_helpers/platform/is-compatible.mts +30 -0
- package/src/_bin/_main/_init-template/_init-apple/_create-asset-catalogs/_init-appiconsets.mts +223 -0
- package/src/_bin/_main/_init-template/_init-apple/_create-asset-catalogs/_init-imagesets.mts +241 -0
- package/src/_bin/_main/_init-template/_init-apple/_create-asset-catalogs/_metadata-check/appearances.mts +24 -0
- package/src/_bin/_main/_init-template/_init-apple/_create-asset-catalogs/_metadata-check/idiom.mts +22 -0
- package/src/_bin/_main/_init-template/_init-apple/_create-asset-catalogs/_metadata-check/image/compression-type.mts +15 -0
- package/src/_bin/_main/_init-template/_init-apple/_create-asset-catalogs/_metadata-check/image/display-gamut.mts +12 -0
- package/src/_bin/_main/_init-template/_init-apple/_create-asset-catalogs/_metadata-check/image/index.mts +3 -0
- package/src/_bin/_main/_init-template/_init-apple/_create-asset-catalogs/_metadata-check/image/language-direction.mts +12 -0
- package/src/_bin/_main/_init-template/_init-apple/_create-asset-catalogs/_metadata-check/index.mts +3 -0
- package/src/_bin/_main/_init-template/_init-apple/_create-asset-catalogs/create-asset-catalogs.mts +54 -0
- package/src/_bin/_main/_init-template/_init-apple/_create-asset-catalogs/index.mts +1 -0
- package/src/_bin/_main/_init-template/_init-apple/_create-string-catalogs/create-string-catalog.mts +134 -0
- package/src/_bin/_main/_init-template/_init-apple/_create-string-catalogs/index.mts +1 -0
- package/src/_bin/_main/_init-template/_init-apple/_mod-files/_app-delegate-swift.mts +62 -0
- package/src/_bin/_main/_init-template/_init-apple/_mod-files/_podfile.mts +31 -0
- package/src/_bin/_main/_init-template/_init-apple/_mod-files/index.mts +1 -0
- package/src/_bin/_main/_init-template/_init-apple/_mod-files/mod-files.mts +17 -0
- package/src/_bin/_main/_init-template/_init-apple/index.mts +1 -0
- package/src/_bin/_main/_init-template/_init-apple/init-apple.mts +81 -0
- package/src/_bin/_main/_init-template/index.mts +1 -0
- package/src/_bin/_main/_init-template/init-template.mts +39 -0
- package/src/_bin/_main/_mod-plugin/index.mts +1 -0
- package/src/_bin/_main/_mod-plugin/mod-plugin.mts +77 -0
- package/src/_bin/_main/_xcodegen/_create-project-spec/_init-resources.mts +86 -0
- package/src/_bin/_main/_xcodegen/_create-project-spec/create-project-spec.mts +216 -0
- package/src/_bin/_main/_xcodegen/_create-project-spec/index.mts +1 -0
- package/src/_bin/_main/_xcodegen/_mod-known-regions/index.ts +1 -0
- package/src/_bin/_main/_xcodegen/_mod-known-regions/mod-known-regions.mts +52 -0
- package/src/_bin/_main/_xcodegen/index.mts +1 -0
- package/src/_bin/_main/_xcodegen/xcodegen.mts +46 -0
- package/src/_bin/_main/index.mts +1 -0
- package/src/_bin/_main/main.mts +160 -0
- package/src/_bin/bin.mts +68 -0
- package/src/_bin/plugin-sandbox-runner/_exec-plugins.mts +135 -0
- package/src/_bin/plugin-sandbox-runner/argv-json.ts +20 -0
- package/src/_bin/plugin-sandbox-runner/evaluated-plugin-registry.ts +12 -0
- package/src/_bin/plugin-sandbox-runner/index.ts +3 -0
- package/src/_bin/plugin-sandbox-runner/plugin-runner-context-result.ts +33 -0
- package/src/_bin/plugin-sandbox-runner/plugin-sandbox-runner.mts +68 -0
- package/src/config/apple/asset-catalog-format/app-icon/index.ts +2 -0
- package/src/config/apple/asset-catalog-format/app-icon/set-type.ts +59 -0
- package/src/config/apple/asset-catalog-format/app-icon/size.ts +37 -0
- package/src/config/apple/asset-catalog-format/appearances.ts +10 -0
- package/src/config/apple/asset-catalog-format/idiom.ts +16 -0
- package/src/config/apple/asset-catalog-format/image/color-space.ts +3 -0
- package/src/config/apple/asset-catalog-format/image/compression-type.ts +6 -0
- package/src/config/apple/asset-catalog-format/image/display-gamut.ts +3 -0
- package/src/config/apple/asset-catalog-format/image/index.ts +6 -0
- package/src/config/apple/asset-catalog-format/image/language-direction.ts +3 -0
- package/src/config/apple/asset-catalog-format/image/scale.ts +11 -0
- package/src/config/apple/asset-catalog-format/image/set-type.ts +85 -0
- package/src/config/apple/asset-catalog-format/index.ts +4 -0
- package/src/config/apple/asset-catalogs-namespaced.ts +13 -0
- package/src/config/apple/asset-catalogs.ts +76 -0
- package/src/config/apple/create-osx-appiconset.mts +135 -0
- package/src/config/apple/data.ts +123 -0
- package/src/config/apple/index.mts +7 -0
- package/src/config/apple/info-plist-value.ts +16 -0
- package/src/config/apple/info-plist.ts +6 -0
- package/src/config/apple/string-catalog.ts +0 -0
- package/src/config/data.ts +59 -0
- package/src/config/index.mts +4 -0
- package/src/config/plugin-item.ts +4 -0
- package/src/config/plugin-registry.ts +5 -0
- package/src/index.mts +2 -0
- package/src/plugin/apple/context.ts +68 -0
- package/src/plugin/apple/files.ts +14 -0
- package/src/plugin/apple/index.ts +5 -0
- package/src/plugin/apple/pod-spec-source-from-cocoapods.ts +9 -0
- package/src/plugin/apple/pod-spec-source-from-git.ts +13 -0
- package/src/plugin/apple/pod-spec-source-from-local.ts +6 -0
- package/src/plugin/context.ts +12 -0
- package/src/plugin/index.ts +2 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Config,
|
|
3
|
+
} from "../../index.mts"
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
globalVars,
|
|
7
|
+
} from "./_global-vars.mts"
|
|
8
|
+
|
|
9
|
+
export namespace GlobalVars {
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* This is evaluated bundo.config.ts from user app.
|
|
13
|
+
*/
|
|
14
|
+
export const appConfig = globalVars<Config.Data>("app_config", {})
|
|
15
|
+
|
|
16
|
+
export const argv = globalVars("argv", {
|
|
17
|
+
clean: false,
|
|
18
|
+
forceCrossPlatform: false,
|
|
19
|
+
path: "",
|
|
20
|
+
xcodegenPath: "",
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* `bundo-appgen` directory
|
|
25
|
+
*/
|
|
26
|
+
export const appgenRoot = globalVars("appgen_root", "")
|
|
27
|
+
|
|
28
|
+
export const configFilePath = globalVars("config_file_path", "")
|
|
29
|
+
|
|
30
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Config,
|
|
3
|
+
} from "../../index.mts"
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
GlobalVars,
|
|
7
|
+
} from "../_global-vars/index.mts"
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
ConfigHelpers,
|
|
11
|
+
} from "./_helpers/index.mts"
|
|
12
|
+
|
|
13
|
+
export function checkConfigValidity(
|
|
14
|
+
config: Config.Data,
|
|
15
|
+
) {
|
|
16
|
+
|
|
17
|
+
if(
|
|
18
|
+
!config.macos /* && !config.windows */
|
|
19
|
+
) {
|
|
20
|
+
throw new Error("No platforms configuration.")
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const isCrossPlatform = GlobalVars.argv.get().forceCrossPlatform
|
|
24
|
+
|
|
25
|
+
if(isCrossPlatform) {
|
|
26
|
+
checkMacosConfig(config)
|
|
27
|
+
// TODO windows
|
|
28
|
+
} else if(process.platform == "darwin") {
|
|
29
|
+
checkMacosConfig(config)
|
|
30
|
+
} else if(process.platform == "win32") {
|
|
31
|
+
// TODO windows
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// check plugin
|
|
35
|
+
if(config.plugins) {
|
|
36
|
+
if(Array.isArray(config.plugins)) {
|
|
37
|
+
config.plugins.forEach(plugin => {
|
|
38
|
+
let isValid = true
|
|
39
|
+
|
|
40
|
+
if(Array.isArray(plugin) && plugin.length) {
|
|
41
|
+
isValid = typeof plugin[0] === "string"
|
|
42
|
+
|
|
43
|
+
if(plugin.length > 2) {
|
|
44
|
+
isValid = false
|
|
45
|
+
} else if(plugin[1]) {
|
|
46
|
+
isValid = typeof plugin[1] === "object" && plugin[1].constructor === Object
|
|
47
|
+
}
|
|
48
|
+
} else if(typeof plugin === "string" && !plugin.length) {
|
|
49
|
+
isValid = false
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if(!isValid) {
|
|
53
|
+
throw new Error("Plugin item needs to be an string of the plugin name, or an array of the plugin name and its parameter.")
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
} else {
|
|
57
|
+
throw new Error("Expected an Array in the plugin registry.")
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
class OSFieldError extends Error {
|
|
64
|
+
|
|
65
|
+
constructor(
|
|
66
|
+
prop: string,
|
|
67
|
+
os: "macos" | "windows",
|
|
68
|
+
) {
|
|
69
|
+
super(`\`${prop}\` is required for ${os} app.`)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function checkMacosConfig(config: Config.Data) {
|
|
75
|
+
if(!ConfigHelpers.getName(config, "macos")) {
|
|
76
|
+
throw new Error("`name` or `macos.name` is required in the config.")
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if(!config.macos) {
|
|
80
|
+
throw new Error(`Missing macos property in the config.`)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if(!config.macos.buildVersion) {
|
|
84
|
+
throw new OSFieldError("buildVersion", "macos")
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if(!config.macos.bundleIdentifier) {
|
|
88
|
+
throw new OSFieldError("bundleIdentifier", "macos")
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if(!config.macos.version) {
|
|
92
|
+
throw new OSFieldError("version", "macos")
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import * as node_fs from "node:fs"
|
|
2
|
+
import * as node_module from "node:module"
|
|
3
|
+
import * as node_path from "node:path"
|
|
4
|
+
|
|
5
|
+
import type {
|
|
6
|
+
Config,
|
|
7
|
+
Plugin,
|
|
8
|
+
} from "../../index.mts"
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
GlobalVars,
|
|
12
|
+
} from "../_global-vars/index.mts"
|
|
13
|
+
|
|
14
|
+
import type {
|
|
15
|
+
EvaluatedPluginRegistry,
|
|
16
|
+
} from "../plugin-sandbox-runner/index.ts"
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Evaluate the plugin registry to get their main function path file and its parameter
|
|
20
|
+
* that will be invoked later through our plugin runner.
|
|
21
|
+
*/
|
|
22
|
+
export function evaluatePluginRegistry(
|
|
23
|
+
plugins: Config.PluginRegistry | undefined,
|
|
24
|
+
): EvaluatedPluginRegistry | undefined {
|
|
25
|
+
|
|
26
|
+
if(!plugins?.length) {
|
|
27
|
+
return undefined
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const registry: NonNullable<ReturnType<typeof evaluatePluginRegistry>> = []
|
|
31
|
+
|
|
32
|
+
for(const plugin of plugins) {
|
|
33
|
+
let
|
|
34
|
+
nameOrPath: string,
|
|
35
|
+
|
|
36
|
+
parameter: Plugin.Context["parameter"] =
|
|
37
|
+
undefined
|
|
38
|
+
|
|
39
|
+
if(typeof plugin === "string" && plugin) {
|
|
40
|
+
nameOrPath = plugin
|
|
41
|
+
} else if(Array.isArray(plugin) && plugin.length && typeof plugin[0] === "string" && plugin[0]) {
|
|
42
|
+
nameOrPath = plugin[0]
|
|
43
|
+
|
|
44
|
+
if(plugin[1]) {
|
|
45
|
+
if(
|
|
46
|
+
typeof plugin[1] === "object" &&
|
|
47
|
+
plugin[1].constructor === Object
|
|
48
|
+
) {
|
|
49
|
+
parameter = plugin[1]
|
|
50
|
+
} else {
|
|
51
|
+
throw new Error(`The plugin parameter is only supported in plain object. Caused by "${nameOrPath}".`)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
} else {
|
|
55
|
+
throw new Error("The plugin registry is not a valid schema in the config.")
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// test if the plugin is in the node_modules
|
|
59
|
+
const mainPathFromNodeModule = getPluginMainPathFromNodeModules(nameOrPath)
|
|
60
|
+
if(mainPathFromNodeModule) {
|
|
61
|
+
registry.push({
|
|
62
|
+
name: nameOrPath,
|
|
63
|
+
mainPath: mainPathFromNodeModule,
|
|
64
|
+
parameter,
|
|
65
|
+
})
|
|
66
|
+
continue
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// test if the plugin is a local file
|
|
70
|
+
const filePath = node_path.join(
|
|
71
|
+
node_path.dirname(GlobalVars.configFilePath.get()),
|
|
72
|
+
nameOrPath,
|
|
73
|
+
)
|
|
74
|
+
if(node_fs.existsSync(filePath)) {
|
|
75
|
+
const lstat = node_fs.lstatSync(filePath)
|
|
76
|
+
|
|
77
|
+
if(lstat.isFile()) {
|
|
78
|
+
registry.push({
|
|
79
|
+
name: nameOrPath,
|
|
80
|
+
mainPath: filePath,
|
|
81
|
+
parameter,
|
|
82
|
+
})
|
|
83
|
+
continue
|
|
84
|
+
} else {
|
|
85
|
+
throw new Error(`${filePath} is not a file.`)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
throw new Error(`"${nameOrPath}" plugin cannot be found.`)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return registry
|
|
93
|
+
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* We try to find `bundo.plugin.mjs`, or `bundo.plugin.js`, or their custom JavaScript file in their module directory.
|
|
98
|
+
*
|
|
99
|
+
* For examples
|
|
100
|
+
*
|
|
101
|
+
* - "@foo-scope/react-native-module-bar"
|
|
102
|
+
* - node_modules/@foo-scope/react-native-module-bar/bundo.plugin.mjs
|
|
103
|
+
* - node_modules/@foo-scope/react-native-module-bar/bundo.plugin.js
|
|
104
|
+
*
|
|
105
|
+
* - "@bar/react-native-module-foo/plugins"
|
|
106
|
+
* - node_modules/@bar/react-native-module-foo/plugins/bundo.plugin.mjs
|
|
107
|
+
* - node_modules/@bar/react-native-module-foo/plugins/bundo.plugin.js
|
|
108
|
+
*
|
|
109
|
+
* - "react-native-abc/foo/bar/xyz.js"
|
|
110
|
+
* - node_modules/react-native-abc/foo/bar/xyz.js
|
|
111
|
+
*
|
|
112
|
+
* This function also resolve the path to actual file path, not the symbolic link.
|
|
113
|
+
*/
|
|
114
|
+
function getPluginMainPathFromNodeModules(name: string): string | undefined {
|
|
115
|
+
let modulePath: string | undefined
|
|
116
|
+
let isDirectory = true
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
const __require = node_module.createRequire(node_path.join(process.cwd(), "package.json"))
|
|
120
|
+
const nodeModulePaths = __require.resolve.paths("bundo-appgen")
|
|
121
|
+
|
|
122
|
+
if(nodeModulePaths?.length) {
|
|
123
|
+
for(const nodeModulePath of nodeModulePaths) {
|
|
124
|
+
const __modulePath = node_path.join(nodeModulePath, name)
|
|
125
|
+
|
|
126
|
+
if(node_fs.existsSync(__modulePath)) {
|
|
127
|
+
const modulePathStat = node_fs.lstatSync(__modulePath)
|
|
128
|
+
|
|
129
|
+
if(modulePathStat.isFile()) {
|
|
130
|
+
isDirectory = false
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if(modulePathStat.isSymbolicLink()) {
|
|
134
|
+
modulePath = node_fs.realpathSync(__modulePath)
|
|
135
|
+
} else {
|
|
136
|
+
modulePath = __modulePath
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
break
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// nothing to found
|
|
145
|
+
if(!modulePath) {
|
|
146
|
+
return undefined
|
|
147
|
+
}
|
|
148
|
+
} catch {
|
|
149
|
+
return undefined
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if(!isDirectory) {
|
|
153
|
+
// `modulePath` is actually a JavaScript file
|
|
154
|
+
// Skip finding the `bundo.plugin.[mjs|js] file`
|
|
155
|
+
return modulePath
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
let mainPath: string | undefined
|
|
159
|
+
|
|
160
|
+
for(const pluginMainFileExt of pluginMainFileExts) {
|
|
161
|
+
const path = node_path.join(modulePath, `bundo.plugin.${pluginMainFileExt}`)
|
|
162
|
+
|
|
163
|
+
if(node_fs.existsSync(path)) {
|
|
164
|
+
// test again for the desired path is symbolic link or not.
|
|
165
|
+
const lstat = node_fs.lstatSync(path)
|
|
166
|
+
if(lstat.isSymbolicLink()) {
|
|
167
|
+
mainPath = node_fs.realpathSync(path)
|
|
168
|
+
} else {
|
|
169
|
+
mainPath = path
|
|
170
|
+
}
|
|
171
|
+
break
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return mainPath
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const pluginMainFileExts = [
|
|
179
|
+
"mjs",
|
|
180
|
+
"js",
|
|
181
|
+
]
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import * as node_childProcess from "node:child_process"
|
|
2
|
+
import * as node_fs from "node:fs"
|
|
3
|
+
import * as node_module from "node:module"
|
|
4
|
+
import * as node_path from "node:path"
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
GlobalVars,
|
|
8
|
+
} from "../../_global-vars/index.mts"
|
|
9
|
+
|
|
10
|
+
import type {
|
|
11
|
+
EvaluatedPluginRegistry,
|
|
12
|
+
PluginRunnerContextResult,
|
|
13
|
+
} from "../../plugin-sandbox-runner/index.ts"
|
|
14
|
+
|
|
15
|
+
import type * as PluginSandboxRunnerType from "../../plugin-sandbox-runner/index.ts"
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* We allow some fs read for some directories by default
|
|
19
|
+
* - node_modules directory lookup
|
|
20
|
+
* - plugins directory
|
|
21
|
+
*/
|
|
22
|
+
export async function spawnPluginSandboxRunner(
|
|
23
|
+
registry: EvaluatedPluginRegistry,
|
|
24
|
+
permissions: {
|
|
25
|
+
"--allow-fs-read": string[] | null,
|
|
26
|
+
"--allow-fs-write": string[] | null,
|
|
27
|
+
"--allow-net": boolean,
|
|
28
|
+
},
|
|
29
|
+
metadata: {
|
|
30
|
+
projectDirectory: string,
|
|
31
|
+
projectName: string,
|
|
32
|
+
},
|
|
33
|
+
): Promise<PluginRunnerContextResult> {
|
|
34
|
+
const
|
|
35
|
+
requireModule =
|
|
36
|
+
node_module.createRequire(process.cwd()),
|
|
37
|
+
|
|
38
|
+
messageID =
|
|
39
|
+
Math.random().toString()
|
|
40
|
+
|
|
41
|
+
return new Promise(resolve => {
|
|
42
|
+
const nodeArgs: string[] = [
|
|
43
|
+
"--permission",
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
permissions["--allow-fs-read"]?.forEach(path => {
|
|
47
|
+
nodeArgs.push(`--allow-fs-read=${path}`)
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
permissions["--allow-fs-write"]?.forEach(path => {
|
|
51
|
+
nodeArgs.push(`--allow-fs-write=${path}`)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
if(permissions["--allow-net"]) {
|
|
55
|
+
nodeArgs.push("--allow-net")
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// allow read for node_modules directory
|
|
59
|
+
// required for plugins to use their external module
|
|
60
|
+
requireModule.resolve.paths("bundo-appgen")?.forEach(nodeModulePath => {
|
|
61
|
+
if(nodeModulePath.slice(-("/node".length)) != "/node") {
|
|
62
|
+
nodeArgs.push(`--allow-fs-read=${nodeModulePath}`)
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
// allow read for plugins directory
|
|
67
|
+
// required for plugins to use their own splitted JavaScript files in their own directory
|
|
68
|
+
registry.forEach(plugin => {
|
|
69
|
+
const pluginDirectory = node_path.dirname(plugin.mainPath)
|
|
70
|
+
const lstat = node_fs.lstatSync(pluginDirectory)
|
|
71
|
+
|
|
72
|
+
if(lstat.isSymbolicLink()) {
|
|
73
|
+
nodeArgs.push(`--allow-fs-read=${node_fs.realpathSync(pluginDirectory)}`)
|
|
74
|
+
}
|
|
75
|
+
nodeArgs.push(`--allow-fs-read=${pluginDirectory}`)
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
// exec plugin-sandbox-runner.mjs
|
|
79
|
+
nodeArgs.push(
|
|
80
|
+
node_path.join(
|
|
81
|
+
GlobalVars.appgenRoot.get(),
|
|
82
|
+
"lib", "bin", "plugin-sandbox-runner.mjs",
|
|
83
|
+
),
|
|
84
|
+
)
|
|
85
|
+
// and its arguments
|
|
86
|
+
nodeArgs.push(
|
|
87
|
+
`--json=${JSON.stringify({
|
|
88
|
+
projectDirectory: metadata.projectDirectory,
|
|
89
|
+
projectName: metadata.projectName,
|
|
90
|
+
evaluatedPluginRegistry: registry,
|
|
91
|
+
messageID,
|
|
92
|
+
} satisfies PluginSandboxRunnerType.ArgvJSON)}`,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
// -------------------------------
|
|
96
|
+
// ----- SPAWN A NEW PROCESS -----
|
|
97
|
+
// -------------------------------
|
|
98
|
+
|
|
99
|
+
const pluginRunner = node_childProcess.spawn(
|
|
100
|
+
"node",
|
|
101
|
+
nodeArgs,
|
|
102
|
+
{
|
|
103
|
+
stdio: [
|
|
104
|
+
"pipe",
|
|
105
|
+
"pipe",
|
|
106
|
+
"inherit",
|
|
107
|
+
"ipc",
|
|
108
|
+
],
|
|
109
|
+
},
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
let message: string
|
|
113
|
+
|
|
114
|
+
pluginRunner.on("message", clientMessage => {
|
|
115
|
+
if(typeof clientMessage === "string") {
|
|
116
|
+
message = clientMessage
|
|
117
|
+
}
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
pluginRunner.on("exit", code => {
|
|
121
|
+
if(code == 0) {
|
|
122
|
+
if(message) {
|
|
123
|
+
// Improve me!
|
|
124
|
+
// Only trust specific JSON message here
|
|
125
|
+
|
|
126
|
+
const json = JSON.parse(message) as Record<string, unknown>
|
|
127
|
+
|
|
128
|
+
// See /packages/bundo-appgen/plugin-sandbox-runner.mts
|
|
129
|
+
// Check the contract
|
|
130
|
+
if(
|
|
131
|
+
json.messageID === messageID &&
|
|
132
|
+
|
|
133
|
+
json.macos &&
|
|
134
|
+
typeof json.macos === "object"
|
|
135
|
+
) {
|
|
136
|
+
delete json.messageID
|
|
137
|
+
resolve(json as PluginRunnerContextResult)
|
|
138
|
+
} else {
|
|
139
|
+
throw new Error("Plugin Sandbox Runner was not sending a valid result.")
|
|
140
|
+
}
|
|
141
|
+
} else {
|
|
142
|
+
throw new Error("Plugin Sandbox Runner was not sending a valid result.")
|
|
143
|
+
}
|
|
144
|
+
} else {
|
|
145
|
+
throw new Error(`Plugin Sandbox Runner exited with ${code} code`)
|
|
146
|
+
}
|
|
147
|
+
})
|
|
148
|
+
})
|
|
149
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import * as node_path from "node:path"
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
GlobalVars,
|
|
5
|
+
} from "../../_global-vars/index.mts"
|
|
6
|
+
|
|
7
|
+
import type {
|
|
8
|
+
EvaluatedPluginRegistry,
|
|
9
|
+
PluginRunnerContextResult,
|
|
10
|
+
} from "../../plugin-sandbox-runner/index.ts"
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
ConfigHelpers,
|
|
14
|
+
} from "../_helpers/index.mts"
|
|
15
|
+
|
|
16
|
+
import {
|
|
17
|
+
spawnPluginSandboxRunner,
|
|
18
|
+
} from "./_spawn-plugin-sandbox-runner.mts"
|
|
19
|
+
|
|
20
|
+
export async function execPluginRunner(
|
|
21
|
+
registry: EvaluatedPluginRegistry | undefined,
|
|
22
|
+
options?: {
|
|
23
|
+
mode:
|
|
24
|
+
| "restricted"
|
|
25
|
+
| "lessRestrictive",
|
|
26
|
+
},
|
|
27
|
+
): Promise<PluginRunnerContextResult | undefined> {
|
|
28
|
+
|
|
29
|
+
if(!registry?.length) {
|
|
30
|
+
return undefined
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const
|
|
34
|
+
projectDirectory =
|
|
35
|
+
node_path.dirname(GlobalVars.configFilePath.get()),
|
|
36
|
+
|
|
37
|
+
projectName =
|
|
38
|
+
ConfigHelpers.getProjectName(GlobalVars.appConfig.get(), "macos")! // already validated
|
|
39
|
+
|
|
40
|
+
if(options?.mode === "restricted") {
|
|
41
|
+
console.log(`Executing ${registry.length} plugin${registry.length == 1 ? "" : "s"}`)
|
|
42
|
+
return await spawnPluginSandboxRunner(
|
|
43
|
+
registry,
|
|
44
|
+
{
|
|
45
|
+
"--allow-fs-read": [
|
|
46
|
+
// +++++ allow read for specific template files +++++
|
|
47
|
+
node_path.join(
|
|
48
|
+
projectDirectory,
|
|
49
|
+
"macos", projectName, "AppDelegate.swift",
|
|
50
|
+
),
|
|
51
|
+
|
|
52
|
+
node_path.join(
|
|
53
|
+
projectDirectory,
|
|
54
|
+
"macos", "Podfile",
|
|
55
|
+
),
|
|
56
|
+
// ----- allow read for specific template files -----
|
|
57
|
+
],
|
|
58
|
+
"--allow-fs-write": null,
|
|
59
|
+
"--allow-net": false,
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
projectDirectory,
|
|
63
|
+
projectName,
|
|
64
|
+
},
|
|
65
|
+
)
|
|
66
|
+
} else {
|
|
67
|
+
console.log(`Executing ${registry.length} less restrictive plugin${registry.length == 1 ? "" : "s"}`)
|
|
68
|
+
|
|
69
|
+
const
|
|
70
|
+
projectDirectoryMacos =
|
|
71
|
+
node_path.join(projectDirectory, "macos")
|
|
72
|
+
// TODO - Windows
|
|
73
|
+
|
|
74
|
+
return await spawnPluginSandboxRunner(
|
|
75
|
+
registry,
|
|
76
|
+
{
|
|
77
|
+
"--allow-fs-read": [
|
|
78
|
+
projectDirectoryMacos,
|
|
79
|
+
],
|
|
80
|
+
"--allow-fs-write": [
|
|
81
|
+
projectDirectoryMacos,
|
|
82
|
+
],
|
|
83
|
+
"--allow-net": true,
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
projectDirectory,
|
|
87
|
+
projectName,
|
|
88
|
+
},
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./exec-plugin-runner.mts"
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import * as node_module from "node:module"
|
|
2
|
+
import * as node_path from "node:path"
|
|
3
|
+
|
|
4
|
+
import type {
|
|
5
|
+
Config,
|
|
6
|
+
} from "../../index.mts"
|
|
7
|
+
|
|
8
|
+
export async function getConfig(
|
|
9
|
+
configFilePath: string,
|
|
10
|
+
): Promise<Config.Data> {
|
|
11
|
+
const ext = node_path.extname(configFilePath)
|
|
12
|
+
|
|
13
|
+
if(ext == ".ts" || ext == ".mts") {
|
|
14
|
+
// Bun with the `--bun` flag
|
|
15
|
+
if(typeof Bun !== "undefined" || process.versions.bun) {
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access
|
|
17
|
+
return import(configFilePath).then(c => c.default)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Transpile and evaluate the TypeScript file
|
|
21
|
+
// Possibly in Node.js with `tsx`
|
|
22
|
+
|
|
23
|
+
// bundo-appgen library is intentionally putting the `tsx` as a optional dependency,
|
|
24
|
+
// instead of peer or dev dependency
|
|
25
|
+
// to respect users by warning them to install `tsx` manually
|
|
26
|
+
|
|
27
|
+
// To be honest, I don't know much about TypeScript compiler API.
|
|
28
|
+
// If someone in the future know much about TypeScript compiler API,
|
|
29
|
+
// we don't need the `tsx` anymore.
|
|
30
|
+
|
|
31
|
+
console.log("Resolving your TypeScript file config…")
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
return import("tsx/cjs/api").then(async tsx => {
|
|
35
|
+
const result = await tsx.require(configFilePath, __filename) as {
|
|
36
|
+
default: Config.Data,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return result.default
|
|
40
|
+
})
|
|
41
|
+
} catch(err) {
|
|
42
|
+
if(err instanceof Error && "code" in err && err.code === "ERR_MODULE_NOT_FOUND") {
|
|
43
|
+
// eslint-disable-next-line preserve-caught-error
|
|
44
|
+
throw new Error(`
|
|
45
|
+
For TypeScript config file, please install \`tsx\` as your dev dependency,
|
|
46
|
+
or you can use Bun, or just use the JavaScript config file.
|
|
47
|
+
`)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
throw err
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Pure JS
|
|
55
|
+
|
|
56
|
+
if(ext == ".mjs") {
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access
|
|
58
|
+
return import(configFilePath).then(c => c.default)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const requireModule = node_module.createRequire(configFilePath)
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
63
|
+
return requireModule(configFilePath)
|
|
64
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Config,
|
|
3
|
+
} from "../../../../index.mts"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Get the app name from the config. This function is not guaranteed to return valid string due to missing value in the config object.
|
|
7
|
+
*/
|
|
8
|
+
export function getName(
|
|
9
|
+
config: Config.Data,
|
|
10
|
+
platform:
|
|
11
|
+
| "macos"
|
|
12
|
+
| "windows"
|
|
13
|
+
| "ios",
|
|
14
|
+
): string | undefined {
|
|
15
|
+
|
|
16
|
+
if(platform == "macos") {
|
|
17
|
+
return config.macos?.name || config.name
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// TODO: Windows
|
|
21
|
+
|
|
22
|
+
return config.name
|
|
23
|
+
|
|
24
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getName,
|
|
3
|
+
} from "./get-name.mts"
|
|
4
|
+
|
|
5
|
+
let cache: string
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Get the project name for Xcode or Visual Studio. This function is not guaranteed to return valid string due to missing value in the config object.
|
|
9
|
+
*/
|
|
10
|
+
export function getProjectName(
|
|
11
|
+
...params: Parameters<typeof getName>
|
|
12
|
+
): string | undefined {
|
|
13
|
+
|
|
14
|
+
if(cache) {
|
|
15
|
+
return cache
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const name = getName(...params)
|
|
19
|
+
|
|
20
|
+
if(!name) {
|
|
21
|
+
return undefined
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
cache = name.replace(/[^a-zA-Z0-9]/g, "")
|
|
25
|
+
return cache
|
|
26
|
+
|
|
27
|
+
}
|