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 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
- const parts = p.split("/").filter(Boolean) // ["comps","button", ...]
86
- if (parts.length >= 2) comps.add(parts[1])
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
@@ -19,4 +19,7 @@ declare global {
19
19
  new (...args: any[]): T;
20
20
  }, count: number) => CS.System.Array;
21
21
  const toJsArray: <T>(csArr: CS.System.Array) => T[];
22
+ const toCsArray: <T>(jsArr: T[], type: {
23
+ new (...args: any[]): T;
24
+ }) => CS.System.Array;
22
25
  }
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "onejs-core",
3
3
  "description": "The JS part of OneJS, a UI framework and Scripting Engine for Unity.",
4
- "version": "2.0.20",
4
+ "version": "2.0.22",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/Singtaa/onejs-core"
@@ -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
- (args[0].toLowerCase().endsWith('.tgz') || /^https?:\/\/.+\.tgz$/i.test(args[0])))
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, 'utf8');
106
- const manifestJson = JSON.parse(manifestContent);
107
-
108
- const dependencies = manifestJson.dependencies;
109
- const oneJSKey = 'com.dragonground.onejs';
110
-
111
- if (dependencies && dependencies[oneJSKey]) {
112
- const packagePath = dependencies[oneJSKey]; // e.g., "file:PATH/TO/OneJS"
113
- if (packagePath.startsWith('file:')) {
114
- oneJSPath = packagePath.substring(5); // Remove "file:" prefix
115
- oneJSPath = path.resolve(projectDir, oneJSPath);
116
- return oneJSPath;
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