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.
Files changed (171) hide show
  1. package/README.md +253 -0
  2. package/bin.mjs +21 -0
  3. package/lib/bin/bin.mjs +1141 -0
  4. package/lib/bin/plugin-sandbox-runner.mjs +105 -0
  5. package/lib/commonjs/index.js +125 -0
  6. package/lib/module/chunk-bhc5nymd.js +12 -0
  7. package/lib/module/chunk-dvyy3g4j.js +25 -0
  8. package/lib/module/chunk-ynqw05p0.js +70 -0
  9. package/lib/module/config/apple/create-osx-appiconset.js +6 -0
  10. package/lib/module/config/apple/index.js +7 -0
  11. package/lib/module/config/index.js +8 -0
  12. package/lib/module/index.js +8 -0
  13. package/lib/typescript/config/apple/asset-catalog-format/app-icon/index.d.ts +3 -0
  14. package/lib/typescript/config/apple/asset-catalog-format/app-icon/index.d.ts.map +1 -0
  15. package/lib/typescript/config/apple/asset-catalog-format/app-icon/set-type.d.ts +42 -0
  16. package/lib/typescript/config/apple/asset-catalog-format/app-icon/set-type.d.ts.map +1 -0
  17. package/lib/typescript/config/apple/asset-catalog-format/app-icon/size.d.ts +21 -0
  18. package/lib/typescript/config/apple/asset-catalog-format/app-icon/size.d.ts.map +1 -0
  19. package/lib/typescript/config/apple/asset-catalog-format/appearances.d.ts +13 -0
  20. package/lib/typescript/config/apple/asset-catalog-format/appearances.d.ts.map +1 -0
  21. package/lib/typescript/config/apple/asset-catalog-format/idiom.d.ts +5 -0
  22. package/lib/typescript/config/apple/asset-catalog-format/idiom.d.ts.map +1 -0
  23. package/lib/typescript/config/apple/asset-catalog-format/image/color-space.d.ts +2 -0
  24. package/lib/typescript/config/apple/asset-catalog-format/image/color-space.d.ts.map +1 -0
  25. package/lib/typescript/config/apple/asset-catalog-format/image/compression-type.d.ts +2 -0
  26. package/lib/typescript/config/apple/asset-catalog-format/image/compression-type.d.ts.map +1 -0
  27. package/lib/typescript/config/apple/asset-catalog-format/image/display-gamut.d.ts +2 -0
  28. package/lib/typescript/config/apple/asset-catalog-format/image/display-gamut.d.ts.map +1 -0
  29. package/lib/typescript/config/apple/asset-catalog-format/image/index.d.ts +6 -0
  30. package/lib/typescript/config/apple/asset-catalog-format/image/index.d.ts.map +1 -0
  31. package/lib/typescript/config/apple/asset-catalog-format/image/language-direction.d.ts +2 -0
  32. package/lib/typescript/config/apple/asset-catalog-format/image/language-direction.d.ts.map +1 -0
  33. package/lib/typescript/config/apple/asset-catalog-format/image/scale.d.ts +9 -0
  34. package/lib/typescript/config/apple/asset-catalog-format/image/scale.d.ts.map +1 -0
  35. package/lib/typescript/config/apple/asset-catalog-format/image/set-type.d.ts +58 -0
  36. package/lib/typescript/config/apple/asset-catalog-format/image/set-type.d.ts.map +1 -0
  37. package/lib/typescript/config/apple/asset-catalog-format/index.d.ts +5 -0
  38. package/lib/typescript/config/apple/asset-catalog-format/index.d.ts.map +1 -0
  39. package/lib/typescript/config/apple/asset-catalogs-namespaced.d.ts +5 -0
  40. package/lib/typescript/config/apple/asset-catalogs-namespaced.d.ts.map +1 -0
  41. package/lib/typescript/config/apple/asset-catalogs.d.ts +73 -0
  42. package/lib/typescript/config/apple/asset-catalogs.d.ts.map +1 -0
  43. package/lib/typescript/config/apple/create-osx-appiconset.d.mts +72 -0
  44. package/lib/typescript/config/apple/create-osx-appiconset.d.mts.map +1 -0
  45. package/lib/typescript/config/apple/data.d.ts +103 -0
  46. package/lib/typescript/config/apple/data.d.ts.map +1 -0
  47. package/lib/typescript/config/apple/index.d.mts +8 -0
  48. package/lib/typescript/config/apple/index.d.mts.map +1 -0
  49. package/lib/typescript/config/apple/info-plist-value.d.ts +8 -0
  50. package/lib/typescript/config/apple/info-plist-value.d.ts.map +1 -0
  51. package/lib/typescript/config/apple/info-plist.d.ts +4 -0
  52. package/lib/typescript/config/apple/info-plist.d.ts.map +1 -0
  53. package/lib/typescript/config/apple/string-catalog.d.ts +2 -0
  54. package/lib/typescript/config/apple/string-catalog.d.ts.map +1 -0
  55. package/lib/typescript/config/data.d.ts +50 -0
  56. package/lib/typescript/config/data.d.ts.map +1 -0
  57. package/lib/typescript/config/index.d.mts +5 -0
  58. package/lib/typescript/config/index.d.mts.map +1 -0
  59. package/lib/typescript/config/plugin-item.d.ts +2 -0
  60. package/lib/typescript/config/plugin-item.d.ts.map +1 -0
  61. package/lib/typescript/config/plugin-registry.d.ts +3 -0
  62. package/lib/typescript/config/plugin-registry.d.ts.map +1 -0
  63. package/lib/typescript/index.d.mts +3 -0
  64. package/lib/typescript/index.d.mts.map +1 -0
  65. package/lib/typescript/plugin/apple/context.d.ts +28 -0
  66. package/lib/typescript/plugin/apple/context.d.ts.map +1 -0
  67. package/lib/typescript/plugin/apple/files.d.ts +7 -0
  68. package/lib/typescript/plugin/apple/files.d.ts.map +1 -0
  69. package/lib/typescript/plugin/apple/index.d.ts +6 -0
  70. package/lib/typescript/plugin/apple/index.d.ts.map +1 -0
  71. package/lib/typescript/plugin/apple/pod-spec-source-from-cocoapods.d.ts +5 -0
  72. package/lib/typescript/plugin/apple/pod-spec-source-from-cocoapods.d.ts.map +1 -0
  73. package/lib/typescript/plugin/apple/pod-spec-source-from-git.d.ts +11 -0
  74. package/lib/typescript/plugin/apple/pod-spec-source-from-git.d.ts.map +1 -0
  75. package/lib/typescript/plugin/apple/pod-spec-source-from-local.d.ts +7 -0
  76. package/lib/typescript/plugin/apple/pod-spec-source-from-local.d.ts.map +1 -0
  77. package/lib/typescript/plugin/context.d.ts +9 -0
  78. package/lib/typescript/plugin/context.d.ts.map +1 -0
  79. package/lib/typescript/plugin/index.d.ts +3 -0
  80. package/lib/typescript/plugin/index.d.ts.map +1 -0
  81. package/package.json +49 -0
  82. package/src/_bin/_global-vars/_global-vars.mts +47 -0
  83. package/src/_bin/_global-vars/index.mts +30 -0
  84. package/src/_bin/_main/_check-config-validity.mts +94 -0
  85. package/src/_bin/_main/_evaluate-plugin-registry.mts +181 -0
  86. package/src/_bin/_main/_exec-plugin-runner/_spawn-plugin-sandbox-runner.mts +149 -0
  87. package/src/_bin/_main/_exec-plugin-runner/exec-plugin-runner.mts +92 -0
  88. package/src/_bin/_main/_exec-plugin-runner/index.mts +1 -0
  89. package/src/_bin/_main/_get-config.mts +64 -0
  90. package/src/_bin/_main/_helpers/config/get-name.mts +24 -0
  91. package/src/_bin/_main/_helpers/config/get-project-name.mts +27 -0
  92. package/src/_bin/_main/_helpers/config/index.mts +2 -0
  93. package/src/_bin/_main/_helpers/index.mts +2 -0
  94. package/src/_bin/_main/_helpers/platform/compatibility-error.mts +7 -0
  95. package/src/_bin/_main/_helpers/platform/data.ts +9 -0
  96. package/src/_bin/_main/_helpers/platform/get-data.mts +48 -0
  97. package/src/_bin/_main/_helpers/platform/index.mts +4 -0
  98. package/src/_bin/_main/_helpers/platform/is-compatible.mts +30 -0
  99. package/src/_bin/_main/_init-template/_init-apple/_create-asset-catalogs/_init-appiconsets.mts +223 -0
  100. package/src/_bin/_main/_init-template/_init-apple/_create-asset-catalogs/_init-imagesets.mts +241 -0
  101. package/src/_bin/_main/_init-template/_init-apple/_create-asset-catalogs/_metadata-check/appearances.mts +24 -0
  102. package/src/_bin/_main/_init-template/_init-apple/_create-asset-catalogs/_metadata-check/idiom.mts +22 -0
  103. package/src/_bin/_main/_init-template/_init-apple/_create-asset-catalogs/_metadata-check/image/compression-type.mts +15 -0
  104. package/src/_bin/_main/_init-template/_init-apple/_create-asset-catalogs/_metadata-check/image/display-gamut.mts +12 -0
  105. package/src/_bin/_main/_init-template/_init-apple/_create-asset-catalogs/_metadata-check/image/index.mts +3 -0
  106. package/src/_bin/_main/_init-template/_init-apple/_create-asset-catalogs/_metadata-check/image/language-direction.mts +12 -0
  107. package/src/_bin/_main/_init-template/_init-apple/_create-asset-catalogs/_metadata-check/index.mts +3 -0
  108. package/src/_bin/_main/_init-template/_init-apple/_create-asset-catalogs/create-asset-catalogs.mts +54 -0
  109. package/src/_bin/_main/_init-template/_init-apple/_create-asset-catalogs/index.mts +1 -0
  110. package/src/_bin/_main/_init-template/_init-apple/_create-string-catalogs/create-string-catalog.mts +134 -0
  111. package/src/_bin/_main/_init-template/_init-apple/_create-string-catalogs/index.mts +1 -0
  112. package/src/_bin/_main/_init-template/_init-apple/_mod-files/_app-delegate-swift.mts +62 -0
  113. package/src/_bin/_main/_init-template/_init-apple/_mod-files/_podfile.mts +31 -0
  114. package/src/_bin/_main/_init-template/_init-apple/_mod-files/index.mts +1 -0
  115. package/src/_bin/_main/_init-template/_init-apple/_mod-files/mod-files.mts +17 -0
  116. package/src/_bin/_main/_init-template/_init-apple/index.mts +1 -0
  117. package/src/_bin/_main/_init-template/_init-apple/init-apple.mts +81 -0
  118. package/src/_bin/_main/_init-template/index.mts +1 -0
  119. package/src/_bin/_main/_init-template/init-template.mts +39 -0
  120. package/src/_bin/_main/_mod-plugin/index.mts +1 -0
  121. package/src/_bin/_main/_mod-plugin/mod-plugin.mts +77 -0
  122. package/src/_bin/_main/_xcodegen/_create-project-spec/_init-resources.mts +86 -0
  123. package/src/_bin/_main/_xcodegen/_create-project-spec/create-project-spec.mts +216 -0
  124. package/src/_bin/_main/_xcodegen/_create-project-spec/index.mts +1 -0
  125. package/src/_bin/_main/_xcodegen/_mod-known-regions/index.ts +1 -0
  126. package/src/_bin/_main/_xcodegen/_mod-known-regions/mod-known-regions.mts +52 -0
  127. package/src/_bin/_main/_xcodegen/index.mts +1 -0
  128. package/src/_bin/_main/_xcodegen/xcodegen.mts +46 -0
  129. package/src/_bin/_main/index.mts +1 -0
  130. package/src/_bin/_main/main.mts +160 -0
  131. package/src/_bin/bin.mts +68 -0
  132. package/src/_bin/plugin-sandbox-runner/_exec-plugins.mts +135 -0
  133. package/src/_bin/plugin-sandbox-runner/argv-json.ts +20 -0
  134. package/src/_bin/plugin-sandbox-runner/evaluated-plugin-registry.ts +12 -0
  135. package/src/_bin/plugin-sandbox-runner/index.ts +3 -0
  136. package/src/_bin/plugin-sandbox-runner/plugin-runner-context-result.ts +33 -0
  137. package/src/_bin/plugin-sandbox-runner/plugin-sandbox-runner.mts +68 -0
  138. package/src/config/apple/asset-catalog-format/app-icon/index.ts +2 -0
  139. package/src/config/apple/asset-catalog-format/app-icon/set-type.ts +59 -0
  140. package/src/config/apple/asset-catalog-format/app-icon/size.ts +37 -0
  141. package/src/config/apple/asset-catalog-format/appearances.ts +10 -0
  142. package/src/config/apple/asset-catalog-format/idiom.ts +16 -0
  143. package/src/config/apple/asset-catalog-format/image/color-space.ts +3 -0
  144. package/src/config/apple/asset-catalog-format/image/compression-type.ts +6 -0
  145. package/src/config/apple/asset-catalog-format/image/display-gamut.ts +3 -0
  146. package/src/config/apple/asset-catalog-format/image/index.ts +6 -0
  147. package/src/config/apple/asset-catalog-format/image/language-direction.ts +3 -0
  148. package/src/config/apple/asset-catalog-format/image/scale.ts +11 -0
  149. package/src/config/apple/asset-catalog-format/image/set-type.ts +85 -0
  150. package/src/config/apple/asset-catalog-format/index.ts +4 -0
  151. package/src/config/apple/asset-catalogs-namespaced.ts +13 -0
  152. package/src/config/apple/asset-catalogs.ts +76 -0
  153. package/src/config/apple/create-osx-appiconset.mts +135 -0
  154. package/src/config/apple/data.ts +123 -0
  155. package/src/config/apple/index.mts +7 -0
  156. package/src/config/apple/info-plist-value.ts +16 -0
  157. package/src/config/apple/info-plist.ts +6 -0
  158. package/src/config/apple/string-catalog.ts +0 -0
  159. package/src/config/data.ts +59 -0
  160. package/src/config/index.mts +4 -0
  161. package/src/config/plugin-item.ts +4 -0
  162. package/src/config/plugin-registry.ts +5 -0
  163. package/src/index.mts +2 -0
  164. package/src/plugin/apple/context.ts +68 -0
  165. package/src/plugin/apple/files.ts +14 -0
  166. package/src/plugin/apple/index.ts +5 -0
  167. package/src/plugin/apple/pod-spec-source-from-cocoapods.ts +9 -0
  168. package/src/plugin/apple/pod-spec-source-from-git.ts +13 -0
  169. package/src/plugin/apple/pod-spec-source-from-local.ts +6 -0
  170. package/src/plugin/context.ts +12 -0
  171. 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
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./get-name.mts"
2
+ export * from "./get-project-name.mts"
@@ -0,0 +1,2 @@
1
+ export * as ConfigHelpers from "./config/index.mts"
2
+ export * as PlatformHelpers from "./platform/index.mts"
@@ -0,0 +1,7 @@
1
+ export const CompatibilityError = new Error(`
2
+ Cannot run bundo.rn appgen CLI in non compatible platform or JavaScript development runtime.
3
+
4
+ bundo.rn CLIs are compatible for
5
+ Platforms: macOS, Windows, Linux
6
+ Development Runtime: Bun, Node.js
7
+ `)
@@ -0,0 +1,9 @@
1
+ export interface Data {
2
+ developmentRuntime: {
3
+ type: "bun" | "node",
4
+ /**
5
+ * The semver without the "v" prepended.
6
+ */
7
+ version: string,
8
+ },
9
+ }