@palettelab/cli 0.3.0 → 0.3.2
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 +103 -10
- package/bin/{palette.js → pltt.js} +1 -1
- package/lib/bundler.js +73 -4
- package/lib/cli.js +37 -12
- package/lib/commands/build.js +2 -0
- package/lib/commands/dev.js +37 -2
- package/lib/commands/doctor.js +143 -0
- package/lib/commands/init.js +45 -13
- package/lib/commands/logs.js +99 -0
- package/lib/commands/package.js +64 -0
- package/lib/commands/publish.js +50 -6
- package/lib/commands/status.js +80 -0
- package/lib/commands/test.js +376 -0
- package/lib/environments.js +1 -1
- package/lib/manifest.js +253 -8
- package/package.json +7 -6
- package/platform-dev/docker-compose.yml +4 -1
- package/template-fallback/backend/api/main.py +9 -3
- package/template-fallback/palette-plugin.json +24 -1
- package/template-fallback/pyproject.toml +1 -1
- package/template-fallback/templates/agent-tool/README.md +4 -0
- package/template-fallback/templates/agent-tool/backend/api/main.py +14 -0
- package/template-fallback/templates/agent-tool/backend/tools/echo.py +15 -0
- package/template-fallback/templates/agent-tool/package.json +5 -0
- package/template-fallback/templates/agent-tool/palette-plugin.json +29 -0
- package/template-fallback/templates/agent-tool/pyproject.toml +5 -0
- package/template-fallback/templates/dashboard/README.md +3 -0
- package/template-fallback/templates/dashboard/backend/api/main.py +23 -0
- package/template-fallback/templates/dashboard/frontend/src/index.tsx +46 -0
- package/template-fallback/templates/dashboard/package.json +9 -0
- package/template-fallback/templates/dashboard/palette-plugin.json +26 -0
- package/template-fallback/templates/dashboard/pyproject.toml +5 -0
- package/template-fallback/templates/database/README.md +7 -0
- package/template-fallback/templates/database/backend/api/main.py +38 -0
- package/template-fallback/templates/database/backend/api/models.py +11 -0
- package/template-fallback/templates/database/backend/migrations/001_init.py +26 -0
- package/template-fallback/templates/database/frontend/src/index.tsx +57 -0
- package/template-fallback/templates/database/package.json +6 -0
- package/template-fallback/templates/database/palette-plugin.json +26 -0
- package/template-fallback/templates/database/pyproject.toml +5 -0
- package/template-fallback/templates/external-service/README.md +4 -0
- package/template-fallback/templates/external-service/backend/api/main.py +28 -0
- package/template-fallback/templates/external-service/frontend/src/index.tsx +26 -0
- package/template-fallback/templates/external-service/package.json +6 -0
- package/template-fallback/templates/external-service/palette-plugin.json +26 -0
- package/template-fallback/templates/external-service/pyproject.toml +5 -0
- package/template-fallback/templates/frontend-only/README.md +7 -0
- package/template-fallback/templates/frontend-only/frontend/src/index.tsx +16 -0
- package/template-fallback/templates/frontend-only/package.json +9 -0
- package/template-fallback/templates/frontend-only/palette-plugin.json +25 -0
package/lib/commands/init.js
CHANGED
|
@@ -9,6 +9,8 @@ const DEFAULT_TEMPLATE_REPO = "palette-lab/plugin-template"
|
|
|
9
9
|
const TEMPLATE_REPO = process.env.PALETTE_TEMPLATE_REPO || DEFAULT_TEMPLATE_REPO
|
|
10
10
|
const TEMPLATE_REF = process.env.PALETTE_TEMPLATE_REF || "main"
|
|
11
11
|
|
|
12
|
+
const KNOWN_TEMPLATES = ["frontend-only", "dashboard", "agent-tool", "external-service", "database"]
|
|
13
|
+
|
|
12
14
|
function toSlug(name) {
|
|
13
15
|
return name
|
|
14
16
|
.toLowerCase()
|
|
@@ -18,7 +20,6 @@ function toSlug(name) {
|
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
function fetchTemplate(destDir) {
|
|
21
|
-
// Try git first — works offline-ish if git is available.
|
|
22
23
|
const git = spawnSync(
|
|
23
24
|
"git",
|
|
24
25
|
["clone", "--depth=1", "--branch", TEMPLATE_REF, `https://github.com/${TEMPLATE_REPO}.git`, destDir],
|
|
@@ -31,10 +32,23 @@ function fetchTemplate(destDir) {
|
|
|
31
32
|
return false
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
function copyLocalFallback(destDir) {
|
|
35
|
+
function copyLocalFallback(destDir, template) {
|
|
36
|
+
if (template) {
|
|
37
|
+
const tplDir = path.resolve(__dirname, "..", "..", "template-fallback", "templates", template)
|
|
38
|
+
if (!fs.existsSync(tplDir)) return false
|
|
39
|
+
fs.cpSync(tplDir, destDir, { recursive: true })
|
|
40
|
+
return true
|
|
41
|
+
}
|
|
35
42
|
const fallback = path.resolve(__dirname, "..", "..", "template-fallback")
|
|
36
43
|
if (!fs.existsSync(fallback)) return false
|
|
37
|
-
|
|
44
|
+
// Skip the templates/ directory when copying default fallback.
|
|
45
|
+
fs.cpSync(fallback, destDir, {
|
|
46
|
+
recursive: true,
|
|
47
|
+
filter: (src) => {
|
|
48
|
+
const rel = path.relative(fallback, src)
|
|
49
|
+
return !rel.startsWith("templates")
|
|
50
|
+
},
|
|
51
|
+
})
|
|
38
52
|
return true
|
|
39
53
|
}
|
|
40
54
|
|
|
@@ -47,10 +61,24 @@ function rewriteManifest(destDir, slug, displayName) {
|
|
|
47
61
|
fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + "\n")
|
|
48
62
|
}
|
|
49
63
|
|
|
64
|
+
function getOpt(args, name) {
|
|
65
|
+
const i = args.indexOf(name)
|
|
66
|
+
if (i >= 0 && args[i + 1]) return args[i + 1]
|
|
67
|
+
return null
|
|
68
|
+
}
|
|
69
|
+
|
|
50
70
|
async function run(args, { cwd }) {
|
|
51
|
-
const
|
|
71
|
+
const positional = args.filter((a) => !a.startsWith("-"))
|
|
72
|
+
const name = positional[0]
|
|
52
73
|
if (!name) {
|
|
53
|
-
console.error("[
|
|
74
|
+
console.error("[pltt] usage: pltt init <plugin-name> [--template <name>]")
|
|
75
|
+
console.error(`[palette] templates: ${KNOWN_TEMPLATES.join(", ")}`)
|
|
76
|
+
process.exit(1)
|
|
77
|
+
}
|
|
78
|
+
const template = getOpt(args, "--template")
|
|
79
|
+
if (template && !KNOWN_TEMPLATES.includes(template)) {
|
|
80
|
+
console.error(`[palette] unknown template: ${template}`)
|
|
81
|
+
console.error(`[palette] templates: ${KNOWN_TEMPLATES.join(", ")}`)
|
|
54
82
|
process.exit(1)
|
|
55
83
|
}
|
|
56
84
|
const slug = toSlug(name)
|
|
@@ -63,18 +91,21 @@ async function run(args, { cwd }) {
|
|
|
63
91
|
process.exit(1)
|
|
64
92
|
}
|
|
65
93
|
|
|
66
|
-
|
|
94
|
+
if (template) {
|
|
95
|
+
console.log(`[palette] creating plugin "${slug}" from template "${template}"`)
|
|
96
|
+
} else {
|
|
97
|
+
console.log(`[palette] creating plugin "${slug}" from ${TEMPLATE_REPO}@${TEMPLATE_REF}`)
|
|
98
|
+
}
|
|
67
99
|
|
|
68
100
|
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "palette-tpl-"))
|
|
69
|
-
let ok =
|
|
70
|
-
if (!
|
|
71
|
-
|
|
72
|
-
ok
|
|
101
|
+
let ok = false
|
|
102
|
+
if (!template) {
|
|
103
|
+
ok = fetchTemplate(tmp)
|
|
104
|
+
if (!ok) console.warn("[palette] git clone failed, falling back to bundled template")
|
|
73
105
|
}
|
|
106
|
+
if (!ok) ok = copyLocalFallback(tmp, template)
|
|
74
107
|
if (!ok) {
|
|
75
|
-
console.error(
|
|
76
|
-
"[palette] no template available — install git or ship template-fallback/ with the CLI",
|
|
77
|
-
)
|
|
108
|
+
console.error("[palette] no template available")
|
|
78
109
|
process.exit(1)
|
|
79
110
|
}
|
|
80
111
|
|
|
@@ -86,6 +117,7 @@ async function run(args, { cwd }) {
|
|
|
86
117
|
console.log("[palette] next steps:")
|
|
87
118
|
console.log(` cd ${slug}`)
|
|
88
119
|
console.log(` npx @palettelab/cli dev`)
|
|
120
|
+
console.log(` # or, after global install: pltt dev`)
|
|
89
121
|
}
|
|
90
122
|
|
|
91
123
|
module.exports = run
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
|
|
3
|
+
const fs = require("fs")
|
|
4
|
+
const path = require("path")
|
|
5
|
+
const { resolveEnvironment, parseFlags } = require("../environments")
|
|
6
|
+
const { loadManifest } = require("../manifest")
|
|
7
|
+
|
|
8
|
+
function readLastPublish(cwd) {
|
|
9
|
+
const p = path.join(cwd, ".palette", "last-publish.json")
|
|
10
|
+
if (!fs.existsSync(p)) return null
|
|
11
|
+
try {
|
|
12
|
+
return JSON.parse(fs.readFileSync(p, "utf8"))
|
|
13
|
+
} catch {
|
|
14
|
+
return null
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function getOpt(argv, name, def) {
|
|
19
|
+
const i = argv.indexOf(name)
|
|
20
|
+
if (i >= 0 && argv[i + 1]) return argv[i + 1]
|
|
21
|
+
return def
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function fetchLogs(env, pluginId, tail) {
|
|
25
|
+
const url = `${env.url}/api/v1/appstore/plugins/${encodeURIComponent(pluginId)}/logs?tail=${tail}`
|
|
26
|
+
const res = await fetch(url, { headers: { Authorization: `Bearer ${env.token}` } })
|
|
27
|
+
if (!res.ok) {
|
|
28
|
+
const text = await res.text()
|
|
29
|
+
throw new Error(`GET ${url} → ${res.status}: ${text}`)
|
|
30
|
+
}
|
|
31
|
+
return res.json()
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function run(argv, { cwd }) {
|
|
35
|
+
const json = argv.includes("--json")
|
|
36
|
+
const follow = argv.includes("--follow") || argv.includes("-f")
|
|
37
|
+
const tail = parseInt(getOpt(argv, "--tail", "50"), 10) || 50
|
|
38
|
+
|
|
39
|
+
const positional = argv.filter((a) => !a.startsWith("-"))
|
|
40
|
+
let pluginId = positional[0]
|
|
41
|
+
const last = readLastPublish(cwd)
|
|
42
|
+
if (!pluginId) {
|
|
43
|
+
if (last && last.plugin_id) pluginId = last.plugin_id
|
|
44
|
+
else {
|
|
45
|
+
try {
|
|
46
|
+
pluginId = loadManifest(cwd).id
|
|
47
|
+
} catch {
|
|
48
|
+
// ignore
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (!pluginId) {
|
|
53
|
+
console.error("[palette] no plugin id provided and no manifest found.")
|
|
54
|
+
process.exit(1)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const { flags } = parseFlags(argv)
|
|
58
|
+
if (!flags.env && last && last.env) flags.env = last.env
|
|
59
|
+
let env
|
|
60
|
+
try {
|
|
61
|
+
env = resolveEnvironment({ cwd, flags })
|
|
62
|
+
} catch (err) {
|
|
63
|
+
console.error(`[palette] ${err.message}`)
|
|
64
|
+
process.exit(1)
|
|
65
|
+
}
|
|
66
|
+
if (!env.token) {
|
|
67
|
+
console.error(`[palette] no publish token for "${env.name}". set $${env.token_env}.`)
|
|
68
|
+
process.exit(1)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
let lastSeenId = 0
|
|
72
|
+
do {
|
|
73
|
+
let data
|
|
74
|
+
try {
|
|
75
|
+
data = await fetchLogs(env, pluginId, tail)
|
|
76
|
+
} catch (err) {
|
|
77
|
+
console.error(`[palette] ${err.message}`)
|
|
78
|
+
process.exit(1)
|
|
79
|
+
}
|
|
80
|
+
const events = data.events || []
|
|
81
|
+
const fresh = events.filter((e) => e.id > lastSeenId)
|
|
82
|
+
if (fresh.length) lastSeenId = Math.max(...fresh.map((e) => e.id))
|
|
83
|
+
if (json) {
|
|
84
|
+
for (const e of fresh) console.log(JSON.stringify(e))
|
|
85
|
+
} else {
|
|
86
|
+
for (const e of fresh) {
|
|
87
|
+
const ts = e.created_at
|
|
88
|
+
const tag = e.event_type.padEnd(11)
|
|
89
|
+
const route = e.route || "-"
|
|
90
|
+
const code = e.status_code != null ? `[${e.status_code}]` : ""
|
|
91
|
+
const err = e.error_message ? ` err=${e.error_message}` : ""
|
|
92
|
+
console.log(`${ts} ${tag} ${route} ${code}${err}`)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (follow) await new Promise((r) => setTimeout(r, 3000))
|
|
96
|
+
} while (follow)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
module.exports = run
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
|
|
3
|
+
const fs = require("fs")
|
|
4
|
+
const path = require("path")
|
|
5
|
+
const crypto = require("crypto")
|
|
6
|
+
const { loadManifest, validateManifest } = require("../manifest")
|
|
7
|
+
const { bundleFrontend, bundleBackend } = require("../bundler")
|
|
8
|
+
|
|
9
|
+
function sha256(buf) {
|
|
10
|
+
return crypto.createHash("sha256").update(buf).digest("hex")
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async function run(argv, { cwd }) {
|
|
14
|
+
const json = argv.includes("--json")
|
|
15
|
+
const manifest = loadManifest(cwd)
|
|
16
|
+
const errors = validateManifest(manifest)
|
|
17
|
+
if (errors.length) {
|
|
18
|
+
console.error("[palette] manifest invalid:")
|
|
19
|
+
for (const e of errors) console.error(` - ${e}`)
|
|
20
|
+
process.exit(1)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const distDir = path.join(cwd, "dist")
|
|
24
|
+
fs.mkdirSync(distDir, { recursive: true })
|
|
25
|
+
|
|
26
|
+
const frontend = manifest.frontend
|
|
27
|
+
? await bundleFrontend(cwd, manifest.frontend.entry || "./frontend/src/index.tsx")
|
|
28
|
+
: null
|
|
29
|
+
const backend = manifest.backend ? await bundleBackend(cwd) : null
|
|
30
|
+
|
|
31
|
+
const out = path.join(distDir, `${manifest.id}-${manifest.version}.tar.gz`)
|
|
32
|
+
// Build a simple tar by piping through node-tar via spawn — avoid extra dep
|
|
33
|
+
// by writing files into a staging dir and shelling out to `tar`. The
|
|
34
|
+
// platform-dev image already ships with tar, and any developer running this
|
|
35
|
+
// CLI will have it too on macOS/Linux.
|
|
36
|
+
const stage = fs.mkdtempSync(path.join(require("os").tmpdir(), "palette-pkg-"))
|
|
37
|
+
fs.writeFileSync(path.join(stage, "palette-plugin.json"), JSON.stringify(manifest, null, 2))
|
|
38
|
+
if (frontend) fs.writeFileSync(path.join(stage, "frontend.mjs"), frontend)
|
|
39
|
+
if (backend) fs.writeFileSync(path.join(stage, "backend.tar.gz"), backend)
|
|
40
|
+
|
|
41
|
+
const { spawnSync } = require("child_process")
|
|
42
|
+
const r = spawnSync("tar", ["-czf", out, "-C", stage, "."], { stdio: "inherit" })
|
|
43
|
+
if (r.status !== 0) {
|
|
44
|
+
console.error("[palette] tar failed")
|
|
45
|
+
process.exit(1)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const buf = fs.readFileSync(out)
|
|
49
|
+
const result = {
|
|
50
|
+
id: manifest.id,
|
|
51
|
+
version: manifest.version,
|
|
52
|
+
path: out,
|
|
53
|
+
bytes: buf.length,
|
|
54
|
+
sha256: sha256(buf),
|
|
55
|
+
}
|
|
56
|
+
if (json) {
|
|
57
|
+
console.log(JSON.stringify(result, null, 2))
|
|
58
|
+
} else {
|
|
59
|
+
console.log(`[palette] packaged ${manifest.id}@${manifest.version} → ${out} (${buf.length} bytes)`)
|
|
60
|
+
console.log(`[palette] sha256: ${result.sha256}`)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
module.exports = run
|
package/lib/commands/publish.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict"
|
|
2
2
|
|
|
3
3
|
const crypto = require("crypto")
|
|
4
|
+
const fs = require("fs")
|
|
5
|
+
const path = require("path")
|
|
4
6
|
const { loadManifest, validateManifest } = require("../manifest")
|
|
5
7
|
const { bundleFrontend, bundleBackend } = require("../bundler")
|
|
6
8
|
const {
|
|
@@ -85,9 +87,14 @@ async function run(argv, { cwd }) {
|
|
|
85
87
|
`[palette] publishing ${manifest.id}@${manifest.version} → ${env.name} (${env.url})`,
|
|
86
88
|
)
|
|
87
89
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
90
|
+
let frontend = null
|
|
91
|
+
if (manifest.frontend?.entry) {
|
|
92
|
+
console.log("[palette] bundling frontend")
|
|
93
|
+
frontend = await bundleFrontend(cwd, manifest.frontend.entry)
|
|
94
|
+
console.log(`[palette] ${frontend.length} bytes`)
|
|
95
|
+
} else {
|
|
96
|
+
console.log("[palette] no frontend declared")
|
|
97
|
+
}
|
|
91
98
|
|
|
92
99
|
console.log("[palette] bundling backend")
|
|
93
100
|
const backend = await bundleBackend(cwd)
|
|
@@ -107,15 +114,18 @@ async function run(argv, { cwd }) {
|
|
|
107
114
|
})
|
|
108
115
|
|
|
109
116
|
console.log("[palette] uploading")
|
|
110
|
-
|
|
111
|
-
put(signed.frontend_upload_url, frontend, "application/javascript"),
|
|
117
|
+
const uploads = [
|
|
112
118
|
put(signed.backend_upload_url, backend, "application/gzip"),
|
|
113
119
|
put(
|
|
114
120
|
signed.manifest_upload_url,
|
|
115
121
|
Buffer.from(JSON.stringify(manifest, null, 2)),
|
|
116
122
|
"application/json",
|
|
117
123
|
),
|
|
118
|
-
]
|
|
124
|
+
]
|
|
125
|
+
if (frontend) {
|
|
126
|
+
uploads.push(put(signed.frontend_upload_url, frontend, "application/javascript"))
|
|
127
|
+
}
|
|
128
|
+
await Promise.all(uploads)
|
|
119
129
|
|
|
120
130
|
console.log("[palette] finalizing")
|
|
121
131
|
const record = await api("/api/v1/appstore/publish", {
|
|
@@ -129,10 +139,44 @@ async function run(argv, { cwd }) {
|
|
|
129
139
|
},
|
|
130
140
|
})
|
|
131
141
|
|
|
142
|
+
try {
|
|
143
|
+
const dir = path.join(cwd, ".palette")
|
|
144
|
+
fs.mkdirSync(dir, { recursive: true })
|
|
145
|
+
fs.writeFileSync(
|
|
146
|
+
path.join(dir, "last-publish.json"),
|
|
147
|
+
JSON.stringify(
|
|
148
|
+
{
|
|
149
|
+
id: record.id,
|
|
150
|
+
plugin_id: record.plugin_id,
|
|
151
|
+
version: record.version,
|
|
152
|
+
env: env.name,
|
|
153
|
+
url: env.url,
|
|
154
|
+
preview_url: record.preview_url,
|
|
155
|
+
published_at: new Date().toISOString(),
|
|
156
|
+
},
|
|
157
|
+
null,
|
|
158
|
+
2,
|
|
159
|
+
),
|
|
160
|
+
)
|
|
161
|
+
} catch (err) {
|
|
162
|
+
// best-effort
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (flags.json) {
|
|
166
|
+
console.log(JSON.stringify(record, null, 2))
|
|
167
|
+
return
|
|
168
|
+
}
|
|
169
|
+
|
|
132
170
|
console.log(
|
|
133
171
|
`[palette] published ${record.plugin_id}@${record.version} (status=${record.status})`,
|
|
134
172
|
)
|
|
135
173
|
console.log(`[palette] awaiting superadmin review on ${env.url}`)
|
|
174
|
+
if (record.review_url) {
|
|
175
|
+
console.log(`[palette] review queue: ${record.review_url}`)
|
|
176
|
+
}
|
|
177
|
+
if (record.preview_url) {
|
|
178
|
+
console.log(`[palette] preview: ${record.preview_url}`)
|
|
179
|
+
}
|
|
136
180
|
console.log(`[palette] once approved, live at ${env.url}${record.catalog_url}`)
|
|
137
181
|
}
|
|
138
182
|
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
|
|
3
|
+
const fs = require("fs")
|
|
4
|
+
const path = require("path")
|
|
5
|
+
const { resolveEnvironment, parseFlags } = require("../environments")
|
|
6
|
+
|
|
7
|
+
function readLastPublish(cwd) {
|
|
8
|
+
const p = path.join(cwd, ".palette", "last-publish.json")
|
|
9
|
+
if (!fs.existsSync(p)) return null
|
|
10
|
+
try {
|
|
11
|
+
return JSON.parse(fs.readFileSync(p, "utf8"))
|
|
12
|
+
} catch {
|
|
13
|
+
return null
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function run(argv, { cwd }) {
|
|
18
|
+
const json = argv.includes("--json")
|
|
19
|
+
const positional = argv.filter((a) => !a.startsWith("-"))
|
|
20
|
+
const last = readLastPublish(cwd)
|
|
21
|
+
const publishId = positional[0] || (last && last.id)
|
|
22
|
+
|
|
23
|
+
if (!publishId) {
|
|
24
|
+
console.error(
|
|
25
|
+
"[palette] no publish id provided and no .palette/last-publish.json found.",
|
|
26
|
+
)
|
|
27
|
+
console.error(" usage: pltt status <publish-id> [--env <name>]")
|
|
28
|
+
process.exit(1)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const { flags } = parseFlags(argv)
|
|
32
|
+
if (!flags.env && last && last.env) flags.env = last.env
|
|
33
|
+
|
|
34
|
+
let env
|
|
35
|
+
try {
|
|
36
|
+
env = resolveEnvironment({ cwd, flags })
|
|
37
|
+
} catch (err) {
|
|
38
|
+
console.error(`[palette] ${err.message}`)
|
|
39
|
+
process.exit(1)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (!env.token) {
|
|
43
|
+
console.error(
|
|
44
|
+
`[palette] no publish token for environment "${env.name}". set $${env.token_env}.`,
|
|
45
|
+
)
|
|
46
|
+
process.exit(1)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const url = `${env.url}/api/v1/appstore/publishes/${publishId}`
|
|
50
|
+
const res = await fetch(url, {
|
|
51
|
+
headers: { Authorization: `Bearer ${env.token}` },
|
|
52
|
+
})
|
|
53
|
+
if (!res.ok) {
|
|
54
|
+
const text = await res.text()
|
|
55
|
+
console.error(`[palette] GET ${url} → ${res.status}: ${text}`)
|
|
56
|
+
process.exit(1)
|
|
57
|
+
}
|
|
58
|
+
const data = await res.json()
|
|
59
|
+
|
|
60
|
+
if (json) {
|
|
61
|
+
console.log(JSON.stringify(data, null, 2))
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
console.log(`[palette] ${data.plugin_id}@${data.version}`)
|
|
66
|
+
console.log(` status: ${data.status}`)
|
|
67
|
+
if (data.review_decision) console.log(` decision: ${data.review_decision}`)
|
|
68
|
+
if (data.review_reason) console.log(` reason: ${data.review_reason}`)
|
|
69
|
+
if (data.preview_url) console.log(` preview: ${data.preview_url}`)
|
|
70
|
+
console.log(` published: ${data.published_at}`)
|
|
71
|
+
if (data.report) {
|
|
72
|
+
console.log(` risk: ${data.report.risk_score.toUpperCase()}`)
|
|
73
|
+
console.log(
|
|
74
|
+
` permissions=${data.report.permission_risk}, migrations=${data.report.migration_risk}, network=${data.report.external_network_risk}`,
|
|
75
|
+
)
|
|
76
|
+
console.log(` bundle=${data.report.bundle_size_bytes} bytes, sandbox=${data.report.sandbox_enabled}`)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
module.exports = run
|