@detergent-software/atk 9.0.0 → 9.1.0-dev.2
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/CHANGELOG.md +17 -0
- package/README.md +47 -42
- package/build/command-manifest.json +40 -2
- package/build/commands/search.d.ts +8 -2
- package/build/commands/search.d.ts.map +1 -1
- package/build/commands/search.js +55 -9
- package/build/commands/search.js.map +1 -1
- package/build/commands/validate.d.ts +13 -0
- package/build/commands/validate.d.ts.map +1 -0
- package/build/commands/validate.js +55 -0
- package/build/commands/validate.js.map +1 -0
- package/build/components/AssetTable.d.ts +4 -0
- package/build/components/AssetTable.d.ts.map +1 -1
- package/build/components/AssetTable.js +1 -1
- package/build/components/AssetTable.js.map +1 -1
- package/build/components/InitSuccess.d.ts.map +1 -1
- package/build/components/InitSuccess.js +1 -1
- package/build/components/InitSuccess.js.map +1 -1
- package/build/hooks/useBrowseState.d.ts.map +1 -1
- package/build/hooks/useBrowseState.js +4 -7
- package/build/hooks/useBrowseState.js.map +1 -1
- package/build/lib/init.d.ts.map +1 -1
- package/build/lib/init.js +1 -1
- package/build/lib/init.js.map +1 -1
- package/build/lib/publisher.d.ts.map +1 -1
- package/build/lib/publisher.js +26 -1
- package/build/lib/publisher.js.map +1 -1
- package/build/lib/search.d.ts +36 -9
- package/build/lib/search.d.ts.map +1 -1
- package/build/lib/search.js +138 -68
- package/build/lib/search.js.map +1 -1
- package/build/lib/validate.d.ts +30 -0
- package/build/lib/validate.d.ts.map +1 -0
- package/build/lib/validate.js +111 -0
- package/build/lib/validate.js.map +1 -0
- package/package.json +1 -1
package/build/lib/search.js
CHANGED
|
@@ -1,70 +1,127 @@
|
|
|
1
1
|
import { filterVisibleAssets, filterVisibleBundles } from './registry.js';
|
|
2
2
|
import { AssetType } from './schemas/index.js';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* Throws an Error if the type string is not recognized.
|
|
4
|
+
* Optimal string alignment distance: Levenshtein plus adjacent transpositions,
|
|
5
|
+
* so `wroktree` is one edit from `worktree`.
|
|
7
6
|
*/
|
|
8
|
-
export function
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
export function editDistance(a, b) {
|
|
8
|
+
const rows = a.length + 1;
|
|
9
|
+
const cols = b.length + 1;
|
|
10
|
+
const d = Array.from({ length: rows }, (_, i) => Array.from({ length: cols }, (_, j) => (i === 0 ? j : j === 0 ? i : 0)));
|
|
11
|
+
for (let i = 1; i < rows; i++) {
|
|
12
|
+
for (let j = 1; j < cols; j++) {
|
|
13
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
14
|
+
let best = Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost);
|
|
15
|
+
if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {
|
|
16
|
+
best = Math.min(best, d[i - 2][j - 2] + 1);
|
|
17
|
+
}
|
|
18
|
+
d[i][j] = best;
|
|
19
|
+
}
|
|
15
20
|
}
|
|
16
|
-
return
|
|
21
|
+
return d[a.length][b.length];
|
|
17
22
|
}
|
|
18
23
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* the raw tags array, the search terms, and the full query string.
|
|
24
|
+
* The one matcher `search` and `browse` share. Every term must match the name
|
|
25
|
+
* (as a substring, a whole name segment, or within a small edit distance), the
|
|
26
|
+
* description, a tag or the author; otherwise the item doesn't match (null).
|
|
27
|
+
* No terms matches everything with score 0. Higher score = better match.
|
|
24
28
|
*/
|
|
25
|
-
export function
|
|
29
|
+
export function matchItem(fields, terms) {
|
|
30
|
+
if (terms.length === 0)
|
|
31
|
+
return 0;
|
|
32
|
+
const name = fields.name.toLowerCase();
|
|
33
|
+
const nameSegments = name.split(NAME_SEPARATORS).filter(Boolean);
|
|
34
|
+
const description = fields.description.toLowerCase();
|
|
35
|
+
const descriptionWords = description.split(/[^\p{L}\p{N}]+/u).filter(Boolean);
|
|
36
|
+
const tags = fields.tags.map((t) => t.toLowerCase());
|
|
37
|
+
const author = fields.author.toLowerCase();
|
|
26
38
|
let score = 0;
|
|
27
|
-
//
|
|
28
|
-
|
|
39
|
+
// Whole-phrase bonuses: the name with its separators read as spaces counts,
|
|
40
|
+
// so `worktree kit` is an exact match for `worktree-kit`. The partial bonus
|
|
41
|
+
// needs the phrase to start a name segment, not sit inside a word.
|
|
42
|
+
const fullQuery = terms.join(' ');
|
|
43
|
+
const spacedQuery = fullQuery.split(NAME_SEPARATORS).filter(Boolean).join(' ');
|
|
44
|
+
const spacedName = nameSegments.join(' ');
|
|
45
|
+
// A query of separators alone (`-`) leaves spacedQuery empty and earns none.
|
|
46
|
+
if (spacedQuery && spacedName === spacedQuery) {
|
|
29
47
|
score += 100;
|
|
30
48
|
}
|
|
31
|
-
|
|
32
|
-
else if (name.includes(fullQuery)) {
|
|
49
|
+
else if (spacedQuery && ` ${spacedName}`.includes(` ${spacedQuery}`)) {
|
|
33
50
|
score += 50;
|
|
34
51
|
}
|
|
35
|
-
|
|
36
|
-
if (description.includes(fullQuery)) {
|
|
52
|
+
if (terms.length > 1 && description.includes(fullQuery)) {
|
|
37
53
|
score += 20;
|
|
38
54
|
}
|
|
39
|
-
//
|
|
55
|
+
// Each field scores a whole word above the start of a word, that above the
|
|
56
|
+
// middle of one (`test` in `contest`), and any literal hit above a fuzzy one.
|
|
57
|
+
// A term's own separators read as spaces, so `code_review` finds `code-review`.
|
|
58
|
+
const spacedDescription = descriptionWords.join(' ');
|
|
40
59
|
for (const term of terms) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
60
|
+
let termScore = 0;
|
|
61
|
+
const spacedTerm = term.split(NAME_SEPARATORS).filter(Boolean).join(' ');
|
|
62
|
+
const startsAWord = (spaced) => spacedTerm !== '' && ` ${spaced}`.includes(` ${spacedTerm}`);
|
|
63
|
+
if (nameSegments.includes(term)) {
|
|
64
|
+
termScore += 15;
|
|
65
|
+
}
|
|
66
|
+
else if (startsAWord(spacedName)) {
|
|
67
|
+
termScore += 10;
|
|
68
|
+
}
|
|
69
|
+
else if (name.includes(term)) {
|
|
70
|
+
termScore += 4;
|
|
71
|
+
}
|
|
72
|
+
else if (isFuzzyNameMatch(term, name, nameSegments)) {
|
|
73
|
+
termScore += 3;
|
|
44
74
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
score += 5;
|
|
75
|
+
if (descriptionWords.includes(term)) {
|
|
76
|
+
termScore += 7;
|
|
48
77
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
78
|
+
else if (startsAWord(spacedDescription)) {
|
|
79
|
+
termScore += 5;
|
|
80
|
+
}
|
|
81
|
+
else if (description.includes(term)) {
|
|
82
|
+
termScore += 2;
|
|
83
|
+
}
|
|
84
|
+
if (tags.includes(term)) {
|
|
85
|
+
termScore += 8;
|
|
86
|
+
}
|
|
87
|
+
else if (tags.some((t) => t.startsWith(term))) {
|
|
88
|
+
termScore += 6;
|
|
89
|
+
}
|
|
90
|
+
else if (tags.some((t) => t.includes(term))) {
|
|
91
|
+
termScore += 4;
|
|
52
92
|
}
|
|
53
|
-
// Author matches
|
|
54
93
|
if (author.includes(term)) {
|
|
55
|
-
|
|
94
|
+
termScore += 3;
|
|
56
95
|
}
|
|
96
|
+
if (termScore === 0)
|
|
97
|
+
return null;
|
|
98
|
+
score += termScore;
|
|
57
99
|
}
|
|
58
100
|
return score;
|
|
59
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Parse and validate a type filter string.
|
|
104
|
+
* Returns 'bundle' for the bundle type, or a validated AssetType.
|
|
105
|
+
* Throws an Error if the type string is not recognized.
|
|
106
|
+
*/
|
|
107
|
+
export function parseTypeFilter(type) {
|
|
108
|
+
if (type === 'bundle') {
|
|
109
|
+
return 'bundle';
|
|
110
|
+
}
|
|
111
|
+
const result = AssetType.safeParse(type);
|
|
112
|
+
if (!result.success) {
|
|
113
|
+
throw new Error(`Invalid type '${type}'. Valid types are: ${AssetType.options.join(', ')}, bundle`);
|
|
114
|
+
}
|
|
115
|
+
return result.data;
|
|
116
|
+
}
|
|
60
117
|
/**
|
|
61
118
|
* Search the registry for assets and bundles matching a query.
|
|
62
|
-
*
|
|
119
|
+
* Current items come first, then deprecated ones; within each, by score
|
|
120
|
+
* (highest first) or by name, with name breaking ties.
|
|
63
121
|
*/
|
|
64
122
|
export function searchRegistry(registry, options) {
|
|
65
|
-
const { org, query, tag, tool, type } = options;
|
|
66
|
-
const
|
|
67
|
-
const queryTerms = queryLower.split(/\s+/).filter(Boolean);
|
|
123
|
+
const { includeDeprecated = true, org, query, sort = 'relevance', tag, tool, type } = options;
|
|
124
|
+
const terms = tokenize(query);
|
|
68
125
|
const results = [];
|
|
69
126
|
// Filter assets and bundles through org visibility (handles shadowing and scoping)
|
|
70
127
|
const visibleAssets = filterVisibleAssets(registry, org);
|
|
@@ -81,14 +138,17 @@ export function searchRegistry(registry, options) {
|
|
|
81
138
|
continue;
|
|
82
139
|
if (tool && !latestVersion.tools.includes(tool))
|
|
83
140
|
continue;
|
|
84
|
-
|
|
141
|
+
const deprecation = deprecationOf(registry, asset.name, asset.type, asset.org);
|
|
142
|
+
if (deprecation && !includeDeprecated)
|
|
143
|
+
continue;
|
|
144
|
+
let score = matchItem({ author: latestVersion.author, description: latestVersion.description, name: asset.name, tags: asset.tags }, terms);
|
|
145
|
+
if (score === null)
|
|
146
|
+
continue;
|
|
85
147
|
// Org-scoped assets get a small scoring bonus when org is active
|
|
86
148
|
if (score > 0 && org && asset.org === org) {
|
|
87
149
|
score += 5;
|
|
88
150
|
}
|
|
89
|
-
|
|
90
|
-
results.push({ item: asset, kind: 'asset', score });
|
|
91
|
-
}
|
|
151
|
+
results.push({ ...(deprecation && { deprecation }), item: asset, kind: 'asset', score });
|
|
92
152
|
}
|
|
93
153
|
}
|
|
94
154
|
// Search bundles (skip when filtering to a specific asset type, or when tool filter is active)
|
|
@@ -97,40 +157,50 @@ export function searchRegistry(registry, options) {
|
|
|
97
157
|
for (const bundle of visibleBundles) {
|
|
98
158
|
if (tag && !bundle.tags.some((t) => t.toLowerCase() === tag.toLowerCase()))
|
|
99
159
|
continue;
|
|
100
|
-
const
|
|
101
|
-
if (
|
|
102
|
-
|
|
103
|
-
|
|
160
|
+
const deprecation = deprecationOf(registry, bundle.name, undefined, bundle.org);
|
|
161
|
+
if (deprecation && !includeDeprecated)
|
|
162
|
+
continue;
|
|
163
|
+
const score = matchItem(bundle, terms);
|
|
164
|
+
if (score === null)
|
|
165
|
+
continue;
|
|
166
|
+
results.push({ ...(deprecation && { deprecation }), item: bundle, kind: 'bundle', score });
|
|
104
167
|
}
|
|
105
168
|
}
|
|
106
169
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return b.score - a.score;
|
|
111
|
-
return a.item.name.localeCompare(b.item.name);
|
|
112
|
-
});
|
|
170
|
+
results.sort((a, b) => Number(a.deprecation !== undefined) - Number(b.deprecation !== undefined) ||
|
|
171
|
+
(sort === 'relevance' ? b.score - a.score : 0) ||
|
|
172
|
+
a.item.name.localeCompare(b.item.name));
|
|
113
173
|
return results;
|
|
114
174
|
}
|
|
175
|
+
/** Split a query into lowercase words. */
|
|
176
|
+
export function tokenize(query) {
|
|
177
|
+
return query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
178
|
+
}
|
|
179
|
+
const NAME_SEPARATORS = /[-_/.\s]+/;
|
|
115
180
|
/**
|
|
116
|
-
*
|
|
117
|
-
*
|
|
181
|
+
* The item's entry in the registry's `deprecated` list, keyed on its kind as
|
|
182
|
+
* well as (name, org): an asset's entry carries its type and a bundle's has
|
|
183
|
+
* none, so a bundle and an asset that share a name don't take each other's.
|
|
184
|
+
* An entry with no type still counts for an asset when no bundle has that
|
|
185
|
+
* name, since older entries may leave the type out.
|
|
118
186
|
*/
|
|
119
|
-
function
|
|
120
|
-
const
|
|
121
|
-
const
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
187
|
+
function deprecationOf(registry, name, type, org) {
|
|
188
|
+
const sameOrg = (other) => (other || undefined) === (org || undefined);
|
|
189
|
+
const untypedIsBundle = (registry.bundles ?? []).some((b) => b.name === name && sameOrg(b.org));
|
|
190
|
+
const entry = (registry.deprecated ?? []).find((d) => d.name === name &&
|
|
191
|
+
sameOrg(d.org) &&
|
|
192
|
+
(d.type === type || (type !== undefined && d.type === undefined && !untypedIsBundle)));
|
|
193
|
+
return entry && { reason: entry.reason, ...(entry.replacement && { replacement: entry.replacement }) };
|
|
125
194
|
}
|
|
126
195
|
/**
|
|
127
|
-
*
|
|
128
|
-
*
|
|
196
|
+
* A term of 5–7 characters may be one edit from the name or a name segment, and
|
|
197
|
+
* one of 8 or more two edits; shorter terms never match fuzzily, since one edit
|
|
198
|
+
* turns them into too many other words (`test` into `text`).
|
|
129
199
|
*/
|
|
130
|
-
function
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const
|
|
134
|
-
return
|
|
200
|
+
function isFuzzyNameMatch(term, name, nameSegments) {
|
|
201
|
+
if (term.length < 5)
|
|
202
|
+
return false;
|
|
203
|
+
const maxDistance = term.length >= 8 ? 2 : 1;
|
|
204
|
+
return [name, ...nameSegments].some((candidate) => Math.abs(candidate.length - term.length) <= maxDistance && editDistance(term, candidate) <= maxDistance);
|
|
135
205
|
}
|
|
136
206
|
//# sourceMappingURL=search.js.map
|
package/build/lib/search.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/lib/search.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/lib/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { PublishType } from './publisher.js';
|
|
2
|
+
import type { AssetType } from './schemas/index.js';
|
|
3
|
+
/** What `atk validate` found for one path. */
|
|
4
|
+
export interface PathValidation {
|
|
5
|
+
errors: string[];
|
|
6
|
+
/** Set once the path's manifest.json or bundle.json satisfies its schema. */
|
|
7
|
+
kind?: PublishType;
|
|
8
|
+
/** A bundle's members: resolved against the registry, or skipped under `--offline`. */
|
|
9
|
+
members?: 'checked' | 'skipped';
|
|
10
|
+
name?: string;
|
|
11
|
+
org?: string;
|
|
12
|
+
/** The path as the user gave it. */
|
|
13
|
+
path: string;
|
|
14
|
+
type?: AssetType;
|
|
15
|
+
valid: boolean;
|
|
16
|
+
version?: string;
|
|
17
|
+
warnings: string[];
|
|
18
|
+
}
|
|
19
|
+
export interface ValidateOutcome {
|
|
20
|
+
outcome: 'invalid' | 'valid';
|
|
21
|
+
results: PathValidation[];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Check each asset or bundle directory as `atk publish` would before it calls the API:
|
|
25
|
+
* the schema (one error per failing field), then {@link validatePublishTarget} without its
|
|
26
|
+
* org-mismatch check, which is about where the asset is published from. Only a bundle's
|
|
27
|
+
* member check reads the registry, fetched once for the run, and `--offline` skips it.
|
|
28
|
+
*/
|
|
29
|
+
export declare function validatePaths(paths: readonly string[]): Promise<ValidateOutcome>;
|
|
30
|
+
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/lib/validate.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAiB,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,KAAK,EAAE,SAAS,EAAY,MAAM,oBAAoB,CAAC;AAS9D,8CAA8C;AAC9C,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,6EAA6E;IAC7E,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,uFAAuF;IACvF,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC;IAC7B,OAAO,EAAE,cAAc,EAAE,CAAC;CAC3B;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CAOtF"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { readFile, stat } from 'node:fs/promises';
|
|
3
|
+
import { join, resolve } from 'node:path';
|
|
4
|
+
import { asSentence, errorGuidance, errorMessage } from './errors.js';
|
|
5
|
+
import { isOffline } from './offline.js';
|
|
6
|
+
import { formatZodIssues } from './parse-json.js';
|
|
7
|
+
import { validatePublishTarget } from './publisher.js';
|
|
8
|
+
import { fetchRegistry } from './registry.js';
|
|
9
|
+
import { BundleSchema, ManifestSchema } from './schemas/index.js';
|
|
10
|
+
/**
|
|
11
|
+
* Check each asset or bundle directory as `atk publish` would before it calls the API:
|
|
12
|
+
* the schema (one error per failing field), then {@link validatePublishTarget} without its
|
|
13
|
+
* org-mismatch check, which is about where the asset is published from. Only a bundle's
|
|
14
|
+
* member check reads the registry, fetched once for the run, and `--offline` skips it.
|
|
15
|
+
*/
|
|
16
|
+
export async function validatePaths(paths) {
|
|
17
|
+
let registry;
|
|
18
|
+
const results = [];
|
|
19
|
+
for (const path of paths) {
|
|
20
|
+
results.push(await validatePath(path, () => (registry ??= fetchRegistry())));
|
|
21
|
+
}
|
|
22
|
+
return { outcome: results.every((r) => r.valid) ? 'valid' : 'invalid', results };
|
|
23
|
+
}
|
|
24
|
+
async function readTarget(dir) {
|
|
25
|
+
const file = existsSync(join(dir, 'manifest.json'))
|
|
26
|
+
? 'manifest.json'
|
|
27
|
+
: existsSync(join(dir, 'bundle.json'))
|
|
28
|
+
? 'bundle.json'
|
|
29
|
+
: undefined;
|
|
30
|
+
if (!file) {
|
|
31
|
+
return { errors: [`No manifest.json or bundle.json found. Run 'atk init' to scaffold a new asset.`] };
|
|
32
|
+
}
|
|
33
|
+
let raw;
|
|
34
|
+
try {
|
|
35
|
+
raw = JSON.parse(await readFile(join(dir, file), 'utf-8'));
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
return { errors: [`${file}: ${err instanceof SyntaxError ? 'Invalid JSON' : errorMessage(err)}`] };
|
|
39
|
+
}
|
|
40
|
+
if (file === 'manifest.json') {
|
|
41
|
+
const parsed = ManifestSchema.safeParse(raw);
|
|
42
|
+
return parsed.success
|
|
43
|
+
? { target: { assetType: parsed.data.type, data: parsed.data, sourceDir: dir, type: 'asset' } }
|
|
44
|
+
: { errors: parsed.error.issues.map((issue) => `${file}: ${formatZodIssues([issue])}`) };
|
|
45
|
+
}
|
|
46
|
+
const parsed = BundleSchema.safeParse(raw);
|
|
47
|
+
return parsed.success
|
|
48
|
+
? { target: { data: parsed.data, sourceDir: dir, type: 'bundle' } }
|
|
49
|
+
: { errors: parsed.error.issues.map((issue) => `${file}: ${formatZodIssues([issue])}`) };
|
|
50
|
+
}
|
|
51
|
+
async function validatePath(path, registry) {
|
|
52
|
+
const dir = resolve(path);
|
|
53
|
+
let isDirectory;
|
|
54
|
+
try {
|
|
55
|
+
isDirectory = (await stat(dir)).isDirectory();
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
const error = err.code === 'ENOENT'
|
|
59
|
+
? `${path} does not exist.`
|
|
60
|
+
: `${path} can't be read: ${errorMessage(err)}`;
|
|
61
|
+
return { errors: [error], path, valid: false, warnings: [] };
|
|
62
|
+
}
|
|
63
|
+
if (!isDirectory) {
|
|
64
|
+
return { errors: [`${path} is not a directory.`], path, valid: false, warnings: [] };
|
|
65
|
+
}
|
|
66
|
+
const read = await readTarget(dir);
|
|
67
|
+
if ('errors' in read) {
|
|
68
|
+
return { errors: read.errors, path, valid: false, warnings: [] };
|
|
69
|
+
}
|
|
70
|
+
const { target } = read;
|
|
71
|
+
const errors = [];
|
|
72
|
+
const warnings = [];
|
|
73
|
+
let members;
|
|
74
|
+
let fetched;
|
|
75
|
+
if (target.type === 'bundle') {
|
|
76
|
+
if (isOffline()) {
|
|
77
|
+
members = 'skipped';
|
|
78
|
+
warnings.push('Bundle members were not checked against the registry (--offline).');
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
try {
|
|
82
|
+
fetched = await registry();
|
|
83
|
+
members = 'checked';
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
const { command } = errorGuidance(err);
|
|
87
|
+
errors.push(`Bundle members could not be checked against the registry: ${asSentence(errorMessage(err))} ` +
|
|
88
|
+
(command
|
|
89
|
+
? `Run '${command}', or pass --offline to skip this check.`
|
|
90
|
+
: 'Pass --offline to skip this check.'));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const result = await validatePublishTarget(target, { force: true, registry: fetched });
|
|
95
|
+
errors.push(...result.errors);
|
|
96
|
+
warnings.push(...result.warnings);
|
|
97
|
+
const { data } = target;
|
|
98
|
+
return {
|
|
99
|
+
errors,
|
|
100
|
+
kind: target.type,
|
|
101
|
+
...(members ? { members } : {}),
|
|
102
|
+
name: data.name,
|
|
103
|
+
...(data.org ? { org: data.org } : {}),
|
|
104
|
+
path,
|
|
105
|
+
...(target.assetType ? { type: target.assetType } : {}),
|
|
106
|
+
valid: errors.length === 0,
|
|
107
|
+
version: data.version,
|
|
108
|
+
warnings,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/lib/validate.ts"],"names":[],"mappings":"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"}
|