@unrift/core 0.0.0 → 0.2.1

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.
Files changed (54) hide show
  1. package/dist/esm/cli.js +75 -5
  2. package/dist/esm/expect.d.ts +8 -0
  3. package/dist/esm/expect.d.ts.map +1 -1
  4. package/dist/esm/expect.js +54 -4
  5. package/dist/esm/index.d.ts +3 -2
  6. package/dist/esm/index.d.ts.map +1 -1
  7. package/dist/esm/index.js +1 -1
  8. package/dist/esm/interface.d.ts +4 -1
  9. package/dist/esm/interface.d.ts.map +1 -1
  10. package/dist/esm/interface.js +4 -1
  11. package/dist/esm/matchers.d.ts +1 -0
  12. package/dist/esm/matchers.d.ts.map +1 -1
  13. package/dist/esm/matchers.js +61 -0
  14. package/dist/esm/run.d.ts +1 -1
  15. package/dist/esm/run.d.ts.map +1 -1
  16. package/dist/esm/run.js +3 -4
  17. package/dist/esm/runner.d.ts.map +1 -1
  18. package/dist/esm/runner.js +201 -33
  19. package/dist/esm/suite.d.ts +2 -10
  20. package/dist/esm/suite.d.ts.map +1 -1
  21. package/dist/esm/suite.js +29 -10
  22. package/dist/esm/test.d.ts +1 -7
  23. package/dist/esm/test.d.ts.map +1 -1
  24. package/dist/esm/test.js +11 -2
  25. package/dist/esm/types.d.ts +3 -3
  26. package/dist/esm/types.d.ts.map +1 -1
  27. package/dist/esm/types.js +1 -0
  28. package/dist/esm/utils/colors.d.ts +21 -0
  29. package/dist/esm/utils/colors.d.ts.map +1 -1
  30. package/dist/esm/utils/colors.js +34 -4
  31. package/dist/esm/utils/compareEngine.d.ts +10 -0
  32. package/dist/esm/utils/compareEngine.d.ts.map +1 -0
  33. package/dist/esm/utils/compareEngine.js +222 -0
  34. package/dist/esm/utils/deepEqual.d.ts.map +1 -1
  35. package/dist/esm/utils/deepEqual.js +7 -185
  36. package/dist/esm/utils/diff.d.ts +2 -0
  37. package/dist/esm/utils/diff.d.ts.map +1 -0
  38. package/dist/esm/utils/diff.js +84 -0
  39. package/dist/esm/utils/discoverTestFiles.d.ts.map +1 -1
  40. package/dist/esm/utils/discoverTestFiles.js +17 -2
  41. package/dist/esm/utils/looseEqual.d.ts +9 -0
  42. package/dist/esm/utils/looseEqual.d.ts.map +1 -1
  43. package/dist/esm/utils/looseEqual.js +16 -197
  44. package/dist/esm/utils/normalizePath.d.ts +2 -0
  45. package/dist/esm/utils/normalizePath.d.ts.map +1 -0
  46. package/dist/esm/utils/normalizePath.js +4 -0
  47. package/dist/esm/utils/toError.d.ts +2 -0
  48. package/dist/esm/utils/toError.d.ts.map +1 -0
  49. package/dist/esm/utils/toError.js +3 -0
  50. package/dist/esm/utils/toThrow.d.ts.map +1 -1
  51. package/dist/esm/utils/toThrow.js +12 -1
  52. package/dist/esm/utils/transform.d.ts.map +1 -1
  53. package/dist/esm/utils/transform.js +31 -21
  54. package/package.json +21 -3
@@ -1,199 +1,14 @@
1
- import { isObjectLike, isPrimitive, isTypedArray, sameValue, } from "./helpers.js";
2
- function looseEqualInternal(left, right, leftToRightSeen, rightToLeftSeen) {
3
- const worklist = [[left, right]];
4
- while (worklist.length) {
5
- const [currentLeft, currentRight] = worklist.pop();
6
- if (sameValue(currentLeft, currentRight))
7
- continue;
8
- if (typeof currentLeft !== typeof currentRight)
9
- return false;
10
- if (isPrimitive(currentLeft) || isPrimitive(currentRight))
11
- return false;
12
- if (!isObjectLike(currentLeft) || !isObjectLike(currentRight))
13
- return false;
14
- const leftObj = currentLeft;
15
- const rightObj = currentRight;
16
- // Cycle / aliasing consistency (bijection-ish)
17
- const mappedRight = leftToRightSeen.get(leftObj);
18
- if (mappedRight !== undefined) {
19
- if (mappedRight !== rightObj)
20
- return false;
21
- continue;
22
- }
23
- const mappedLeft = rightToLeftSeen.get(rightObj);
24
- if (mappedLeft !== undefined) {
25
- if (mappedLeft !== leftObj)
26
- return false;
27
- continue;
28
- }
29
- leftToRightSeen.set(leftObj, rightObj);
30
- rightToLeftSeen.set(rightObj, leftObj);
31
- // Arrays: sparse holes treated as undefined
32
- const leftIsArray = Array.isArray(currentLeft);
33
- const rightIsArray = Array.isArray(currentRight);
34
- if (leftIsArray || rightIsArray) {
35
- if (!leftIsArray || !rightIsArray)
36
- return false;
37
- const leftArr = currentLeft;
38
- const rightArr = currentRight;
39
- if (leftArr.length !== rightArr.length)
40
- return false;
41
- for (let index = 0; index < leftArr.length; index++) {
42
- const leftValue = Object.hasOwn(leftArr, index)
43
- ? leftArr[index]
44
- : undefined;
45
- const rightValue = Object.hasOwn(rightArr, index)
46
- ? rightArr[index]
47
- : undefined;
48
- worklist.push([leftValue, rightValue]);
49
- }
50
- continue;
51
- }
52
- // Typed arrays
53
- const leftIsTypedArray = isTypedArray(currentLeft);
54
- const rightIsTypedArray = isTypedArray(currentRight);
55
- if (leftIsTypedArray || rightIsTypedArray) {
56
- if (!leftIsTypedArray || !rightIsTypedArray)
57
- return false;
58
- const leftTypedArray = currentLeft;
59
- const rightTypedArray = currentRight;
60
- if (leftTypedArray.constructor !== rightTypedArray.constructor)
61
- return false;
62
- if (leftTypedArray.length !== rightTypedArray.length)
63
- return false;
64
- for (let index = 0; index < leftTypedArray.length; index++) {
65
- if (!sameValue(leftTypedArray[index], rightTypedArray[index]))
66
- return false;
67
- }
68
- continue;
69
- }
70
- // ArrayBuffer
71
- const leftIsBuffer = currentLeft instanceof ArrayBuffer;
72
- const rightIsBuffer = currentRight instanceof ArrayBuffer;
73
- if (leftIsBuffer || rightIsBuffer) {
74
- if (!leftIsBuffer || !rightIsBuffer)
75
- return false;
76
- const leftBuffer = currentLeft;
77
- const rightBuffer = currentRight;
78
- if (leftBuffer.byteLength !== rightBuffer.byteLength)
79
- return false;
80
- const leftBytes = new Uint8Array(leftBuffer);
81
- const rightBytes = new Uint8Array(rightBuffer);
82
- for (let index = 0; index < leftBytes.length; index++) {
83
- if (leftBytes[index] !== rightBytes[index])
84
- return false;
85
- }
86
- continue;
87
- }
88
- // DataView
89
- const leftIsDataView = currentLeft instanceof DataView;
90
- const rightIsDataView = currentRight instanceof DataView;
91
- if (leftIsDataView || rightIsDataView) {
92
- if (!leftIsDataView || !rightIsDataView)
93
- return false;
94
- const leftView = currentLeft;
95
- const rightView = currentRight;
96
- if (leftView.byteLength !== rightView.byteLength)
97
- return false;
98
- for (let offset = 0; offset < leftView.byteLength; offset++) {
99
- if (leftView.getUint8(offset) !== rightView.getUint8(offset))
100
- return false;
101
- }
102
- continue;
103
- }
104
- // Date
105
- const leftIsDate = currentLeft instanceof Date;
106
- const rightIsDate = currentRight instanceof Date;
107
- if (leftIsDate || rightIsDate) {
108
- if (!leftIsDate || !rightIsDate)
109
- return false;
110
- if (currentLeft.getTime() !== currentRight.getTime()) {
111
- return false;
112
- }
113
- continue;
114
- }
115
- // RegExp
116
- const leftIsRegExp = currentLeft instanceof RegExp;
117
- const rightIsRegExp = currentRight instanceof RegExp;
118
- if (leftIsRegExp || rightIsRegExp) {
119
- if (!leftIsRegExp || !rightIsRegExp)
120
- return false;
121
- const leftRe = currentLeft;
122
- const rightRe = currentRight;
123
- if (leftRe.source !== rightRe.source)
124
- return false;
125
- if (leftRe.flags !== rightRe.flags)
126
- return false;
127
- continue;
128
- }
129
- // Set (order-insensitive)
130
- const leftIsSet = currentLeft instanceof Set;
131
- const rightIsSet = currentRight instanceof Set;
132
- if (leftIsSet || rightIsSet) {
133
- if (!leftIsSet || !rightIsSet)
134
- return false;
135
- const leftSet = currentLeft;
136
- const rightSet = currentRight;
137
- if (leftSet.size !== rightSet.size)
138
- return false;
139
- const remainingRight = new Set(rightSet);
140
- outer: for (const leftValue of leftSet) {
141
- for (const rightValue of remainingRight) {
142
- if (looseEqualInternal(leftValue, rightValue, leftToRightSeen, rightToLeftSeen)) {
143
- remainingRight.delete(rightValue);
144
- continue outer;
145
- }
146
- }
147
- return false;
148
- }
149
- continue;
150
- }
151
- // Map (order-insensitive by entries; keys compared via looseEqual)
152
- const leftIsMap = currentLeft instanceof Map;
153
- const rightIsMap = currentRight instanceof Map;
154
- if (leftIsMap || rightIsMap) {
155
- if (!leftIsMap || !rightIsMap)
156
- return false;
157
- const leftMap = currentLeft;
158
- const rightMap = currentRight;
159
- if (leftMap.size !== rightMap.size)
160
- return false;
161
- const remainingRightEntries = new Set(rightMap.entries());
162
- outer: for (const [leftKey, leftValue] of leftMap.entries()) {
163
- for (const candidate of remainingRightEntries) {
164
- const [rightKey, rightValue] = candidate;
165
- if (looseEqualInternal(leftKey, rightKey, leftToRightSeen, rightToLeftSeen) &&
166
- looseEqualInternal(leftValue, rightValue, leftToRightSeen, rightToLeftSeen)) {
167
- remainingRightEntries.delete(candidate);
168
- continue outer;
169
- }
170
- }
171
- return false;
172
- }
173
- continue;
174
- }
175
- // Fallback: compare by enumerable shape (prototype-insensitive).
176
- // Missing ≈ undefined via union-of-keys comparison.
177
- const leftKeys = Object.keys(currentLeft);
178
- const rightKeys = Object.keys(currentRight);
179
- const allKeys = new Set([...leftKeys, ...rightKeys]);
180
- const leftRecord = currentLeft;
181
- const rightRecord = currentRight;
182
- for (const key of allKeys) {
183
- const leftHasKey = Object.hasOwn(leftRecord, key);
184
- const rightHasKey = Object.hasOwn(rightRecord, key);
185
- const leftValue = leftHasKey ? leftRecord[key] : undefined;
186
- const rightValue = rightHasKey ? rightRecord[key] : undefined;
187
- // If one side is missing and the other side is present-but-not-undefined, fail.
188
- if (leftHasKey !== rightHasKey) {
189
- if (leftValue !== undefined || rightValue !== undefined)
190
- return false;
191
- }
192
- worklist.push([leftValue, rightValue]);
193
- }
194
- }
195
- return true;
196
- }
1
+ import { isObjectLike, isPrimitive, sameValue } from "./helpers.js";
2
+ import { compareInternal } from "./compareEngine.js";
3
+ /**
4
+ * Loose structural equality with:
5
+ * - Value semantics for primitives (+ NaN equal, +0/-0 equal)
6
+ * - Prototype-insensitive object comparison
7
+ * - Sparse array holes treated as undefined
8
+ * - Missing keys ≈ undefined (union-of-keys approach)
9
+ * - Bidirectional cycle tracking
10
+ * - Order-insensitive Set/Map comparison
11
+ */
197
12
  export function looseEqual(left, right) {
198
13
  if (sameValue(left, right))
199
14
  return true;
@@ -201,5 +16,9 @@ export function looseEqual(left, right) {
201
16
  return false;
202
17
  if (!isObjectLike(left) || !isObjectLike(right))
203
18
  return false;
204
- return looseEqualInternal(left, right, new WeakMap(), new WeakMap());
19
+ return compareInternal(left, right, {
20
+ checkPrototype: false,
21
+ treatSparseAsUndefined: true,
22
+ bijectiveCycleCheck: true,
23
+ }, new WeakMap(), new WeakMap());
205
24
  }
@@ -0,0 +1,2 @@
1
+ export declare function normalizePath(p: string): string;
2
+ //# sourceMappingURL=normalizePath.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizePath.d.ts","sourceRoot":"","sources":["../../../src/utils/normalizePath.ts"],"names":[],"mappings":"AAAA,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAG/C"}
@@ -0,0 +1,4 @@
1
+ export function normalizePath(p) {
2
+ // Stable for matching/reporting across platforms
3
+ return p.replace(/\\/g, "/");
4
+ }
@@ -0,0 +1,2 @@
1
+ export declare function toError(err: unknown): Error;
2
+ //# sourceMappingURL=toError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toError.d.ts","sourceRoot":"","sources":["../../../src/utils/toError.ts"],"names":[],"mappings":"AAAA,wBAAgB,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,KAAK,CAE3C"}
@@ -0,0 +1,3 @@
1
+ export function toError(err) {
2
+ return err instanceof Error ? err : new Error(String(err));
3
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"toThrow.d.ts","sourceRoot":"","sources":["../../../src/utils/toThrow.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GACvB,SAAS,GACT,MAAM,GACN,MAAM,GACN,CAAC,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,KAAK,CAAC,GACnC;IAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD,UAAU,WAAW;IACnB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,MAAM,CAAC;CACvB;AAgED,wBAAgB,OAAO,CACrB,QAAQ,EAAE,OAAO,EACjB,QAAQ,CAAC,EAAE,eAAe,EAC1B,KAAK,UAAQ,GACZ,WAAW,CAgDb"}
1
+ {"version":3,"file":"toThrow.d.ts","sourceRoot":"","sources":["../../../src/utils/toThrow.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GACvB,SAAS,GACT,MAAM,GACN,MAAM,GACN,CAAC,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,KAAK,CAAC,GACnC;IAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD,UAAU,WAAW;IACnB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,MAAM,CAAC;CACvB;AAgED,wBAAgB,OAAO,CACrB,QAAQ,EAAE,OAAO,EACjB,QAAQ,CAAC,EAAE,eAAe,EAC1B,KAAK,UAAQ,GACZ,WAAW,CAgEb"}
@@ -60,13 +60,24 @@ export function toThrow(received, expected, isNot = false) {
60
60
  }
61
61
  let threw = false;
62
62
  let thrown;
63
+ let result;
63
64
  try {
64
- received();
65
+ result = received();
65
66
  }
66
67
  catch (e) {
67
68
  threw = true;
68
69
  thrown = e;
69
70
  }
71
+ if (!threw &&
72
+ result != null &&
73
+ typeof result.then === "function") {
74
+ // Suppress the unhandled rejection from the returned promise
75
+ result.catch(() => { });
76
+ return {
77
+ pass: false,
78
+ message: () => "toThrow() received an async function. Use expect(fn).rejects.toThrow() for async errors.",
79
+ };
80
+ }
70
81
  const matched = threw && matchThrown(thrown, expected);
71
82
  const pass = isNot ? !matched : matched;
72
83
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../src/utils/transform.ts"],"names":[],"mappings":"AAuIA,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG;IACtD,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,gBAAgB,EAAE,OAAO,CAAC;CAC3B,CAgBA;AAED,KAAK,IAAI,GAAG,eAAe,GAAG,aAAa,CAAC;AAqE5C,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,IAAoB,GACzB,MAAM,CAyDR"}
1
+ {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../src/utils/transform.ts"],"names":[],"mappings":"AAuIA,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG;IACtD,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,gBAAgB,EAAE,OAAO,CAAC;CAC3B,CAgBA;AAED,KAAK,IAAI,GAAG,eAAe,GAAG,aAAa,CAAC;AAqE5C,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,IAAoB,GACzB,MAAM,CAwER"}
@@ -88,7 +88,7 @@ function projectNodeModulesCacheRoot(projectRoot) {
88
88
  }
89
89
  function tempCacheRootForProject(projectRoot) {
90
90
  const projectKey = hashString(resolve(projectRoot));
91
- return getTmpCacheRoot(projectKey);
91
+ return join(os.tmpdir(), "unrift", projectKey);
92
92
  }
93
93
  function rmDirIfExists(dir) {
94
94
  try {
@@ -187,26 +187,36 @@ export function toImportUrl(filePath, mode = "bundle-test") {
187
187
  const outDir = cacheDirForMode(cacheRoot, mode);
188
188
  ensureDir(outDir);
189
189
  const outFile = cacheOutPath(outDir, filePath, hashStr);
190
- buildSync({
191
- entryPoints: [filePath],
192
- outfile: outFile,
193
- bundle: true,
194
- format: "esm",
195
- platform: "node",
196
- target: "node18",
197
- packages: "external",
198
- external: ["@unrift/*", "@unrift/core", "@unrift/core/*"],
199
- absWorkingDir: projectRoot,
200
- inject: [resolveInjectedGlobals()],
201
- define: {
202
- __dirname: "injectedDirname",
203
- __filename: "injectedFilename",
204
- require: "injectedRequire",
205
- },
206
- sourcemap: "inline",
207
- sourcesContent: true,
208
- logLevel: "silent",
209
- });
190
+ try {
191
+ buildSync({
192
+ entryPoints: [filePath],
193
+ outfile: outFile,
194
+ bundle: true,
195
+ format: "esm",
196
+ platform: "node",
197
+ target: "node18",
198
+ packages: "external",
199
+ external: ["@unrift/*", "@unrift/core", "@unrift/core/*"],
200
+ absWorkingDir: projectRoot,
201
+ inject: [resolveInjectedGlobals()],
202
+ define: {
203
+ __dirname: "injectedDirname",
204
+ __filename: "injectedFilename",
205
+ require: "injectedRequire",
206
+ },
207
+ sourcemap: "inline",
208
+ sourcesContent: true,
209
+ logLevel: "silent",
210
+ });
211
+ }
212
+ catch (err) {
213
+ const msg = err instanceof Error ? err.message : String(err);
214
+ if (msg.includes("Cannot find module") ||
215
+ msg.includes("MODULE_NOT_FOUND")) {
216
+ throw new Error(`esbuild is required but could not be loaded. Run: npm install esbuild\n\nOriginal error: ${msg}`);
217
+ }
218
+ throw err;
219
+ }
210
220
  const outUrl = pathToFileURL(outFile).href;
211
221
  cache.set(key, { hash: hashStr, outUrl });
212
222
  return outUrl;
package/package.json CHANGED
@@ -1,12 +1,15 @@
1
1
  {
2
2
  "name": "@unrift/core",
3
- "version": "0.0.0",
3
+ "version": "0.2.1",
4
4
  "description": "unrift core package",
5
5
  "private": false,
6
6
  "main": "./dist/cjs/index.cjs",
7
7
  "module": "./dist/esm/index.js",
8
8
  "types": "./dist/esm/index.d.ts",
9
9
  "type": "module",
10
+ "engines": {
11
+ "node": ">=18"
12
+ },
10
13
  "files": [
11
14
  "dist",
12
15
  "bin"
@@ -29,12 +32,26 @@
29
32
  "bin": {
30
33
  "unrift": "./bin/unrift.mjs"
31
34
  },
32
- "keywords": [],
35
+ "keywords": [
36
+ "testing",
37
+ "test",
38
+ "test-runner",
39
+ "typescript",
40
+ "javascript",
41
+ "esm",
42
+ "assert",
43
+ "expect",
44
+ "matchers"
45
+ ],
33
46
  "author": "elijah kotyluk <elijah@elijahkotyluk.com>",
34
47
  "repository": {
35
48
  "type": "git",
36
49
  "url": "https://github.com/elijahkotyluk/unrift"
37
50
  },
51
+ "bugs": {
52
+ "url": "https://github.com/elijahkotyluk/unrift/issues"
53
+ },
54
+ "homepage": "https://unrift.pages.dev",
38
55
  "license": "MIT",
39
56
  "dependencies": {
40
57
  "esbuild": "^0.27.2"
@@ -48,12 +65,13 @@
48
65
  "build:esm": "tsc -p tsconfig.build.esm.json && node scripts/patch-esm-extensions.js",
49
66
  "clean": "rm -rf ./dist",
50
67
  "compile": "tsc -p tsconfig.build.json && node scripts/patch-esm-extensions.js",
51
- "test": "pnpm test:internal && pnpm test:fail && pnpm test:bail && pnpm test:only",
68
+ "test": "pnpm test:internal && pnpm test:fail && pnpm test:bail && pnpm test:only && pnpm test:todo && pnpm test:hooks",
52
69
  "test:bail": "node bin/unrift.mjs --config ./test/bail/unrift.outer.config.ts",
53
70
  "test:fail": "node bin/unrift.mjs --config ./test/fail/unrift.outer.config.ts",
54
71
  "test:hooks": "node bin/unrift.mjs --config ./test/hooks/unrift.outer.config.ts",
55
72
  "test:internal": "node bin/unrift.mjs --config ./test/internal/unrift.config.ts",
56
73
  "test:only": "node bin/unrift.mjs --config ./test/only/unrift.outer.config.ts",
74
+ "test:todo": "node bin/unrift.mjs --config ./test/todo/unrift.outer.config.ts",
57
75
  "test:publish": "pnpm clean && pnpm build && pnpm pack --pack-destination ./dist-pack",
58
76
  "typecheck": "tsc -p tsconfig.build.esm.json --noEmit"
59
77
  }