Skip to content

Commit 75d9d29

Browse files
Fix bug with storing element declaration references (#1372)
1 parent c8f6c1a commit 75d9d29

File tree

11 files changed

+1529
-8
lines changed

11 files changed

+1529
-8
lines changed

packages/catalog-server/src/lib/firestore/firestore-repository.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -342,14 +342,17 @@ export class FirestoreRepository implements Repository {
342342
className: c.declaration.name,
343343
customElementExport: referenceString(
344344
packageName,
345-
c.module,
345+
c.module.path,
346346
c.export.name
347347
),
348-
declaration: referenceString(packageName, c.module, c.declaration.name),
348+
declaration: referenceString(
349+
packageName,
350+
c.declarationReference.module ?? c.module.path,
351+
c.declaration.name
352+
),
349353
searchTerms,
350354
});
351355
}
352-
353356
await batch.commit();
354357
}
355358

packages/catalog-server/src/test/lib/catalog_test.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,27 @@ import {
1818
} from '@webcomponents/catalog-api/lib/schema.js';
1919
import {fileURLToPath} from 'url';
2020
import {Temporal} from '@js-temporal/polyfill';
21+
import {
22+
getModule,
23+
parseReferenceString,
24+
resolveReference,
25+
} from '@webcomponents/custom-elements-manifest-tools';
2126

2227
const test = suite('Catalog tests');
2328

2429
const testPackage1Path = fileURLToPath(
2530
new URL('../test-packages/test-1/', import.meta.url)
2631
);
32+
const testPackage2Path = fileURLToPath(
33+
new URL('../test-packages/test-2/', import.meta.url)
34+
);
2735

2836
// A set of import, fetch, search tests that use the same data
2937
const TEST_SEQUENCE_ONE = 'test-data-1';
3038

3139
// Other tests than can run independently
3240
const TEST_SEQUENCE_TWO = 'test-data-2';
41+
const TEST_SEQUENCE_THREE = 'test-data-3';
3342

3443
test('Imports a package with no problems', async () => {
3544
const packageName = 'test-1';
@@ -223,4 +232,57 @@ test('Updates a package', async () => {
223232
assert.equal(isReadablePackageVersion(result), true);
224233
});
225234

235+
test('Imports a package with separate define and implementation modules', async () => {
236+
const packageName = 'test-2';
237+
const version = '1.0.0';
238+
const files = new LocalFsPackageFiles({
239+
path: testPackage2Path,
240+
packageName,
241+
publishedVersions: ['1.0.0'],
242+
distTags: {
243+
latest: '1.0.0',
244+
},
245+
});
246+
const repository = new FirestoreRepository(TEST_SEQUENCE_THREE);
247+
const catalog = new Catalog({files, repository});
248+
await catalog.importPackage(packageName);
249+
250+
const packageVersion = (await catalog.getPackageVersion(
251+
packageName,
252+
version
253+
)) as ReadablePackageVersion;
254+
255+
const customElements = await catalog.getCustomElements(
256+
packageName,
257+
version,
258+
undefined
259+
);
260+
261+
assert.ok(packageVersion.customElementsManifest);
262+
const manifest =
263+
packageVersion.customElementsManifest !== undefined &&
264+
JSON.parse(packageVersion.customElementsManifest);
265+
266+
assert.ok(customElements);
267+
const fooElement = customElements.find((c) => c.tagName === 'foo-element');
268+
assert.ok(fooElement);
269+
assert.ok(fooElement.declaration);
270+
271+
const declarationRefString = fooElement.declaration;
272+
const declarationRef = parseReferenceString(declarationRefString);
273+
assert.ok(declarationRef.module);
274+
275+
const module = getModule(manifest, declarationRef.module);
276+
assert.ok(module);
277+
278+
const declaration = resolveReference(
279+
manifest,
280+
module,
281+
declarationRef,
282+
packageName,
283+
''
284+
);
285+
assert.ok(declaration);
286+
});
287+
226288
test.run();
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"schemaVersion": "1.0.0",
3+
"description": "A set of cool elements",
4+
"modules": [
5+
{
6+
"kind": "javascript-module",
7+
"path": "foo.js",
8+
"exports": [
9+
{
10+
"kind": "custom-element-definition",
11+
"name": "foo-element",
12+
"declaration": {
13+
"name": "FooElement",
14+
"module": "/foo-impl.js"
15+
}
16+
}
17+
],
18+
"declarations": []
19+
},
20+
{
21+
"kind": "javascript-module",
22+
"path": "foo-impl.js",
23+
"exports": [
24+
{
25+
"kind": "js",
26+
"name": "FooElement",
27+
"declaration": {
28+
"name": "FooElement"
29+
}
30+
}
31+
],
32+
"declarations": [
33+
{
34+
"kind": "class",
35+
"customElement": true,
36+
"tagName": "foo-element",
37+
"name": "FooElement",
38+
"superclass": {
39+
"name": "HTMLElement"
40+
}
41+
}
42+
]
43+
}
44+
]
45+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"name": "test-2",
3+
"version": "1.0.0",
4+
"description": "A set of cool elements",
5+
"customElements": "custom-elements.json"
6+
}

packages/custom-elements-manifest-tools/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"lib/",
2727
"test/",
2828
"!test/test-data/shoelace-2.0.0-beta.83.json",
29+
"!test/test-data/lion-button-0.18.1.json",
2930
"tsconfig.tsbuildinfo"
3031
],
3132
"clean": "if-file-deleted"
@@ -36,7 +37,8 @@
3637
"build"
3738
],
3839
"files": [
39-
"test/test-data/shoelace-2.0.0-beta.83.json"
40+
"test/test-data/shoelace-2.0.0-beta.83.json",
41+
"test/test-data/lion-button-0.18.1.json"
4042
],
4143
"output": []
4244
}

packages/custom-elements-manifest-tools/src/lib/get-custom-elements.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type {
99
CustomElementExport,
1010
Module,
1111
Package,
12+
Reference,
1213
} from 'custom-elements-manifest/schema.js';
1314
import {isCustomElementDeclaration} from './predicates.js';
1415
import {resolveReference} from './resolve-reference.js';
@@ -18,6 +19,7 @@ export type CustomElementInfo = {
1819
module: Module;
1920
export: CustomElementExport;
2021
declaration: CustomElementDeclaration;
22+
declarationReference: Reference;
2123
};
2224

2325
/**
@@ -48,6 +50,7 @@ export const getCustomElements = (
4850
module: mod,
4951
export: e,
5052
declaration: decl,
53+
declarationReference: e.declaration,
5154
});
5255
} else {
5356
// This is some kind of manifest error, should we warn?

packages/custom-elements-manifest-tools/src/lib/reference-string.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7-
import type {Module, Reference} from 'custom-elements-manifest/schema.js';
7+
import type {Reference} from 'custom-elements-manifest/schema.js';
88

99
/**
1010
* Serializes a reference to a string, as used in the GraphQL API of the
@@ -15,10 +15,13 @@ import type {Module, Reference} from 'custom-elements-manifest/schema.js';
1515
*/
1616
export const referenceString = (
1717
packageName: string,
18-
mod: Module,
18+
modulePath: string,
1919
name: string
2020
) => {
21-
return `${packageName}/${mod.path}#${name}`;
21+
if (modulePath.startsWith('/')) {
22+
modulePath = modulePath.substring(1);
23+
}
24+
return `${packageName}/${modulePath}#${name}`;
2225
};
2326

2427
/**

packages/custom-elements-manifest-tools/src/test/lib/get-custom-elements_test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,22 @@ test('Get elements from Shoelace', async () => {
101101
assert.equal(customElements.length, 54);
102102
});
103103

104+
test('Get elements from @liton/burron', async () => {
105+
const manifestPath = fileURLToPath(
106+
new URL('../test-data/lion-button-0.18.1.json', import.meta.url)
107+
);
108+
const manifestSource = await readFile(manifestPath, 'utf-8');
109+
const manifest = JSON.parse(manifestSource);
110+
const customElements = getCustomElements(
111+
manifest,
112+
'@lion/button',
113+
'0.18.1'
114+
);
115+
assert.equal(customElements.length, 3);
116+
117+
const element = customElements.find((e) => e.export.name === 'lion-button-submit');
118+
assert.ok(element);
119+
assert.ok(element.declaration);
120+
});
121+
104122
test.run();

packages/custom-elements-manifest-tools/src/test/lib/resolve-reference_test.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,42 @@ const pkg: Package = {
4848
},
4949
],
5050
},
51+
{
52+
kind: 'javascript-module',
53+
path: 'x-foo.js',
54+
declarations: [],
55+
exports: [
56+
{
57+
kind: 'custom-element-definition',
58+
name: 'x-foo',
59+
declaration: {
60+
name: 'XFoo',
61+
module: '/src/components/x-foo.js',
62+
},
63+
},
64+
],
65+
},
66+
{
67+
kind: 'javascript-module',
68+
path: 'src/components/x-foo.js',
69+
declarations: [
70+
{
71+
kind: 'class',
72+
name: 'XFoo',
73+
customElement: true,
74+
},
75+
],
76+
exports: [
77+
{
78+
kind: 'js',
79+
name: 'XFoo',
80+
declaration: {
81+
name: 'XFoo',
82+
module: 'src/components/x-foo.js',
83+
},
84+
},
85+
],
86+
},
5187
],
5288
};
5389

@@ -120,4 +156,19 @@ test('cross-package references are unsupported', () => {
120156
assert.equal(result, undefined);
121157
});
122158

159+
test(`resolves a custom element defintion to it's declaration`, () => {
160+
const definitionModule = pkg.modules.find((m) => m.path === 'x-foo.js')!;
161+
const elementExport = definitionModule.exports![0];
162+
const declarationReference = elementExport!.declaration;
163+
const result = resolveReference(
164+
pkg,
165+
definitionModule,
166+
declarationReference,
167+
'test-package',
168+
'1.0.0'
169+
);
170+
console.log('result', result);
171+
assert.ok(result);
172+
});
173+
123174
test.run();

0 commit comments

Comments
 (0)