executable-stories-formatters 1.21.0 → 1.21.1
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/cli.js +81 -22
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -11626,9 +11626,12 @@ import * as fs13 from "fs";
|
|
|
11626
11626
|
import * as path19 from "path";
|
|
11627
11627
|
import { parseArgs as parseArgs2 } from "util";
|
|
11628
11628
|
import { canonicalizeRun as canonicalizeRun5 } from "executable-stories-core/converters/acl/canonicalize";
|
|
11629
|
-
import { collectReportAssets, rewriteReportAssets } from "executable-stories-core/report-assets";
|
|
11630
11629
|
import { toStoryReport as toStoryReport8 } from "executable-stories-core/converters/story-report";
|
|
11631
11630
|
import { synthesizeStories as synthesizeStories3 } from "executable-stories-core/converters/synthesize";
|
|
11631
|
+
import {
|
|
11632
|
+
collectReportAssets,
|
|
11633
|
+
rewriteReportAssets
|
|
11634
|
+
} from "executable-stories-core/report-assets";
|
|
11632
11635
|
var EXIT_SUCCESS2 = 0;
|
|
11633
11636
|
var EXIT_SHARE_FAILED = 1;
|
|
11634
11637
|
var EXIT_USAGE2 = 4;
|
|
@@ -11733,13 +11736,20 @@ function loadReport(filePath, deps) {
|
|
|
11733
11736
|
const text2 = deps.readFile(filePath);
|
|
11734
11737
|
if (filePath.endsWith(".html")) {
|
|
11735
11738
|
const match = HTML_REPORT_DATA.exec(text2);
|
|
11736
|
-
if (!match?.[1])
|
|
11737
|
-
|
|
11739
|
+
if (!match?.[1])
|
|
11740
|
+
throw new Error(
|
|
11741
|
+
`${filePath} is an HTML page with no report embedded in it`
|
|
11742
|
+
);
|
|
11743
|
+
return asStoryReport(
|
|
11744
|
+
JSON.parse(match[1]),
|
|
11745
|
+
filePath
|
|
11746
|
+
);
|
|
11738
11747
|
}
|
|
11739
11748
|
return asStoryReport(JSON.parse(text2), filePath);
|
|
11740
11749
|
}
|
|
11741
11750
|
function asStoryReport(data, filePath) {
|
|
11742
|
-
if (typeof data.schemaVersion === "string")
|
|
11751
|
+
if (typeof data.schemaVersion === "string")
|
|
11752
|
+
return data;
|
|
11743
11753
|
try {
|
|
11744
11754
|
return toStoryReport8(canonicalizeRun5(synthesizeStories3(data)));
|
|
11745
11755
|
} catch (err) {
|
|
@@ -11775,7 +11785,12 @@ function planAssets(report, reportDir, deps) {
|
|
|
11775
11785
|
missing.push(assetPath);
|
|
11776
11786
|
continue;
|
|
11777
11787
|
}
|
|
11778
|
-
assets.push({
|
|
11788
|
+
assets.push({
|
|
11789
|
+
path: key,
|
|
11790
|
+
localPath,
|
|
11791
|
+
contentType: contentTypeFor(key),
|
|
11792
|
+
bytes
|
|
11793
|
+
});
|
|
11779
11794
|
}
|
|
11780
11795
|
return { assets, missing, keyByPath };
|
|
11781
11796
|
}
|
|
@@ -11790,6 +11805,10 @@ async function describeFailure(response) {
|
|
|
11790
11805
|
if (error?.type === "SHARE_TOO_LARGE") {
|
|
11791
11806
|
return `the report and its assets are over the ${error.maxBytes ?? 0} byte limit for a share.`;
|
|
11792
11807
|
}
|
|
11808
|
+
if (error?.type === "STORAGE_LIMIT") {
|
|
11809
|
+
const mb = (bytes) => `${Math.round(bytes / 1024 / 1024)} MB`;
|
|
11810
|
+
return `stored evidence is at the plan's ${mb(error.limit ?? 0)} (${mb(error.used ?? 0)} used). Delete a share or an attachment in your cloud settings, or upgrade.`;
|
|
11811
|
+
}
|
|
11793
11812
|
if (error?.message) return error.message;
|
|
11794
11813
|
if (error?.type) return error.type;
|
|
11795
11814
|
} catch {
|
|
@@ -11824,7 +11843,9 @@ async function runShare(rawArgs, depsOverride = {}) {
|
|
|
11824
11843
|
}
|
|
11825
11844
|
const inputPath = parsed.positionals[0];
|
|
11826
11845
|
if (!inputPath) {
|
|
11827
|
-
deps.error(
|
|
11846
|
+
deps.error(
|
|
11847
|
+
"share needs a report: executable-stories share <reports-dir|report.html|report.json>"
|
|
11848
|
+
);
|
|
11828
11849
|
deps.error(HELP2);
|
|
11829
11850
|
return EXIT_USAGE2;
|
|
11830
11851
|
}
|
|
@@ -11838,7 +11859,9 @@ async function runShare(rawArgs, depsOverride = {}) {
|
|
|
11838
11859
|
const expiresRaw = parsed.values["expires-days"];
|
|
11839
11860
|
const expiresInDays = expiresRaw === void 0 ? 30 : Number(expiresRaw);
|
|
11840
11861
|
if (!Number.isInteger(expiresInDays) || expiresInDays < 0) {
|
|
11841
|
-
deps.error(
|
|
11862
|
+
deps.error(
|
|
11863
|
+
`--expires-days takes a whole number of days (0 never expires), not "${expiresRaw}".`
|
|
11864
|
+
);
|
|
11842
11865
|
return EXIT_USAGE2;
|
|
11843
11866
|
}
|
|
11844
11867
|
let reportPath;
|
|
@@ -11846,16 +11869,23 @@ async function runShare(rawArgs, depsOverride = {}) {
|
|
|
11846
11869
|
try {
|
|
11847
11870
|
({ path: reportPath, report } = resolveReport(inputPath, deps));
|
|
11848
11871
|
} catch (err) {
|
|
11849
|
-
deps.error(
|
|
11872
|
+
deps.error(
|
|
11873
|
+
`Could not read ${inputPath}: ${err instanceof Error ? err.message : String(err)}`
|
|
11874
|
+
);
|
|
11850
11875
|
return EXIT_USAGE2;
|
|
11851
11876
|
}
|
|
11852
11877
|
const reportDir = path19.dirname(reportPath);
|
|
11853
11878
|
const { assets, missing, keyByPath } = planAssets(report, reportDir, deps);
|
|
11854
11879
|
for (const assetPath of missing) {
|
|
11855
|
-
deps.error(
|
|
11880
|
+
deps.error(
|
|
11881
|
+
`Warning: ${assetPath} is missing, so it will not be in the share.`
|
|
11882
|
+
);
|
|
11856
11883
|
}
|
|
11857
11884
|
const shareReport = {
|
|
11858
|
-
...rewriteReportAssets(
|
|
11885
|
+
...rewriteReportAssets(
|
|
11886
|
+
report,
|
|
11887
|
+
(assetPath) => keyByPath.get(assetPath) ?? assetPath
|
|
11888
|
+
),
|
|
11859
11889
|
projectRoot: ""
|
|
11860
11890
|
};
|
|
11861
11891
|
const emails = (parsed.values.emails ?? "").split(",").map((email) => email.trim()).filter(Boolean);
|
|
@@ -11864,7 +11894,10 @@ async function runShare(rawArgs, depsOverride = {}) {
|
|
|
11864
11894
|
try {
|
|
11865
11895
|
const response = await deps.fetchFn(new URL("/api/v1/shares", baseUrl), {
|
|
11866
11896
|
method: "POST",
|
|
11867
|
-
headers: {
|
|
11897
|
+
headers: {
|
|
11898
|
+
"Content-Type": "application/json",
|
|
11899
|
+
Authorization: `Bearer ${key}`
|
|
11900
|
+
},
|
|
11868
11901
|
body: JSON.stringify({
|
|
11869
11902
|
title: parsed.values.title,
|
|
11870
11903
|
report: shareReport,
|
|
@@ -11884,21 +11917,32 @@ async function runShare(rawArgs, depsOverride = {}) {
|
|
|
11884
11917
|
}
|
|
11885
11918
|
created = await response.json();
|
|
11886
11919
|
} catch (err) {
|
|
11887
|
-
deps.error(
|
|
11920
|
+
deps.error(
|
|
11921
|
+
`Could not reach ${baseUrl}: ${err instanceof Error ? err.message : String(err)}`
|
|
11922
|
+
);
|
|
11888
11923
|
return EXIT_SHARE_FAILED;
|
|
11889
11924
|
}
|
|
11890
|
-
const localByKey = new Map(
|
|
11925
|
+
const localByKey = new Map(
|
|
11926
|
+
assets.map((asset) => [asset.path, asset.localPath])
|
|
11927
|
+
);
|
|
11891
11928
|
for (const upload of created.uploads ?? []) {
|
|
11892
11929
|
const filePath = localByKey.get(upload.path);
|
|
11893
11930
|
if (filePath === void 0) {
|
|
11894
|
-
deps.error(
|
|
11931
|
+
deps.error(
|
|
11932
|
+
`Share asked for a file this report did not offer: ${upload.path}`
|
|
11933
|
+
);
|
|
11895
11934
|
return EXIT_SHARE_FAILED;
|
|
11896
11935
|
}
|
|
11897
11936
|
try {
|
|
11898
11937
|
const response = await deps.fetchFn(upload.url, {
|
|
11899
11938
|
method: "PUT",
|
|
11900
|
-
headers: {
|
|
11901
|
-
|
|
11939
|
+
headers: {
|
|
11940
|
+
"Content-Type": contentTypeFor(upload.path),
|
|
11941
|
+
...upload.headers
|
|
11942
|
+
},
|
|
11943
|
+
body: new Blob([deps.readBinary(filePath)], {
|
|
11944
|
+
type: contentTypeFor(upload.path)
|
|
11945
|
+
})
|
|
11902
11946
|
});
|
|
11903
11947
|
if (!response.ok) {
|
|
11904
11948
|
deps.error(`Upload of ${upload.path} failed: HTTP ${response.status}`);
|
|
@@ -11912,12 +11956,17 @@ async function runShare(rawArgs, depsOverride = {}) {
|
|
|
11912
11956
|
}
|
|
11913
11957
|
}
|
|
11914
11958
|
try {
|
|
11915
|
-
const response = await deps.fetchFn(
|
|
11916
|
-
|
|
11917
|
-
|
|
11918
|
-
|
|
11959
|
+
const response = await deps.fetchFn(
|
|
11960
|
+
new URL(`/api/v1/shares/${created.id}/complete`, baseUrl),
|
|
11961
|
+
{
|
|
11962
|
+
method: "POST",
|
|
11963
|
+
headers: { Authorization: `Bearer ${key}` }
|
|
11964
|
+
}
|
|
11965
|
+
);
|
|
11919
11966
|
if (!response.ok) {
|
|
11920
|
-
deps.error(
|
|
11967
|
+
deps.error(
|
|
11968
|
+
`Share could not be published: ${await describeFailure(response)}`
|
|
11969
|
+
);
|
|
11921
11970
|
return EXIT_SHARE_FAILED;
|
|
11922
11971
|
}
|
|
11923
11972
|
} catch (err) {
|
|
@@ -11926,8 +11975,15 @@ async function runShare(rawArgs, depsOverride = {}) {
|
|
|
11926
11975
|
);
|
|
11927
11976
|
return EXIT_SHARE_FAILED;
|
|
11928
11977
|
}
|
|
11978
|
+
const notStored = created.notStored ?? [];
|
|
11929
11979
|
if (parsed.values.json) {
|
|
11930
|
-
deps.log(
|
|
11980
|
+
deps.log(
|
|
11981
|
+
JSON.stringify(
|
|
11982
|
+
{ id: created.id, url: created.url, assets: assets.length, notStored },
|
|
11983
|
+
null,
|
|
11984
|
+
2
|
|
11985
|
+
)
|
|
11986
|
+
);
|
|
11931
11987
|
return EXIT_SUCCESS2;
|
|
11932
11988
|
}
|
|
11933
11989
|
const withAssets = assets.length === 1 ? "1 asset" : `${assets.length} assets`;
|
|
@@ -11936,6 +11992,9 @@ async function runShare(rawArgs, depsOverride = {}) {
|
|
|
11936
11992
|
deps.log(
|
|
11937
11993
|
emails.length > 0 ? ` Only ${emails.join(", ")} can open it, after signing in.` : " Anyone with the link can open it."
|
|
11938
11994
|
);
|
|
11995
|
+
for (const skipped of notStored) {
|
|
11996
|
+
deps.log(` Not stored: ${skipped.path} (${skipped.reason})`);
|
|
11997
|
+
}
|
|
11939
11998
|
return EXIT_SUCCESS2;
|
|
11940
11999
|
}
|
|
11941
12000
|
|