@palettelab/cli 0.3.48 → 0.3.50
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 +56 -8
- package/backend-sdk/palette_sdk/__init__.py +12 -0
- package/backend-sdk/palette_sdk/apps.py +12 -0
- package/backend-sdk/palette_sdk/events.py +35 -1
- package/backend-sdk/palette_sdk/manifest.py +48 -3
- package/backend-sdk/palette_sdk/services.py +147 -0
- package/docs/python-backend-sdk.md +65 -35
- package/lib/bundler.js +58 -5
- package/lib/cli.js +10 -0
- package/lib/commands/dev.js +4 -1
- package/lib/commands/doctor.js +9 -5
- package/lib/commands/package.js +4 -1
- package/lib/commands/publish.js +97 -19
- package/lib/commands/services.js +426 -0
- package/lib/commands/test.js +21 -11
- package/lib/css-scope.js +124 -0
- package/lib/dev-simulator.js +34 -4
- package/lib/manifest.js +120 -5
- package/lib/secrets.js +83 -8
- package/package.json +4 -2
package/lib/bundler.js
CHANGED
|
@@ -4,6 +4,7 @@ const path = require("path")
|
|
|
4
4
|
const fs = require("fs")
|
|
5
5
|
const os = require("os")
|
|
6
6
|
const { generatePaletteAppEntry } = require("./app-router")
|
|
7
|
+
const { appendCssExport, scopePluginCss } = require("./css-scope")
|
|
7
8
|
|
|
8
9
|
const NEXT_CONFIG_NAMES = [
|
|
9
10
|
"frontend/next.config.ts",
|
|
@@ -382,6 +383,43 @@ function mergePlugins(...pluginGroups) {
|
|
|
382
383
|
return pluginGroups.flat().filter(Boolean)
|
|
383
384
|
}
|
|
384
385
|
|
|
386
|
+
function pluginCssScopeId(frontend = {}) {
|
|
387
|
+
return frontend.pluginId || frontend.id || "plugin"
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
function cssOutputForJs(outfile) {
|
|
391
|
+
const ext = path.extname(outfile)
|
|
392
|
+
return `${outfile.slice(0, outfile.length - ext.length)}.css`
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
function outputPathFromMetafile(result, suffix) {
|
|
396
|
+
const outputs = Object.keys(result.metafile?.outputs || {})
|
|
397
|
+
return outputs.find((output) => output.endsWith(suffix)) || null
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
function writeScopedCssExport({ jsPath, cssPath, pluginId, deleteCss = true }) {
|
|
401
|
+
if (!cssPath || !fs.existsSync(cssPath)) return
|
|
402
|
+
const css = fs.readFileSync(cssPath, "utf8")
|
|
403
|
+
const scopedCss = scopePluginCss(css, pluginId)
|
|
404
|
+
if (scopedCss.trim()) {
|
|
405
|
+
const js = fs.readFileSync(jsPath, "utf8")
|
|
406
|
+
fs.writeFileSync(jsPath, appendCssExport(js, scopedCss))
|
|
407
|
+
}
|
|
408
|
+
if (deleteCss) fs.rmSync(cssPath, { force: true })
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
function bundleOutputsToFrontendBuffer(result, pluginId) {
|
|
412
|
+
const outputs = result.outputFiles || []
|
|
413
|
+
const jsOutput = outputs.find((file) => /\.(mjs|js)$/.test(file.path))
|
|
414
|
+
if (!jsOutput) throw new Error("esbuild produced no JavaScript output")
|
|
415
|
+
const css = outputs
|
|
416
|
+
.filter((file) => file.path.endsWith(".css"))
|
|
417
|
+
.map((file) => file.text)
|
|
418
|
+
.join("\n")
|
|
419
|
+
const js = jsOutput.text
|
|
420
|
+
return Buffer.from(appendCssExport(js, scopePluginCss(css, pluginId)))
|
|
421
|
+
}
|
|
422
|
+
|
|
385
423
|
/**
|
|
386
424
|
* Bundle the plugin's frontend entry into a single ESM file.
|
|
387
425
|
*
|
|
@@ -393,8 +431,8 @@ function mergePlugins(...pluginGroups) {
|
|
|
393
431
|
async function bundleFrontend(pluginDir, entry, frontend = {}) {
|
|
394
432
|
pluginDir = path.resolve(pluginDir)
|
|
395
433
|
const esbuild = loadEsbuild()
|
|
396
|
-
const tmp =
|
|
397
|
-
const bundleEntry =
|
|
434
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "palette-frontend-"))
|
|
435
|
+
const bundleEntry = isPaletteApp(frontend)
|
|
398
436
|
? generatePaletteAppEntry(pluginDir, entry || "./frontend/app", path.join(tmp, "entry.tsx"))
|
|
399
437
|
: entry
|
|
400
438
|
const absEntry = path.resolve(pluginDir, bundleEntry)
|
|
@@ -407,6 +445,7 @@ async function bundleFrontend(pluginDir, entry, frontend = {}) {
|
|
|
407
445
|
const result = await esbuild.build({
|
|
408
446
|
entryPoints: [absEntry],
|
|
409
447
|
bundle: true,
|
|
448
|
+
outfile: path.join(tmp, "frontend.mjs"),
|
|
410
449
|
format: "esm",
|
|
411
450
|
platform: "browser",
|
|
412
451
|
target: ["es2022"],
|
|
@@ -432,9 +471,9 @@ async function bundleFrontend(pluginDir, entry, frontend = {}) {
|
|
|
432
471
|
if (!result.outputFiles || result.outputFiles.length === 0) {
|
|
433
472
|
throw new Error("esbuild produced no output")
|
|
434
473
|
}
|
|
435
|
-
return
|
|
474
|
+
return bundleOutputsToFrontendBuffer(result, pluginCssScopeId(frontend))
|
|
436
475
|
} finally {
|
|
437
|
-
|
|
476
|
+
fs.rmSync(tmp, { recursive: true, force: true })
|
|
438
477
|
}
|
|
439
478
|
}
|
|
440
479
|
|
|
@@ -473,6 +512,7 @@ async function watchFrontend(pluginDir, entry, outfile, frontend = {}) {
|
|
|
473
512
|
],
|
|
474
513
|
minify: false,
|
|
475
514
|
sourcemap: "inline",
|
|
515
|
+
metafile: true,
|
|
476
516
|
logLevel: "silent",
|
|
477
517
|
absWorkingDir: pluginDir,
|
|
478
518
|
plugins: [
|
|
@@ -488,6 +528,12 @@ async function watchFrontend(pluginDir, entry, outfile, frontend = {}) {
|
|
|
488
528
|
}
|
|
489
529
|
return
|
|
490
530
|
}
|
|
531
|
+
const cssPath = outputPathFromMetafile(result, ".css") || cssOutputForJs(outfile)
|
|
532
|
+
writeScopedCssExport({
|
|
533
|
+
jsPath: outfile,
|
|
534
|
+
cssPath,
|
|
535
|
+
pluginId: pluginCssScopeId(frontend),
|
|
536
|
+
})
|
|
491
537
|
const size = fs.existsSync(outfile) ? fs.statSync(outfile).size : 0
|
|
492
538
|
console.log(`[pltt] frontend bundle ready (${size} bytes)`)
|
|
493
539
|
})
|
|
@@ -509,7 +555,7 @@ async function watchFrontend(pluginDir, entry, outfile, frontend = {}) {
|
|
|
509
555
|
* ./backend/...
|
|
510
556
|
* ./palette-plugin.json
|
|
511
557
|
*/
|
|
512
|
-
async function bundleBackend(pluginDir) {
|
|
558
|
+
async function bundleBackend(pluginDir, options = {}) {
|
|
513
559
|
pluginDir = path.resolve(pluginDir)
|
|
514
560
|
const { spawnSync } = require("child_process")
|
|
515
561
|
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "palette-bundle-"))
|
|
@@ -531,9 +577,16 @@ async function bundleBackend(pluginDir) {
|
|
|
531
577
|
const backendDir = path.join(pluginDir, "backend")
|
|
532
578
|
if (fs.existsSync(backendDir)) copy(backendDir, path.join(stage, "backend"))
|
|
533
579
|
for (const metadataFile of ["package.json", "pyproject.toml", "palette-plugin.json"]) {
|
|
580
|
+
if (metadataFile === "palette-plugin.json" && options.manifest) continue
|
|
534
581
|
const src = path.join(pluginDir, metadataFile)
|
|
535
582
|
if (fs.existsSync(src)) fs.copyFileSync(src, path.join(stage, metadataFile))
|
|
536
583
|
}
|
|
584
|
+
if (options.manifest) {
|
|
585
|
+
fs.writeFileSync(
|
|
586
|
+
path.join(stage, "palette-plugin.json"),
|
|
587
|
+
JSON.stringify(options.manifest, null, 2),
|
|
588
|
+
)
|
|
589
|
+
}
|
|
537
590
|
|
|
538
591
|
const sdkDir = path.resolve(__dirname, "..", "backend-sdk", "palette_sdk")
|
|
539
592
|
const targetSdkDir = path.join(stage, "backend", "palette_sdk")
|
package/lib/cli.js
CHANGED
|
@@ -11,6 +11,7 @@ const pkg = require("./commands/package")
|
|
|
11
11
|
const status = require("./commands/status")
|
|
12
12
|
const logs = require("./commands/logs")
|
|
13
13
|
const secrets = require("./commands/secrets")
|
|
14
|
+
const services = require("./commands/services")
|
|
14
15
|
|
|
15
16
|
const COMMANDS = {
|
|
16
17
|
init: { run: init, help: "Scaffold a new plugin directory from the template" },
|
|
@@ -50,6 +51,10 @@ const COMMANDS = {
|
|
|
50
51
|
run: secrets,
|
|
51
52
|
help: "Initialize local env files and manage plugin-scope secrets",
|
|
52
53
|
},
|
|
54
|
+
services: {
|
|
55
|
+
run: services,
|
|
56
|
+
help: "Inspect / pull / scaffold OS-broker services (list, pull, scaffold)",
|
|
57
|
+
},
|
|
53
58
|
}
|
|
54
59
|
|
|
55
60
|
function printHelp() {
|
|
@@ -77,6 +82,11 @@ function printHelp() {
|
|
|
77
82
|
console.log("\nLogs flags:")
|
|
78
83
|
console.log(" --tail <n> Tail last n events (default 50)")
|
|
79
84
|
console.log(" -f, --follow Stream events (poll every 3s)")
|
|
85
|
+
console.log("\nServices (OS broker):")
|
|
86
|
+
console.log(" pltt services list # show provided services/events in the org")
|
|
87
|
+
console.log(" pltt services add TARGET # add a consumed service/event target")
|
|
88
|
+
console.log(" pltt services pull # generate typed TS+Python clients from consumes")
|
|
89
|
+
console.log(" pltt services scaffold NAME # add a provider method (schemas + handler stub)")
|
|
80
90
|
console.log("\nSecrets:")
|
|
81
91
|
console.log(" pltt secrets init")
|
|
82
92
|
console.log(" pltt secrets set NAME --value <secret> --env staging")
|
package/lib/commands/dev.js
CHANGED
|
@@ -172,7 +172,10 @@ async function run(args, { cwd }) {
|
|
|
172
172
|
if (manifest.frontend?.entry) {
|
|
173
173
|
console.log(`[pltt] bundling frontend ${frontendEntry} → .palette/dist/frontend.mjs`)
|
|
174
174
|
try {
|
|
175
|
-
frontendWatcher = await watchFrontend(cwd, frontendEntry, frontendBundle,
|
|
175
|
+
frontendWatcher = await watchFrontend(cwd, frontendEntry, frontendBundle, {
|
|
176
|
+
...manifest.frontend,
|
|
177
|
+
pluginId,
|
|
178
|
+
})
|
|
176
179
|
} catch (err) {
|
|
177
180
|
console.error(
|
|
178
181
|
`[pltt] could not start frontend bundler: ${
|
package/lib/commands/doctor.js
CHANGED
|
@@ -6,7 +6,7 @@ const { spawnSync } = require("child_process")
|
|
|
6
6
|
const { loadManifest, validateManifest } = require("../manifest")
|
|
7
7
|
const { bundleFrontend } = require("../bundler")
|
|
8
8
|
const { DEFAULT_BACKEND_DEV_PORT, DEFAULT_FRONTEND_DEV_PORT, resolveDevPorts } = require("../ports")
|
|
9
|
-
const { declaredSecrets,
|
|
9
|
+
const { declaredSecrets, loadLocalEnvDetails } = require("../secrets")
|
|
10
10
|
|
|
11
11
|
const DEFAULT_IMAGE =
|
|
12
12
|
process.env.PALETTE_DEV_IMAGE || "ghcr.io/palette-lab/platform-dev:latest"
|
|
@@ -122,19 +122,20 @@ async function run(args, { cwd }) {
|
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
const secrets = declaredSecrets(manifest)
|
|
125
|
-
const
|
|
125
|
+
const localEnv = loadLocalEnvDetails(cwd, { apply: false })
|
|
126
|
+
const localSecrets = localEnv.values
|
|
126
127
|
if (Object.keys(secrets).length === 0) {
|
|
127
128
|
ok("no manifest secrets declared")
|
|
128
129
|
} else {
|
|
129
130
|
ok(`manifest declares ${Object.keys(secrets).length} secret(s)`)
|
|
130
131
|
for (const [name, spec] of Object.entries(secrets)) {
|
|
131
132
|
if (spec.scope.includes("dev") && !localSecrets[name]) {
|
|
132
|
-
warn(`local dev secret missing: ${name}`, "
|
|
133
|
+
warn(`local dev secret missing: ${name}`, "Add it to .env, .env.local, or an environment-specific .env file.")
|
|
133
134
|
}
|
|
134
135
|
if (spec.scope.includes("plugin") && spec.required && !localSecrets[name] && !process.env[name]) {
|
|
135
136
|
warn(
|
|
136
137
|
`plugin secret missing locally: ${name}`,
|
|
137
|
-
"
|
|
138
|
+
"Add it to .env/.env.local, set an env var, pass --secrets-file, or run pltt secrets set.",
|
|
138
139
|
)
|
|
139
140
|
}
|
|
140
141
|
}
|
|
@@ -142,7 +143,10 @@ async function run(args, { cwd }) {
|
|
|
142
143
|
|
|
143
144
|
if (manifest.frontend?.entry) {
|
|
144
145
|
try {
|
|
145
|
-
const bundle = await bundleFrontend(cwd, manifest.frontend.entry,
|
|
146
|
+
const bundle = await bundleFrontend(cwd, manifest.frontend.entry, {
|
|
147
|
+
...manifest.frontend,
|
|
148
|
+
pluginId: manifest.id,
|
|
149
|
+
})
|
|
146
150
|
ok(`frontend bundles successfully (${bundle.length} bytes)`)
|
|
147
151
|
} catch (err) {
|
|
148
152
|
failures += fail(
|
package/lib/commands/package.js
CHANGED
|
@@ -43,7 +43,10 @@ async function run(argv, { cwd }) {
|
|
|
43
43
|
fs.mkdirSync(distDir, { recursive: true })
|
|
44
44
|
|
|
45
45
|
const frontend = manifest.frontend
|
|
46
|
-
? await bundleFrontend(cwd, manifest.frontend.entry || "./frontend/src/index.tsx",
|
|
46
|
+
? await bundleFrontend(cwd, manifest.frontend.entry || "./frontend/src/index.tsx", {
|
|
47
|
+
...manifest.frontend,
|
|
48
|
+
pluginId: manifest.id,
|
|
49
|
+
})
|
|
47
50
|
: null
|
|
48
51
|
const backend = manifest.backend ? await bundleBackend(cwd) : null
|
|
49
52
|
|
package/lib/commands/publish.js
CHANGED
|
@@ -12,10 +12,13 @@ const {
|
|
|
12
12
|
confirmProduction,
|
|
13
13
|
} = require("../environments")
|
|
14
14
|
const {
|
|
15
|
+
canAutoUploadEnvKey,
|
|
15
16
|
declaredSecrets,
|
|
17
|
+
isPublicEnvKey,
|
|
18
|
+
isReservedAutoEnvKey,
|
|
19
|
+
loadLocalEnvDetails,
|
|
16
20
|
loadLocalEnv,
|
|
17
21
|
parseDotEnv,
|
|
18
|
-
readDotEnvFile,
|
|
19
22
|
redactValue,
|
|
20
23
|
} = require("../secrets")
|
|
21
24
|
|
|
@@ -138,12 +141,12 @@ function printPreflightFailure(payload, fallbackOutput) {
|
|
|
138
141
|
console.error("[pltt] Need machine-readable details? Run `pltt test --json`.")
|
|
139
142
|
}
|
|
140
143
|
|
|
141
|
-
function runPreflight(cwd, json, publishType = "release") {
|
|
144
|
+
function runPreflight(cwd, json, publishType = "release", environment) {
|
|
142
145
|
const cliBin = path.resolve(__dirname, "..", "..", "bin", "pltt.js")
|
|
143
146
|
const res = spawnSync(process.execPath, [cliBin, "test", "--json", "--publish-type", publishType], {
|
|
144
147
|
cwd,
|
|
145
148
|
encoding: "utf8",
|
|
146
|
-
env: process.env,
|
|
149
|
+
env: environment ? { ...process.env, PALETTE_ENV: environment } : process.env,
|
|
147
150
|
})
|
|
148
151
|
|
|
149
152
|
if (res.status === 0) {
|
|
@@ -218,7 +221,18 @@ async function put(url, buf, contentType) {
|
|
|
218
221
|
}
|
|
219
222
|
}
|
|
220
223
|
|
|
221
|
-
function
|
|
224
|
+
function scopesOf(spec) {
|
|
225
|
+
if (!spec || typeof spec !== "object" || Array.isArray(spec)) return ["dev"]
|
|
226
|
+
if (Array.isArray(spec.scope)) return spec.scope
|
|
227
|
+
if (typeof spec.scope === "string") return [spec.scope]
|
|
228
|
+
return ["dev"]
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function cloneManifest(manifest) {
|
|
232
|
+
return JSON.parse(JSON.stringify(manifest))
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function collectPluginSecrets(cwd, manifest, env, flags, log, localEnv) {
|
|
222
236
|
const declared = declaredSecrets(manifest)
|
|
223
237
|
const pluginSecrets = Object.entries(declared).filter(([, spec]) => spec.scope.includes("plugin"))
|
|
224
238
|
const devRequired = Object.entries(declared).filter(([, spec]) => spec.scope.includes("dev") && spec.required)
|
|
@@ -232,7 +246,8 @@ function collectPluginSecrets(cwd, manifest, env, flags, log) {
|
|
|
232
246
|
if (flags.secretsFile) {
|
|
233
247
|
fileValues = parseDotEnv(fs.readFileSync(path.resolve(cwd, flags.secretsFile), "utf8"))
|
|
234
248
|
}
|
|
235
|
-
const localValues =
|
|
249
|
+
const localValues = localEnv?.values || loadLocalEnv(cwd, { apply: false, environment: env.name })
|
|
250
|
+
const candidateValues = { ...localValues, ...fileValues }
|
|
236
251
|
const values = {}
|
|
237
252
|
const missing = []
|
|
238
253
|
for (const [name, spec] of pluginSecrets) {
|
|
@@ -249,10 +264,61 @@ function collectPluginSecrets(cwd, manifest, env, flags, log) {
|
|
|
249
264
|
`Set env vars, pass --secrets-file, or run pltt secrets set <NAME> --env ${env.name}.`,
|
|
250
265
|
)
|
|
251
266
|
}
|
|
267
|
+
const effectiveManifest = cloneManifest(manifest)
|
|
268
|
+
effectiveManifest.secrets =
|
|
269
|
+
effectiveManifest.secrets && typeof effectiveManifest.secrets === "object" && !Array.isArray(effectiveManifest.secrets)
|
|
270
|
+
? { ...effectiveManifest.secrets }
|
|
271
|
+
: {}
|
|
272
|
+
const autoUploaded = []
|
|
273
|
+
const publicBundled = []
|
|
274
|
+
const skippedReserved = []
|
|
275
|
+
const skippedInvalid = []
|
|
276
|
+
for (const [name, value] of Object.entries(candidateValues)) {
|
|
277
|
+
if (!value) continue
|
|
278
|
+
if (isPublicEnvKey(name)) {
|
|
279
|
+
publicBundled.push(name)
|
|
280
|
+
continue
|
|
281
|
+
}
|
|
282
|
+
const explicitSpec = effectiveManifest.secrets[name]
|
|
283
|
+
if (explicitSpec) {
|
|
284
|
+
if (scopesOf(explicitSpec).includes("plugin")) values[name] = fileValues[name] ?? process.env[name] ?? localValues[name]
|
|
285
|
+
continue
|
|
286
|
+
}
|
|
287
|
+
if (isReservedAutoEnvKey(name)) {
|
|
288
|
+
skippedReserved.push(name)
|
|
289
|
+
continue
|
|
290
|
+
}
|
|
291
|
+
if (!canAutoUploadEnvKey(name)) {
|
|
292
|
+
skippedInvalid.push(name)
|
|
293
|
+
continue
|
|
294
|
+
}
|
|
295
|
+
effectiveManifest.secrets[name] = {
|
|
296
|
+
scope: "plugin",
|
|
297
|
+
required: false,
|
|
298
|
+
help: "Auto-uploaded from local .env by Palette CLI.",
|
|
299
|
+
}
|
|
300
|
+
values[name] = fileValues[name] ?? process.env[name] ?? localValues[name]
|
|
301
|
+
autoUploaded.push(name)
|
|
302
|
+
}
|
|
303
|
+
if (localEnv?.files?.length) {
|
|
304
|
+
log(`[pltt] env files: ${localEnv.files.join(", ")}`)
|
|
305
|
+
}
|
|
306
|
+
if (autoUploaded.length) {
|
|
307
|
+
log(`[pltt] auto plugin secrets from .env: ${autoUploaded.sort().join(", ")}`)
|
|
308
|
+
}
|
|
309
|
+
if (publicBundled.length) {
|
|
310
|
+
log(`[pltt] public env bundled in frontend: ${Array.from(new Set(publicBundled)).sort().join(", ")}`)
|
|
311
|
+
}
|
|
312
|
+
if (skippedReserved.length) {
|
|
313
|
+
log(`[pltt] skipped reserved env keys: ${Array.from(new Set(skippedReserved)).sort().join(", ")}`)
|
|
314
|
+
}
|
|
315
|
+
if (skippedInvalid.length) {
|
|
316
|
+
log(`[pltt] skipped invalid env keys: ${Array.from(new Set(skippedInvalid)).sort().join(", ")}`)
|
|
317
|
+
}
|
|
252
318
|
for (const [name, value] of Object.entries(values)) {
|
|
253
319
|
log(`[pltt] plugin secret ${name}=${redactValue(value)} (${env.name})`)
|
|
254
320
|
}
|
|
255
|
-
return values
|
|
321
|
+
return { manifest: effectiveManifest, pluginSecrets: values }
|
|
256
322
|
}
|
|
257
323
|
|
|
258
324
|
async function run(argv, { cwd }) {
|
|
@@ -288,7 +354,7 @@ async function run(argv, { cwd }) {
|
|
|
288
354
|
|
|
289
355
|
const manifest = loadManifest(cwd)
|
|
290
356
|
const publishType = parsePublishType(argv)
|
|
291
|
-
|
|
357
|
+
const localEnv = loadLocalEnvDetails(cwd, { environment: env.name })
|
|
292
358
|
const errors = validateManifest(manifest)
|
|
293
359
|
if (errors.length) {
|
|
294
360
|
console.error("[pltt] manifest invalid:")
|
|
@@ -296,7 +362,23 @@ async function run(argv, { cwd }) {
|
|
|
296
362
|
process.exit(1)
|
|
297
363
|
}
|
|
298
364
|
|
|
299
|
-
runPreflight(cwd, flags.json, publishType)
|
|
365
|
+
runPreflight(cwd, flags.json, publishType, env.name)
|
|
366
|
+
let pluginSecrets = {}
|
|
367
|
+
let publishManifest = manifest
|
|
368
|
+
try {
|
|
369
|
+
const collected = collectPluginSecrets(cwd, manifest, env, flags, log, localEnv)
|
|
370
|
+
pluginSecrets = collected.pluginSecrets
|
|
371
|
+
publishManifest = collected.manifest
|
|
372
|
+
} catch (err) {
|
|
373
|
+
console.error(`[pltt] ${err instanceof Error ? err.message : String(err)}`)
|
|
374
|
+
process.exit(1)
|
|
375
|
+
}
|
|
376
|
+
const effectiveErrors = validateManifest(publishManifest)
|
|
377
|
+
if (effectiveErrors.length) {
|
|
378
|
+
console.error("[pltt] generated manifest invalid:")
|
|
379
|
+
for (const e of effectiveErrors) console.error(` - ${e}`)
|
|
380
|
+
process.exit(1)
|
|
381
|
+
}
|
|
300
382
|
|
|
301
383
|
log(
|
|
302
384
|
`[pltt] publishing ${manifest.id}@${manifest.version} → ${env.name} (${env.url})`,
|
|
@@ -305,25 +387,21 @@ async function run(argv, { cwd }) {
|
|
|
305
387
|
let frontend = null
|
|
306
388
|
if (manifest.frontend?.entry) {
|
|
307
389
|
log("[pltt] bundling frontend")
|
|
308
|
-
frontend = await bundleFrontend(cwd, manifest.frontend.entry,
|
|
390
|
+
frontend = await bundleFrontend(cwd, manifest.frontend.entry, {
|
|
391
|
+
...manifest.frontend,
|
|
392
|
+
pluginId: manifest.id,
|
|
393
|
+
})
|
|
309
394
|
log(`[pltt] ${frontend.length} bytes`)
|
|
310
395
|
} else {
|
|
311
396
|
log("[pltt] no frontend declared")
|
|
312
397
|
}
|
|
313
398
|
|
|
314
399
|
log("[pltt] bundling backend")
|
|
315
|
-
const backend = await bundleBackend(cwd)
|
|
400
|
+
const backend = await bundleBackend(cwd, { manifest: publishManifest })
|
|
316
401
|
log(`[pltt] ${backend.length} bytes`)
|
|
317
402
|
|
|
318
403
|
const backendSha = sha256(backend)
|
|
319
404
|
const api = makeApi(env)
|
|
320
|
-
let pluginSecrets = {}
|
|
321
|
-
try {
|
|
322
|
-
pluginSecrets = collectPluginSecrets(cwd, manifest, env, flags, log)
|
|
323
|
-
} catch (err) {
|
|
324
|
-
console.error(`[pltt] ${err instanceof Error ? err.message : String(err)}`)
|
|
325
|
-
process.exit(1)
|
|
326
|
-
}
|
|
327
405
|
|
|
328
406
|
log("[pltt] requesting signed URLs")
|
|
329
407
|
const signed = await api("/api/v1/appstore/sign-upload", {
|
|
@@ -341,7 +419,7 @@ async function run(argv, { cwd }) {
|
|
|
341
419
|
put(signed.backend_upload_url, backend, "application/gzip"),
|
|
342
420
|
put(
|
|
343
421
|
signed.manifest_upload_url,
|
|
344
|
-
Buffer.from(JSON.stringify(
|
|
422
|
+
Buffer.from(JSON.stringify(publishManifest, null, 2)),
|
|
345
423
|
"application/json",
|
|
346
424
|
),
|
|
347
425
|
]
|
|
@@ -356,7 +434,7 @@ async function run(argv, { cwd }) {
|
|
|
356
434
|
version: manifest.version,
|
|
357
435
|
bundle_path: signed.bundle_path,
|
|
358
436
|
bundle_sha256: backendSha,
|
|
359
|
-
manifest,
|
|
437
|
+
manifest: publishManifest,
|
|
360
438
|
publish_type: publishType,
|
|
361
439
|
environment: env.name,
|
|
362
440
|
}
|