@mikro-orm/core 7.0.0-dev.107 → 7.0.0-dev.109

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.
@@ -63,7 +63,7 @@ export class FileCacheAdapter {
63
63
  let path = typeof this.options.combined === 'string'
64
64
  ? this.options.combined
65
65
  : './metadata.json';
66
- path = Utils.normalizePath(this.options.cacheDir, path);
66
+ path = fs.normalizePath(this.options.cacheDir, path);
67
67
  this.options.combined = path; // override in the options, so we can log it from the CLI in `cache:generate` command
68
68
  writeFileSync(path, JSON.stringify(this.cache, null, this.pretty ? 2 : undefined));
69
69
  return path;
@@ -73,7 +73,7 @@ export class FileCacheAdapter {
73
73
  return `${this.options.cacheDir}/${name}.json`;
74
74
  }
75
75
  getHash(origin) {
76
- origin = Utils.absolutePath(origin, this.baseDir);
76
+ origin = fs.absolutePath(origin, this.baseDir);
77
77
  if (!existsSync(origin)) {
78
78
  return null;
79
79
  }
@@ -6,6 +6,7 @@ import { WrappedEntity } from './WrappedEntity.js';
6
6
  import { ReferenceKind } from '../enums.js';
7
7
  import { helper } from './wrap.js';
8
8
  import { inspect } from '../logging/inspect.js';
9
+ import { getEnv } from '../utils/env-vars.js';
9
10
  /**
10
11
  * @internal
11
12
  */
@@ -130,7 +131,7 @@ export class EntityHelper {
130
131
  .forEach(prop => delete object[prop.name]);
131
132
  const ret = inspect(object, { depth });
132
133
  let name = this.constructor.name;
133
- const showEM = ['true', 't', '1'].includes(process.env.MIKRO_ORM_LOG_EM_ID?.toString().toLowerCase() ?? '');
134
+ const showEM = ['true', 't', '1'].includes(getEnv('MIKRO_ORM_LOG_EM_ID')?.toLowerCase() ?? '');
134
135
  if (showEM) {
135
136
  if (helper(this).__em) {
136
137
  name += ` [managed by ${helper(this).__em.id}]`;
@@ -5,5 +5,5 @@ export declare const colors: {
5
5
  yellow: (text: string) => string;
6
6
  grey: (text: string) => string;
7
7
  cyan: (text: string) => string;
8
- enabled: () => boolean | "" | undefined;
8
+ enabled: () => boolean;
9
9
  };
package/logging/colors.js CHANGED
@@ -1,9 +1,10 @@
1
- const bool = (v) => v && ['true', 't', '1'].includes(v.toLowerCase());
2
- const boolIfDefined = (v) => v != null ? bool(v) : true;
3
- const enabled = () => !bool(process.env.NO_COLOR)
4
- && !bool(process.env.MIKRO_ORM_NO_COLOR)
5
- && boolIfDefined(process.env.FORCE_COLOR)
6
- && boolIfDefined(process.env.MIKRO_ORM_COLORS);
1
+ import { getEnv } from '../utils/env-vars.js';
2
+ const bool = (k) => ['true', 't', '1'].includes(getEnv(k)?.toLowerCase() ?? '');
3
+ const boolIfDefined = (k) => getEnv(k) != null ? bool(k) : true;
4
+ const enabled = () => !bool('NO_COLOR')
5
+ && !bool('MIKRO_ORM_NO_COLOR')
6
+ && boolIfDefined('FORCE_COLOR')
7
+ && boolIfDefined('MIKRO_ORM_COLORS');
7
8
  const wrap = (fn) => (text) => enabled() ? fn(text) : text;
8
9
  /** @internal */
9
10
  export const colors = {
@@ -1,12 +1,7 @@
1
1
  let nodeInspect;
2
2
  /** @internal */
3
3
  export function inspect(value, options) {
4
- if (nodeInspect === undefined) {
5
- /* v8 ignore else */
6
- if (globalThis.process?.getBuiltinModule) {
7
- nodeInspect = globalThis.process.getBuiltinModule('node:util').inspect;
8
- }
9
- }
4
+ nodeInspect ??= globalThis.process?.getBuiltinModule?.('node:util').inspect;
10
5
  /* v8 ignore else */
11
6
  if (nodeInspect) {
12
7
  return nodeInspect(value, options);
@@ -153,15 +153,19 @@ export class MetadataDiscovery {
153
153
  const { entities, entitiesTs, baseDir } = this.config.getAll();
154
154
  const targets = (preferTs && entitiesTs.length > 0) ? entitiesTs : entities;
155
155
  const processed = [];
156
+ const paths = [];
156
157
  for (const entity of targets) {
157
158
  if (typeof entity === 'string') {
158
- const { discoverEntities } = await import('@mikro-orm/core/file-discovery');
159
- processed.push(...await discoverEntities(entity, { baseDir }));
159
+ paths.push(entity);
160
160
  }
161
161
  else {
162
162
  processed.push(entity);
163
163
  }
164
164
  }
165
+ if (paths.length > 0) {
166
+ const { discoverEntities } = await import('@mikro-orm/core/file-discovery');
167
+ processed.push(...await discoverEntities(paths, { baseDir }));
168
+ }
165
169
  return this.discoverReferences(processed);
166
170
  }
167
171
  discoverMissingTargets() {
@@ -253,7 +257,7 @@ export class MetadataDiscovery {
253
257
  const path = entity[MetadataStorage.PATH_SYMBOL];
254
258
  if (path) {
255
259
  const meta = Utils.copy(MetadataStorage.getMetadata(entity.name, path), false);
256
- meta.path = Utils.relativePath(path, this.config.get('baseDir'));
260
+ meta.path = path;
257
261
  this.metadata.set(entity.name, meta);
258
262
  }
259
263
  const exists = this.metadata.has(entity.name);
@@ -279,7 +283,7 @@ export class MetadataDiscovery {
279
283
  const path = meta.path;
280
284
  this.logger.log('discovery', `- processing entity ${colors.cyan(meta.className)}${colors.grey(path ? ` (${path})` : '')}`);
281
285
  const root = this.getRootEntity(meta);
282
- schema.meta.path = Utils.relativePath(meta.path, this.config.get('baseDir'));
286
+ schema.meta.path = meta.path;
283
287
  const cache = this.metadataProvider.getCachedMetadata(meta, root);
284
288
  if (cache) {
285
289
  this.logger.log('discovery', `- using cached metadata for entity ${colors.cyan(meta.className)}`);
@@ -4,8 +4,8 @@ import { Utils } from '../utils/Utils.js';
4
4
  import { MetadataStorage } from './MetadataStorage.js';
5
5
  import { EntitySchema } from './EntitySchema.js';
6
6
  async function getEntityClassOrSchema(filepath, allTargets, baseDir) {
7
- const path = Utils.normalizePath(baseDir, filepath);
8
- const exports = await Utils.dynamicImport(path);
7
+ const path = fs.normalizePath(baseDir, filepath);
8
+ const exports = await fs.dynamicImport(path);
9
9
  const targets = Object.values(exports);
10
10
  // ignore class implementations that are linked from an EntitySchema
11
11
  for (const item of targets) {
@@ -25,9 +25,9 @@ async function getEntityClassOrSchema(filepath, allTargets, baseDir) {
25
25
  }
26
26
  }
27
27
  export async function discoverEntities(paths, options) {
28
- paths = Utils.asArray(paths).map(path => Utils.normalizePath(path));
29
- const baseDir = options?.baseDir ?? process.cwd();
30
- const files = fs.glob(paths, Utils.normalizePath(baseDir));
28
+ paths = Utils.asArray(paths).map(path => fs.normalizePath(path));
29
+ const baseDir = fs.absolutePath(options?.baseDir ?? process.cwd());
30
+ const files = fs.glob(paths, fs.normalizePath(baseDir));
31
31
  const found = new Map();
32
32
  for (const filepath of files) {
33
33
  const filename = basename(filepath);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mikro-orm/core",
3
3
  "type": "module",
4
- "version": "7.0.0-dev.107",
4
+ "version": "7.0.0-dev.109",
5
5
  "description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
6
6
  "exports": {
7
7
  "./package.json": "./package.json",
@@ -10,6 +10,7 @@ import { RequestContext } from './RequestContext.js';
10
10
  import { DataloaderType, FlushMode, LoadStrategy, PopulateHint } from '../enums.js';
11
11
  import { MemoryCacheAdapter } from '../cache/MemoryCacheAdapter.js';
12
12
  import { EntityComparator } from './EntityComparator.js';
13
+ import { setEnv } from './env-vars.js';
13
14
  const DEFAULTS = {
14
15
  pool: {},
15
16
  entities: [],
@@ -34,7 +35,7 @@ const DEFAULTS = {
34
35
  colors: true,
35
36
  findOneOrFailHandler: (entityName, where) => NotFoundError.findOneFailed(entityName, where),
36
37
  findExactlyOneOrFailHandler: (entityName, where) => NotFoundError.findExactlyOneFailed(entityName, where),
37
- baseDir: process.cwd(),
38
+ baseDir: globalThis.process?.cwd?.(),
38
39
  hydrator: ObjectHydrator,
39
40
  flushMode: FlushMode.AUTO,
40
41
  loadStrategy: LoadStrategy.BALANCED,
@@ -135,10 +136,9 @@ export class Configuration {
135
136
  extensions = new Map();
136
137
  constructor(options, validate = true) {
137
138
  if (options.dynamicImportProvider) {
138
- Utils.dynamicImportProvider = options.dynamicImportProvider;
139
+ globalThis.dynamicImportProvider = options.dynamicImportProvider;
139
140
  }
140
141
  this.options = Utils.mergeConfig({}, DEFAULTS, options);
141
- this.options.baseDir = Utils.absolutePath(this.options.baseDir);
142
142
  if (validate) {
143
143
  this.validateOptions();
144
144
  }
@@ -328,7 +328,7 @@ export class Configuration {
328
328
  }
329
329
  }
330
330
  sync() {
331
- process.env.MIKRO_ORM_COLORS = '' + this.options.colors;
331
+ setEnv('MIKRO_ORM_COLORS', this.options.colors);
332
332
  this.logger.setDebugMode(this.options.debug);
333
333
  }
334
334
  validateOptions() {
package/utils/Utils.d.ts CHANGED
@@ -14,7 +14,6 @@ export declare function parseJsonSafe<T = unknown>(value: unknown): T;
14
14
  export declare class Utils {
15
15
  #private;
16
16
  static readonly PK_SEPARATOR = "~~~";
17
- static dynamicImportProvider: (id: string) => Promise<any>;
18
17
  /**
19
18
  * Checks if the argument is instance of `Object`. Returns false for arrays.
20
19
  */
@@ -129,25 +128,6 @@ export declare class Utils {
129
128
  */
130
129
  static runSerial<T = any, U = any>(items: Iterable<U>, cb: (item: U) => Promise<T>): Promise<T[]>;
131
130
  static isCollection<T extends object, O extends object = object>(item: any): item is Collection<T, O>;
132
- static fileURLToPath(url: string | URL): string;
133
- /**
134
- * Resolves and normalizes a series of path parts relative to each preceding part.
135
- * If any part is a `file:` URL, it is converted to a local path. If any part is an
136
- * absolute path, it replaces preceding paths (similar to `path.resolve` in NodeJS).
137
- * Trailing directory separators are removed, and all directory separators are converted
138
- * to POSIX-style separators (`/`).
139
- */
140
- static normalizePath(...parts: string[]): string;
141
- /**
142
- * Determines the relative path between two paths. If either path is a `file:` URL,
143
- * it is converted to a local path.
144
- */
145
- static relativePath(path: string, relativeTo: string): string;
146
- /**
147
- * Computes the absolute path to for the given path relative to the provided base directory.
148
- * If either `path` or `baseDir` are `file:` URLs, they are converted to local paths.
149
- */
150
- static absolutePath(path: string, baseDir?: string): string;
151
131
  static hash(data: string, length?: number): string;
152
132
  static runIfNotEmpty(clause: () => any, data: any): void;
153
133
  static defaultValue<T extends Dictionary>(prop: T, option: keyof T, defaultValue: any): void;
@@ -161,7 +141,6 @@ export declare class Utils {
161
141
  static flatten<T>(arrays: T[][]): T[];
162
142
  static isOperator(key: PropertyKey, includeGroupOperators?: boolean): boolean;
163
143
  static hasNestedKey(object: unknown, key: string): boolean;
164
- static dynamicImport<T = any>(id: string): Promise<T>;
165
144
  static getORMVersion(): string;
166
145
  static createFunction(context: Map<string, any>, code: string): any;
167
146
  static callCompiledFunction<T extends unknown[], R>(fn: (...args: T) => R, ...args: T): R;
package/utils/Utils.js CHANGED
@@ -1,5 +1,3 @@
1
- import { isAbsolute, normalize, relative } from 'node:path';
2
- import { fileURLToPath, pathToFileURL } from 'node:url';
3
1
  import { clone } from './clone.js';
4
2
  import { GroupOperator, PlainObject, QueryOperator, ReferenceKind } from '../enums.js';
5
3
  import { helper } from '../entity/wrap.js';
@@ -125,9 +123,7 @@ export function parseJsonSafe(value) {
125
123
  }
126
124
  export class Utils {
127
125
  static PK_SEPARATOR = '~~~';
128
- static #ORM_VERSION = '7.0.0-dev.107';
129
- /* v8 ignore next */
130
- static dynamicImportProvider = (id) => import(id);
126
+ static #ORM_VERSION = '7.0.0-dev.109';
131
127
  /**
132
128
  * Checks if the argument is instance of `Object`. Returns false for arrays.
133
129
  */
@@ -537,14 +533,16 @@ export class Utils {
537
533
  * Tries to detect TypeScript support.
538
534
  */
539
535
  static detectTypeScriptSupport() {
536
+ /* v8 ignore next */
537
+ const process = globalThis.process ?? {};
540
538
  /* v8 ignore next */
541
539
  return process.argv[0].endsWith('ts-node') // running via ts-node directly
542
- || !!process.env.MIKRO_ORM_CLI_ALWAYS_ALLOW_TS // forced explicitly or enabled via `registerTypeScriptSupport()`
543
- || !!process.env.TS_JEST // check if ts-jest is used (works only with v27.0.4+)
544
- || !!process.env.VITEST // check if vitest is used
545
- || !!process.versions.bun // check if bun is used
546
- || process.argv.slice(1).some(arg => arg.match(/\.([mc]?ts|tsx)$/)) // executing `.ts` file
547
- || process.execArgv.some(arg => {
540
+ || !!process.env?.MIKRO_ORM_CLI_ALWAYS_ALLOW_TS // forced explicitly or enabled via `registerTypeScriptSupport()`
541
+ || !!process.env?.TS_JEST // check if ts-jest is used
542
+ || !!process.env?.VITEST // check if vitest is used
543
+ || !!process.versions?.bun // check if bun is used
544
+ || process.argv?.slice(1).some(arg => arg.match(/\.([mc]?ts|tsx)$/)) // executing `.ts` file
545
+ || process.execArgv?.some(arg => {
548
546
  return arg.includes('ts-node') // check for ts-node loader
549
547
  || arg.includes('@swc-node/register') // check for swc-node/register loader
550
548
  || arg.includes('node_modules/tsx/'); // check for tsx loader
@@ -589,64 +587,6 @@ export class Utils {
589
587
  static isCollection(item) {
590
588
  return item?.__collection;
591
589
  }
592
- static fileURLToPath(url) {
593
- // expose `fileURLToPath` on Utils so that it can be properly mocked in tests
594
- return fileURLToPath(url);
595
- }
596
- /**
597
- * Resolves and normalizes a series of path parts relative to each preceding part.
598
- * If any part is a `file:` URL, it is converted to a local path. If any part is an
599
- * absolute path, it replaces preceding paths (similar to `path.resolve` in NodeJS).
600
- * Trailing directory separators are removed, and all directory separators are converted
601
- * to POSIX-style separators (`/`).
602
- */
603
- static normalizePath(...parts) {
604
- let start = 0;
605
- for (let i = 0; i < parts.length; i++) {
606
- const part = parts[i];
607
- if (isAbsolute(part)) {
608
- start = i;
609
- }
610
- else if (part.startsWith('file:')) {
611
- start = i;
612
- parts[i] = Utils.fileURLToPath(part);
613
- }
614
- }
615
- if (start > 0) {
616
- parts = parts.slice(start);
617
- }
618
- let path = parts.join('/').replace(/\\/g, '/').replace(/\/$/, '');
619
- path = normalize(path).replace(/\\/g, '/');
620
- return (path.match(/^[/.]|[a-zA-Z]:/) || path.startsWith('!')) ? path : './' + path;
621
- }
622
- /**
623
- * Determines the relative path between two paths. If either path is a `file:` URL,
624
- * it is converted to a local path.
625
- */
626
- static relativePath(path, relativeTo) {
627
- if (!path) {
628
- return path;
629
- }
630
- path = Utils.normalizePath(path);
631
- if (path.startsWith('.')) {
632
- return path;
633
- }
634
- path = relative(Utils.normalizePath(relativeTo), path);
635
- return Utils.normalizePath(path);
636
- }
637
- /**
638
- * Computes the absolute path to for the given path relative to the provided base directory.
639
- * If either `path` or `baseDir` are `file:` URLs, they are converted to local paths.
640
- */
641
- static absolutePath(path, baseDir = process.cwd()) {
642
- if (!path) {
643
- return Utils.normalizePath(baseDir);
644
- }
645
- if (!isAbsolute(path) && !path.startsWith('file://')) {
646
- path = baseDir + '/' + path;
647
- }
648
- return Utils.normalizePath(path);
649
- }
650
590
  // FNV-1a 64-bit
651
591
  static hash(data, length) {
652
592
  let h1 = 0xcbf29ce484222325n;
@@ -723,11 +663,6 @@ export class Utils {
723
663
  }
724
664
  return false;
725
665
  }
726
- static async dynamicImport(id) {
727
- /* v8 ignore next */
728
- const specifier = id.startsWith('file://') ? id : pathToFileURL(id).href;
729
- return this.dynamicImportProvider(specifier);
730
- }
731
666
  static getORMVersion() {
732
667
  return this.#ORM_VERSION;
733
668
  }
@@ -1,3 +1,7 @@
1
1
  import { type Options } from './Configuration.js';
2
2
  /** @internal */
3
+ export declare function setEnv(key: string, value: unknown): void;
4
+ /** @internal */
5
+ export declare function getEnv(key: string): string | undefined;
6
+ /** @internal */
3
7
  export declare function loadEnvironmentVars(): Partial<Options>;
package/utils/env-vars.js CHANGED
@@ -1,5 +1,15 @@
1
1
  import { Utils } from './Utils.js';
2
2
  /** @internal */
3
+ export function setEnv(key, value) {
4
+ if (globalThis.process?.env) {
5
+ globalThis.process.env[key] = String(value);
6
+ }
7
+ }
8
+ /** @internal */
9
+ export function getEnv(key) {
10
+ return globalThis.process?.env?.[key];
11
+ }
12
+ /** @internal */
3
13
  export function loadEnvironmentVars() {
4
14
  const ret = {};
5
15
  const getEnvKey = (key, envPrefix = 'MIKRO_ORM_') => {
@@ -13,8 +23,9 @@ export function loadEnvironmentVars() {
13
23
  const num = (v) => +v;
14
24
  const read = (o, envPrefix, key, mapper = v => v) => {
15
25
  const envKey = getEnvKey(key, envPrefix);
16
- if (envKey in process.env) {
17
- o[key] = mapper(process.env[envKey]);
26
+ /* v8 ignore next */
27
+ if (envKey in (globalThis.process?.env ?? {})) {
28
+ o[key] = mapper(getEnv(envKey));
18
29
  }
19
30
  };
20
31
  const cleanup = (o, k) => Utils.hasObjectKeys(o[k]) ? {} : delete o[k];
@@ -4,9 +4,29 @@ export declare const fs: {
4
4
  ensureDir(path: string): void;
5
5
  readJSONSync<T = Dictionary>(path: string): T;
6
6
  glob(input: string | string[], cwd?: string): string[];
7
+ resolveGlob(input: string | string[], cwd?: string): string[];
7
8
  getPackageConfig<T extends Dictionary>(basePath?: string): T;
8
9
  getORMPackages(): Set<string>;
9
10
  getORMPackageVersion(name: string): string | undefined;
10
11
  checkPackageVersion(): void;
12
+ /**
13
+ * Resolves and normalizes a series of path parts relative to each preceding part.
14
+ * If any part is a `file:` URL, it is converted to a local path. If any part is an
15
+ * absolute path, it replaces preceding paths (similar to `path.resolve` in NodeJS).
16
+ * Trailing directory separators are removed, and all directory separators are converted
17
+ * to POSIX-style separators (`/`).
18
+ */
19
+ normalizePath(...parts: string[]): string;
20
+ /**
21
+ * Determines the relative path between two paths. If either path is a `file:` URL,
22
+ * it is converted to a local path.
23
+ */
24
+ relativePath(path: string, relativeTo: string): string;
25
+ /**
26
+ * Computes the absolute path to for the given path relative to the provided base directory.
27
+ * If either `path` or `baseDir` are `file:` URLs, they are converted to local paths.
28
+ */
29
+ absolutePath(path: string, baseDir?: string): string;
30
+ dynamicImport<T = any>(id: string): Promise<T>;
11
31
  };
12
32
  export * from '../cache/FileCacheAdapter.js';
package/utils/fs-utils.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { existsSync, globSync, mkdirSync, readFileSync, realpathSync, statSync } from 'node:fs';
2
- import { join } from 'node:path';
3
- import { fileURLToPath } from 'node:url';
2
+ import { isAbsolute, join, normalize, relative } from 'node:path';
3
+ import { fileURLToPath, pathToFileURL } from 'node:url';
4
4
  import { Utils } from './Utils.js';
5
5
  import { colors } from '../logging/colors.js';
6
6
  export const fs = {
@@ -20,13 +20,34 @@ export const fs = {
20
20
  return JSON.parse(file.toString());
21
21
  },
22
22
  glob(input, cwd) {
23
+ const patterns = Array.isArray(input) ? input : [input];
24
+ const positive = [];
25
+ const negative = [];
26
+ for (const p of patterns) {
27
+ if (p.startsWith('!')) {
28
+ negative.push(p.slice(1));
29
+ }
30
+ else {
31
+ positive.push(p);
32
+ }
33
+ }
34
+ const included = new Set(this.resolveGlob(positive, cwd));
35
+ if (included.size > 0 && negative.length > 0) {
36
+ const excluded = this.resolveGlob(negative, cwd);
37
+ for (const file of excluded) {
38
+ included.delete(file);
39
+ }
40
+ }
41
+ return [...included];
42
+ },
43
+ resolveGlob(input, cwd) {
23
44
  if (Array.isArray(input)) {
24
- return input.flatMap(paths => this.glob(paths, cwd));
45
+ return input.flatMap(paths => this.resolveGlob(paths, cwd));
25
46
  }
26
47
  const hasGlobChars = /[*?[\]]/.test(input);
27
48
  if (!hasGlobChars) {
28
49
  try {
29
- const s = statSync(cwd ? Utils.normalizePath(cwd, input) : input);
50
+ const s = statSync(cwd ? this.normalizePath(cwd, input) : input);
30
51
  if (s.isDirectory()) {
31
52
  const files = globSync(join(input, '**'), { cwd, withFileTypes: true });
32
53
  return files.filter(f => f.isFile()).map(f => join(f.parentPath, f.name));
@@ -93,5 +114,65 @@ export const fs = {
93
114
  }
94
115
  }
95
116
  },
117
+ /**
118
+ * Resolves and normalizes a series of path parts relative to each preceding part.
119
+ * If any part is a `file:` URL, it is converted to a local path. If any part is an
120
+ * absolute path, it replaces preceding paths (similar to `path.resolve` in NodeJS).
121
+ * Trailing directory separators are removed, and all directory separators are converted
122
+ * to POSIX-style separators (`/`).
123
+ */
124
+ normalizePath(...parts) {
125
+ let start = 0;
126
+ for (let i = 0; i < parts.length; i++) {
127
+ const part = parts[i];
128
+ if (isAbsolute(part)) {
129
+ start = i;
130
+ }
131
+ else if (part.startsWith('file:')) {
132
+ start = i;
133
+ parts[i] = fileURLToPath(part);
134
+ }
135
+ }
136
+ if (start > 0) {
137
+ parts = parts.slice(start);
138
+ }
139
+ let path = parts.join('/').replace(/\\/g, '/').replace(/\/$/, '');
140
+ path = normalize(path).replace(/\\/g, '/');
141
+ return (path.match(/^[/.]|[a-zA-Z]:/) || path.startsWith('!')) ? path : './' + path;
142
+ },
143
+ /**
144
+ * Determines the relative path between two paths. If either path is a `file:` URL,
145
+ * it is converted to a local path.
146
+ */
147
+ relativePath(path, relativeTo) {
148
+ if (!path) {
149
+ return path;
150
+ }
151
+ path = this.normalizePath(path);
152
+ if (path.startsWith('.')) {
153
+ return path;
154
+ }
155
+ path = relative(this.normalizePath(relativeTo), path);
156
+ return this.normalizePath(path);
157
+ },
158
+ /**
159
+ * Computes the absolute path to for the given path relative to the provided base directory.
160
+ * If either `path` or `baseDir` are `file:` URLs, they are converted to local paths.
161
+ */
162
+ absolutePath(path, baseDir = process.cwd()) {
163
+ if (!path) {
164
+ return this.normalizePath(baseDir);
165
+ }
166
+ if (!isAbsolute(path) && !path.startsWith('file://')) {
167
+ path = baseDir + '/' + path;
168
+ }
169
+ return this.normalizePath(path);
170
+ },
171
+ async dynamicImport(id) {
172
+ /* v8 ignore next */
173
+ const specifier = id.startsWith('file://') ? id : pathToFileURL(id).href;
174
+ const dynamicImportProvider = globalThis.dynamicImportProvider ?? ((id) => import(id));
175
+ return dynamicImportProvider(specifier);
176
+ },
96
177
  };
97
178
  export * from '../cache/FileCacheAdapter.js';