consume: Add support for asXFilePath methods and add asKey method to get a Consumer for the property key
MODIFY
packages/@romejs/codec-js-manifest/index.ts
packages/@romejs/codec-js-manifest/index.ts
@@ -433,9 +433,15 @@ function normalizeExports(consumer: Consumer): boolean | ManifestExports {
for (const [relative, value] of consumer.asMap()) {
// If it's not a relative path then it's a platform for the root
if (relative[0] !== '.') {
+ if (exports.size > 0) {
+ value.unexpected(
+ 'Cannot mix a root conditional export with relative paths',
+ );
+ }
+
dotConditions.set(relative, {
consumer: value,
- relative: createRelativeFilePath(value.asString()),
+ relative: value.asExplicitRelativeFilePath(),
});
continue;
}
@@ -451,13 +457,13 @@ function normalizeExports(consumer: Consumer): boolean | ManifestExports {
if (typeof value.asUnknown() === 'string') {
conditions.set('default', {
consumer: value,
- relative: createRelativeFilePath(value.asString()),
+ relative: value.asExplicitRelativeFilePath(),
});
} else {
for (const [type, relativeAlias] of value.asMap()) {
conditions.set(type, {
consumer: relativeAlias,
- relative: createRelativeFilePath(relativeAlias.asString()),
+ relative: relativeAlias.asExplicitRelativeFilePath(),
});
}
}
@@ -466,7 +472,7 @@ function normalizeExports(consumer: Consumer): boolean | ManifestExports {
exports.set(createRelativeFilePath('.'), dotConditions);
}
- exports.set(createRelativeFilePath(relative), conditions);
+ exports.set(value.getKey().asExplicitRelativeFilePath(), conditions);
}
return exports;

MODIFY
packages/@romejs/consume/Consumer.ts
packages/@romejs/consume/Consumer.ts
@@ -42,7 +42,16 @@ import {
} from '@romejs/ob1';
import {isValidIdentifierName} from '@romejs/js-ast-utils';
import {escapeString} from '@romejs/string-escape';
-import {UnknownFilePath} from '@romejs/path';
+import {
+ UnknownFilePath,
+ RelativeFilePath,
+ URLFilePath,
+ createUnknownFilePath,
+ createRelativeFilePath,
+ AbsoluteFilePath,
+ createURLFilePath,
+ createAbsoluteFilePath,
+} from '@romejs/path';
type UnexpectedConsumerOptions = {
loc?: SourceLocation;
@@ -99,6 +108,7 @@ export default class Consumer {
this.propertyMetadata = opts.propertyMetadata;
this.usedNames = new Set();
this.forkCache = new Map();
+ this.forceDiagnosticTarget = opts.forceDiagnosticTarget;
// See shouldDispatchUnexpected for explanation
this.hasHandledUnexpected = false;
@@ -118,6 +128,7 @@ export default class Consumer {
usedNames: Set<string>;
forkCache: Map<string, Consumer>;
hasHandledUnexpected: boolean;
+ forceDiagnosticTarget: undefined | ConsumeSourceLocationRequestTarget;
async capture<T>(
callback: (consumer: Consumer) => Promise<T> | T,
@@ -176,6 +187,10 @@ export default class Consumer {
getDiagnosticPointer(
target: ConsumeSourceLocationRequestTarget = 'all',
): undefined | DiagnosticPointer {
+ const {forceDiagnosticTarget} = this;
+ if (forceDiagnosticTarget !== undefined) {
+ target = forceDiagnosticTarget;
+ }
return this.context.getDiagnosticPointer(this.keyPath, target);
}
@@ -228,7 +243,14 @@ export default class Consumer {
};
}
- getKey(): ConsumeKey {
+ getKey(): Consumer {
+ return this.clone({
+ forceDiagnosticTarget: 'key',
+ value: this.getParentKey(),
+ });
+ }
+
+ getParentKey(): ConsumeKey {
return this.keyPath[this.keyPath.length - 1];
}
@@ -464,7 +486,7 @@ export default class Consumer {
// Mutate the parent
const parentObj = parent.asUnknownObject();
- const key = this.getKey();
+ const key = this.getParentKey();
parentObj[String(key)] = value;
parent.setValue(parentObj);
@@ -866,6 +888,55 @@ export default class Consumer {
return BigInt('0');
}
+ // PATHS
+
+ asURLFilePath(): URLFilePath {
+ const path = this.asUnknownFilePath();
+ if (path.isURL()) {
+ return path.assertURL();
+ } else {
+ this.unexpected('Expected a URL');
+ return createURLFilePath('unknown://').append(path);
+ }
+ }
+
+ asUnknownFilePath(): UnknownFilePath {
+ return createUnknownFilePath(this.asString());
+ }
+
+ asAbsoluteFilePath(): AbsoluteFilePath {
+ const path = this.asUnknownFilePath();
+ if (path.isAbsolute()) {
+ return path.assertAbsolute();
+ } else {
+ this.unexpected('Expected an absolute file path');
+ return createAbsoluteFilePath('/').append(path);
+ }
+ }
+
+ asRelativeFilePath(): RelativeFilePath {
+ const path = this.asUnknownFilePath();
+ if (path.isRelative()) {
+ return path.assertRelative();
+ } else {
+ this.unexpected('Expected a relative file path');
+ return path.toExplicitRelative();
+ }
+ }
+
+ asExplicitRelativeFilePath(): RelativeFilePath {
+ const path = this.asRelativeFilePath();
+
+ if (path.isExplicitRelative()) {
+ return path;
+ } else {
+ this.unexpected(
+ 'Expected an explicit relative file path. This is one that starts with <emphasis>./</emphasis> or <emphasis>../</emphasis>',
+ );
+ return path.toExplicitRelative();
+ }
+ }
+
// NUMBER
asNumberOrVoid(def?: number): undefined | number {

MODIFY
packages/@romejs/consume/types.ts
packages/@romejs/consume/types.ts
@@ -70,12 +70,13 @@ export type ConsumerOnDefinition = (
export type ConsumerHandleUnexpected = (diagnostic: PartialDiagnostic) => void;
export type ConsumerOptions = {
- handleUnexpectedDiagnostic: undefined | ConsumerHandleUnexpected;
- onDefinition: undefined | ConsumerOnDefinition;
- propertyMetadata: undefined | ConsumePropertyMetadata;
- filePath: undefined | UnknownFilePath;
+ handleUnexpectedDiagnostic?: ConsumerHandleUnexpected;
+ onDefinition?: ConsumerOnDefinition;
+ propertyMetadata?: ConsumePropertyMetadata;
+ filePath?: UnknownFilePath;
objectPath: ConsumePath;
context: ConsumeContext;
value: unknown;
- parent: undefined | Consumer;
+ parent?: Consumer;
+ forceDiagnosticTarget?: ConsumeSourceLocationRequestTarget;
};

consume: Add support for asXFilePath methods and add asKey method to get a Consumer for the property key