@goliapkg/sentori-cli 0.2.1 → 0.4.0
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/lib/index.js +275 -57
- package/lib/index.js.map +1 -1
- package/lib/issue.d.ts +28 -0
- package/lib/issue.d.ts.map +1 -0
- package/lib/issue.js +53 -0
- package/lib/issue.js.map +1 -0
- package/lib/react-native.d.ts +25 -0
- package/lib/react-native.d.ts.map +1 -0
- package/lib/react-native.js +74 -0
- package/lib/react-native.js.map +1 -0
- package/package.json +1 -1
- package/src/__tests__/issue.test.ts +95 -0
- package/src/__tests__/react-native.test.ts +37 -0
- package/src/index.ts +287 -58
- package/src/issue.ts +81 -0
- package/src/react-native.ts +87 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process'
|
|
2
|
+
import { existsSync, mkdtempSync, rmSync } from 'node:fs'
|
|
3
|
+
import { createRequire } from 'node:module'
|
|
4
|
+
import { tmpdir } from 'node:os'
|
|
5
|
+
import { join } from 'node:path'
|
|
6
|
+
|
|
7
|
+
import { uploadSourcemaps } from './upload.js'
|
|
8
|
+
|
|
9
|
+
/** Resolve `react-native/scripts/compose-source-maps.js` from the
|
|
10
|
+
* current project's node_modules. Returns null if react-native isn't
|
|
11
|
+
* installed or the version doesn't ship that script. */
|
|
12
|
+
export function resolveComposeScript(fromDir = process.cwd()): null | string {
|
|
13
|
+
const req = createRequire(join(fromDir, 'noop.js'))
|
|
14
|
+
for (const id of [
|
|
15
|
+
'react-native/scripts/compose-source-maps.js',
|
|
16
|
+
'@react-native/community-cli-plugin/dist/utils/composeSourceMaps.js',
|
|
17
|
+
]) {
|
|
18
|
+
try {
|
|
19
|
+
const p = req.resolve(id)
|
|
20
|
+
if (existsSync(p)) return p
|
|
21
|
+
} catch {
|
|
22
|
+
// try next
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return null
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Compose a Metro packager source map + a Hermes source map into a
|
|
29
|
+
* single map (a temp file the caller is responsible for deleting).
|
|
30
|
+
* Throws if react-native's compose script can't be found or fails. */
|
|
31
|
+
export function composeSourceMaps(metroMap: string, hermesMap: string): string {
|
|
32
|
+
for (const p of [metroMap, hermesMap]) {
|
|
33
|
+
if (!existsSync(p)) throw new Error(`no such file: ${p}`)
|
|
34
|
+
}
|
|
35
|
+
const script = resolveComposeScript()
|
|
36
|
+
if (!script) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
"couldn't find react-native's compose-source-maps.js — install react-native, or " +
|
|
39
|
+
'compose the maps yourself and use `sentori-cli upload sourcemap <composed.map>`',
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
const out = join(mkdtempSync(join(tmpdir(), 'sentori-rn-')), 'composed.map')
|
|
43
|
+
const r = spawnSync('node', [script, metroMap, hermesMap, '-o', out], { stdio: 'inherit' })
|
|
44
|
+
if (r.status !== 0) {
|
|
45
|
+
throw new Error(`compose-source-maps.js exited with ${r.status ?? 'signal'}`)
|
|
46
|
+
}
|
|
47
|
+
if (!existsSync(out)) throw new Error('compose-source-maps.js produced no output')
|
|
48
|
+
return out
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type RnUploadOptions = {
|
|
52
|
+
apiUrl: string
|
|
53
|
+
/** Optional bundle file (.jsbundle / .bundle) to upload alongside the map. */
|
|
54
|
+
bundle?: string
|
|
55
|
+
dryRun?: boolean
|
|
56
|
+
hermesMap: string
|
|
57
|
+
metroMap: string
|
|
58
|
+
release: string
|
|
59
|
+
token: string
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Compose the Metro + Hermes maps, then upload the result (and the
|
|
63
|
+
* bundle, if given). Cleans up the temp composed map. */
|
|
64
|
+
export async function reactNativeUpload(opts: RnUploadOptions): Promise<{
|
|
65
|
+
files: string[]
|
|
66
|
+
uploaded?: number
|
|
67
|
+
}> {
|
|
68
|
+
const composed = composeSourceMaps(opts.metroMap, opts.hermesMap)
|
|
69
|
+
try {
|
|
70
|
+
const paths = [composed, ...(opts.bundle ? [opts.bundle] : [])]
|
|
71
|
+
const r = await uploadSourcemaps({
|
|
72
|
+
apiUrl: opts.apiUrl,
|
|
73
|
+
dryRun: opts.dryRun,
|
|
74
|
+
paths,
|
|
75
|
+
release: opts.release,
|
|
76
|
+
token: opts.token,
|
|
77
|
+
})
|
|
78
|
+
return { files: r.files, uploaded: r.uploaded }
|
|
79
|
+
} finally {
|
|
80
|
+
try {
|
|
81
|
+
rmSync(composed, { force: true })
|
|
82
|
+
rmSync(join(composed, '..'), { force: true, recursive: true })
|
|
83
|
+
} catch {
|
|
84
|
+
// best-effort cleanup
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|