pterm 0.0.24 → 0.0.25
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 +181 -15
- package/endpoint.js +163 -0
- package/index.js +70 -15
- package/package.json +1 -1
- package/rpc.js +26 -8
- package/script.js +114 -59
- package/target.js +437 -0
- package/util.js +146 -18
package/util.js
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
1
2
|
const os = require('os')
|
|
2
3
|
const axios = require('axios')
|
|
3
4
|
const path = require('path')
|
|
4
5
|
const RPC = require('./rpc')
|
|
6
|
+
const { resolveHttpBaseUrl, resolveWsBaseUrl } = require('./endpoint')
|
|
7
|
+
const { isPinokioRef, parsePinokioRef, buildPinokioRef } = require('./target')
|
|
5
8
|
class Util {
|
|
9
|
+
resolveLocalPath(value) {
|
|
10
|
+
const raw = String(value)
|
|
11
|
+
if (raw.startsWith('~/')) {
|
|
12
|
+
return path.resolve(os.homedir(), raw.slice(2))
|
|
13
|
+
}
|
|
14
|
+
return path.resolve(process.cwd(), raw)
|
|
15
|
+
}
|
|
6
16
|
printJson(payload) {
|
|
7
17
|
process.stdout.write(JSON.stringify(payload, null, 2))
|
|
8
18
|
process.stdout.write("\n")
|
|
@@ -18,6 +28,27 @@ class Util {
|
|
|
18
28
|
const value = String(process.env.PINOKIO_REGISTRY_API_BASE || "https://api.pinokio.co").trim()
|
|
19
29
|
return value.replace(/\/$/, "")
|
|
20
30
|
}
|
|
31
|
+
async resolveResourceRequestTarget(value) {
|
|
32
|
+
const raw = String(value || '').trim()
|
|
33
|
+
if (isPinokioRef(raw)) {
|
|
34
|
+
const parsedRef = parsePinokioRef(raw)
|
|
35
|
+
if (!parsedRef.valid) {
|
|
36
|
+
throw new Error(parsedRef.error || 'Invalid ref')
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
baseUrl: await resolveHttpBaseUrl(),
|
|
40
|
+
ref: buildPinokioRef(parsedRef),
|
|
41
|
+
legacyId: null,
|
|
42
|
+
parsedRef
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
baseUrl: await resolveHttpBaseUrl(),
|
|
47
|
+
ref: null,
|
|
48
|
+
legacyId: raw,
|
|
49
|
+
parsedRef: null
|
|
50
|
+
}
|
|
51
|
+
}
|
|
21
52
|
async search(argv) {
|
|
22
53
|
const query = (argv._.slice(1).join(" ") || argv.q || "").trim()
|
|
23
54
|
const params = { q: query }
|
|
@@ -39,7 +70,8 @@ class Util {
|
|
|
39
70
|
params.limit = String(limit)
|
|
40
71
|
}
|
|
41
72
|
}
|
|
42
|
-
const
|
|
73
|
+
const baseUrl = await resolveHttpBaseUrl()
|
|
74
|
+
const response = await axios.get(`${baseUrl}/apps/search`, {
|
|
43
75
|
params
|
|
44
76
|
})
|
|
45
77
|
this.printJson(response.data)
|
|
@@ -78,15 +110,20 @@ class Util {
|
|
|
78
110
|
console.error("required argument: <app_id>")
|
|
79
111
|
return
|
|
80
112
|
}
|
|
81
|
-
const
|
|
113
|
+
const target = await this.resolveResourceRequestTarget(argv._[1])
|
|
82
114
|
const probe = argv.probe ? "1" : "0"
|
|
83
115
|
const timeout = argv.timeout ? Number.parseInt(String(argv.timeout), 10) : null
|
|
84
116
|
const params = new URLSearchParams()
|
|
117
|
+
if (target.ref) {
|
|
118
|
+
params.set("ref", target.ref)
|
|
119
|
+
}
|
|
85
120
|
params.set("probe", probe)
|
|
86
121
|
if (Number.isFinite(timeout) && timeout > 0) {
|
|
87
122
|
params.set("timeout", String(timeout))
|
|
88
123
|
}
|
|
89
|
-
const url =
|
|
124
|
+
const url = target.ref
|
|
125
|
+
? `${target.baseUrl}/pinokio/resource/status?${params.toString()}`
|
|
126
|
+
: `${target.baseUrl}/apps/status/${encodeURIComponent(target.legacyId)}?${params.toString()}`
|
|
90
127
|
const response = await axios.get(url)
|
|
91
128
|
this.printJson(response.data)
|
|
92
129
|
}
|
|
@@ -95,8 +132,11 @@ class Util {
|
|
|
95
132
|
console.error("required argument: <app_id>")
|
|
96
133
|
return
|
|
97
134
|
}
|
|
98
|
-
const
|
|
135
|
+
const target = await this.resolveResourceRequestTarget(argv._[1])
|
|
99
136
|
const params = new URLSearchParams()
|
|
137
|
+
if (target.ref) {
|
|
138
|
+
params.set("ref", target.ref)
|
|
139
|
+
}
|
|
100
140
|
if (argv.script) {
|
|
101
141
|
params.set("script", String(argv.script))
|
|
102
142
|
}
|
|
@@ -107,15 +147,71 @@ class Util {
|
|
|
107
147
|
}
|
|
108
148
|
}
|
|
109
149
|
const suffix = params.toString() ? `?${params.toString()}` : ""
|
|
110
|
-
const url =
|
|
150
|
+
const url = target.ref
|
|
151
|
+
? `${target.baseUrl}/pinokio/resource/logs${suffix}`
|
|
152
|
+
: `${target.baseUrl}/apps/logs/${encodeURIComponent(target.legacyId)}${suffix}`
|
|
111
153
|
const response = await axios.get(url)
|
|
112
154
|
this.printJson(response.data)
|
|
113
155
|
}
|
|
156
|
+
async upload(argv) {
|
|
157
|
+
if (argv._.length <= 2) {
|
|
158
|
+
console.error("required arguments: <app_id> <file...>")
|
|
159
|
+
process.exitCode = 1
|
|
160
|
+
return
|
|
161
|
+
}
|
|
162
|
+
const target = await this.resolveResourceRequestTarget(argv._[1])
|
|
163
|
+
if (!target.ref && !target.legacyId) {
|
|
164
|
+
console.error("required argument: <app_id>")
|
|
165
|
+
process.exitCode = 1
|
|
166
|
+
return
|
|
167
|
+
}
|
|
168
|
+
const fileArgs = argv._.slice(2)
|
|
169
|
+
const form = new FormData()
|
|
170
|
+
for (const rawPath of fileArgs) {
|
|
171
|
+
const resolvedPath = this.resolveLocalPath(rawPath)
|
|
172
|
+
let stat
|
|
173
|
+
try {
|
|
174
|
+
stat = await fs.promises.stat(resolvedPath)
|
|
175
|
+
} catch (_) {
|
|
176
|
+
console.error(`file not found: ${resolvedPath}`)
|
|
177
|
+
process.exitCode = 1
|
|
178
|
+
return
|
|
179
|
+
}
|
|
180
|
+
if (!stat.isFile()) {
|
|
181
|
+
console.error(`not a file: ${resolvedPath}`)
|
|
182
|
+
process.exitCode = 1
|
|
183
|
+
return
|
|
184
|
+
}
|
|
185
|
+
const buffer = await fs.promises.readFile(resolvedPath)
|
|
186
|
+
form.append('files', new Blob([buffer]), path.basename(resolvedPath))
|
|
187
|
+
}
|
|
188
|
+
const uploadUrl = target.ref
|
|
189
|
+
? `${target.baseUrl}/pinokio/resource/upload?ref=${encodeURIComponent(target.ref)}`
|
|
190
|
+
: `${target.baseUrl}/apps/${encodeURIComponent(target.legacyId)}/upload`
|
|
191
|
+
const response = await fetch(uploadUrl, {
|
|
192
|
+
method: 'POST',
|
|
193
|
+
body: form
|
|
194
|
+
})
|
|
195
|
+
const raw = await response.text()
|
|
196
|
+
let payload
|
|
197
|
+
try {
|
|
198
|
+
payload = raw ? JSON.parse(raw) : {}
|
|
199
|
+
} catch (_) {
|
|
200
|
+
payload = { error: raw || `Upload failed (${response.status})` }
|
|
201
|
+
}
|
|
202
|
+
if (!response.ok) {
|
|
203
|
+
this.printJson(payload)
|
|
204
|
+
process.exitCode = 1
|
|
205
|
+
return
|
|
206
|
+
}
|
|
207
|
+
this.printJson(payload)
|
|
208
|
+
}
|
|
114
209
|
async stars(argv) {
|
|
115
210
|
const query = (argv._.slice(1).join(" ") || argv.q || "").trim().toLowerCase()
|
|
211
|
+
const baseUrl = await resolveHttpBaseUrl()
|
|
116
212
|
const [preferenceResponse, appResponse] = await Promise.all([
|
|
117
|
-
axios.get(
|
|
118
|
-
axios.get(
|
|
213
|
+
axios.get(`${baseUrl}/apps/preferences`),
|
|
214
|
+
axios.get(`${baseUrl}/info/apps`)
|
|
119
215
|
])
|
|
120
216
|
const preferenceItems = preferenceResponse && preferenceResponse.data && preferenceResponse.data.items
|
|
121
217
|
? preferenceResponse.data.items
|
|
@@ -165,7 +261,8 @@ class Util {
|
|
|
165
261
|
return
|
|
166
262
|
}
|
|
167
263
|
const appId = argv._[1]
|
|
168
|
-
const
|
|
264
|
+
const baseUrl = await resolveHttpBaseUrl()
|
|
265
|
+
const response = await axios.put(`${baseUrl}/apps/preferences/${encodeURIComponent(appId)}`, {
|
|
169
266
|
starred: Boolean(starred)
|
|
170
267
|
})
|
|
171
268
|
this.printJson(response.data)
|
|
@@ -181,7 +278,8 @@ class Util {
|
|
|
181
278
|
return
|
|
182
279
|
}
|
|
183
280
|
try {
|
|
184
|
-
const
|
|
281
|
+
const baseUrl = await resolveHttpBaseUrl()
|
|
282
|
+
const response = await axios.get(`${baseUrl}/pinokio/path/${encodeURIComponent(command)}`)
|
|
185
283
|
if (argv.json) {
|
|
186
284
|
this.printJson(response.data)
|
|
187
285
|
} else if (response.data && response.data.path) {
|
|
@@ -198,7 +296,8 @@ class Util {
|
|
|
198
296
|
}
|
|
199
297
|
}
|
|
200
298
|
async home(argv) {
|
|
201
|
-
const
|
|
299
|
+
const baseUrl = await resolveHttpBaseUrl()
|
|
300
|
+
const response = await axios.get(`${baseUrl}/pinokio/home`)
|
|
202
301
|
if (argv.json) {
|
|
203
302
|
this.printJson(response.data)
|
|
204
303
|
} else if (response.data && response.data.path) {
|
|
@@ -207,9 +306,9 @@ class Util {
|
|
|
207
306
|
}
|
|
208
307
|
}
|
|
209
308
|
async filepicker(argv) {
|
|
210
|
-
const rpc = new RPC(
|
|
309
|
+
const rpc = new RPC(await resolveWsBaseUrl())
|
|
211
310
|
if (argv.path) {
|
|
212
|
-
argv.path =
|
|
311
|
+
argv.path = this.resolveLocalPath(argv.path)
|
|
213
312
|
}
|
|
214
313
|
await rpc.run({
|
|
215
314
|
method: "kernel.bin.filepicker",
|
|
@@ -236,7 +335,8 @@ class Util {
|
|
|
236
335
|
if (argv._.length > 2) {
|
|
237
336
|
payload.text = argv._[2]
|
|
238
337
|
}
|
|
239
|
-
|
|
338
|
+
const baseUrl = await resolveHttpBaseUrl()
|
|
339
|
+
let response = await axios.post(`${baseUrl}/clipboard`, payload)
|
|
240
340
|
if (response.data && response.data.text) {
|
|
241
341
|
console.log(response.data.text)
|
|
242
342
|
}
|
|
@@ -247,15 +347,43 @@ class Util {
|
|
|
247
347
|
argv.message = argv._[1]
|
|
248
348
|
}
|
|
249
349
|
if (argv.image && !path.isAbsolute(argv.image)) {
|
|
250
|
-
argv.image =
|
|
350
|
+
argv.image = this.resolveLocalPath(argv.image)
|
|
251
351
|
}
|
|
252
|
-
|
|
352
|
+
const baseUrl = await resolveHttpBaseUrl()
|
|
353
|
+
let response = await axios.post(`${baseUrl}/push`, argv)
|
|
253
354
|
return response
|
|
254
355
|
}
|
|
255
356
|
async open_url(url) {
|
|
256
|
-
|
|
357
|
+
const baseUrl = await resolveHttpBaseUrl()
|
|
358
|
+
let response = await axios.post(`${baseUrl}/go`, { url })
|
|
257
359
|
return response
|
|
258
360
|
}
|
|
361
|
+
async open(argv) {
|
|
362
|
+
if (argv._.length <= 1) {
|
|
363
|
+
console.error("required argument: <url>")
|
|
364
|
+
process.exitCode = 1
|
|
365
|
+
return
|
|
366
|
+
}
|
|
367
|
+
const url = String(argv._[1] || '').trim()
|
|
368
|
+
if (!url) {
|
|
369
|
+
console.error("required argument: <url>")
|
|
370
|
+
process.exitCode = 1
|
|
371
|
+
return
|
|
372
|
+
}
|
|
373
|
+
const payload = { url }
|
|
374
|
+
if (typeof argv.peer === 'string' && argv.peer.trim()) {
|
|
375
|
+
payload.peer = argv.peer.trim()
|
|
376
|
+
}
|
|
377
|
+
if (typeof argv.surface === 'string' && argv.surface.trim()) {
|
|
378
|
+
payload.surface = argv.surface.trim()
|
|
379
|
+
}
|
|
380
|
+
if (typeof argv.preset === 'string' && argv.preset.trim()) {
|
|
381
|
+
payload.preset = argv.preset.trim()
|
|
382
|
+
}
|
|
383
|
+
const baseUrl = await resolveHttpBaseUrl()
|
|
384
|
+
const response = await axios.post(`${baseUrl}/pinokio/open`, payload)
|
|
385
|
+
this.printJson(response.data)
|
|
386
|
+
}
|
|
259
387
|
async appDownload(argv) {
|
|
260
388
|
if (argv._.length <= 1) {
|
|
261
389
|
console.error("required argument: <uri>")
|
|
@@ -267,7 +395,7 @@ class Util {
|
|
|
267
395
|
const branch = typeof argv.b === "string"
|
|
268
396
|
? argv.b.trim()
|
|
269
397
|
: (typeof argv.branch === "string" ? argv.branch.trim() : "")
|
|
270
|
-
const rpc = new RPC(
|
|
398
|
+
const rpc = new RPC(await resolveWsBaseUrl())
|
|
271
399
|
let exitCode = 0
|
|
272
400
|
await rpc.run({
|
|
273
401
|
method: "app.download",
|
|
@@ -304,7 +432,7 @@ class Util {
|
|
|
304
432
|
async download(argv) {
|
|
305
433
|
if (argv._.length > 1) {
|
|
306
434
|
let uri = argv._[1]
|
|
307
|
-
const rpc = new RPC(
|
|
435
|
+
const rpc = new RPC(await resolveWsBaseUrl())
|
|
308
436
|
await rpc.run({
|
|
309
437
|
method: "kernel.bin.install2",
|
|
310
438
|
params: {}
|