@palettelab/cli 0.3.47 → 0.3.48

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 CHANGED
@@ -678,9 +678,10 @@ Run local contract checks before publishing.
678
678
  ```bash
679
679
  pltt test
680
680
  pltt test --json
681
+ pltt test --publish-type preview
681
682
  ```
682
683
 
683
- Checks include manifest validity, SDK/platform compatibility, semver bump detection, forbidden platform imports, frontend bundling and size limits, sandbox bridge smoke, backend dependency installation/import, route permission gates, route permission declarations, migration linting, frontend sandbox policy, and dependency policy for `package.json` / `pyproject.toml`. The default frontend and backend bundle limits are 15 MiB; set `PALETTE_MAX_FRONTEND_BUNDLE_BYTES` or `PALETTE_MAX_BACKEND_BUNDLE_BYTES` for reviewed exceptions.
684
+ Checks include manifest validity, SDK/platform compatibility, release semver bump detection, forbidden platform imports, frontend bundling and size limits, sandbox bridge smoke, backend dependency installation/import, route permission gates, route permission declarations, migration linting, frontend sandbox policy, and dependency policy for `package.json` / `pyproject.toml`. The semver bump check is skipped for `--publish-type preview` because hosted previews may reuse the current app version. The default frontend and backend bundle limits are 15 MiB; set `PALETTE_MAX_FRONTEND_BUNDLE_BYTES` or `PALETTE_MAX_BACKEND_BUNDLE_BYTES` for reviewed exceptions.
684
685
 
685
686
  ### `pltt package`
686
687
 
@@ -706,7 +707,7 @@ pltt publish --env staging --json
706
707
  pltt publish --env staging --ttl-hours 24
707
708
  ```
708
709
 
709
- Publishing first runs the same contract checks as `pltt test`. If preflight passes, it bundles frontend/backend artifacts, uploads them, creates a `pending_review` publish record, and prints review/preview URLs when the platform returns them.
710
+ Publishing first runs the same contract checks as `pltt test`. Preview publishes skip the release semver bump check, while release publishes still require a version newer than the last release. If preflight passes, it bundles frontend/backend artifacts, uploads them, creates a review record, and prints review/preview URLs when the platform returns them.
710
711
 
711
712
  `--ttl-hours` sets an expiration on the preview URL. It is mainly used by `pltt dev --sandbox`, which defaults previews to 24 hours.
712
713
 
@@ -138,9 +138,9 @@ function printPreflightFailure(payload, fallbackOutput) {
138
138
  console.error("[pltt] Need machine-readable details? Run `pltt test --json`.")
139
139
  }
140
140
 
141
- function runPreflight(cwd, json) {
141
+ function runPreflight(cwd, json, publishType = "release") {
142
142
  const cliBin = path.resolve(__dirname, "..", "..", "bin", "pltt.js")
143
- const res = spawnSync(process.execPath, [cliBin, "test", "--json"], {
143
+ const res = spawnSync(process.execPath, [cliBin, "test", "--json", "--publish-type", publishType], {
144
144
  cwd,
145
145
  encoding: "utf8",
146
146
  env: process.env,
@@ -296,7 +296,7 @@ async function run(argv, { cwd }) {
296
296
  process.exit(1)
297
297
  }
298
298
 
299
- runPreflight(cwd, flags.json)
299
+ runPreflight(cwd, flags.json, publishType)
300
300
 
301
301
  log(
302
302
  `[pltt] publishing ${manifest.id}@${manifest.version} → ${env.name} (${env.url})`,
@@ -368,28 +368,28 @@ async function run(argv, { cwd }) {
368
368
  method: "POST",
369
369
  body: publishBody,
370
370
  })
371
+ const lastPublish = {
372
+ id: record.id,
373
+ plugin_id: record.plugin_id,
374
+ version: record.version,
375
+ env: env.name,
376
+ url: env.url,
377
+ publish_type: record.publish_type || publishType,
378
+ preview_url: record.preview_url,
379
+ preview_expires_at: record.preview_expires_at,
380
+ published_at: new Date().toISOString(),
381
+ }
371
382
 
372
383
  try {
373
384
  const dir = path.join(cwd, ".palette")
374
385
  fs.mkdirSync(dir, { recursive: true })
375
386
  fs.writeFileSync(
376
387
  path.join(dir, "last-publish.json"),
377
- JSON.stringify(
378
- {
379
- id: record.id,
380
- plugin_id: record.plugin_id,
381
- version: record.version,
382
- env: env.name,
383
- url: env.url,
384
- publish_type: record.publish_type || publishType,
385
- preview_url: record.preview_url,
386
- preview_expires_at: record.preview_expires_at,
387
- published_at: new Date().toISOString(),
388
- },
389
- null,
390
- 2,
391
- ),
388
+ JSON.stringify(lastPublish, null, 2),
392
389
  )
390
+ if ((record.publish_type || publishType) === "release") {
391
+ fs.writeFileSync(path.join(dir, "last-release.json"), JSON.stringify(lastPublish, null, 2))
392
+ }
393
393
  } catch (err) {
394
394
  // best-effort
395
395
  }
@@ -554,17 +554,51 @@ function scanForbiddenImports(cwd, manifest, out) {
554
554
  return issues.length
555
555
  }
556
556
 
557
- function checkSemverBump(cwd, manifest, out) {
558
- const statePath = path.join(cwd, ".palette", "last-publish.json")
557
+ function parsePublishType(argv) {
558
+ for (let i = 0; i < argv.length; i += 1) {
559
+ const arg = argv[i]
560
+ if (arg === "--preview") return "preview"
561
+ if (arg === "--release") return "release"
562
+ if (arg === "--publish-type") return argv[i + 1] === "preview" ? "preview" : "release"
563
+ if (arg.startsWith("--publish-type=")) {
564
+ return arg.slice("--publish-type=".length) === "preview" ? "preview" : "release"
565
+ }
566
+ }
567
+ return "release"
568
+ }
569
+
570
+ function readPublishState(statePath) {
559
571
  if (!fs.existsSync(statePath)) {
560
- out.ok("semver bump check skipped; no previous publish state")
561
- return 0
572
+ return { state: null, invalid: false }
562
573
  }
563
- let previous
564
574
  try {
565
- previous = JSON.parse(fs.readFileSync(statePath, "utf8"))
575
+ return { state: JSON.parse(fs.readFileSync(statePath, "utf8")), invalid: false }
566
576
  } catch (_err) {
567
- out.warn("semver bump check skipped; .palette/last-publish.json is invalid JSON")
577
+ return { state: null, invalid: true }
578
+ }
579
+ }
580
+
581
+ function checkSemverBump(cwd, manifest, out, publishType = "release") {
582
+ if (publishType === "preview") {
583
+ out.ok("semver bump check skipped for preview publish")
584
+ return 0
585
+ }
586
+
587
+ const releaseStatePath = path.join(cwd, ".palette", "last-release.json")
588
+ const publishStatePath = path.join(cwd, ".palette", "last-publish.json")
589
+ let { state: previous, invalid } = readPublishState(releaseStatePath)
590
+ if (!previous && !invalid) {
591
+ const lastPublish = readPublishState(publishStatePath)
592
+ invalid = lastPublish.invalid
593
+ if (lastPublish.state?.publish_type !== "preview") previous = lastPublish.state
594
+ }
595
+
596
+ if (!previous && !invalid) {
597
+ out.ok("semver bump check skipped; no previous release state")
598
+ return 0
599
+ }
600
+ if (invalid) {
601
+ out.warn("semver bump check skipped; previous publish state is invalid JSON")
568
602
  return 0
569
603
  }
570
604
  const previousVersion = previous.version || previous.manifest?.version
@@ -574,7 +608,7 @@ function checkSemverBump(cwd, manifest, out) {
574
608
  }
575
609
  if (compareVersions(manifest.version, previousVersion) <= 0) {
576
610
  return out.fail(
577
- `plugin version ${manifest.version} is not newer than last publish ${previousVersion}`,
611
+ `plugin version ${manifest.version} is not newer than last release ${previousVersion}`,
578
612
  "Bump manifest.version before publishing another build.",
579
613
  { current: manifest.version, previous: previousVersion },
580
614
  )
@@ -683,6 +717,7 @@ function checkFrontendSecretLeaks(cwd, frontendBuffer, manifest, out) {
683
717
 
684
718
  async function run(args, { cwd }) {
685
719
  const json = args.includes("--json")
720
+ const publishType = parsePublishType(args)
686
721
  let failures = 0
687
722
  const results = []
688
723
  const out = reporter(json, results)
@@ -709,7 +744,7 @@ async function run(args, { cwd }) {
709
744
 
710
745
  failures += checkSdkCompatibility(cwd, manifest, out)
711
746
  failures += scanForbiddenImports(cwd, manifest, out)
712
- failures += checkSemverBump(cwd, manifest, out)
747
+ failures += checkSemverBump(cwd, manifest, out, publishType)
713
748
  failures += checkDeclaredSecrets(cwd, manifest, out)
714
749
 
715
750
  for (const permission of manifest.permissions || []) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@palettelab/cli",
3
- "version": "0.3.47",
3
+ "version": "0.3.48",
4
4
  "description": "Developer CLI for building Palette platform plugins — no platform source access required.",
5
5
  "bin": {
6
6
  "pltt": "bin/pltt.js"