Skip to content

Commit bbbb5d4

Browse files
authored
docs(metadat): bundle metadata shape #2 @W-7263561@ (#34)
* docs(metadat): bundle metadata shape #2 * wip: add documentation * wip: second pass * wip: review comments * wip: correct types
1 parent c90df8b commit bbbb5d4

File tree

1 file changed

+235
-1
lines changed

1 file changed

+235
-1
lines changed

text/0000-canonical-metadata.md

Lines changed: 235 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1216,6 +1216,240 @@ interface StaticResourceReference {
12161216
```
12171217
</details>
12181218

1219+
## Metadata Shape Option 2
1220+
Overview:
1221+
The vision is to allow expert users to retrieve file based metadata and for the regular users to retrieve an easy, self-contained metadata object that exposes all publicly available/accessible properties of the current bundle.
1222+
1223+
The main differences in proposed shape #2:
1224+
- no decorators: external consumer shouldn't be concerned if the class fields are decorated or not. All they need is the information that describes whether the class member is public. With that, instead of collecting decorators, each class member will carry 'isPublic' property to indicate its access.
1225+
- success: an indication of successful collection. If errors occurred during the metadata collection, then 'success' will be false and diagnostics will be reported.
1226+
- diagnostics: even though metadata collection is not responsible for validating the syntax, any unexpected failures during the collection should be handled gracefully and surfaced to the user
1227+
- javascript declarations: file metadata revolves around declarations (both exported and private) - that can be functions, classes, consts, etc. The reason for this is that we don't know the content of the file and cannot make an assumption about its shape, therefore the metadata is collected from declarations.
1228+
- bundle interface: an interpretation of the bundle shape. It is an object that contains public properties, slots, events or anything that is accessible from the outside of the component/module. The reason for doing so is that individual file metadata doesn't have the notion of other files in the bundle and therefore cannot make assumption about an overall shape. With that, the interface is an additional step that attempts to deduce the shape and provide a union of all public properties.
1229+
1230+
### TypeScript
1231+
1232+
#### Root Metadata Object
1233+
```ts
1234+
interface BundleMetadata {
1235+
success: boolean;
1236+
version: string;
1237+
diagnostics: Array<Diagnostic>;
1238+
entry: string;
1239+
results: { [name: string]: FileMetadata } // metadata for each source
1240+
interface: BundleInterface; // public methods, events, css properties, exports, slots.
1241+
}
1242+
1243+
interface Diagnostic {
1244+
message: string;
1245+
code: number;
1246+
filename?: string;
1247+
location?: Location;
1248+
level: DiagnosticLevel;
1249+
}
1250+
1251+
enum DiagnosticLevel { Fatal, Error, Warning, Log }
1252+
1253+
// A bundle interface; which contains a union of all file-based
1254+
// metadata objects with some wits about inheritance and overrides.
1255+
interface BundleInterface {
1256+
type: 'module' | 'component';
1257+
eventListener: Array<EventListener>;
1258+
emittedEvents: Array<ClassEvent>;
1259+
publicProperties: Array<ClassMember>;
1260+
publicMethods: Array<ClassMember>;
1261+
slots: Array<SlotMeta>;
1262+
exports: Array<ClassMetadata | FunctionMetadata | VariableMetadata>
1263+
}
1264+
```
1265+
1266+
<details>
1267+
<summary>Click to view format</summary>
1268+
1269+
#### Root Metadata Object Per File
1270+
```ts
1271+
interface FileMetadata {
1272+
name: string,
1273+
path: string;
1274+
type: 'script' | 'html'| 'css',
1275+
dependencies: Array<Reference>, // dynamic import is treated as a module dependency type of 'dynamic'
1276+
}
1277+
1278+
interface Reference {
1279+
type: ReferenceType;
1280+
id: string;
1281+
namespacedId?: string;
1282+
file: string;
1283+
locations: Location[];
1284+
}
1285+
interface ReferenceReport {
1286+
references: Reference[];
1287+
diagnostics: Diagnostic[];
1288+
}
1289+
type ReferenceType = 'apexClass' | 'apexMethod' | 'apexContinuation' | 'client' | 'community' | 'component' | 'contentAssetUrl' | 'customPermission' | 'dynamicComponent' | 'slds' | 'messageChannel' | 'i18n' | 'gate' | 'label' | 'metric' | 'module' | 'internal' | 'resourceUrl' | 'schema' | 'sobjectClass' | 'sobjectField' | 'user' | 'userPermission';
1290+
```
1291+
1292+
For every source in the bundle there will be a corresponding typed class which extends from the base FileMetadata.
1293+
1294+
#### Script Metadata (.js|.ts)
1295+
```ts
1296+
interface ScriptMetadata extends FileMetadata {
1297+
type: 'script';
1298+
declarations: Array<ClassMetadata | FunctionMetadata | VariableMetadata>
1299+
}
1300+
1301+
interface FunctionMetadata {
1302+
name?: string;
1303+
params?: Array<any>;
1304+
returnValue?: ClassMemberValue;
1305+
context?: ClassMemberValue; // invocation context
1306+
}
1307+
1308+
interface VariableMetadata {
1309+
name?: string;
1310+
value?: ClassMemberValue;
1311+
}
1312+
1313+
interface ClassMetadata {
1314+
name?: string; // optional due to anonymous class
1315+
extends: ExtendsMeta; // id; resource; location of the super
1316+
classMembers: Array<ClassMember>; // includes private/public props/methods
1317+
documentation: ClassDocumentation;
1318+
events: Array<ClassEvent>;
1319+
listeners: Array<ClassListener> // programmatic or declarative event listeners found in the file
1320+
}
1321+
1322+
interface ClassEvent {
1323+
name: string;
1324+
className: string; // class the event is fired from
1325+
location: Location;
1326+
}
1327+
1328+
interface ClassListener {
1329+
name: string;
1330+
handlerName: string;
1331+
className: string; // class the event is fired from
1332+
location: Location;
1333+
}
1334+
1335+
interface ClassDocumentation {
1336+
classDescription: string;
1337+
html: string;
1338+
metadata: Object;
1339+
}
1340+
1341+
interface ExtendsMeta {
1342+
id: string;
1343+
type: 'class' | 'function';
1344+
resource: string;
1345+
location: Location;
1346+
}
1347+
1348+
interface ClassMember {
1349+
name: string;
1350+
type: string;
1351+
isPublic: boolean;
1352+
documentation?: ClassMemberDocumentation;
1353+
wire?: WireDependency
1354+
}
1355+
1356+
interface ClassMemberDocumentation {
1357+
description: string;
1358+
defaultValue: string;
1359+
dataType: string;
1360+
isRequired: boolean
1361+
}
1362+
1363+
interface ClassProperty extends ClassMember {
1364+
hasGetter: boolean;
1365+
hasSetter: boolean;
1366+
value?: ClassMemberValue;
1367+
}
1368+
1369+
interface ClassMethod extends ClassMember {
1370+
returnValue?: ClassMemberValue;
1371+
}
1372+
1373+
interface ClassMemberValue {
1374+
type: ClassMemberValueType;
1375+
value: any;
1376+
importedName: string;
1377+
}
1378+
1379+
enum ClassMemberValueType {
1380+
ARRAY, BOOLEAN, MODULE, NUMBER, NULL, OBJECT, STRING, UNDEFINED, UNRESOLVED,
1381+
}
1382+
1383+
interface WireDependency {
1384+
adapter: WireTargetAdapter;
1385+
params?: { [name: string]: ClassMemberValue }; // value has type and actual value
1386+
1387+
}
1388+
1389+
interface WireTargetAdapter {
1390+
adapterId: string;
1391+
moduleSpecifier: string; // points to the adapter resource
1392+
}
1393+
1394+
interface SlotMeta {
1395+
name: string;
1396+
scope: string; // parent element name
1397+
}
1398+
```
1399+
1400+
### HTML Metadata
1401+
```ts
1402+
interface HTMLMetadata extends FileMetadata {
1403+
type: 'html';
1404+
tags: Array<CustomElementMetadata>;
1405+
slots: Array<SlotMeta>;
1406+
staticResources: Array<Reference>, //images, urls, etc with location
1407+
}
1408+
1409+
interface CustomElementMetadata {
1410+
attributes: {
1411+
[name: string]: DependencyParameter;
1412+
};
1413+
properties: {
1414+
[name: string]: DependencyParameter;
1415+
};
1416+
events: Array<HTMLEventListener>, // not sure if the even belongs to a js or html meta
1417+
}
1418+
1419+
interface DependencyParameter {
1420+
type: 'literal' | 'expression';
1421+
value: string | boolean;
1422+
}
1423+
1424+
interface HTMLEventListener {
1425+
name: string;
1426+
handlerName: string;
1427+
tagName: string; // custom element the handle is attached to
1428+
location: Location;
1429+
}
1430+
```
1431+
1432+
### CSS Metadata
1433+
```ts
1434+
interface CSSMetadata extends FileMetadata {
1435+
type: 'css';
1436+
imports: Array<Reference>; // css only module imports
1437+
customProperties: Array<CssCustomProperty>;
1438+
}
1439+
1440+
interface CssCustomProperty {
1441+
external: boolean; // determines if the custom property is defined in the current file
1442+
name: string;
1443+
fallback: string;
1444+
value?: {
1445+
type: string;
1446+
value: string;
1447+
fallback: string;
1448+
}
1449+
}
1450+
```
1451+
</details>
1452+
12191453
# Open questions
12201454
* Should gathering metadata about configuration(`*.js-meta.xml`) file in a bundle be in the scope of this RFC?
12211455
* Dean Moses from Builder Framework team says it is not required.
@@ -1229,4 +1463,4 @@ interface StaticResourceReference {
12291463
- [JSON Schema type system](https://salesforce.quip.com/SH2FA614DXQO)<sup>*</sup>
12301464
- [RFC - Canonical View Metadata](https://salesforce.quip.com/ZJ93A0XQZvnU)<sup>*</sup>
12311465

1232-
<sup>*</sup> _restricted access_
1466+
<sup>*</sup> _restricted access_

0 commit comments

Comments
 (0)