sitevision-cli 1.0.0-beta.24 → 1.0.0-beta.25
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/dist/shell/CommandPalette.js +1 -1
- package/dist/shell/actions.d.ts +1 -0
- package/dist/shell/actions.js +0 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/utils/i18n.js +4 -0
- package/dist/utils/sitevision-api.d.ts +8 -0
- package/dist/utils/sitevision-api.js +25 -4
- package/dist/utils/tasks.d.ts +2 -0
- package/dist/utils/tasks.js +23 -4
- package/package.json +1 -1
|
@@ -12,7 +12,7 @@ const GROUPS = [
|
|
|
12
12
|
export function CommandPalette({ project, onRun, onClose, height, }) {
|
|
13
13
|
const [query, setQuery] = useState('');
|
|
14
14
|
const [index, setIndex] = useState(0);
|
|
15
|
-
const matches = actions.filter(a => fuzzyMatch(query, t(a.label)));
|
|
15
|
+
const matches = actions.filter(a => !a.hidden?.(project) && fuzzyMatch(query, t(a.label)));
|
|
16
16
|
const ordered = GROUPS.flatMap(g => matches.filter(a => a.group === g.id));
|
|
17
17
|
useInput((input, key) => {
|
|
18
18
|
if (key.escape) {
|
package/dist/shell/actions.d.ts
CHANGED
|
@@ -30,6 +30,7 @@ export interface Action {
|
|
|
30
30
|
label: string;
|
|
31
31
|
detail?: (project: ProjectInfo) => string | undefined;
|
|
32
32
|
enabled?: (project: ProjectInfo) => boolean;
|
|
33
|
+
hidden?: (project: ProjectInfo) => boolean;
|
|
33
34
|
run: (ctx: ActionContext) => Promise<void>;
|
|
34
35
|
}
|
|
35
36
|
export declare function forgetSession(project: ProjectInfo): void;
|
package/dist/shell/actions.js
CHANGED
|
Binary file
|
package/dist/types/index.d.ts
CHANGED
package/dist/utils/i18n.js
CHANGED
|
@@ -94,6 +94,10 @@ const sv = {
|
|
|
94
94
|
'to {env}': 'till {env}',
|
|
95
95
|
'Switch environment': 'Byt miljö',
|
|
96
96
|
'Add environment': 'Lägg till miljö',
|
|
97
|
+
'Create addon': 'Skapa tillägg',
|
|
98
|
+
'Create addon failed': 'Kunde inte skapa tillägget',
|
|
99
|
+
'addon {addon} created': 'tillägget {addon} skapat',
|
|
100
|
+
'Addon {addon} does not exist on {domain}. Create it and deploy again?': 'Tillägget {addon} finns inte på {domain}. Skapa det och driftsätt igen?',
|
|
97
101
|
'e.g. test or prod, overriding domain and auth': 't.ex. test eller prod, med egen domän och auth',
|
|
98
102
|
'Environment name (e.g. test, prod)': 'Miljönamn (t.ex. test, prod)',
|
|
99
103
|
'Deploy the signed {id} to {env} and activate it?': 'Driftsätt signerade {id} till {env} och aktivera?',
|
|
@@ -144,4 +144,12 @@ export declare function listAddons(config: DeployConfig): Promise<{
|
|
|
144
144
|
addons?: AddonNode[];
|
|
145
145
|
error?: string;
|
|
146
146
|
}>;
|
|
147
|
+
/**
|
|
148
|
+
* Whether an addon exists, judged from a listAddons result. A failed or empty
|
|
149
|
+
* listing is "unknown": a dead session can look exactly like an empty site.
|
|
150
|
+
*/
|
|
151
|
+
export declare function classifyAddon(listed: {
|
|
152
|
+
success: boolean;
|
|
153
|
+
addons?: AddonNode[];
|
|
154
|
+
}, name: string): 'missing' | 'present' | 'unknown';
|
|
147
155
|
export { createBasicAuth, configAuth, unauthorizedMessage };
|
|
@@ -391,6 +391,14 @@ export async function deployApp(zipPath, config, appType, force = false) {
|
|
|
391
391
|
error: 'Conflict. Addon already exists. Use --force to overwrite.',
|
|
392
392
|
};
|
|
393
393
|
}
|
|
394
|
+
if (response.statusCode === 400 &&
|
|
395
|
+
response.body.toString().includes('could not resolve context node')) {
|
|
396
|
+
return {
|
|
397
|
+
success: false,
|
|
398
|
+
error: `Deployment failed with status 400: ${summarizeErrorBody(response.body, response.headers)}`,
|
|
399
|
+
contextNodeMissing: true,
|
|
400
|
+
};
|
|
401
|
+
}
|
|
394
402
|
return {
|
|
395
403
|
success: false,
|
|
396
404
|
error: `Deployment failed with status ${response.statusCode}: ${summarizeErrorBody(response.body, response.headers)}`,
|
|
@@ -445,10 +453,11 @@ export async function deployProduction(signedZipPath, config, appType) {
|
|
|
445
453
|
*/
|
|
446
454
|
export async function createAddon(config, appType) {
|
|
447
455
|
const url = buildAddonEndpointUrl(config.domain, config.siteName, appType, config.useHTTP);
|
|
448
|
-
const
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
456
|
+
const payload = { name: config.addonName };
|
|
457
|
+
// Only the custommodule endpoints take (and require) a category.
|
|
458
|
+
if (appType === 'web' || appType === 'widget')
|
|
459
|
+
payload['category'] = 'Other';
|
|
460
|
+
const body = JSON.stringify(payload);
|
|
452
461
|
const { auth, kind } = configAuth(config);
|
|
453
462
|
try {
|
|
454
463
|
const response = await makeRequest(url, {
|
|
@@ -617,6 +626,18 @@ export async function listAddons(config) {
|
|
|
617
626
|
};
|
|
618
627
|
}
|
|
619
628
|
}
|
|
629
|
+
/**
|
|
630
|
+
* Whether an addon exists, judged from a listAddons result. A failed or empty
|
|
631
|
+
* listing is "unknown": a dead session can look exactly like an empty site.
|
|
632
|
+
*/
|
|
633
|
+
export function classifyAddon(listed, name) {
|
|
634
|
+
if (!listed.success || !listed.addons?.length)
|
|
635
|
+
return 'unknown';
|
|
636
|
+
const wanted = name.toLowerCase();
|
|
637
|
+
return listed.addons.some(addon => addon.name.toLowerCase() === wanted)
|
|
638
|
+
? 'present'
|
|
639
|
+
: 'missing';
|
|
640
|
+
}
|
|
620
641
|
// =============================================================================
|
|
621
642
|
// HELPER EXPORTS
|
|
622
643
|
// =============================================================================
|
package/dist/utils/tasks.d.ts
CHANGED
|
@@ -30,6 +30,7 @@ export interface DeployOptions {
|
|
|
30
30
|
force?: boolean;
|
|
31
31
|
production?: boolean;
|
|
32
32
|
activate?: boolean;
|
|
33
|
+
onAddonMissing?: (addonName: string) => Promise<boolean>;
|
|
33
34
|
}
|
|
34
35
|
export declare function startBuild(project: ProjectInfo): Task;
|
|
35
36
|
export declare function startSign(project: ProjectInfo, credentials: SigningCredentials): Task;
|
|
@@ -40,6 +41,7 @@ export interface DevOptions {
|
|
|
40
41
|
deploy: boolean;
|
|
41
42
|
signingCredentials?: SigningCredentials;
|
|
42
43
|
deployConfig?: DeployConfig;
|
|
44
|
+
onAddonMissing?: DeployOptions['onAddonMissing'];
|
|
43
45
|
}
|
|
44
46
|
/**
|
|
45
47
|
* Dev / watch loop: build on every source change, then optionally sign and
|
package/dist/utils/tasks.js
CHANGED
|
@@ -6,7 +6,7 @@ import { WebpackRunner, hasLocalWebpackConfig } from './webpack-runner.js';
|
|
|
6
6
|
import { hasSitevisionScripts, runSitevisionScriptsBuild, getDelegatedZipPath, checkSitevisionScriptsCompatibility, } from './sitevision-scripts-runner.js';
|
|
7
7
|
import { copyStaticToBuild, copySrcToBuild, cleanBuild, createBuildZip, zipExists, } from './zip.js';
|
|
8
8
|
import { isBundledApp, getAppType, getFullAppId, getZipPath, getSignedZipPath, getDeployZipPath, localizedText, } from './project-detection.js';
|
|
9
|
-
import { signApp, deployApp, deployProduction, activateApp, } from './sitevision-api.js';
|
|
9
|
+
import { signApp, deployApp, deployProduction, activateApp, createAddon, listAddons, classifyAddon, } from './sitevision-api.js';
|
|
10
10
|
import { ProcessRunner } from './process-runner.js';
|
|
11
11
|
const MAX_LINES = 2000;
|
|
12
12
|
const emitter = new EventEmitter();
|
|
@@ -149,9 +149,27 @@ async function deployOnce(project, task, log, zipPath, config, options) {
|
|
|
149
149
|
setPhase(task, 'deploying');
|
|
150
150
|
const appType = getAppType(project.manifest);
|
|
151
151
|
log('dep', `POST multipart → ${options.production ? 'production' : 'dev'} import · ${config.addonName} · ${path.basename(zipPath)}`);
|
|
152
|
-
const
|
|
153
|
-
?
|
|
154
|
-
:
|
|
152
|
+
const upload = async () => options.production
|
|
153
|
+
? deployProduction(zipPath, { ...config, activate: options.activate }, appType)
|
|
154
|
+
: deployApp(zipPath, config, appType, options.force);
|
|
155
|
+
let result = await upload();
|
|
156
|
+
if (!result.success && result.contextNodeMissing) {
|
|
157
|
+
const addon = classifyAddon(await listAddons(config), config.addonName);
|
|
158
|
+
if (addon === 'unknown') {
|
|
159
|
+
throw new Error(`${result.error}\nCould not list the site's addons either, so the session may have expired. Press l to log in again.`);
|
|
160
|
+
}
|
|
161
|
+
if (addon === 'missing' && options.onAddonMissing) {
|
|
162
|
+
log('dep', `addon ${config.addonName} does not exist`, 'warn');
|
|
163
|
+
if (await options.onAddonMissing(config.addonName)) {
|
|
164
|
+
const created = await createAddon(config, appType);
|
|
165
|
+
if (!created.success) {
|
|
166
|
+
throw new Error(created.error ?? 'Create addon failed');
|
|
167
|
+
}
|
|
168
|
+
log('dep', `created addon ${config.addonName}`, 'ok');
|
|
169
|
+
result = await upload();
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
155
173
|
if (!result.success)
|
|
156
174
|
throw new Error(result.error ?? 'Deployment failed');
|
|
157
175
|
log('dep', `${result.message ?? 'deployed'}${result.executableId ? ` · exec ${result.executableId}` : ''}`, 'ok');
|
|
@@ -288,6 +306,7 @@ export function startDev(project, options) {
|
|
|
288
306
|
if (options.deploy && options.deployConfig) {
|
|
289
307
|
await deployOnce(project, task, log, deployZip, options.deployConfig, {
|
|
290
308
|
force: true,
|
|
309
|
+
onAddonMissing: options.onAddonMissing,
|
|
291
310
|
});
|
|
292
311
|
}
|
|
293
312
|
setPhase(task, 'watching');
|