@sequenceholdings/artifact-studio 0.9.0 → 0.9.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.
@@ -1,179 +0,0 @@
1
- import yaml from 'js-yaml';
2
- const UUID_SOURCE = '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}';
3
- const SCANNED_EXTENSIONS = new Set(['.ts', '.tsx', '.mts', '.cts', '.js', '.jsx', '.mjs', '.cjs', '.json', '.yml', '.yaml']);
4
- export function originsDeclaredInFiles(files) {
5
- const origins = [];
6
- for (const file of files) {
7
- if (file.encoding === 'base64' || basename(file.path) !== 'artifact.bundle.yml')
8
- continue;
9
- for (const [name, url] of Object.entries(declaredTargets(file.content))) {
10
- try {
11
- origins.push({ name, origin: new URL(url).origin.toLowerCase() });
12
- }
13
- catch {
14
- // A target that is not a URL is reported when the selected environment is checked.
15
- }
16
- }
17
- }
18
- return origins;
19
- }
20
- export function declaredTargets(content) {
21
- let parsed;
22
- try {
23
- parsed = yaml.load(content);
24
- }
25
- catch {
26
- return {};
27
- }
28
- if (!parsed || typeof parsed !== 'object' || !('targets' in parsed))
29
- return {};
30
- const targets = parsed.targets;
31
- if (!targets || typeof targets !== 'object')
32
- return {};
33
- const urls = {};
34
- for (const [name, value] of Object.entries(targets)) {
35
- if (value && typeof value === 'object' && 'url' in value && typeof value.url === 'string')
36
- urls[name] = value.url;
37
- }
38
- return urls;
39
- }
40
- export function contentContainsOrigin(content, origin, skippedLines) {
41
- const haystack = content.toLowerCase();
42
- const needle = origin.toLowerCase();
43
- let from = 0;
44
- while (from < haystack.length) {
45
- const at = haystack.indexOf(needle, from);
46
- if (at < 0)
47
- return false;
48
- const next = haystack[at + needle.length];
49
- const line = haystack.slice(0, at).split('\n').length - 1;
50
- if (!skippedLines.has(line) && (next === undefined || !/[a-z0-9.-]/.test(next)))
51
- return true;
52
- from = at + needle.length;
53
- }
54
- return false;
55
- }
56
- /** Manifest text with the root `targets` map removed, so its URLs are declarations. */
57
- export function contentOutsideTargets(content) {
58
- let parsed;
59
- try {
60
- parsed = yaml.load(content);
61
- }
62
- catch {
63
- return content;
64
- }
65
- if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed) || !('targets' in parsed))
66
- return content;
67
- const rest = {};
68
- for (const [key, value] of Object.entries(parsed)) {
69
- if (key !== 'targets')
70
- rest[key] = value;
71
- }
72
- return yaml.dump(rest, { lineWidth: -1 });
73
- }
74
- export function collectWorkspaceSlotIds(files) {
75
- const ids = new Set();
76
- for (const file of files) {
77
- if (!scannable(file))
78
- continue;
79
- for (const workspaceId of workspaceSlotIds(file))
80
- ids.add(workspaceId);
81
- }
82
- return [...ids];
83
- }
84
- export function workspaceSlotIds(file) {
85
- const ids = new Set();
86
- if (file.path.endsWith('.yml') || file.path.endsWith('.yaml'))
87
- collectYamlWorkspaceIds(file.content, ids);
88
- const marker = /workspace/gi;
89
- let match;
90
- while ((match = marker.exec(file.content))) {
91
- const region = workspaceExpression(file.content, match.index);
92
- for (const id of region.matchAll(new RegExp(UUID_SOURCE, 'gi')))
93
- ids.add(id[0].toLowerCase());
94
- }
95
- return [...ids];
96
- }
97
- function workspaceExpression(content, start) {
98
- let depth = 0;
99
- let quote;
100
- const limit = Math.min(content.length, start + 500);
101
- for (let index = start; index < limit; index += 1) {
102
- const char = content[index] ?? '';
103
- const step = stepExpression({ char, depth, quote });
104
- depth = step.depth;
105
- quote = step.quote;
106
- if (step.skip) {
107
- index += 1;
108
- continue;
109
- }
110
- if (step.done)
111
- return content.slice(start, index);
112
- if (char === '\n' && depth === 0 && expressionEnds(content.slice(index + 1))) {
113
- return content.slice(start, index);
114
- }
115
- }
116
- return content.slice(start, limit);
117
- }
118
- function stepExpression({ char, depth, quote }) {
119
- if (quote) {
120
- if (char === '\\')
121
- return { depth, quote, skip: true };
122
- return { depth, quote: char === quote ? undefined : quote };
123
- }
124
- if (char === '"' || char === "'" || char === '`')
125
- return { depth, quote: char };
126
- if (char === '(' || char === '[' || char === '{')
127
- return { depth: depth + 1, quote };
128
- if (char === ')' || char === ']' || char === '}')
129
- return { depth: Math.max(0, depth - 1), quote };
130
- if (char === ';' && depth === 0)
131
- return { depth, quote, done: true };
132
- return { depth, quote };
133
- }
134
- function expressionEnds(rest) {
135
- const next = rest.split('\n')[0] ?? '';
136
- return next.trim() === '' || (!/^[ \t]/.test(next) && !/^[)\]},.]/.test(next.trimStart()));
137
- }
138
- export function scannable(file) {
139
- if (file.encoding === 'base64')
140
- return false;
141
- const name = basename(file.path);
142
- if (name === 'pnpm-lock.yaml' || name === 'package-lock.json' || name === 'yarn.lock' || name.endsWith('.md'))
143
- return false;
144
- if (name === '.env')
145
- return true;
146
- const extension = name.includes('.') ? name.slice(name.lastIndexOf('.')) : '';
147
- return SCANNED_EXTENSIONS.has(extension);
148
- }
149
- export function basename(path) {
150
- const parts = path.split('/');
151
- return parts[parts.length - 1] ?? path;
152
- }
153
- function collectYamlWorkspaceIds(content, ids) {
154
- let parsed;
155
- try {
156
- parsed = yaml.load(content);
157
- }
158
- catch {
159
- return;
160
- }
161
- walkYaml(parsed, null, ids);
162
- }
163
- function walkYaml(node, parentKey, ids) {
164
- if (!node || typeof node !== 'object')
165
- return;
166
- if (Array.isArray(node)) {
167
- for (const item of node)
168
- walkYaml(item, parentKey, ids);
169
- return;
170
- }
171
- for (const [key, value] of Object.entries(node)) {
172
- if (parentKey === 'storage' && new RegExp(`^${UUID_SOURCE}$`, 'i').test(key))
173
- ids.add(key.toLowerCase());
174
- if (/workspace/i.test(key) && typeof value === 'string' && new RegExp(`^${UUID_SOURCE}$`, 'i').test(value)) {
175
- ids.add(value.toLowerCase());
176
- }
177
- walkYaml(value, key, ids);
178
- }
179
- }