@casekit/toolbox 0.0.0-20250322230249
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.
- package/build/index.d.ts +6 -0
- package/build/index.js +5 -0
- package/build/interleave.d.ts +1 -0
- package/build/interleave.js +9 -0
- package/build/interleave.test.d.ts +1 -0
- package/build/interleave.test.js +31 -0
- package/build/notNull.d.ts +1 -0
- package/build/notNull.js +1 -0
- package/build/notNull.test.d.ts +1 -0
- package/build/notNull.test.js +19 -0
- package/build/toSentence.d.ts +1 -0
- package/build/toSentence.js +13 -0
- package/build/toSentence.test.d.ts +1 -0
- package/build/toSentence.test.js +22 -0
- package/build/types/Conform.d.ts +11 -0
- package/build/types/Conform.js +1 -0
- package/build/types/Conform.test-d.d.ts +1 -0
- package/build/types/Conform.test-d.js +21 -0
- package/build/types/MarkNonNullable.d.ts +3 -0
- package/build/types/MarkNonNullable.js +1 -0
- package/build/types/MarkNonNullable.test-d.d.ts +1 -0
- package/build/types/MarkNonNullable.test-d.js +25 -0
- package/build/types/Simplify.d.ts +3 -0
- package/build/types/Simplify.js +1 -0
- package/build/types/Simplify.test-d.d.ts +1 -0
- package/build/types/Simplify.test-d.js +6 -0
- package/package.json +50 -0
package/build/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { interleave } from "./interleave.js";
|
|
2
|
+
export { notNull } from "./notNull.js";
|
|
3
|
+
export { toSentence } from "./toSentence.js";
|
|
4
|
+
export type { Conform } from "./types/Conform.js";
|
|
5
|
+
export type { MarkNonNullable } from "./types/MarkNonNullable.js";
|
|
6
|
+
export type { Simplify } from "./types/Simplify.js";
|
package/build/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const interleave: <T, U>(xs: T[], y: U) => (T | U)[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import { interleave } from "#interleave.js";
|
|
3
|
+
describe("interleave", () => {
|
|
4
|
+
test("it interleaves a value between elements of a list", () => {
|
|
5
|
+
expect(interleave([1, 2, 3], "x")).toEqual([1, "x", 2, "x", 3]);
|
|
6
|
+
});
|
|
7
|
+
test("it works with empty lists", () => {
|
|
8
|
+
expect(interleave([], "x")).toEqual([]);
|
|
9
|
+
});
|
|
10
|
+
test("it works with long lists", () => {
|
|
11
|
+
expect(interleave([1, 2, 3, 1, 2, 3, 1, 2, 3], "x")).toEqual([
|
|
12
|
+
1,
|
|
13
|
+
"x",
|
|
14
|
+
2,
|
|
15
|
+
"x",
|
|
16
|
+
3,
|
|
17
|
+
"x",
|
|
18
|
+
1,
|
|
19
|
+
"x",
|
|
20
|
+
2,
|
|
21
|
+
"x",
|
|
22
|
+
3,
|
|
23
|
+
"x",
|
|
24
|
+
1,
|
|
25
|
+
"x",
|
|
26
|
+
2,
|
|
27
|
+
"x",
|
|
28
|
+
3,
|
|
29
|
+
]);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const notNull: <T>(x: T) => x is NonNullable<T>;
|
package/build/notNull.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const notNull = (x) => x !== null;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { expect, test } from "vitest";
|
|
2
|
+
import { notNull } from "./notNull.js";
|
|
3
|
+
test("notNull returns false for null", () => {
|
|
4
|
+
expect(notNull(null)).toBe(false);
|
|
5
|
+
});
|
|
6
|
+
test("notNull returns true for non-null values", () => {
|
|
7
|
+
expect(notNull(0)).toBe(true);
|
|
8
|
+
expect(notNull("")).toBe(true);
|
|
9
|
+
expect(notNull(false)).toBe(true);
|
|
10
|
+
expect(notNull({})).toBe(true);
|
|
11
|
+
expect(notNull([])).toBe(true);
|
|
12
|
+
expect(notNull(undefined)).toBe(true);
|
|
13
|
+
});
|
|
14
|
+
test("notNull type guard narrows type correctly", () => {
|
|
15
|
+
const arr = [1, null, 2, null, 3];
|
|
16
|
+
const numbers = arr.filter(notNull);
|
|
17
|
+
// @ts-expect-error numbers should not contain null
|
|
18
|
+
const _test = numbers[0];
|
|
19
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const toSentence: (iter: Iterable<string>, conjunction?: string) => string | undefined;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const toSentence = (iter, conjunction = "and") => {
|
|
2
|
+
const items = Array.from(iter);
|
|
3
|
+
switch (items.length) {
|
|
4
|
+
case 0:
|
|
5
|
+
return "";
|
|
6
|
+
case 1:
|
|
7
|
+
return items[0];
|
|
8
|
+
case 2:
|
|
9
|
+
return items.join(` ${conjunction} `);
|
|
10
|
+
default:
|
|
11
|
+
return `${items.slice(0, -1).join(", ")}, ${conjunction} ${items[items.length - 1]}`;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { expect, test } from "vitest";
|
|
2
|
+
import { toSentence } from "./toSentence.js";
|
|
3
|
+
test("toSentence returns empty string for empty array", () => {
|
|
4
|
+
expect(toSentence([])).toBe("");
|
|
5
|
+
});
|
|
6
|
+
test("toSentence returns single item for array of one", () => {
|
|
7
|
+
expect(toSentence(["one"])).toBe("one");
|
|
8
|
+
});
|
|
9
|
+
test("toSentence joins two items with conjunction", () => {
|
|
10
|
+
expect(toSentence(["one", "two"])).toBe("one and two");
|
|
11
|
+
});
|
|
12
|
+
test("toSentence joins multiple items with commas and conjunction", () => {
|
|
13
|
+
expect(toSentence(["one", "two", "three"])).toBe("one, two, and three");
|
|
14
|
+
expect(toSentence(["one", "two", "three", "four"])).toBe("one, two, three, and four");
|
|
15
|
+
});
|
|
16
|
+
test("toSentence uses custom conjunction", () => {
|
|
17
|
+
expect(toSentence(["one", "two"], "or")).toBe("one or two");
|
|
18
|
+
expect(toSentence(["one", "two", "three"], "or")).toBe("one, two, or three");
|
|
19
|
+
});
|
|
20
|
+
test("toSentence works with Set", () => {
|
|
21
|
+
expect(toSentence(new Set(["one", "two", "three"]))).toBe("one, two, and three");
|
|
22
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Not really an exact type and not exactly what we'd like -
|
|
3
|
+
* all we need is excess property checking, but that's
|
|
4
|
+
* unlikely to happen. See https://github.com/microsoft/TypeScript/issues/58031
|
|
5
|
+
* for more information.
|
|
6
|
+
*/
|
|
7
|
+
export type Conform<Base, T extends Base> = {
|
|
8
|
+
[K in keyof T]: T[K];
|
|
9
|
+
} & {
|
|
10
|
+
[K in keyof T as K extends keyof Base ? never : K]: never;
|
|
11
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { describe, test } from "vitest";
|
|
2
|
+
describe("Conform", () => {
|
|
3
|
+
test("should allow exact matching types", () => {
|
|
4
|
+
const _ = {
|
|
5
|
+
name: "John",
|
|
6
|
+
age: 30,
|
|
7
|
+
};
|
|
8
|
+
});
|
|
9
|
+
test("should not allow extra properties", () => {
|
|
10
|
+
const _person = {
|
|
11
|
+
name: "John",
|
|
12
|
+
age: 30,
|
|
13
|
+
// @ts-expect-error - Extra property 'email' is not allowed
|
|
14
|
+
email: "john@example.com",
|
|
15
|
+
};
|
|
16
|
+
});
|
|
17
|
+
test("should not allow missing properties", () => {
|
|
18
|
+
// @ts-expect-error - Missing property 'age'
|
|
19
|
+
const _person = { name: "John" };
|
|
20
|
+
});
|
|
21
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { describe, expectTypeOf, test } from "vitest";
|
|
2
|
+
describe("MarkNonNullable", () => {
|
|
3
|
+
test("should make specified properties non-nullable while preserving other properties", () => {
|
|
4
|
+
// name should be string only (not null)
|
|
5
|
+
expectTypeOf().toExtend();
|
|
6
|
+
// other properties should remain unchanged
|
|
7
|
+
expectTypeOf().toEqualTypeOf();
|
|
8
|
+
expectTypeOf().toEqualTypeOf();
|
|
9
|
+
});
|
|
10
|
+
test("should handle multiple properties", () => {
|
|
11
|
+
expectTypeOf().toExtend();
|
|
12
|
+
});
|
|
13
|
+
test("should handle nested properties", () => {
|
|
14
|
+
// The address object itself should remain the same structure
|
|
15
|
+
expectTypeOf().toEqualTypeOf();
|
|
16
|
+
});
|
|
17
|
+
test("should preserve required properties", () => {
|
|
18
|
+
// id was already required, should remain number
|
|
19
|
+
expectTypeOf().toEqualTypeOf();
|
|
20
|
+
});
|
|
21
|
+
test("should handle optional properties", () => {
|
|
22
|
+
// Optional properties should become required and non-nullable
|
|
23
|
+
expectTypeOf().toExtend();
|
|
24
|
+
});
|
|
25
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@casekit/toolbox",
|
|
3
|
+
"description": "",
|
|
4
|
+
"version": "0.0.0-20250322230249",
|
|
5
|
+
"author": "",
|
|
6
|
+
"devDependencies": {
|
|
7
|
+
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
|
8
|
+
"@types/node": "^22.13.11",
|
|
9
|
+
"@types/pg": "^8.11.11",
|
|
10
|
+
"@vitest/coverage-v8": "^3.0.9",
|
|
11
|
+
"dotenv": "^16.4.7",
|
|
12
|
+
"prettier": "^3.5.3",
|
|
13
|
+
"prettier-plugin-svelte": "^3.3.3",
|
|
14
|
+
"typescript": "^5.8.2",
|
|
15
|
+
"vite-tsconfig-paths": "^5.1.4",
|
|
16
|
+
"vitest": "^3.0.9",
|
|
17
|
+
"@casekit/prettier-config": "0.0.0-20250322230249",
|
|
18
|
+
"@casekit/tsconfig": "0.0.0-20250322230249"
|
|
19
|
+
},
|
|
20
|
+
"exports": {
|
|
21
|
+
".": "./build/index.js"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"/build"
|
|
25
|
+
],
|
|
26
|
+
"imports": {
|
|
27
|
+
"#*": "./build/*"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [],
|
|
30
|
+
"license": "ISC",
|
|
31
|
+
"main": "index.js",
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"pg": "^8.13.1",
|
|
34
|
+
"zod": "^3.24.2"
|
|
35
|
+
},
|
|
36
|
+
"prettier": "@casekit/prettier-config",
|
|
37
|
+
"type": "module",
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"ts-essentials": "^10.0.4"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "rm -rf ./build && tsc --build",
|
|
43
|
+
"format:check": "prettier --check .",
|
|
44
|
+
"format": "prettier --write .",
|
|
45
|
+
"lint": "eslint src --max-warnings 0",
|
|
46
|
+
"test": "vitest --run --typecheck --coverage",
|
|
47
|
+
"test:watch": "vitest",
|
|
48
|
+
"typecheck": "tsc --noEmit"
|
|
49
|
+
}
|
|
50
|
+
}
|