From 03614e50ba00fe2655b8085ebcc2a893096aa6ef Mon Sep 17 00:00:00 2001 From: james-owen Date: Tue, 25 Aug 2026 10:21:43 -0400 Subject: [PATCH] import -p publishes pages and layouts only --- lib/cmd/import.js | 20 ++++++++++++++++++-- lib/cmd/import.test.js | 27 +++++++++++++++++++++++---- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/lib/cmd/import.js b/lib/cmd/import.js index 15a514cc..219507cd 100644 --- a/lib/cmd/import.js +++ b/lib/cmd/import.js @@ -2,6 +2,7 @@ const _ = require('lodash'), h = require('highland'), yaml = require('js-yaml'), + utils = require('clayutils'), split = require('split-lines'), formatting = require('../formatting'), prefixes = require('../prefixes'), @@ -19,6 +20,19 @@ function isURI(url) { return _.includes(url, 'uris/'); } +/** + * Decides which dispatches the publish option publishes directly. + * + * amphora's page publish creates the page's component @published versions itself; a solo + * component publish has no page context (no publishUrl), so it writes draft-shaped published + * data and races the page publish for last write + * @param {string} url + * @return {Boolean} + */ +function isPublishable(url) { + return utils.isPage(url) || utils.isLayout(url); +} + function sendDispatchToClay(dispatch, prefix, key, options) { const rootURI = Object.keys(dispatch)[0], url = prefixes.uriToUrl(prefix, rootURI), @@ -33,9 +47,11 @@ function sendDispatchToClay(dispatch, prefix, key, options) { // user wants to publish something, but isn't importing latest data // so make it for them and add a warning return h(rest.put(url.replace('@published', ''), data, { key }).toPromise(Promise).then((res) => { - return h.of(res).concat(rest.put(url, undefined, { key })).concat(h.of({ type: 'warning', message: 'Generated latest data for @published item', details: url })); + const published = isPublishable(url) ? rest.put(url, undefined, { key }) : h([]); + + return h.of(res).concat(published).concat(h.of({ type: 'warning', message: 'Generated latest data for @published item', details: url })); })).flatten(); - } else if (options.publish) { + } else if (options.publish && isPublishable(url)) { // PUT to latest and then PUT to @published return h(rest.put(url, data, { key }).toPromise(Promise).then((res) => { return h.of(res).concat(rest.put(`${url}@published`, undefined, { key })); diff --git a/lib/cmd/import.test.js b/lib/cmd/import.test.js index f38fb511..9d600c21 100644 --- a/lib/cmd/import.test.js +++ b/lib/cmd/import.test.js @@ -52,10 +52,17 @@ describe('import', () => { }); it('adds warning when importing @published item', () => { - fetch.mockResponseOnce('{}'); fetch.mockResponseOnce('{}'); return lib(h.of(yaml.dump({ _components: { a: { instances: { 'b@published': { c: 'd' }} }} })), url, { yaml: true, publish: true, key, concurrency }).collect().toPromise(Promise).then((res) => { - expect(res).toEqual([{ type: 'success', message: 'http://domain.com/_components/a/instances/b' }, { type: 'success', message: 'http://domain.com/_components/a/instances/b@published' }, { type: 'warning', message: 'Generated latest data for @published item', details: 'http://domain.com/_components/a/instances/b@published' }]); + expect(res).toEqual([{ type: 'success', message: 'http://domain.com/_components/a/instances/b' }, { type: 'warning', message: 'Generated latest data for @published item', details: 'http://domain.com/_components/a/instances/b@published' }]); + }); + }); + + it('publishes @published page dispatches after generating latest', () => { + fetch.mockResponseOnce('{}'); + fetch.mockResponseOnce('{}'); + return lib(h.of(yaml.dump({ _pages: { 'foo@published': { layout: 'domain.com/_layouts/l/instances/a', main: ['domain.com/_components/a/instances/b'] }} })), url, { yaml: true, publish: true, key, concurrency }).collect().toPromise(Promise).then((res) => { + expect(res).toEqual([{ type: 'success', message: 'http://domain.com/_pages/foo' }, { type: 'success', message: 'http://domain.com/_pages/foo@published' }, { type: 'warning', message: 'Generated latest data for @published item', details: 'http://domain.com/_pages/foo@published' }]); }); }); @@ -149,8 +156,20 @@ describe('import', () => { }); }); - it('publishes items', () => { + it('publishes page dispatches', () => { + fetch.mockResponseOnce('{}'); fetch.mockResponseOnce('{}'); + return lib(JSON.stringify({ + '/_pages/foo': { + layout: '/_layouts/layout/instances/default', + main: ['/_components/article/instances/foo'] + } + }), url, { key, concurrency, publish: true }).collect().toPromise(Promise).then((res) => { + expect(res).toEqual([{ type: 'success', message: 'http://domain.com/_pages/foo' }, { type: 'success', message: 'http://domain.com/_pages/foo@published' }]); + }); + }); + + it('does not solo-publish component dispatches', () => { fetch.mockResponseOnce('{}'); return lib(JSON.stringify({ '/_components/article/instances/foo': { @@ -161,7 +180,7 @@ describe('import', () => { }] } }), url, { key, concurrency, publish: true }).collect().toPromise(Promise).then((res) => { - expect(res).toEqual([{ type: 'success', message: 'http://domain.com/_components/article/instances/foo' }, { type: 'success', message: 'http://domain.com/_components/article/instances/foo@published' }]); + expect(res).toEqual([{ type: 'success', message: 'http://domain.com/_components/article/instances/foo' }]); }); });