@mesadev/sdk 0.47.3 → 0.48.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.
Files changed (71) hide show
  1. package/README.md +21 -25
  2. package/dist/api/access-token.d.ts +24 -41
  3. package/dist/api/access-token.d.ts.map +1 -1
  4. package/dist/api/access-token.js +119 -71
  5. package/dist/api/access-token.js.map +1 -1
  6. package/dist/api/client.d.ts +2 -2
  7. package/dist/api/client.d.ts.map +1 -1
  8. package/dist/api/client.js +3 -3
  9. package/dist/api/client.js.map +1 -1
  10. package/dist/api/index.d.ts +0 -1
  11. package/dist/api/index.d.ts.map +1 -1
  12. package/dist/api/index.js +0 -1
  13. package/dist/api/index.js.map +1 -1
  14. package/dist/api/{signing-key.d.ts → private-key.d.ts} +1 -1
  15. package/dist/api/{signing-key.d.ts.map → private-key.d.ts.map} +1 -1
  16. package/dist/api/{signing-key.js → private-key.js} +1 -1
  17. package/dist/api/{signing-key.js.map → private-key.js.map} +1 -1
  18. package/dist/api/repo-tag-filter.d.ts +1 -1
  19. package/dist/api/repo-tag-filter.d.ts.map +1 -1
  20. package/dist/api/repo-tag-filter.js +3 -1
  21. package/dist/api/repo-tag-filter.js.map +1 -1
  22. package/dist/api/resources.d.ts +25 -66
  23. package/dist/api/resources.d.ts.map +1 -1
  24. package/dist/api/resources.js +24 -41
  25. package/dist/api/resources.js.map +1 -1
  26. package/dist/fs/grep-pattern.d.ts +28 -0
  27. package/dist/fs/grep-pattern.d.ts.map +1 -0
  28. package/dist/fs/grep-pattern.js +172 -0
  29. package/dist/fs/grep-pattern.js.map +1 -0
  30. package/dist/fs/index.d.ts +1 -1
  31. package/dist/fs/index.d.ts.map +1 -1
  32. package/dist/fs/index.js +1 -1
  33. package/dist/fs/index.js.map +1 -1
  34. package/dist/fs/layout.d.ts +7 -25
  35. package/dist/fs/layout.d.ts.map +1 -1
  36. package/dist/fs/layout.js +2 -40
  37. package/dist/fs/layout.js.map +1 -1
  38. package/dist/fs/mesa-file-system.d.ts +37 -36
  39. package/dist/fs/mesa-file-system.d.ts.map +1 -1
  40. package/dist/fs/mesa-file-system.js +74 -30
  41. package/dist/fs/mesa-file-system.js.map +1 -1
  42. package/dist/fs/native-loader.d.ts +3 -4
  43. package/dist/fs/native-loader.d.ts.map +1 -1
  44. package/dist/fs/native-loader.js.map +1 -1
  45. package/dist/fs/search-grep.d.ts +44 -0
  46. package/dist/fs/search-grep.d.ts.map +1 -0
  47. package/dist/fs/search-grep.js +208 -0
  48. package/dist/fs/search-grep.js.map +1 -0
  49. package/dist/fs/search-rg.d.ts +204 -0
  50. package/dist/fs/search-rg.d.ts.map +1 -0
  51. package/dist/fs/search-rg.js +502 -0
  52. package/dist/fs/search-rg.js.map +1 -0
  53. package/dist/index.d.ts +4 -3
  54. package/dist/index.d.ts.map +1 -1
  55. package/dist/index.js +3 -2
  56. package/dist/index.js.map +1 -1
  57. package/dist/lib/errors.d.ts +5 -2
  58. package/dist/lib/errors.d.ts.map +1 -1
  59. package/dist/lib/errors.js +10 -4
  60. package/dist/lib/errors.js.map +1 -1
  61. package/dist/mesa.d.ts +29 -97
  62. package/dist/mesa.d.ts.map +1 -1
  63. package/dist/mesa.js +75 -153
  64. package/dist/mesa.js.map +1 -1
  65. package/dist/version.d.ts +1 -1
  66. package/dist/version.js +1 -1
  67. package/dist/webhooks/schemas.d.ts +20 -20
  68. package/dist/webhooks/schemas.d.ts.map +1 -1
  69. package/dist/webhooks/schemas.js +8 -1
  70. package/dist/webhooks/schemas.js.map +1 -1
  71. package/package.json +3 -3
@@ -0,0 +1,208 @@
1
+ /**
2
+ * A `grep -r` that searches next to the storage instead of walking the mount.
3
+ *
4
+ * This is a narrower replacement than the `rg` one, because grep's defaults
5
+ * differ from ripgrep's in ways that change answers rather than performance:
6
+ * patterns are Basic Regular Expressions, matching is case-sensitive, and
7
+ * recursion happens only with `-r` and a named path. Anything the built-in
8
+ * would reject, or answer from standard input, is left to the built-in, so a
9
+ * command line means the same thing whether or not the endpoint answered it.
10
+ *
11
+ * `-c` is left to the built-in for the same reason: grep counts every file it
12
+ * visited, printing `path:0` for the ones that did not match, and the endpoint
13
+ * reports only the files that did.
14
+ */
15
+ import { breToRustRegex, ereToRustRegex } from './grep-pattern.js';
16
+ import { absolute, belowTarget, displayPath, expandShortFlags, isDirectory, isHidden, MAX_PARALLEL_LEGS, mapBounded, mountsFromLayout, resolveLegs, searchLeg, } from './search-rg.js';
17
+ /**
18
+ * Translate a grep command line into one search, or explain why it cannot be.
19
+ *
20
+ * Only what the built-in accepts is accepted here, and only what the endpoint
21
+ * answers exactly is served. Everything else falls back.
22
+ */
23
+ export function planGrep(args, cwd, mounts) {
24
+ let pattern;
25
+ let patternFromFlag = false;
26
+ const positionals = [];
27
+ const includeGlobs = [];
28
+ const excludeGlobs = [];
29
+ let recursive = false;
30
+ let caseInsensitive = false;
31
+ let literal = false;
32
+ let extended = false;
33
+ let word = false;
34
+ let mode = 'lines';
35
+ let lineNumbers = false;
36
+ let showFilename = true;
37
+ const expanded = expandShortFlags(args, 'e');
38
+ for (let i = 0; i < expanded.length; i++) {
39
+ const arg = expanded[i] ?? '';
40
+ if (arg.startsWith('--include=') || arg.startsWith('--exclude=')) {
41
+ const glob = arg.slice('--include='.length);
42
+ // The built-in matches these against the basename alone and reads braces
43
+ // literally; the endpoint anchors a slashed glob at the repo root and
44
+ // expands braces. Neither is wrong, so neither is approximated.
45
+ if (/[/{]/.test(glob))
46
+ return { unservable: 'glob with a path or braces' };
47
+ (arg.startsWith('--include=') ? includeGlobs : excludeGlobs).push(glob);
48
+ continue;
49
+ }
50
+ if (!arg.startsWith('-') || arg === '-') {
51
+ if (pattern === undefined && !patternFromFlag)
52
+ pattern = arg;
53
+ else
54
+ positionals.push(arg);
55
+ continue;
56
+ }
57
+ switch (arg) {
58
+ case '-r':
59
+ case '-R':
60
+ case '--recursive':
61
+ recursive = true;
62
+ break;
63
+ case '-i':
64
+ case '--ignore-case':
65
+ caseInsensitive = true;
66
+ break;
67
+ case '-F':
68
+ case '--fixed-strings':
69
+ literal = true;
70
+ break;
71
+ case '-E':
72
+ case '--extended-regexp':
73
+ extended = true;
74
+ break;
75
+ case '-w':
76
+ case '--word-regexp':
77
+ word = true;
78
+ break;
79
+ case '-l':
80
+ case '--files-with-matches':
81
+ mode = 'files';
82
+ break;
83
+ case '-n':
84
+ case '--line-number':
85
+ lineNumbers = true;
86
+ break;
87
+ case '-h':
88
+ case '--no-filename':
89
+ showFilename = false;
90
+ break;
91
+ case '-e': {
92
+ const value = expanded[++i];
93
+ if (value === undefined)
94
+ return { unservable: '-e requires a pattern' };
95
+ // One pattern per search: a second would need a union the endpoint
96
+ // does not take.
97
+ if (patternFromFlag || pattern !== undefined)
98
+ return { unservable: 'more than one pattern' };
99
+ pattern = value;
100
+ patternFromFlag = true;
101
+ break;
102
+ }
103
+ default:
104
+ return { unservable: `${arg} is not supported by server-side search` };
105
+ }
106
+ }
107
+ if (pattern === undefined)
108
+ return { unservable: 'no pattern given' };
109
+ // Without -r, or without a path, the built-in reads a named file or standard
110
+ // input rather than walking anything.
111
+ if (!recursive || positionals.length === 0)
112
+ return { unservable: 'not a recursive search of a path' };
113
+ if (positionals.length > 1)
114
+ return { unservable: 'more than one search path' };
115
+ // `-F` is literal in both dialects and needs no translation.
116
+ let translated = pattern;
117
+ if (!literal) {
118
+ const converted = extended ? ereToRustRegex(pattern) : breToRustRegex(pattern);
119
+ if (converted === null)
120
+ return { unservable: 'pattern has no equivalent in the search dialect' };
121
+ translated = converted;
122
+ }
123
+ const typed = positionals[0];
124
+ const legs = resolveLegs(absolute(cwd, typed), mounts);
125
+ if ('unservable' in legs)
126
+ return legs;
127
+ return {
128
+ legs,
129
+ target: { typed, absolute: absolute(cwd, typed) },
130
+ request: {
131
+ pattern: translated,
132
+ mode,
133
+ caseMode: caseInsensitive ? 'insensitive' : 'sensitive',
134
+ literal,
135
+ word,
136
+ includeGlobs,
137
+ excludeGlobs,
138
+ },
139
+ lineNumbers,
140
+ showFilename,
141
+ };
142
+ }
143
+ /**
144
+ * Order paths the way a recursive walk over name-sorted directories visits
145
+ * them: segment by segment, so `utils/index.ts` precedes `utils.ts`.
146
+ */
147
+ function walkOrder(a, b) {
148
+ const left = a.split('/');
149
+ const right = b.split('/');
150
+ for (let i = 0; i < Math.min(left.length, right.length); i++) {
151
+ const l = left[i];
152
+ const r = right[i];
153
+ if (l !== r)
154
+ return l < r ? -1 : 1;
155
+ }
156
+ return left.length - right.length;
157
+ }
158
+ /** Render results the way grep does. `-h` does not reach `-l`, whose answer is the path. */
159
+ function format(matches, query) {
160
+ if (query.request.mode === 'files') {
161
+ return matches.map(({ path }) => `${path}\n`).join('');
162
+ }
163
+ return matches
164
+ .flatMap(({ path, match }) => match.lines.map((line) => `${query.showFilename ? `${path}:` : ''}${query.lineNumbers ? `${line.line_number}:` : ''}${line.text}\n`))
165
+ .join('');
166
+ }
167
+ /**
168
+ * Build the `grep` replacement.
169
+ *
170
+ * `fallback` runs the original command line through the built-in, and is
171
+ * called for anything this cannot answer exactly.
172
+ */
173
+ export function createSearchGrep(config, fallback) {
174
+ const mounts = mountsFromLayout(config.layout);
175
+ return {
176
+ name: 'grep',
177
+ async execute(args, ctx) {
178
+ const plan = planGrep(args, ctx.cwd, mounts);
179
+ if ('unservable' in plan || !(await isDirectory(ctx, plan.target.absolute))) {
180
+ return fallback(args, ctx);
181
+ }
182
+ let found;
183
+ try {
184
+ const perLeg = await mapBounded(plan.legs, MAX_PARALLEL_LEGS, async (leg) => {
185
+ const root = leg.mount.path === '/' ? '' : leg.mount.path;
186
+ const kept = [];
187
+ for await (const match of searchLeg(config, leg, plan.request)) {
188
+ const suffix = belowTarget(`${root}/${match.path}`, plan.target);
189
+ // The built-in walks past dot-prefixed entries during recursion,
190
+ // even though POSIX grep does not.
191
+ if (isHidden(suffix))
192
+ continue;
193
+ kept.push({ path: displayPath(suffix, plan.target), match });
194
+ }
195
+ return kept;
196
+ });
197
+ // The built-in walks the tree in sorted order and the endpoint does not.
198
+ found = perLeg.flat().sort((a, b) => walkOrder(a.path, b.path));
199
+ }
200
+ catch {
201
+ return fallback(args, ctx);
202
+ }
203
+ // grep's convention: 0 when something matched, 1 when nothing did.
204
+ return { stdout: format(found, plan), stderr: '', exitCode: found.length > 0 ? 0 : 1 };
205
+ },
206
+ };
207
+ }
208
+ //# sourceMappingURL=search-grep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-grep.js","sourceRoot":"","sources":["../../src/fs/search-grep.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,204 @@
1
+ /**
2
+ * A `rg` that searches next to the storage instead of walking the mount.
3
+ *
4
+ * just-bash's built-in `rg` reads the filesystem, which over a Mesa mount costs
5
+ * a round trip per directory. This one translates the same command line into a
6
+ * single repository search and formats the response the way ripgrep would.
7
+ *
8
+ * A path may span several repositories, because a layout can nest one mount
9
+ * inside another. Each becomes its own search, issued in parallel, with the
10
+ * parent excluding the subtrees its children shadow so no file is counted
11
+ * twice or attributed to the wrong repository.
12
+ *
13
+ * It only replaces the built-in when it can answer exactly what was asked. A
14
+ * flag it does not implement, or a path outside every mount, defers to the
15
+ * built-in, so the worst case is the behaviour that exists today rather than a
16
+ * wrong answer.
17
+ */
18
+ import type { Command, CommandContext, ExecResult } from 'just-bash';
19
+ import type { Layout } from './layout.js';
20
+ /** One repository as it appears in the mount namespace. */
21
+ export type Mount = {
22
+ /** Absolute path in the mount where this repository's root sits. */
23
+ path: string;
24
+ repo: string;
25
+ bookmark?: string;
26
+ changeId?: string;
27
+ };
28
+ /** One repository's share of a search. */
29
+ export type SearchLeg = {
30
+ mount: Mount;
31
+ /** Repo-relative directory to search under. */
32
+ pathPrefix: string;
33
+ /** Subtrees this repository owns but a nested mount covers. */
34
+ excludes: string[];
35
+ };
36
+ /** What the server needs to answer one search, across every repository it spans. */
37
+ type SearchQuery = {
38
+ legs: SearchLeg[];
39
+ /**
40
+ * The search path as the caller typed it, and its absolute form.
41
+ *
42
+ * ripgrep reports each file the way the caller named its directory: a
43
+ * relative argument yields relative output, an absolute one absolute, and no
44
+ * argument at all yields paths relative to the working directory. Results
45
+ * come back repo-relative, so both are needed to put them back.
46
+ */
47
+ target: {
48
+ typed: string;
49
+ absolute: string;
50
+ };
51
+ hidden: boolean;
52
+ request: SearchRequest;
53
+ };
54
+ /**
55
+ * One search, in the endpoint's own vocabulary rather than any command's.
56
+ *
57
+ * `rg` and `grep` disagree about defaults — smart case against case-sensitive,
58
+ * Rust regex against a translated BRE — so each planner spells out what it
59
+ * means here and the request is sent as written.
60
+ */
61
+ export type SearchRequest = {
62
+ pattern: string;
63
+ mode: 'lines' | 'count' | 'files';
64
+ caseMode: 'smart' | 'sensitive' | 'insensitive';
65
+ literal: boolean;
66
+ word: boolean;
67
+ includeGlobs: string[];
68
+ excludeGlobs: string[];
69
+ };
70
+ /**
71
+ * Searches issued at once for a single command.
72
+ *
73
+ * The server admits a small number of concurrent searches per task, so a
74
+ * layout with many nested repositories would otherwise let one `rg` fill the
75
+ * queue by itself and stall every other caller.
76
+ */
77
+ export declare const MAX_PARALLEL_LEGS = 4;
78
+ /** Why a command line could not be served, phrased for the reader of a log. */
79
+ export type Unservable = {
80
+ unservable: string;
81
+ };
82
+ export type ServerSearchConfig = {
83
+ /** Versioned API root, e.g. `https://api.mesa.dev/v1`. */
84
+ apiBaseUrl: string;
85
+ org: string;
86
+ accessToken: string;
87
+ layout: Layout;
88
+ fetch?: typeof globalThis.fetch;
89
+ };
90
+ /**
91
+ * Flatten a layout into the repository roots it presents, longest path first.
92
+ *
93
+ * A single declaration mounts at its key; an array mounts each element in a
94
+ * child directory named by its alias. Nested declarations shadow the parent at
95
+ * their own path, which is why the list is ordered longest-first: the deepest
96
+ * mount containing a path is the one that owns it.
97
+ */
98
+ export declare function mountsFromLayout(layout: Layout): Mount[];
99
+ /** Absolute form of a path as typed on the command line. */
100
+ export declare function absolute(cwd: string, path: string): string;
101
+ export declare function resolveLegs(target: string, mounts: Mount[]): SearchLeg[] | Unservable;
102
+ /**
103
+ * Translate a ripgrep command line into one search.
104
+ *
105
+ * The supported set is deliberately small. Anything else defers rather than
106
+ * approximating, because a flag that silently does nothing changes the answer.
107
+ */
108
+ export declare function planSearch(args: string[], cwd: string, mounts: Mount[]): SearchQuery | Unservable;
109
+ export type SearchMatch = {
110
+ path: string;
111
+ line_count: number;
112
+ lines: {
113
+ line_number: number;
114
+ text: string;
115
+ }[];
116
+ };
117
+ /**
118
+ * Run one leg's search, yielding each matching file as its row arrives.
119
+ *
120
+ * Shared by both command overrides so there is a single place that knows how
121
+ * the endpoint is addressed and how its rows arrive.
122
+ */
123
+ export declare function searchLeg(config: ServerSearchConfig, leg: SearchLeg, request: SearchRequest): AsyncGenerator<SearchMatch>;
124
+ /**
125
+ * Whether the search target is a directory the endpoint can search under.
126
+ *
127
+ * The endpoint's path prefix names a directory, so a file operand or a missing
128
+ * path would come back empty where the built-in prints the file's matches or
129
+ * its own error. Either way the built-in has to answer.
130
+ */
131
+ export declare function isDirectory(ctx: CommandContext, path: string): Promise<boolean>;
132
+ /** The part of a path below the directory the caller named. */
133
+ export declare function belowTarget(absolutePath: string, target: {
134
+ absolute: string;
135
+ }): string;
136
+ /**
137
+ * Name a file the way ripgrep would, given how the caller named the directory.
138
+ *
139
+ * `rg love sonnets` reports `sonnets/x.md`, `rg love /repo/sonnets` reports
140
+ * `/repo/sonnets/x.md`, and a bare `rg love` reports paths relative to the
141
+ * working directory.
142
+ */
143
+ export declare function displayPath(suffix: string, target: {
144
+ typed: string;
145
+ }): string;
146
+ /**
147
+ * Whether ripgrep would have walked past this file without opening it.
148
+ *
149
+ * ripgrep skips dot-prefixed entries during traversal, but searches a path the
150
+ * caller named explicitly even when it is hidden. Only the part below the
151
+ * named directory is examined, so `rg foo .agents` still searches `.agents`.
152
+ *
153
+ * The search endpoint does not apply this rule — hiding dotfiles is a
154
+ * convention of the command-line tool, not of the repository — so `rg` applies
155
+ * it here instead.
156
+ */
157
+ export declare function isHidden(suffix: string): boolean;
158
+ /**
159
+ * Translate one `.gitignore` line into repository-root-relative exclude globs.
160
+ *
161
+ * `dir` is the directory holding the ignore file, so a nested file's rules
162
+ * stay scoped to its own subtree. A bare name matches at any depth below that
163
+ * directory and may name either a file or a directory, so it yields both forms.
164
+ *
165
+ * Returns nothing for blanks and comments, and `null` for a negation, which
166
+ * the exclude parameter cannot express: the server prefixes every exclude with
167
+ * `!` already, so a re-inclusion would arrive as a double negation.
168
+ */
169
+ export declare function gitignoreLineToGlobs(line: string, dir: string): string[] | null;
170
+ /**
171
+ * Every ignore rule in a subtree, as exclude globs, or `null` when one of them
172
+ * cannot be expressed and the caller should fall back.
173
+ *
174
+ * The ignore files are read through the search endpoint rather than the mount:
175
+ * one request returns the contents of every `.gitignore` under the path, where
176
+ * walking the tree for them would cost the round trips this command exists to
177
+ * avoid.
178
+ */
179
+ export declare function gitignoreExcludes(files: {
180
+ path: string;
181
+ lines: string[];
182
+ }[]): string[] | null;
183
+ /**
184
+ * Split clustered short flags into separate ones.
185
+ *
186
+ * `-rn` means `-r -n`, which is how people actually type these commands. The
187
+ * built-in clusters boolean flags only — `-re PATTERN` is an error there rather
188
+ * than a pattern flag — so a cluster naming any flag that takes a value is left
189
+ * whole, and the built-in gets to reject it in its own words.
190
+ *
191
+ * `valueFlags` is the set of short flags that consume the next argument.
192
+ */
193
+ export declare function expandShortFlags(args: string[], valueFlags: string): string[];
194
+ /** Run `work` over `items`, at most `limit` at a time, preserving input order. */
195
+ export declare function mapBounded<T, R>(items: T[], limit: number, work: (item: T) => Promise<R>): Promise<R[]>;
196
+ /**
197
+ * Build the `rg` replacement.
198
+ *
199
+ * `fallback` runs the original command line through the built-in, and is called
200
+ * whenever this command cannot answer precisely.
201
+ */
202
+ export declare function createSearchRg(config: ServerSearchConfig, fallback: (args: string[], ctx: CommandContext) => Promise<ExecResult>): Command;
203
+ export {};
204
+ //# sourceMappingURL=search-rg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-rg.d.ts","sourceRoot":"","sources":["../../src/fs/search-rg.ts"],"names":[],"mappings":"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"}