@extenshi/cli 0.21.0 → 0.22.0
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 +4 -0
- package/dist/amo-source-detect.d.ts +18 -0
- package/dist/amo-source-detect.d.ts.map +1 -0
- package/dist/amo-source-detect.js +41 -0
- package/dist/amo-source-detect.js.map +1 -0
- package/dist/amo-source.d.ts +41 -0
- package/dist/amo-source.d.ts.map +1 -0
- package/dist/amo-source.js +240 -0
- package/dist/amo-source.js.map +1 -0
- package/dist/amowebstore-md.d.ts +38 -0
- package/dist/amowebstore-md.d.ts.map +1 -0
- package/dist/amowebstore-md.js +118 -0
- package/dist/amowebstore-md.js.map +1 -0
- package/dist/auto-evidence.d.ts +100 -0
- package/dist/auto-evidence.d.ts.map +1 -0
- package/dist/auto-evidence.js +197 -0
- package/dist/auto-evidence.js.map +1 -0
- package/dist/cli.js +265 -8
- package/dist/cli.js.map +1 -1
- package/dist/edgewebstore-md.d.ts +26 -0
- package/dist/edgewebstore-md.d.ts.map +1 -0
- package/dist/edgewebstore-md.js +95 -0
- package/dist/edgewebstore-md.js.map +1 -0
- package/dist/evidence-ingest.d.ts +60 -0
- package/dist/evidence-ingest.d.ts.map +1 -0
- package/dist/evidence-ingest.js +141 -0
- package/dist/evidence-ingest.js.map +1 -0
- package/dist/firefox-rdp.d.ts +55 -0
- package/dist/firefox-rdp.d.ts.map +1 -0
- package/dist/firefox-rdp.js +203 -0
- package/dist/firefox-rdp.js.map +1 -0
- package/dist/gecko-id.d.ts +55 -0
- package/dist/gecko-id.d.ts.map +1 -0
- package/dist/gecko-id.js +132 -0
- package/dist/gecko-id.js.map +1 -0
- package/dist/generate-listing.d.ts +19 -8
- package/dist/generate-listing.d.ts.map +1 -1
- package/dist/generate-listing.js +66 -18
- package/dist/generate-listing.js.map +1 -1
- package/dist/icon.d.ts +18 -0
- package/dist/icon.d.ts.map +1 -1
- package/dist/icon.js +29 -20
- package/dist/icon.js.map +1 -1
- package/dist/media.d.ts +42 -0
- package/dist/media.d.ts.map +1 -0
- package/dist/media.js +96 -0
- package/dist/media.js.map +1 -0
- package/dist/package.d.ts +163 -0
- package/dist/package.d.ts.map +1 -0
- package/dist/package.js +500 -0
- package/dist/package.js.map +1 -0
- package/dist/page.d.ts +10 -0
- package/dist/page.d.ts.map +1 -1
- package/dist/page.js +32 -2
- package/dist/page.js.map +1 -1
- package/dist/pay-contract.d.ts +10 -3
- package/dist/pay-contract.d.ts.map +1 -1
- package/dist/pay-contract.js +9 -0
- package/dist/pay-contract.js.map +1 -1
- package/dist/pay-test-cycle.d.ts +40 -0
- package/dist/pay-test-cycle.d.ts.map +1 -0
- package/dist/pay-test-cycle.js +207 -0
- package/dist/pay-test-cycle.js.map +1 -0
- package/dist/pay.d.ts +1 -1
- package/dist/pay.d.ts.map +1 -1
- package/dist/pay.js +1 -0
- package/dist/pay.js.map +1 -1
- package/dist/project.d.ts +39 -1
- package/dist/project.d.ts.map +1 -1
- package/dist/project.js +231 -20
- package/dist/project.js.map +1 -1
- package/dist/publish.d.ts +33 -0
- package/dist/publish.d.ts.map +1 -1
- package/dist/publish.js +113 -2
- package/dist/publish.js.map +1 -1
- package/dist/review-checks.d.ts +13 -0
- package/dist/review-checks.d.ts.map +1 -1
- package/dist/review-checks.js.map +1 -1
- package/dist/review-risk.d.ts +10 -1
- package/dist/review-risk.d.ts.map +1 -1
- package/dist/review-risk.js +1 -0
- package/dist/review-risk.js.map +1 -1
- package/dist/scan.d.ts +3 -2
- package/dist/scan.d.ts.map +1 -1
- package/dist/scan.js +4 -2
- package/dist/scan.js.map +1 -1
- package/dist/screenshots-scenes.d.ts +1383 -0
- package/dist/screenshots-scenes.d.ts.map +1 -0
- package/dist/screenshots-scenes.js +276 -0
- package/dist/screenshots-scenes.js.map +1 -0
- package/dist/screenshots.d.ts +145 -0
- package/dist/screenshots.d.ts.map +1 -0
- package/dist/screenshots.js +557 -0
- package/dist/screenshots.js.map +1 -0
- package/dist/smoke.d.ts +81 -0
- package/dist/smoke.d.ts.map +1 -0
- package/dist/smoke.js +491 -0
- package/dist/smoke.js.map +1 -0
- package/dist/store-assets.d.ts +139 -0
- package/dist/store-assets.d.ts.map +1 -0
- package/dist/store-assets.js +582 -0
- package/dist/store-assets.js.map +1 -0
- package/dist/zip.d.ts +57 -0
- package/dist/zip.d.ts.map +1 -0
- package/dist/zip.js +134 -0
- package/dist/zip.js.map +1 -0
- package/package.json +4 -3
package/dist/package.js
ADDED
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `extenshi package <dir> --browser chrome,edge,firefox` — one reproducible
|
|
3
|
+
* store package per browser from an unpacked build directory.
|
|
4
|
+
*
|
|
5
|
+
* REPRODUCIBLE means byte-identical for the same files on any machine, in any
|
|
6
|
+
* timezone, under any umask: Dojo release readiness binds every piece of
|
|
7
|
+
* evidence (tests, scan, installed smoke) to the package's SHA-256, so a CI
|
|
8
|
+
* build and a local build of one commit must agree to the byte. The archive is
|
|
9
|
+
* written by the SAME writer Dojo uses (`zip.ts`, a byte-identical copy of
|
|
10
|
+
* dojo/src/lib/tools/zip.ts) with the same choices as Dojo's extension archive:
|
|
11
|
+
* - entries sorted by path, manifest.json at the root, no directory entries;
|
|
12
|
+
* - every entry stamped 2000-01-01 00:00:00 (DOS fields carry no timezone, so
|
|
13
|
+
* the constant is built from LOCAL components — see REPRODUCIBLE_MTIME);
|
|
14
|
+
* - STORE (no compression): deflate output depends on the zlib build, which
|
|
15
|
+
* differs between Node releases, and reproducibility across machines is the
|
|
16
|
+
* point. Store uploads accept uncompressed archives;
|
|
17
|
+
* - "version made by" MS-DOS with zero external attributes, so no Unix mode
|
|
18
|
+
* bits, owners or extra fields — nothing machine-specific survives.
|
|
19
|
+
*
|
|
20
|
+
* The user's source directory is never modified. `--fix-war` and `--gecko-id`
|
|
21
|
+
* rewrite manifest.json in the PACKAGED copy only, and every rewrite is listed
|
|
22
|
+
* in the output (`changes`).
|
|
23
|
+
*/
|
|
24
|
+
import { createHash } from 'node:crypto';
|
|
25
|
+
import fs from 'node:fs';
|
|
26
|
+
import path from 'node:path';
|
|
27
|
+
import { hashMetadata } from '@extenshi/contracts';
|
|
28
|
+
import { InvalidInputError } from './expected-error.js';
|
|
29
|
+
import { isPlaceholderGeckoId, isValidGeckoId, PLACEHOLDER_GECKO_ID, projectGeckoId } from './gecko-id.js';
|
|
30
|
+
import { ZipBuilder } from './zip.js';
|
|
31
|
+
export const PACKAGE_BROWSERS = ['chrome', 'edge', 'firefox'];
|
|
32
|
+
/** Written next to the zips; `release prepare`, `test smoke`, `evidence ingest` read it directly. */
|
|
33
|
+
export const PACKAGES_MANIFEST_FILE = 'extenshi-packages.json';
|
|
34
|
+
export const PACKAGES_MANIFEST_SCHEMA_VERSION = 1;
|
|
35
|
+
/**
|
|
36
|
+
* Same stamp as Dojo's extension archive (dojo/src/lib/tools/extension-zip.ts):
|
|
37
|
+
* 2000-01-01 00:00:00 LOCAL. A UTC instant would render as different DOS fields
|
|
38
|
+
* per timezone; local components always render as the same fields. 2000 rather
|
|
39
|
+
* than the DOS epoch because local midnight 1980-01-01 in a positive-offset zone
|
|
40
|
+
* falls below the earliest representable date.
|
|
41
|
+
*
|
|
42
|
+
* Built per archive rather than once at module load: the writer renders it with
|
|
43
|
+
* the CURRENT zone, so a value captured under another TZ (a test, a process that
|
|
44
|
+
* changes process.env.TZ) would no longer be local midnight — and no longer the
|
|
45
|
+
* same bytes.
|
|
46
|
+
*/
|
|
47
|
+
const reproducibleMtime = () => new Date(2000, 0, 1, 0, 0, 0, 0);
|
|
48
|
+
/** Classic ZIP (no ZIP64) limits. */
|
|
49
|
+
const MAX_ENTRIES = 0xffff;
|
|
50
|
+
const MAX_TOTAL_BYTES = 1024 * 1024 * 1024;
|
|
51
|
+
/** Never part of a store package, whatever the build directory holds. */
|
|
52
|
+
const ALWAYS_SKIPPED_DIRS = new Set(['node_modules']);
|
|
53
|
+
// ── Globs ───────────────────────────────────────────────────────────────────
|
|
54
|
+
const escapeRe = (s) => s.replace(/[.+^${}()|[\]\\]/g, '\\$&');
|
|
55
|
+
/**
|
|
56
|
+
* `--exclude` pattern → matcher, gitignore-style: `*` stays inside one path
|
|
57
|
+
* segment, `**` crosses segments, a pattern without `/` matches a basename at any
|
|
58
|
+
* depth, a pattern with `/` is anchored at the package root, and a pattern naming
|
|
59
|
+
* a directory excludes everything under it.
|
|
60
|
+
*/
|
|
61
|
+
export function excludeMatcher(patterns) {
|
|
62
|
+
const compiled = patterns
|
|
63
|
+
.flatMap((p) => p.split(','))
|
|
64
|
+
// `dir/**` is `dir`: the suffix below already covers everything under a match.
|
|
65
|
+
.map((p) => p
|
|
66
|
+
.trim()
|
|
67
|
+
.replace(/^\.\//, '')
|
|
68
|
+
.replace(/\/+$/, '')
|
|
69
|
+
.replace(/\/\*\*$/, ''))
|
|
70
|
+
.filter(Boolean)
|
|
71
|
+
.map((pattern) => {
|
|
72
|
+
const source = pattern
|
|
73
|
+
.split('**')
|
|
74
|
+
.map((part) => part
|
|
75
|
+
.split('*')
|
|
76
|
+
.map((chunk) => escapeRe(chunk).replace(/\?/g, '[^/]'))
|
|
77
|
+
.join('[^/]*'))
|
|
78
|
+
.join('.*');
|
|
79
|
+
const anchored = pattern.includes('/');
|
|
80
|
+
return anchored ? new RegExp(`^${source}(?:/.*)?$`) : new RegExp(`(?:^|/)${source}(?:/.*)?$`);
|
|
81
|
+
});
|
|
82
|
+
return (relative) => compiled.some((re) => re.test(relative));
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* A `web_accessible_resources` entry as the BROWSER matches it: `*` matches any
|
|
86
|
+
* run of characters INCLUDING `/` (Chromium's MatchPattern and Firefox's
|
|
87
|
+
* MatchGlob both work this way), `?` one character. Leading `/` is ignored.
|
|
88
|
+
*/
|
|
89
|
+
export function warGlobToRegExp(glob) {
|
|
90
|
+
const body = glob
|
|
91
|
+
.replace(/^\/+/, '')
|
|
92
|
+
.split('*')
|
|
93
|
+
.map((chunk) => escapeRe(chunk).replace(/\?/g, '.'))
|
|
94
|
+
.join('.*');
|
|
95
|
+
return new RegExp(`^${body}$`);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Read every file under `root`, sorted, skipping dot-entries (`.git`, `.github`,
|
|
99
|
+
* `.extenshi`, `.DS_Store`, …), `node_modules` and `skipDirs` (the output
|
|
100
|
+
* directory when it sits inside the source). Symlinks are refused: following one
|
|
101
|
+
* would pack bytes from outside the directory, and a link itself is not
|
|
102
|
+
* something every store unpacks the same way.
|
|
103
|
+
*/
|
|
104
|
+
export function collectFiles(root, options = {}) {
|
|
105
|
+
const stat = fs.statSync(root, { throwIfNoEntry: false });
|
|
106
|
+
if (!stat?.isDirectory())
|
|
107
|
+
throw new InvalidInputError(`Build directory not found: ${root}`);
|
|
108
|
+
const excluded = excludeMatcher(options.exclude ?? []);
|
|
109
|
+
const skip = new Set((options.skipDirs ?? []).map((dir) => path.resolve(dir)));
|
|
110
|
+
const files = [];
|
|
111
|
+
const left = [];
|
|
112
|
+
let total = 0;
|
|
113
|
+
const walk = (dir, prefix) => {
|
|
114
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true }).sort((a, b) => (a.name < b.name ? -1 : 1));
|
|
115
|
+
for (const entry of entries) {
|
|
116
|
+
if (entry.name.startsWith('.') || ALWAYS_SKIPPED_DIRS.has(entry.name))
|
|
117
|
+
continue;
|
|
118
|
+
const full = path.join(dir, entry.name);
|
|
119
|
+
const relative = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
120
|
+
if (skip.has(path.resolve(full)))
|
|
121
|
+
continue;
|
|
122
|
+
if (excluded(relative)) {
|
|
123
|
+
left.push(relative);
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (entry.isSymbolicLink())
|
|
127
|
+
throw new InvalidInputError(`${relative} is a symbolic link. Packages contain files only — copy the target in, or exclude it.`);
|
|
128
|
+
if (entry.isDirectory())
|
|
129
|
+
walk(full, relative);
|
|
130
|
+
else if (entry.isFile()) {
|
|
131
|
+
const bytes = fs.readFileSync(full);
|
|
132
|
+
total += bytes.byteLength;
|
|
133
|
+
if (total > MAX_TOTAL_BYTES)
|
|
134
|
+
throw new InvalidInputError('The build directory exceeds 1 GiB.');
|
|
135
|
+
files.push({ path: relative, bytes: new Uint8Array(bytes) });
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
walk(root, '');
|
|
140
|
+
if (files.length > MAX_ENTRIES)
|
|
141
|
+
throw new InvalidInputError(`Too many files for a ZIP (${files.length}).`);
|
|
142
|
+
return { files, excluded: left.sort() };
|
|
143
|
+
}
|
|
144
|
+
const asObject = (v) => v && typeof v === 'object' && !Array.isArray(v) ? v : undefined;
|
|
145
|
+
const asStrings = (v) => Array.isArray(v) ? v.filter((x) => typeof x === 'string') : typeof v === 'string' ? [v] : [];
|
|
146
|
+
const normalizeRef = (p) => p.trim().replace(/^\.?\/+/, '');
|
|
147
|
+
/**
|
|
148
|
+
* Every file the manifest names, which the browser loads or refuses to install
|
|
149
|
+
* without: background, pages, content scripts, icons, locale, rulesets.
|
|
150
|
+
* `web_accessible_resources` is not here — its entries are patterns, handled by
|
|
151
|
+
* the WAR check.
|
|
152
|
+
*/
|
|
153
|
+
export function manifestReferences(manifest) {
|
|
154
|
+
const refs = [];
|
|
155
|
+
const bg = asObject(manifest.background);
|
|
156
|
+
refs.push(...asStrings(bg?.service_worker), ...asStrings(bg?.scripts), ...asStrings(bg?.page));
|
|
157
|
+
for (const key of ['action', 'browser_action', 'page_action']) {
|
|
158
|
+
const action = asObject(manifest[key]);
|
|
159
|
+
refs.push(...asStrings(action?.default_popup));
|
|
160
|
+
const icon = action?.default_icon;
|
|
161
|
+
refs.push(...(typeof icon === 'string' ? [icon] : Object.values(asObject(icon) ?? {}).flatMap(asStrings)));
|
|
162
|
+
}
|
|
163
|
+
refs.push(...asStrings(manifest.options_page), ...asStrings(asObject(manifest.options_ui)?.page));
|
|
164
|
+
refs.push(...asStrings(asObject(manifest.side_panel)?.default_path));
|
|
165
|
+
const sidebar = asObject(manifest.sidebar_action);
|
|
166
|
+
refs.push(...asStrings(sidebar?.default_panel));
|
|
167
|
+
refs.push(...asStrings(manifest.devtools_page));
|
|
168
|
+
refs.push(...Object.values(asObject(manifest.chrome_url_overrides) ?? {}).flatMap(asStrings));
|
|
169
|
+
for (const cs of Array.isArray(manifest.content_scripts) ? manifest.content_scripts : [])
|
|
170
|
+
refs.push(...asStrings(asObject(cs)?.js), ...asStrings(asObject(cs)?.css));
|
|
171
|
+
refs.push(...Object.values(asObject(manifest.icons) ?? {}).flatMap(asStrings));
|
|
172
|
+
if (typeof manifest.default_locale === 'string')
|
|
173
|
+
refs.push(`_locales/${manifest.default_locale}/messages.json`);
|
|
174
|
+
const dnr = asObject(manifest.declarative_net_request);
|
|
175
|
+
for (const rule of Array.isArray(dnr?.rule_resources) ? dnr.rule_resources : [])
|
|
176
|
+
refs.push(...asStrings(asObject(rule)?.path));
|
|
177
|
+
refs.push(...asStrings(asObject(manifest.sandbox)?.pages));
|
|
178
|
+
return [
|
|
179
|
+
...new Set(refs.map(normalizeRef).filter((p) => p && !/^[a-z]+:/i.test(p) && !p.startsWith('__MSG_'))),
|
|
180
|
+
].sort();
|
|
181
|
+
}
|
|
182
|
+
export function warWildcards(manifest) {
|
|
183
|
+
const war = Array.isArray(manifest.web_accessible_resources) ? manifest.web_accessible_resources : [];
|
|
184
|
+
const out = [];
|
|
185
|
+
war.forEach((item, entry) => {
|
|
186
|
+
// MV2: plain strings. MV3: { resources: [...], matches|extension_ids }.
|
|
187
|
+
const patterns = typeof item === 'string' ? [item] : asStrings(asObject(item)?.resources);
|
|
188
|
+
for (const pattern of patterns)
|
|
189
|
+
if (pattern.includes('*'))
|
|
190
|
+
out.push({ entry, pattern });
|
|
191
|
+
});
|
|
192
|
+
return out;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Replace every wildcard in `web_accessible_resources` with the explicit list of
|
|
196
|
+
* packaged files it matches (as the browser would match it). Exact entries stay.
|
|
197
|
+
* manifest.json itself is never exposed. Returns human-readable change notes.
|
|
198
|
+
*/
|
|
199
|
+
export function expandWarWildcards(manifest, packagedPaths) {
|
|
200
|
+
const changes = [];
|
|
201
|
+
const candidates = packagedPaths.filter((p) => p !== 'manifest.json');
|
|
202
|
+
const expand = (patterns) => {
|
|
203
|
+
const out = new Set();
|
|
204
|
+
for (const pattern of patterns) {
|
|
205
|
+
if (!pattern.includes('*')) {
|
|
206
|
+
out.add(pattern);
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
const re = warGlobToRegExp(pattern);
|
|
210
|
+
const matched = candidates.filter((p) => re.test(p));
|
|
211
|
+
changes.push(matched.length
|
|
212
|
+
? `web_accessible_resources: "${pattern}" → ${matched.length} explicit file${matched.length === 1 ? '' : 's'}`
|
|
213
|
+
: `web_accessible_resources: "${pattern}" matched no packaged file and was removed`);
|
|
214
|
+
for (const p of matched)
|
|
215
|
+
out.add(p);
|
|
216
|
+
}
|
|
217
|
+
return [...out].sort();
|
|
218
|
+
};
|
|
219
|
+
const war = manifest.web_accessible_resources;
|
|
220
|
+
if (!Array.isArray(war))
|
|
221
|
+
return changes;
|
|
222
|
+
if (war.every((item) => typeof item === 'string')) {
|
|
223
|
+
manifest.web_accessible_resources = expand(war);
|
|
224
|
+
return changes;
|
|
225
|
+
}
|
|
226
|
+
manifest.web_accessible_resources = war
|
|
227
|
+
.map((item) => {
|
|
228
|
+
const obj = asObject(item);
|
|
229
|
+
if (!obj || !Array.isArray(obj.resources))
|
|
230
|
+
return item;
|
|
231
|
+
return { ...obj, resources: expand(asStrings(obj.resources)) };
|
|
232
|
+
})
|
|
233
|
+
.filter((item) => !(asObject(item) &&
|
|
234
|
+
Array.isArray(asObject(item)?.resources) &&
|
|
235
|
+
asObject(item)?.resources.length === 0));
|
|
236
|
+
return changes;
|
|
237
|
+
}
|
|
238
|
+
/** `browser_specific_settings.gecko.id`, or the MV2 `applications.gecko.id` spelling. */
|
|
239
|
+
export function manifestGeckoId(manifest) {
|
|
240
|
+
for (const key of ['browser_specific_settings', 'applications']) {
|
|
241
|
+
const id = asObject(asObject(manifest[key])?.gecko)?.id;
|
|
242
|
+
if (typeof id === 'string' && id.trim())
|
|
243
|
+
return id.trim();
|
|
244
|
+
}
|
|
245
|
+
return undefined;
|
|
246
|
+
}
|
|
247
|
+
function geckoIdHelp(projectId) {
|
|
248
|
+
const example = projectId ? projectGeckoId(projectId) : '{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}';
|
|
249
|
+
return (`Set browser_specific_settings.gecko.id in manifest.json (email-style "name@yourdomain" or a GUID like "${example}"), ` +
|
|
250
|
+
`or pass --gecko-id <id> to write it into the packaged copy. AMO makes the ID permanent at the first upload, so pick it once.` +
|
|
251
|
+
(projectId
|
|
252
|
+
? ` The bound Dojo project's default is ${example} (the ID Dojo's scaffold writes) — pass --gecko-id "${example}" to use it.`
|
|
253
|
+
: ''));
|
|
254
|
+
}
|
|
255
|
+
export function packExtension(source, options) {
|
|
256
|
+
const byPath = new Map(source.map((f) => [f.path, f]));
|
|
257
|
+
const seen = new Map();
|
|
258
|
+
for (const f of source) {
|
|
259
|
+
const folded = f.path.toLowerCase();
|
|
260
|
+
const other = seen.get(folded);
|
|
261
|
+
// Case-only twins unpack as ONE file on macOS/Windows, so which one the store
|
|
262
|
+
// or a reviewer sees would depend on their machine.
|
|
263
|
+
if (other)
|
|
264
|
+
throw new InvalidInputError(`${other} and ${f.path} differ only in letter case.`);
|
|
265
|
+
seen.set(folded, f.path);
|
|
266
|
+
}
|
|
267
|
+
const manifestFile = byPath.get('manifest.json');
|
|
268
|
+
if (!manifestFile)
|
|
269
|
+
throw new InvalidInputError('No manifest.json at the root of the build directory — point at the unpacked build.');
|
|
270
|
+
let manifest;
|
|
271
|
+
try {
|
|
272
|
+
manifest = JSON.parse(new TextDecoder().decode(manifestFile.bytes).replace(/^/, ''));
|
|
273
|
+
}
|
|
274
|
+
catch (error) {
|
|
275
|
+
throw new InvalidInputError(`manifest.json is not valid JSON: ${error.message}`);
|
|
276
|
+
}
|
|
277
|
+
if (!asObject(manifest))
|
|
278
|
+
throw new InvalidInputError('manifest.json must be a JSON object.');
|
|
279
|
+
const missing = manifestReferences(manifest).filter((ref) => !byPath.has(ref));
|
|
280
|
+
if (missing.length)
|
|
281
|
+
throw new InvalidInputError(`manifest.json names file${missing.length === 1 ? '' : 's'} the package does not contain: ${missing.join(', ')}. ` +
|
|
282
|
+
'Browsers refuse to load such a package. Add the files, or check --exclude.');
|
|
283
|
+
const changes = [];
|
|
284
|
+
const warnings = [];
|
|
285
|
+
const wildcards = warWildcards(manifest);
|
|
286
|
+
if (wildcards.length && options.fixWar) {
|
|
287
|
+
changes.push(...expandWarWildcards(manifest, source.map((f) => f.path)));
|
|
288
|
+
}
|
|
289
|
+
else if (wildcards.length) {
|
|
290
|
+
warnings.push(`web_accessible_resources uses wildcard${wildcards.length === 1 ? '' : 's'} (${wildcards.map((w) => `"${w.pattern}"`).join(', ')}) — ` +
|
|
291
|
+
'every matching file becomes readable by web pages, and reviewers ask why. Pass --fix-war to list the files explicitly in the packaged copy.');
|
|
292
|
+
}
|
|
293
|
+
if (options.browser === 'firefox') {
|
|
294
|
+
const existing = manifestGeckoId(manifest);
|
|
295
|
+
if (options.geckoId !== undefined) {
|
|
296
|
+
const id = options.geckoId.trim();
|
|
297
|
+
if (!isValidGeckoId(id) || isPlaceholderGeckoId(id))
|
|
298
|
+
throw new InvalidInputError(`--gecko-id "${id}" is ${isValidGeckoId(id) ? 'a placeholder' : 'not a valid add-on ID'}. ${geckoIdHelp(options.projectId)}`);
|
|
299
|
+
if (id !== existing) {
|
|
300
|
+
const settings = asObject(manifest.browser_specific_settings) ?? {};
|
|
301
|
+
manifest.browser_specific_settings = {
|
|
302
|
+
...settings,
|
|
303
|
+
gecko: { ...(asObject(settings.gecko) ?? {}), id },
|
|
304
|
+
};
|
|
305
|
+
changes.push(`browser_specific_settings.gecko.id set to ${id}${existing ? ` (was ${existing})` : ''}`);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
else if (!existing) {
|
|
309
|
+
throw new InvalidInputError(`The Firefox package has no add-on ID. ${geckoIdHelp(options.projectId)}`);
|
|
310
|
+
}
|
|
311
|
+
else if (isPlaceholderGeckoId(existing) || !isValidGeckoId(existing)) {
|
|
312
|
+
throw new InvalidInputError(`The Firefox add-on ID "${existing}" is ${existing === PLACEHOLDER_GECKO_ID || isPlaceholderGeckoId(existing) ? 'a placeholder' : 'not a valid add-on ID'} — an AMO upload would own it forever. ${geckoIdHelp(options.projectId)}`);
|
|
313
|
+
}
|
|
314
|
+
const bg = asObject(manifest.background);
|
|
315
|
+
if (manifest.manifest_version === 3 && bg?.service_worker && !bg.scripts && !bg.page)
|
|
316
|
+
throw new InvalidInputError('Firefox does not run MV3 background service workers and refuses this manifest ("background.service_worker is currently disabled"). ' +
|
|
317
|
+
'Add "scripts": ["<your background file>"] next to service_worker in the Firefox build — Chromium ignores it.');
|
|
318
|
+
}
|
|
319
|
+
const files = changes.length
|
|
320
|
+
? source.map((f) => f.path === 'manifest.json'
|
|
321
|
+
? { path: f.path, bytes: new TextEncoder().encode(`${JSON.stringify(manifest, null, 2)}\n`) }
|
|
322
|
+
: f)
|
|
323
|
+
: [...source];
|
|
324
|
+
files.sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));
|
|
325
|
+
const zip = new ZipBuilder({ mtime: reproducibleMtime() });
|
|
326
|
+
for (const f of files)
|
|
327
|
+
zip.addFile(f.path, f.bytes);
|
|
328
|
+
const bytes = zip.toBytes();
|
|
329
|
+
return {
|
|
330
|
+
browser: options.browser,
|
|
331
|
+
bytes,
|
|
332
|
+
sha256: createHash('sha256').update(bytes).digest('hex'),
|
|
333
|
+
entries: files.map((f) => f.path),
|
|
334
|
+
manifest,
|
|
335
|
+
changes,
|
|
336
|
+
warnings,
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
/** `dyslexia-font-reading-ruler-chrome-0.1.0.zip`: browser in the name so the wrong upload is hard. */
|
|
340
|
+
export function packageFileName(name, browser, version) {
|
|
341
|
+
const slug = name
|
|
342
|
+
.toLowerCase()
|
|
343
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
344
|
+
.replace(/^-+|-+$/g, '')
|
|
345
|
+
.slice(0, 60) || 'extension';
|
|
346
|
+
const safeVersion = version.replace(/[^0-9A-Za-z.-]/g, '') || '0.0.0';
|
|
347
|
+
return `${slug}-${browser}-${safeVersion}.zip`;
|
|
348
|
+
}
|
|
349
|
+
/** Resolve `__MSG_key__` against the default locale, for the file name only. */
|
|
350
|
+
export function displayName(manifest, files) {
|
|
351
|
+
const raw = typeof manifest.name === 'string' ? manifest.name : '';
|
|
352
|
+
const token = /^__MSG_(\w+)__$/.exec(raw)?.[1];
|
|
353
|
+
if (!token || typeof manifest.default_locale !== 'string')
|
|
354
|
+
return raw;
|
|
355
|
+
const file = files.find((f) => f.path === `_locales/${manifest.default_locale}/messages.json`);
|
|
356
|
+
try {
|
|
357
|
+
const messages = JSON.parse(new TextDecoder().decode(file?.bytes).replace(/^/, ''));
|
|
358
|
+
const hit = Object.entries(messages).find(([key]) => key.toLowerCase() === token.toLowerCase())?.[1];
|
|
359
|
+
return typeof hit?.message === 'string' ? hit.message : raw;
|
|
360
|
+
}
|
|
361
|
+
catch {
|
|
362
|
+
return raw;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
export function isPackagesManifest(value) {
|
|
366
|
+
const obj = asObject(value);
|
|
367
|
+
return obj?.schemaVersion === PACKAGES_MANIFEST_SCHEMA_VERSION && Array.isArray(obj.packages);
|
|
368
|
+
}
|
|
369
|
+
const sha256File = (file) => createHash('sha256').update(fs.readFileSync(file)).digest('hex');
|
|
370
|
+
/**
|
|
371
|
+
* `<artifact>` for `release prepare`, `test smoke` and `evidence ingest`: a zip,
|
|
372
|
+
* or the packages manifest `extenshi package` wrote (then `browser` picks the
|
|
373
|
+
* entry). The zip's bytes must still hash to what the manifest recorded — a
|
|
374
|
+
* package rebuilt or edited since then is refused rather than silently used.
|
|
375
|
+
*/
|
|
376
|
+
export function resolvePackagedArtifact(file, browser) {
|
|
377
|
+
if (!file.toLowerCase().endsWith('.json'))
|
|
378
|
+
return { artifactPath: file };
|
|
379
|
+
let parsed;
|
|
380
|
+
try {
|
|
381
|
+
parsed = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
382
|
+
}
|
|
383
|
+
catch (error) {
|
|
384
|
+
throw new InvalidInputError(`Could not read ${file}: ${error.message}`);
|
|
385
|
+
}
|
|
386
|
+
if (!isPackagesManifest(parsed))
|
|
387
|
+
throw new InvalidInputError(`${file} is not an ${PACKAGES_MANIFEST_FILE} written by extenshi package.`);
|
|
388
|
+
const matches = browser ? parsed.packages.filter((p) => p.browser === browser) : parsed.packages;
|
|
389
|
+
if (matches.length !== 1)
|
|
390
|
+
throw new InvalidInputError(browser
|
|
391
|
+
? `${file} has no ${browser} package (it lists: ${parsed.packages.map((p) => p.browser).join(', ') || 'none'}).`
|
|
392
|
+
: `${file} lists ${parsed.packages.length} packages — pass --browser to pick one.`);
|
|
393
|
+
const entry = matches[0];
|
|
394
|
+
const artifactPath = path.resolve(path.dirname(file), entry.file);
|
|
395
|
+
if (!fs.existsSync(artifactPath))
|
|
396
|
+
throw new InvalidInputError(`Package not found: ${artifactPath}`);
|
|
397
|
+
if (sha256File(artifactPath) !== entry.sha256)
|
|
398
|
+
throw new InvalidInputError(`${entry.file} no longer matches the sha256 in ${path.basename(file)} — it changed after extenshi package. Re-run extenshi package.`);
|
|
399
|
+
return { artifactPath, entry };
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Browsers a zip was packaged for, from the packages manifest next to it. Chrome
|
|
403
|
+
* and Edge built from one directory are byte-identical, so one zip can be both.
|
|
404
|
+
*/
|
|
405
|
+
export function packagedBrowsersFor(artifactPath, sha256) {
|
|
406
|
+
const manifestPath = path.join(path.dirname(artifactPath), PACKAGES_MANIFEST_FILE);
|
|
407
|
+
try {
|
|
408
|
+
const parsed = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
409
|
+
if (!isPackagesManifest(parsed))
|
|
410
|
+
return [];
|
|
411
|
+
return parsed.packages.filter((p) => p.sha256 === sha256).map((p) => p.browser);
|
|
412
|
+
}
|
|
413
|
+
catch {
|
|
414
|
+
return [];
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
export function parsePackageBrowsers(value) {
|
|
418
|
+
const list = (value ?? 'chrome')
|
|
419
|
+
.split(',')
|
|
420
|
+
.map((s) => s.trim().toLowerCase())
|
|
421
|
+
.filter(Boolean)
|
|
422
|
+
.map((s) => (s === 'chromium' ? 'chrome' : s));
|
|
423
|
+
const bad = list.filter((s) => !PACKAGE_BROWSERS.includes(s));
|
|
424
|
+
if (bad.length || !list.length)
|
|
425
|
+
throw new InvalidInputError(`--browser takes a comma-separated list of: ${PACKAGE_BROWSERS.join(', ')}`);
|
|
426
|
+
return [...new Set(list)];
|
|
427
|
+
}
|
|
428
|
+
function boundProjectId(cwd) {
|
|
429
|
+
try {
|
|
430
|
+
const binding = JSON.parse(fs.readFileSync(path.join(cwd, '.extenshi/project.json'), 'utf8'));
|
|
431
|
+
return typeof binding.projectId === 'string' ? binding.projectId : undefined;
|
|
432
|
+
}
|
|
433
|
+
catch {
|
|
434
|
+
return undefined;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
export function runPackage(options) {
|
|
438
|
+
const cwd = options.cwd ?? process.cwd();
|
|
439
|
+
const outDir = path.resolve(cwd, options.outDir);
|
|
440
|
+
const projectId = boundProjectId(cwd);
|
|
441
|
+
const results = [];
|
|
442
|
+
for (const browser of options.browsers) {
|
|
443
|
+
const dir = options.dirs?.[browser] ?? options.dir;
|
|
444
|
+
if (!dir)
|
|
445
|
+
throw new InvalidInputError(`No build directory for ${browser}: pass <dir> or --${browser}-dir <dir>.`);
|
|
446
|
+
const root = path.resolve(cwd, dir);
|
|
447
|
+
const { files } = collectFiles(root, { exclude: options.exclude, skipDirs: [outDir] });
|
|
448
|
+
const packed = packExtension(files, {
|
|
449
|
+
browser,
|
|
450
|
+
geckoId: options.geckoId,
|
|
451
|
+
fixWar: options.fixWar,
|
|
452
|
+
projectId,
|
|
453
|
+
});
|
|
454
|
+
const version = typeof packed.manifest.version === 'string' ? packed.manifest.version : '0.0.0';
|
|
455
|
+
const name = displayName(packed.manifest, files);
|
|
456
|
+
results.push({
|
|
457
|
+
bytes: packed.bytes,
|
|
458
|
+
entry: {
|
|
459
|
+
browser,
|
|
460
|
+
file: packageFileName(name || path.basename(root), browser, version),
|
|
461
|
+
sha256: packed.sha256,
|
|
462
|
+
bytes: packed.bytes.byteLength,
|
|
463
|
+
entries: packed.entries.length,
|
|
464
|
+
name,
|
|
465
|
+
version,
|
|
466
|
+
manifestDigest: hashMetadata(packed.manifest),
|
|
467
|
+
...(browser === 'firefox' ? { geckoId: manifestGeckoId(packed.manifest) } : {}),
|
|
468
|
+
source: path.relative(cwd, root).split(path.sep).join('/') || '.',
|
|
469
|
+
changes: packed.changes,
|
|
470
|
+
warnings: packed.warnings,
|
|
471
|
+
},
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
475
|
+
for (const { entry, bytes } of results)
|
|
476
|
+
fs.writeFileSync(path.join(outDir, entry.file), bytes);
|
|
477
|
+
const manifest = {
|
|
478
|
+
schemaVersion: PACKAGES_MANIFEST_SCHEMA_VERSION,
|
|
479
|
+
tool: `extenshi-cli/${options.cliVersion}`,
|
|
480
|
+
packages: results.map((r) => r.entry),
|
|
481
|
+
};
|
|
482
|
+
fs.writeFileSync(path.join(outDir, PACKAGES_MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}\n`);
|
|
483
|
+
if (options.json) {
|
|
484
|
+
process.stdout.write(`${JSON.stringify({ ...manifest, outDir }, null, 2)}\n`);
|
|
485
|
+
}
|
|
486
|
+
else {
|
|
487
|
+
// sha256sum format, so `shasum -a 256 -c` can check the files later.
|
|
488
|
+
for (const { entry } of results)
|
|
489
|
+
process.stdout.write(`${entry.sha256} ${path.join(outDir, entry.file)}\n`);
|
|
490
|
+
for (const { entry } of results) {
|
|
491
|
+
for (const change of entry.changes)
|
|
492
|
+
process.stderr.write(`${entry.browser}: changed in the package: ${change}\n`);
|
|
493
|
+
for (const warning of entry.warnings)
|
|
494
|
+
process.stderr.write(`${entry.browser}: warning: ${warning}\n`);
|
|
495
|
+
}
|
|
496
|
+
process.stderr.write(`Wrote ${path.join(outDir, PACKAGES_MANIFEST_FILE)}\n`);
|
|
497
|
+
}
|
|
498
|
+
return manifest;
|
|
499
|
+
}
|
|
500
|
+
//# sourceMappingURL=package.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package.js","sourceRoot":"","sources":["../src/package.ts"],"names":[],"mappings":"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"}
|
package/dist/page.d.ts
CHANGED
|
@@ -119,7 +119,17 @@ export interface PagePublishOptions {
|
|
|
119
119
|
logo?: string;
|
|
120
120
|
/** commander's --no-homepage sets this to false. */
|
|
121
121
|
homepage?: boolean;
|
|
122
|
+
/** Upload local screenshot / logoUrl paths to the project's public media store first. */
|
|
123
|
+
uploadLocal?: boolean;
|
|
122
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* `--upload-local`: replace every local screenshot path (and a local `logoUrl`)
|
|
127
|
+
* with the stable public URL `extenshi media upload` returns. Paths resolve
|
|
128
|
+
* against the config file's directory. Exported for tests.
|
|
129
|
+
*/
|
|
130
|
+
export declare function uploadLocalMedia(form: LandingForm, projectId: string, configPath: string, upload?: (projectId: string, file: string) => Promise<{
|
|
131
|
+
url: string;
|
|
132
|
+
}>): Promise<string[]>;
|
|
123
133
|
/**
|
|
124
134
|
* `extenshi page publish`: host the page on page.extenshi.io. Sends the form —
|
|
125
135
|
* the BFF renders it with the same builder — never the HTML file.
|
package/dist/page.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../src/page.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,OAAO,EAIN,KAAK,WAAW,EAIhB,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../src/page.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,OAAO,EAIN,KAAK,WAAW,EAIhB,MAAM,mBAAmB,CAAA;AAgB1B,mFAAmF;AACnF,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2B9B,CAAA;AAEF,MAAM,WAAW,mBAAmB;IACnC,MAAM,EAAE,MAAM,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,EAAE,CAAA;CAClB;AAgBD,mFAAmF;AACnF,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAoB3D;AA2BD,wBAAsB,eAAe,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAc5F;AAED,MAAM,WAAW,mBAAmB;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,CAAC,EAAE,MAAM,CAAA;CACb;AAYD,wBAAsB,eAAe,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAejG;AAED,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,oDAAoD;IACpD,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,yFAAyF;IACzF,WAAW,CAAC,EAAE,OAAO,CAAA;CACrB;AAMD;;;;GAIG;AACH,wBAAsB,gBAAgB,CACrC,IAAI,EAAE,WAAW,EACjB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,MAAM,GAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAmB,GACrF,OAAO,CAAC,MAAM,EAAE,CAAC,CAenB;AAID;;;GAGG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAqC/F;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAYlG"}
|
package/dist/page.js
CHANGED
|
@@ -18,6 +18,7 @@ import { z } from 'zod';
|
|
|
18
18
|
import { loadConfig } from './config.js';
|
|
19
19
|
import { InvalidInputError } from './expected-error.js';
|
|
20
20
|
import { buildLandingPage, DEFAULT_LANDING_FORM, LANDING_LIMITS, landingFormToInput, landingLogoSvgProblem, landingPageWarnings, } from './landing-page.js';
|
|
21
|
+
import { uploadMediaFile } from './media.js';
|
|
21
22
|
import { projectRequest } from './project.js';
|
|
22
23
|
const MAX_CONFIG_BYTES = 1024 * 1024;
|
|
23
24
|
const MAX_RASTER_LOGO_BYTES = 256 * 1024;
|
|
@@ -157,6 +158,30 @@ export async function runPageRegister(opts) {
|
|
|
157
158
|
}
|
|
158
159
|
return result;
|
|
159
160
|
}
|
|
161
|
+
/** A path, not a URL: no scheme (screenshots/popup.png, ./shots/1.png, C:\\shots\\1.png). */
|
|
162
|
+
const isLocalPath = (value) => !/^[a-z][a-z0-9+.-]*:/i.test(value.trim()) || /^[a-z]:[\\/]/i.test(value.trim());
|
|
163
|
+
/**
|
|
164
|
+
* `--upload-local`: replace every local screenshot path (and a local `logoUrl`)
|
|
165
|
+
* with the stable public URL `extenshi media upload` returns. Paths resolve
|
|
166
|
+
* against the config file's directory. Exported for tests.
|
|
167
|
+
*/
|
|
168
|
+
export async function uploadLocalMedia(form, projectId, configPath, upload = uploadMediaFile) {
|
|
169
|
+
const base = path.dirname(path.resolve(process.cwd(), configPath));
|
|
170
|
+
const uploaded = [];
|
|
171
|
+
for (const shot of form.screenshots ?? []) {
|
|
172
|
+
if (!isLocalPath(shot.url))
|
|
173
|
+
continue;
|
|
174
|
+
const file = path.resolve(base, shot.url.trim());
|
|
175
|
+
shot.url = (await upload(projectId, file)).url;
|
|
176
|
+
uploaded.push(`${path.relative(process.cwd(), file)} → ${shot.url}`);
|
|
177
|
+
}
|
|
178
|
+
if (form.logoUrl && isLocalPath(form.logoUrl)) {
|
|
179
|
+
const file = path.resolve(base, form.logoUrl.trim());
|
|
180
|
+
form.logoUrl = (await upload(projectId, file)).url;
|
|
181
|
+
uploaded.push(`${path.relative(process.cwd(), file)} → ${form.logoUrl}`);
|
|
182
|
+
}
|
|
183
|
+
return uploaded;
|
|
184
|
+
}
|
|
160
185
|
const projectIdSchema = z.string().uuid({ message: '--project must be a project UUID' });
|
|
161
186
|
/**
|
|
162
187
|
* `extenshi page publish`: host the page on page.extenshi.io. Sends the form —
|
|
@@ -170,10 +195,15 @@ export async function runPagePublish(opts) {
|
|
|
170
195
|
const form = parseLandingConfig(raw);
|
|
171
196
|
if (opts.logo)
|
|
172
197
|
await applyLogoFile(form, opts.logo);
|
|
198
|
+
if (opts.uploadLocal) {
|
|
199
|
+
for (const line of await uploadLocalMedia(form, projectId.data, opts.config))
|
|
200
|
+
process.stderr.write(` uploaded ${line}\n`);
|
|
201
|
+
}
|
|
173
202
|
const local = (form.screenshots ?? []).filter((s) => !/^https:\/\//i.test(s.url.trim()));
|
|
174
203
|
if (local.length) {
|
|
175
|
-
throw new InvalidInputError(`Hosted pages cannot show local screenshots (${local.map((s) => s.url).join(', ')}).
|
|
176
|
-
|
|
204
|
+
throw new InvalidInputError(`Hosted pages cannot show local screenshots (${local.map((s) => s.url).join(', ')}). Pass ` +
|
|
205
|
+
"--upload-local to upload them to the project's public media store (or run `extenshi media upload`), " +
|
|
206
|
+
'use store screenshot URLs or Dojo Page generator uploads, or host the file yourself with ' +
|
|
177
207
|
'`extenshi page generate` + `extenshi page register`.');
|
|
178
208
|
}
|
|
179
209
|
const result = await projectRequest(await loadConfig(), 'agentPublishLandingPage', { projectId: projectId.data, form, registerAsHomepage: opts.homepage !== false }, true);
|