Skip to content

Commit 76a089a

Browse files
committed
feat(compartment-mapper): Add subpath match and replace utility
1 parent 51ec9b0 commit 76a089a

File tree

3 files changed

+64
-0
lines changed

3 files changed

+64
-0
lines changed

packages/compartment-mapper/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
"dependencies": {
5858
"@endo/cjs-module-analyzer": "workspace:^",
5959
"@endo/module-source": "workspace:^",
60+
"@endo/regexp-escape": "workspace:^",
6061
"@endo/trampoline": "workspace:^",
6162
"@endo/zip": "workspace:^",
6263
"ses": "workspace:^"
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { escapeRegExp } from '@endo/regexp-escape';
2+
3+
/**
4+
* @param {string} pattern a subpath pattern of asterisk-delimited literals
5+
* @param {string} pattern of respective replacements delimited by asterisks
6+
*/
7+
export const makeSubpathReplacer = (pattern, replacement) => {
8+
const patternParts = pattern.split('*');
9+
const replacementParts = replacement.split('*');
10+
const re = new RegExp(`^${patternParts.map(escapeRegExp).join('(.*)')}$`);
11+
return path => {
12+
if (patternParts.length !== replacementParts.length) {
13+
return null;
14+
}
15+
const match = re.exec(path);
16+
if (match === null) {
17+
return null;
18+
}
19+
let reconstruction = '';
20+
let i;
21+
for (i = 0; i < replacementParts.length - 1; i++) {
22+
reconstruction += replacementParts[i] + match[i + 1];
23+
}
24+
reconstruction += replacementParts[i];
25+
return reconstruction;
26+
};
27+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import test from 'ava';
2+
import { makeSubpathReplacer } from '../src/subpath.js';
3+
4+
test('no wildcard subpath replacement', t => {
5+
const replaceSubpath = makeSubpathReplacer('a/b/c', 'x/y/z');
6+
t.is(replaceSubpath(''), null);
7+
t.is(replaceSubpath('a'), null);
8+
t.is(replaceSubpath('a/b'), null);
9+
t.is(replaceSubpath('a/b/c'), 'x/y/z');
10+
t.is(replaceSubpath('a/b/c/d'), null);
11+
});
12+
13+
test('single wildcard subpath replacement', t => {
14+
const replaceSubpath = makeSubpathReplacer('a/*/c', 'x/*/z');
15+
t.is(replaceSubpath(''), null);
16+
t.is(replaceSubpath('a'), null);
17+
t.is(replaceSubpath('a/b'), null);
18+
t.is(replaceSubpath('a/*/c'), 'x/*/z');
19+
t.is(replaceSubpath('a/b/c'), 'x/b/z');
20+
t.is(replaceSubpath('a/1/2/c'), 'x/1/2/z');
21+
});
22+
23+
test('double wildcard subpath replacement', t => {
24+
const replaceSubpath = makeSubpathReplacer('a/*/b/*/c', 'x/*/y/*/z');
25+
t.is(replaceSubpath('a/1/2/b/3/4/c'), 'x/1/2/y/3/4/z');
26+
});
27+
28+
test('double wildcard subpath replacement without slashes', t => {
29+
const replaceSubpath = makeSubpathReplacer('a*b*c', 'x*y*z');
30+
t.is(replaceSubpath('a12b34c'), 'x12y34z');
31+
});
32+
33+
test('mismatched subpath', t => {
34+
const replaceSubpath = makeSubpathReplacer('*-*', '*');
35+
t.is(replaceSubpath('1-2'), null);
36+
});

0 commit comments

Comments
 (0)