create-shape-app 0.1.3 → 0.1.4
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/template/release.js +80 -1
- package/package.json +1 -1
package/dist/template/release.js
CHANGED
|
@@ -23,10 +23,11 @@ export async function fetchTemplateRelease(options = {}) {
|
|
|
23
23
|
const endpoint = templateRef
|
|
24
24
|
? `https://api.github.com/repos/${owner}/${repo}/releases/tags/${encodeURIComponent(templateRef)}`
|
|
25
25
|
: `https://api.github.com/repos/${owner}/${repo}/releases/latest`;
|
|
26
|
+
const headers = buildHeaders(githubToken);
|
|
26
27
|
let response;
|
|
27
28
|
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
28
29
|
response = await fetchImpl(endpoint, {
|
|
29
|
-
headers
|
|
30
|
+
headers,
|
|
30
31
|
});
|
|
31
32
|
if (response.ok) {
|
|
32
33
|
break;
|
|
@@ -40,6 +41,37 @@ export async function fetchTemplateRelease(options = {}) {
|
|
|
40
41
|
throw new Error('Failed to resolve template release: no response received.');
|
|
41
42
|
}
|
|
42
43
|
if (!response.ok) {
|
|
44
|
+
if (response.status === 404) {
|
|
45
|
+
if (templateRef) {
|
|
46
|
+
const resolvedTag = await resolveTemplateRefTag({
|
|
47
|
+
owner,
|
|
48
|
+
repo,
|
|
49
|
+
templateRef,
|
|
50
|
+
githubToken,
|
|
51
|
+
fetchImpl,
|
|
52
|
+
});
|
|
53
|
+
if (resolvedTag) {
|
|
54
|
+
return {
|
|
55
|
+
tag: resolvedTag,
|
|
56
|
+
tarballUrl: buildTagTarballUrl(owner, repo, resolvedTag),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
const latestTag = await resolveLatestSupportedTag({
|
|
62
|
+
owner,
|
|
63
|
+
repo,
|
|
64
|
+
githubToken,
|
|
65
|
+
fetchImpl,
|
|
66
|
+
});
|
|
67
|
+
if (latestTag) {
|
|
68
|
+
return {
|
|
69
|
+
tag: latestTag,
|
|
70
|
+
tarballUrl: buildTagTarballUrl(owner, repo, latestTag),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
43
75
|
throw new Error(await buildReleaseLookupError(response, templateRef));
|
|
44
76
|
}
|
|
45
77
|
const payload = (await response.json());
|
|
@@ -54,6 +86,9 @@ export async function fetchTemplateRelease(options = {}) {
|
|
|
54
86
|
tarballUrl,
|
|
55
87
|
};
|
|
56
88
|
}
|
|
89
|
+
function buildTagTarballUrl(owner, repo, tag) {
|
|
90
|
+
return `https://api.github.com/repos/${owner}/${repo}/tarball/${encodeURIComponent(tag)}`;
|
|
91
|
+
}
|
|
57
92
|
function buildHeaders(githubToken) {
|
|
58
93
|
const headers = {
|
|
59
94
|
Accept: 'application/vnd.github+json',
|
|
@@ -84,6 +119,50 @@ async function buildReleaseLookupError(response, templateRef) {
|
|
|
84
119
|
}
|
|
85
120
|
return `Failed to resolve ${refLabel}: HTTP ${response.status}.`;
|
|
86
121
|
}
|
|
122
|
+
async function resolveLatestSupportedTag(options) {
|
|
123
|
+
const tags = await fetchTagNames(options);
|
|
124
|
+
return tags.find((tag) => isSupportedTag(tag));
|
|
125
|
+
}
|
|
126
|
+
async function resolveTemplateRefTag(options) {
|
|
127
|
+
const tags = await fetchTagNames(options);
|
|
128
|
+
const exactMatch = tags.find((tag) => tag === options.templateRef && isSupportedTag(tag));
|
|
129
|
+
if (exactMatch) {
|
|
130
|
+
return exactMatch;
|
|
131
|
+
}
|
|
132
|
+
const normalizedTemplateRef = normalizeTag(options.templateRef);
|
|
133
|
+
return tags.find((tag) => normalizeTag(tag) === normalizedTemplateRef && isSupportedTag(tag));
|
|
134
|
+
}
|
|
135
|
+
async function fetchTagNames(options) {
|
|
136
|
+
const response = await options.fetchImpl(`https://api.github.com/repos/${options.owner}/${options.repo}/tags?per_page=100`, {
|
|
137
|
+
headers: buildHeaders(options.githubToken),
|
|
138
|
+
});
|
|
139
|
+
if (!response.ok) {
|
|
140
|
+
return [];
|
|
141
|
+
}
|
|
142
|
+
const payload = (await response.json());
|
|
143
|
+
if (!Array.isArray(payload)) {
|
|
144
|
+
return [];
|
|
145
|
+
}
|
|
146
|
+
return payload.flatMap((item) => {
|
|
147
|
+
if (!item || typeof item !== 'object') {
|
|
148
|
+
return [];
|
|
149
|
+
}
|
|
150
|
+
const name = item.name;
|
|
151
|
+
return typeof name === 'string' && name.trim() ? [name] : [];
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
function isSupportedTag(tag) {
|
|
155
|
+
try {
|
|
156
|
+
assertTagIsSupported(tag);
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function normalizeTag(tag) {
|
|
164
|
+
return tag.startsWith('v') ? tag.slice(1) : tag;
|
|
165
|
+
}
|
|
87
166
|
async function readApiMessage(response) {
|
|
88
167
|
try {
|
|
89
168
|
const payload = (await response.clone().json());
|