@magicpixelart/cli 0.5.35 → 0.5.36

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/CHANGELOG.md CHANGED
@@ -5,6 +5,11 @@ All notable changes to `@magicpixelart/cli` will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
+ ## [0.5.36] - 2026-10-07
9
+
10
+ ### Changed
11
+ - `push --force` no longer replaces files whose newer copy was saved in the MagicPixel editor; they are listed as "edited in MagicPixel — skipped". Add `--overwrite-editor-changes` to replace them too.
12
+
8
13
  ## [0.5.35] - 2026-10-07
9
14
 
10
15
  ### Changed
package/README.md CHANGED
@@ -150,6 +150,10 @@ npx @magicpixelart/cli sync --watch --only Runtime/Sprites/Entities/decorations
150
150
 
151
151
  Only that folder is pushed, pulled, or pruned. Every other file stays exactly as it is. Repeat `--only` for more folders, or set `"syncOnly"` in `magicpixel.json`. Changing the folder list triggers one full check. `sync <folder>` without `--only` stops with an error instead of syncing everything.
152
152
 
153
+ ## Forced pushes and editor edits
154
+
155
+ `push --force` keeps your local copy when a sprite changed on both sides, except for files last saved in the MagicPixel editor: those are skipped and listed, so a forced push never silently undoes editor work. Add `--overwrite-editor-changes` to replace them as well.
156
+
153
157
  ## Keep a folder out of MagicPixel
154
158
 
155
159
  To leave game files on disk but out of your library, add them to `exclude` in `magicpixel.json`:
@@ -255,7 +255,7 @@ export async function runPushWith(config, state, opts = {}) {
255
255
  // without a live sha, and the retry as an update is what makes the server
256
256
  // composite the artboard and report one.
257
257
  for (let round = 0; round < 2; round++) {
258
- const retry = forcedRetrySprites(results, spriteByKey, opts.flatten === true);
258
+ const retry = forcedRetrySprites(results, spriteByKey, opts.flatten === true, opts.overwriteEditorChanges === true);
259
259
  if (retry.length === 0)
260
260
  break;
261
261
  const retryResults = await pushSpritesAdaptive(retry);
@@ -300,7 +300,7 @@ export async function runPushWith(config, state, opts = {}) {
300
300
  for (const r of results) {
301
301
  if (r.status === 'conflict') {
302
302
  if (printedIssues++ < 10)
303
- console.log(` ${kleur.yellow('!')} ${r.key}: ${conflictHint(r.reason)}`);
303
+ console.log(` ${kleur.yellow('!')} ${r.key}: ${opts.force && r.lastWriteSource === 'editor' && !opts.overwriteEditorChanges ? `edited in MagicPixel — skipped. Add --overwrite-editor-changes to replace it.` : conflictHint(r.reason)}`);
304
304
  }
305
305
  else if (r.status === 'error') {
306
306
  if (printedIssues++ < 10)
@@ -344,11 +344,14 @@ export function collectKeptAssetIds(candidates, synced, results) {
344
344
  * reported. Not a bypass — the server still compares, so a save that lands in
345
345
  * between refuses again.
346
346
  */
347
- export function forcedRetrySprites(results, spriteByKey, flatten) {
347
+ export function forcedRetrySprites(results, spriteByKey, flatten, overwriteEditorChanges = false) {
348
348
  const out = [];
349
349
  for (const r of results) {
350
350
  if (r.status !== 'conflict' || r.reason !== 'cloud-changed' || !r.assetId)
351
351
  continue;
352
+ // A newer save made in the MagicPixel editor is never silently undone.
353
+ if (r.lastWriteSource === 'editor' && !overwriteEditorChanges)
354
+ continue;
352
355
  const original = spriteByKey.get(r.key);
353
356
  if (!original)
354
357
  continue;
package/dist/index.js CHANGED
@@ -108,7 +108,8 @@ program
108
108
  .description('Upload local sprite edits back to MagicPixel (two-way sync)')
109
109
  .option('--dry-run', 'Print what would be pushed without sending anything')
110
110
  .option('--flatten', 'Allow replacing multi-layer artboards with the flat local image')
111
- .option('--force', 'Keep your local copy when a sprite also changed in MagicPixel')
111
+ .option('--force', 'Keep your local copy when a sprite also changed in MagicPixel (skips files saved in the MagicPixel editor)')
112
+ .option('--overwrite-editor-changes', 'With --force: also replace files saved in the MagicPixel editor')
112
113
  .addHelpText('after', '\nExamples:\n $ magicpixel push --dry-run # see what changed on disk\n $ magicpixel push # send local edits + new sprites\n $ magicpixel push --force # your local copy wins on both-sides-changed\n')
113
114
  .action(wrap("push", async (opts) => pushCommand(opts)));
114
115
  program
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magicpixelart/cli",
3
- "version": "0.5.35",
3
+ "version": "0.5.36",
4
4
  "description": "Sync MagicPixel pixel-art assets to your local project.",
5
5
  "type": "module",
6
6
  "bin": {