onejs-core 2.0.20 → 2.0.22
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/bin/oj.js +12 -5
- package/dist/index.d.ts +3 -0
- package/index.ts +1 -0
- package/package.json +1 -1
- package/scripts/switch.cjs +85 -77
package/bin/oj.js
CHANGED
|
@@ -36,7 +36,7 @@ function findAssetsDir(startDir, explicit) {
|
|
|
36
36
|
if (fs.existsSync(explicit) && fs.statSync(explicit).isDirectory()) return explicit
|
|
37
37
|
return null
|
|
38
38
|
}
|
|
39
|
-
let dir = startDir
|
|
39
|
+
let dir = path.dirname(startDir) // Up a level, preventing `App/assets` getting returned
|
|
40
40
|
const { root } = path.parse(dir)
|
|
41
41
|
while (dir !== root) {
|
|
42
42
|
const probe = path.join(dir, "Assets")
|
|
@@ -80,10 +80,17 @@ async function scanComponents(tarPath) {
|
|
|
80
80
|
await tar.t({
|
|
81
81
|
file: tarPath,
|
|
82
82
|
onentry: (entry) => {
|
|
83
|
-
const p = entry.path
|
|
83
|
+
const p = entry.path.replace(/\\/g, "/")
|
|
84
84
|
if (!p.startsWith("comps/")) return
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
|
|
86
|
+
// Only treat entries inside a top-level folder under comps/
|
|
87
|
+
// e.g. "comps/button/**" → "button"
|
|
88
|
+
const rest = p.slice("comps/".length)
|
|
89
|
+
const firstSlash = rest.indexOf("/")
|
|
90
|
+
if (firstSlash === -1) return // file directly under comps/ → skip
|
|
91
|
+
|
|
92
|
+
const top = rest.slice(0, firstSlash)
|
|
93
|
+
if (top) comps.add(top)
|
|
87
94
|
},
|
|
88
95
|
})
|
|
89
96
|
return comps
|
|
@@ -244,4 +251,4 @@ program
|
|
|
244
251
|
program.parseAsync().catch((err) => {
|
|
245
252
|
console.error(err)
|
|
246
253
|
process.exit(1)
|
|
247
|
-
})
|
|
254
|
+
})
|
package/dist/index.d.ts
CHANGED
package/index.ts
CHANGED
|
@@ -44,6 +44,7 @@ declare global {
|
|
|
44
44
|
}
|
|
45
45
|
const newCsArray: <T>(type: { new(...args: any[]): T }, count: number) => CS.System.Array
|
|
46
46
|
const toJsArray: <T>(csArr: CS.System.Array) => T[]
|
|
47
|
+
const toCsArray: <T>(jsArr: T[], type: { new(...args: any[]): T }) => CS.System.Array
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
if (typeof globalThis.___document != "undefined") {
|
package/package.json
CHANGED
package/scripts/switch.cjs
CHANGED
|
@@ -33,16 +33,16 @@ if (args.length > 0 && args[0].toLowerCase() == "clear") {
|
|
|
33
33
|
} else if (
|
|
34
34
|
args.length > 0 &&
|
|
35
35
|
(["quickjs", "v8", "nodejs"].includes(args[0].toLowerCase()) ||
|
|
36
|
-
|
|
36
|
+
(args[0].toLowerCase().endsWith('.tgz') || /^https?:\/\/.+\.tgz$/i.test(args[0])))
|
|
37
37
|
) {
|
|
38
|
-
let backend
|
|
39
|
-
const outputDir = "./tmp"
|
|
38
|
+
let backend
|
|
39
|
+
const outputDir = "./tmp"
|
|
40
40
|
if (["quickjs", "v8", "nodejs"].includes(args[0].toLowerCase())) {
|
|
41
|
-
backend = backends.find(b => b.name.toLowerCase() === args[0])
|
|
41
|
+
backend = backends.find(b => b.name.toLowerCase() === args[0])
|
|
42
42
|
} else {
|
|
43
|
-
backend = { name: "Custom", tgzUrl: args[0] }
|
|
43
|
+
backend = { name: "Custom", tgzUrl: args[0] }
|
|
44
44
|
}
|
|
45
|
-
Process(backend, outputDir)
|
|
45
|
+
Process(backend, outputDir)
|
|
46
46
|
} else {
|
|
47
47
|
console.log("Usage: npm run switch <quickjs|v8|nodejs|clear|tgz-url>\n")
|
|
48
48
|
console.log(" quickjs: Switch to QuickJS backend")
|
|
@@ -98,130 +98,138 @@ async function Process(backend, outputDir) {
|
|
|
98
98
|
// }
|
|
99
99
|
|
|
100
100
|
async function getOneJSUnityDir() {
|
|
101
|
-
let oneJSPath = null
|
|
101
|
+
let oneJSPath = null
|
|
102
102
|
|
|
103
103
|
// Step 1: Check manifest.json
|
|
104
104
|
if (fs.existsSync(manifestPath)) {
|
|
105
|
-
const manifestContent = fs.readFileSync(manifestPath,
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
105
|
+
const manifestContent = fs.readFileSync(manifestPath, "utf8")
|
|
106
|
+
let manifestJson
|
|
107
|
+
try { manifestJson = JSON.parse(manifestContent) } catch {
|
|
108
|
+
console.error('Could not parse manifest.json at ' + manifestPath)
|
|
109
|
+
return null
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const dependencies = manifestJson && manifestJson.dependencies
|
|
113
|
+
const oneJSKeys = ["com.dragonground.onejs", "com.singtaa.onejs"]
|
|
114
|
+
|
|
115
|
+
if (dependencies) {
|
|
116
|
+
for (const key of oneJSKeys) {
|
|
117
|
+
const packagePath = dependencies[key]
|
|
118
|
+
if (typeof packagePath === "string") {
|
|
119
|
+
const v = packagePath.trim() // e.g., "file:PATH/TO/OneJS"
|
|
120
|
+
if (v.startsWith("file:")) {
|
|
121
|
+
oneJSPath = path.resolve(projectDir, v.substring(5)) // strip "file:"
|
|
122
|
+
return oneJSPath
|
|
123
|
+
}
|
|
124
|
+
}
|
|
117
125
|
}
|
|
118
126
|
}
|
|
119
127
|
}
|
|
120
128
|
|
|
121
129
|
// Step 2: If not found, parse OneJS.Runtime.csproj
|
|
122
130
|
if (!oneJSPath) {
|
|
123
|
-
const csprojPath = path.join(projectDir, 'OneJS.Runtime.csproj')
|
|
131
|
+
const csprojPath = path.join(projectDir, 'OneJS.Runtime.csproj')
|
|
124
132
|
|
|
125
133
|
if (fs.existsSync(csprojPath)) {
|
|
126
|
-
const csprojContent = fs.readFileSync(csprojPath, 'utf8')
|
|
127
|
-
const parser = new xml2js.Parser()
|
|
134
|
+
const csprojContent = fs.readFileSync(csprojPath, 'utf8')
|
|
135
|
+
const parser = new xml2js.Parser()
|
|
128
136
|
|
|
129
137
|
try {
|
|
130
|
-
const result = await parser.parseStringPromise(csprojContent)
|
|
138
|
+
const result = await parser.parseStringPromise(csprojContent)
|
|
131
139
|
|
|
132
|
-
const project = result.Project
|
|
133
|
-
const itemGroups = project.ItemGroup
|
|
140
|
+
const project = result.Project
|
|
141
|
+
const itemGroups = project.ItemGroup
|
|
134
142
|
|
|
135
143
|
if (itemGroups && itemGroups.length > 0) {
|
|
136
144
|
for (const itemGroup of itemGroups) {
|
|
137
145
|
if (itemGroup.Compile) {
|
|
138
146
|
for (const compileItem of itemGroup.Compile) {
|
|
139
|
-
const includePath = compileItem.$.Include
|
|
147
|
+
const includePath = compileItem.$.Include
|
|
140
148
|
|
|
141
149
|
// Normalize path separators for cross-platform compatibility
|
|
142
|
-
const normalizedIncludePath = includePath.replace(/\\/g, '/')
|
|
143
|
-
const searchIndex = normalizedIncludePath.indexOf('OneJS/Runtime/Engine/ScriptEngine.cs')
|
|
150
|
+
const normalizedIncludePath = includePath.replace(/\\/g, '/')
|
|
151
|
+
const searchIndex = normalizedIncludePath.indexOf('OneJS/Runtime/Engine/ScriptEngine.cs')
|
|
144
152
|
|
|
145
153
|
if (searchIndex !== -1) {
|
|
146
|
-
oneJSPath = normalizedIncludePath.substring(0, searchIndex + 'OneJS'.length)
|
|
147
|
-
oneJSPath = path.resolve(projectDir, oneJSPath)
|
|
148
|
-
return oneJSPath
|
|
154
|
+
oneJSPath = normalizedIncludePath.substring(0, searchIndex + 'OneJS'.length)
|
|
155
|
+
oneJSPath = path.resolve(projectDir, oneJSPath)
|
|
156
|
+
return oneJSPath
|
|
149
157
|
}
|
|
150
158
|
}
|
|
151
159
|
}
|
|
152
160
|
}
|
|
153
161
|
}
|
|
154
162
|
|
|
155
|
-
console.error('Could not find OneJS path in csproj file.')
|
|
156
|
-
return null
|
|
163
|
+
console.error('Could not find OneJS path in csproj file.')
|
|
164
|
+
return null
|
|
157
165
|
} catch (err) {
|
|
158
|
-
console.error('Error parsing csproj file:', err)
|
|
159
|
-
return null
|
|
166
|
+
console.error('Error parsing csproj file:', err)
|
|
167
|
+
return null
|
|
160
168
|
}
|
|
161
169
|
} else {
|
|
162
|
-
console.error('OneJS.Runtime.csproj file does not exist.')
|
|
163
|
-
return null
|
|
170
|
+
console.error('OneJS.Runtime.csproj file does not exist.')
|
|
171
|
+
return null
|
|
164
172
|
}
|
|
165
173
|
}
|
|
166
174
|
|
|
167
|
-
return oneJSPath
|
|
175
|
+
return oneJSPath
|
|
168
176
|
}
|
|
169
177
|
|
|
170
178
|
function ensureDirectoryExistence(filePath) {
|
|
171
|
-
const dirname = path.dirname(filePath)
|
|
179
|
+
const dirname = path.dirname(filePath)
|
|
172
180
|
if (fs.existsSync(dirname)) {
|
|
173
|
-
return true
|
|
181
|
+
return true
|
|
174
182
|
}
|
|
175
|
-
fs.mkdirSync(dirname, { recursive: true })
|
|
183
|
+
fs.mkdirSync(dirname, { recursive: true })
|
|
176
184
|
}
|
|
177
185
|
|
|
178
186
|
function getFilenameFromUrl(fileUrl) {
|
|
179
|
-
const parsedUrl = url.parse(fileUrl)
|
|
180
|
-
return path.basename(parsedUrl.pathname)
|
|
187
|
+
const parsedUrl = url.parse(fileUrl)
|
|
188
|
+
return path.basename(parsedUrl.pathname)
|
|
181
189
|
}
|
|
182
190
|
|
|
183
191
|
async function downloadFile(fileUrl, outputDir) {
|
|
184
|
-
const filename = getFilenameFromUrl(fileUrl)
|
|
185
|
-
const outputLocationPath = path.join(outputDir, filename)
|
|
192
|
+
const filename = getFilenameFromUrl(fileUrl)
|
|
193
|
+
const outputLocationPath = path.join(outputDir, filename)
|
|
186
194
|
|
|
187
|
-
ensureDirectoryExistence(outputLocationPath)
|
|
195
|
+
ensureDirectoryExistence(outputLocationPath)
|
|
188
196
|
|
|
189
197
|
// Check if file exists (keep existing code)
|
|
190
198
|
if (fs.existsSync(outputLocationPath)) {
|
|
191
|
-
console.log(`Local .tgz found: ${outputLocationPath}`)
|
|
192
|
-
return outputLocationPath
|
|
199
|
+
console.log(`Local .tgz found: ${outputLocationPath}`)
|
|
200
|
+
return outputLocationPath
|
|
193
201
|
}
|
|
194
202
|
|
|
195
|
-
console.log(`Downloading ${filename}`)
|
|
196
|
-
const response = await fetch(fileUrl)
|
|
203
|
+
console.log(`Downloading ${filename}`)
|
|
204
|
+
const response = await fetch(fileUrl)
|
|
197
205
|
|
|
198
206
|
if (!response.ok) {
|
|
199
|
-
throw new Error(`Failed to fetch ${fileUrl}: ${response.statusText}`)
|
|
207
|
+
throw new Error(`Failed to fetch ${fileUrl}: ${response.statusText}`)
|
|
200
208
|
}
|
|
201
209
|
|
|
202
210
|
// Get the total size for the progress bar
|
|
203
|
-
const totalSize = parseInt(response.headers.get('content-length'), 10)
|
|
204
|
-
|
|
211
|
+
const totalSize = parseInt(response.headers.get('content-length'), 10)
|
|
212
|
+
|
|
205
213
|
// Create progress bar
|
|
206
214
|
const progressBar = new ProgressBar('[:bar] :percent ETA: :etas', {
|
|
207
215
|
complete: '=',
|
|
208
216
|
incomplete: ' ',
|
|
209
217
|
width: 40,
|
|
210
218
|
total: totalSize
|
|
211
|
-
})
|
|
219
|
+
})
|
|
212
220
|
|
|
213
|
-
const fileStream = fs.createWriteStream(outputLocationPath)
|
|
221
|
+
const fileStream = fs.createWriteStream(outputLocationPath)
|
|
214
222
|
for await (const chunk of response.body) {
|
|
215
|
-
fileStream.write(chunk)
|
|
216
|
-
progressBar.tick(chunk.length)
|
|
223
|
+
fileStream.write(chunk)
|
|
224
|
+
progressBar.tick(chunk.length)
|
|
217
225
|
}
|
|
218
226
|
|
|
219
|
-
fileStream.end()
|
|
227
|
+
fileStream.end()
|
|
220
228
|
|
|
221
229
|
return new Promise((resolve, reject) => {
|
|
222
|
-
fileStream.on('close', () => resolve(outputLocationPath))
|
|
223
|
-
fileStream.on('error', reject)
|
|
224
|
-
})
|
|
230
|
+
fileStream.on('close', () => resolve(outputLocationPath))
|
|
231
|
+
fileStream.on('error', reject)
|
|
232
|
+
})
|
|
225
233
|
}
|
|
226
234
|
|
|
227
235
|
async function extractTgz(filePath, outputDir) {
|
|
@@ -229,47 +237,47 @@ async function extractTgz(filePath, outputDir) {
|
|
|
229
237
|
file: filePath,
|
|
230
238
|
cwd: outputDir,
|
|
231
239
|
})
|
|
232
|
-
console.log(`Extraction completed.`)
|
|
240
|
+
console.log(`Extraction completed.`)
|
|
233
241
|
}
|
|
234
242
|
|
|
235
243
|
|
|
236
244
|
|
|
237
245
|
async function checkFileInUse(file) {
|
|
238
246
|
try {
|
|
239
|
-
const handle = await fsp.open(file, 'r+')
|
|
240
|
-
await handle.close()
|
|
247
|
+
const handle = await fsp.open(file, 'r+')
|
|
248
|
+
await handle.close()
|
|
241
249
|
} catch (err) {
|
|
242
250
|
if (err.code === 'EBUSY' || err.code === 'EPERM' || err.code === 'EACCES') {
|
|
243
|
-
console.error('File is in use by another program or access is denied:', err)
|
|
244
|
-
return false
|
|
251
|
+
console.error('File is in use by another program or access is denied:', err)
|
|
252
|
+
return false
|
|
245
253
|
} else {
|
|
246
|
-
console.error('Cannot access file:', err)
|
|
247
|
-
return false
|
|
254
|
+
console.error('Cannot access file:', err)
|
|
255
|
+
return false
|
|
248
256
|
}
|
|
249
257
|
}
|
|
250
|
-
return true
|
|
258
|
+
return true
|
|
251
259
|
}
|
|
252
260
|
|
|
253
261
|
async function checkAllDeletable(currentPath) {
|
|
254
262
|
try {
|
|
255
|
-
const stats = await fsp.stat(currentPath)
|
|
263
|
+
const stats = await fsp.stat(currentPath)
|
|
256
264
|
|
|
257
265
|
if (stats.isDirectory()) {
|
|
258
|
-
const files = await fsp.readdir(currentPath)
|
|
266
|
+
const files = await fsp.readdir(currentPath)
|
|
259
267
|
|
|
260
268
|
for (const file of files) {
|
|
261
|
-
const deletable = await checkAllDeletable(path.join(currentPath, file))
|
|
269
|
+
const deletable = await checkAllDeletable(path.join(currentPath, file))
|
|
262
270
|
if (!deletable) {
|
|
263
|
-
return false
|
|
271
|
+
return false
|
|
264
272
|
}
|
|
265
273
|
}
|
|
266
|
-
return true
|
|
274
|
+
return true
|
|
267
275
|
} else {
|
|
268
|
-
return await checkFileInUse(currentPath)
|
|
276
|
+
return await checkFileInUse(currentPath)
|
|
269
277
|
}
|
|
270
278
|
} catch (err) {
|
|
271
|
-
console.log(`Error accessing: ${currentPath}, ${err}`)
|
|
272
|
-
return false
|
|
279
|
+
console.log(`Error accessing: ${currentPath}, ${err}`)
|
|
280
|
+
return false
|
|
273
281
|
}
|
|
274
282
|
}
|
|
275
283
|
|