@fluojs/testing 1.0.5 → 2.0.0

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.
@@ -1,62 +1,117 @@
1
- import { existsSync, readFileSync, readdirSync } from 'node:fs';
2
- import { extname, join, relative, sep } from 'node:path';
1
+ import { existsSync, readdirSync, readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
4
  import { defineConfig, mergeConfig } from 'vitest/config';
5
5
  import { fluoBabelDecoratorsPlugin } from '../vitest.js';
6
6
  const workspaceAliasCache = new Map();
7
- function collectSourceEntries(sourceRoot) {
8
- const entries = [];
9
- for (const directoryEntry of readdirSync(sourceRoot, {
10
- withFileTypes: true
11
- })) {
12
- const entryPath = join(sourceRoot, directoryEntry.name);
13
- if (directoryEntry.isDirectory()) {
14
- entries.push(...collectSourceEntries(entryPath));
7
+ const runtimeExportConditions = ['import', 'default', 'node', 'browser', 'worker'];
8
+ const typeOnlyExportConditions = new Set(['types', 'typings']);
9
+ const javascriptExtensions = ['.js', '.mjs', '.cjs'];
10
+ function isRecord(value) {
11
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
12
+ }
13
+ function collectExportEntries(exportsField) {
14
+ if (typeof exportsField === 'string' || Array.isArray(exportsField)) {
15
+ return [['.', exportsField]];
16
+ }
17
+ if (!isRecord(exportsField)) {
18
+ return [];
19
+ }
20
+ const entries = Object.entries(exportsField);
21
+ const hasSubpathKeys = entries.some(([subpath]) => subpath === '.' || subpath.startsWith('./'));
22
+ if (!hasSubpathKeys) {
23
+ return [['.', exportsField]];
24
+ }
25
+ return entries.filter(([subpath]) => subpath === '.' || subpath.startsWith('./'));
26
+ }
27
+ function resolveRuntimeExportTarget(exportTarget) {
28
+ if (typeof exportTarget === 'string') {
29
+ return exportTarget;
30
+ }
31
+ if (Array.isArray(exportTarget)) {
32
+ for (const candidate of exportTarget) {
33
+ const resolvedCandidate = resolveRuntimeExportTarget(candidate);
34
+ if (resolvedCandidate) {
35
+ return resolvedCandidate;
36
+ }
37
+ }
38
+ return undefined;
39
+ }
40
+ if (!isRecord(exportTarget)) {
41
+ return undefined;
42
+ }
43
+ for (const condition of runtimeExportConditions) {
44
+ const resolvedCondition = resolveRuntimeExportTarget(exportTarget[condition]);
45
+ if (resolvedCondition) {
46
+ return resolvedCondition;
47
+ }
48
+ }
49
+ for (const [condition, nestedTarget] of Object.entries(exportTarget)) {
50
+ if (typeOnlyExportConditions.has(condition)) {
15
51
  continue;
16
52
  }
17
- if (directoryEntry.isFile()) {
18
- entries.push(entryPath);
53
+ const resolvedNestedTarget = resolveRuntimeExportTarget(nestedTarget);
54
+ if (resolvedNestedTarget) {
55
+ return resolvedNestedTarget;
19
56
  }
20
57
  }
21
- return entries;
58
+ return undefined;
59
+ }
60
+ function resolveSourcePathFromExportTarget(packageRoot, exportTarget) {
61
+ const runtimeTarget = resolveRuntimeExportTarget(exportTarget);
62
+ if (!runtimeTarget?.startsWith('./dist/')) {
63
+ return undefined;
64
+ }
65
+ for (const extension of javascriptExtensions) {
66
+ if (!runtimeTarget.endsWith(extension)) {
67
+ continue;
68
+ }
69
+ const sourcePath = join(packageRoot, 'src', `${runtimeTarget.slice('./dist/'.length, -extension.length)}.ts`);
70
+ if (existsSync(sourcePath)) {
71
+ return sourcePath;
72
+ }
73
+ }
74
+ return undefined;
75
+ }
76
+ function toAliasName(packageName, exportSubpath) {
77
+ if (exportSubpath === '.') {
78
+ return packageName;
79
+ }
80
+ return `${packageName}/${exportSubpath.slice('./'.length)}`;
22
81
  }
23
82
  function collectWorkspaceAliasesFromRoot(repoRoot) {
24
83
  const packagesRoot = join(repoRoot, 'packages');
25
84
  const aliases = {};
26
85
  for (const packageDirectoryName of readdirSync(packagesRoot)) {
27
86
  const packageRoot = join(packagesRoot, packageDirectoryName);
28
- const sourceRoot = join(packageRoot, 'src');
29
87
  const manifestPath = join(packageRoot, 'package.json');
30
- if (!existsSync(sourceRoot) || !existsSync(manifestPath)) {
88
+ if (!existsSync(manifestPath)) {
31
89
  continue;
32
90
  }
33
91
  const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
34
- const scopeName = manifest.name ?? `@fluojs/${packageDirectoryName}`;
35
- for (const sourceEntryPath of collectSourceEntries(sourceRoot)) {
36
- const relativeSourceEntry = relative(sourceRoot, sourceEntryPath);
37
- if (extname(sourceEntryPath) !== '.ts' || relativeSourceEntry.endsWith('.test.ts') || relativeSourceEntry === 'index.ts') {
38
- continue;
39
- }
40
- const subpath = relativeSourceEntry.slice(0, -3).split(sep).join('/');
41
- aliases[`${scopeName}/${subpath}`] = sourceEntryPath;
42
- }
43
- const indexPath = join(sourceRoot, 'index.ts');
44
- if (existsSync(indexPath)) {
45
- aliases[scopeName] = indexPath;
92
+ const packageName = manifest.name ?? `@fluojs/${packageDirectoryName}`;
93
+ const exportAliases = collectExportEntries(manifest.exports).map(([exportSubpath, exportTarget]) => {
94
+ const sourcePath = resolveSourcePathFromExportTarget(packageRoot, exportTarget);
95
+ return sourcePath ? {
96
+ aliasName: toAliasName(packageName, exportSubpath),
97
+ sourcePath
98
+ } : undefined;
99
+ }).filter(entry => entry !== undefined).sort((left, right) => right.aliasName.length - left.aliasName.length);
100
+ for (const {
101
+ aliasName,
102
+ sourcePath
103
+ } of exportAliases) {
104
+ aliases[aliasName] = sourcePath;
46
105
  }
47
106
  }
48
- return {
49
- '@fluojs/runtime/internal/http-adapter': join(packagesRoot, 'runtime', 'src', 'internal-http-adapter.ts'),
50
- '@fluojs/runtime/internal/request-response-factory': join(packagesRoot, 'runtime', 'src', 'internal-request-response-factory.ts'),
51
- ...aliases
52
- };
107
+ return aliases;
53
108
  }
54
109
 
55
110
  /**
56
- * Collects source-file aliases for a fluo monorepo checkout.
111
+ * Collects package-export aliases for a fluo monorepo checkout.
57
112
  *
58
113
  * @param repoRootUrl - Repository root as a file URL or absolute path URL string.
59
- * @returns A Vite/Vitest alias map that points public package imports at workspace source files.
114
+ * @returns A Vite/Vitest alias map that points exported package imports at workspace source files.
60
115
  */
61
116
  export function collectWorkspaceAliases(repoRootUrl) {
62
117
  const repoRoot = fileURLToPath(repoRootUrl);
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "override",
10
10
  "module-builder"
11
11
  ],
12
- "version": "1.0.5",
12
+ "version": "2.0.0",
13
13
  "private": false,
14
14
  "license": "MIT",
15
15
  "repository": {
@@ -80,11 +80,11 @@
80
80
  "dist"
81
81
  ],
82
82
  "dependencies": {
83
- "@fluojs/config": "^1.0.2",
84
- "@fluojs/http": "^1.1.0",
85
- "@fluojs/di": "^1.1.0",
86
- "@fluojs/core": "^1.0.3",
87
- "@fluojs/runtime": "^1.1.6"
83
+ "@fluojs/config": "^1.0.4",
84
+ "@fluojs/core": "^1.1.0",
85
+ "@fluojs/http": "^2.0.1",
86
+ "@fluojs/di": "^2.0.0",
87
+ "@fluojs/runtime": "^2.0.1"
88
88
  },
89
89
  "peerDependencies": {
90
90
  "@babel/core": ">=7.0.0",
@@ -92,12 +92,12 @@
92
92
  },
93
93
  "devDependencies": {
94
94
  "vitest": "^3.2.4",
95
- "@fluojs/platform-bun": "^1.0.5",
96
- "@fluojs/platform-deno": "^1.0.6",
97
- "@fluojs/platform-nodejs": "^1.0.5",
98
- "@fluojs/platform-cloudflare-workers": "^1.0.3",
99
- "@fluojs/platform-express": "^1.0.5",
100
- "@fluojs/platform-fastify": "^1.0.6"
95
+ "@fluojs/platform-bun": "^2.0.0",
96
+ "@fluojs/platform-cloudflare-workers": "^1.0.5",
97
+ "@fluojs/platform-deno": "^1.1.0",
98
+ "@fluojs/platform-nodejs": "^1.0.6",
99
+ "@fluojs/platform-express": "^1.1.0",
100
+ "@fluojs/platform-fastify": "^1.0.9"
101
101
  },
102
102
  "scripts": {
103
103
  "prebuild": "node ../../tooling/scripts/clean-dist.mjs",