@mulmoclaude/common 0.1.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.
- package/README.md +33 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +48 -0
- package/package.json +32 -0
package/README.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# @mulmoclaude/common
|
|
2
|
+
|
|
3
|
+
General-purpose, **dependency-free** runtime type guards shared across the
|
|
4
|
+
MulmoClaude host (`server/`, `src/`), the chat bridges (`@mulmobridge/*`), and
|
|
5
|
+
the plugins.
|
|
6
|
+
|
|
7
|
+
This is a **leaf package** — it imports nothing, so any tier can depend on it
|
|
8
|
+
without creating an uphill edge (see the dependency-direction rule in the repo
|
|
9
|
+
`CLAUDE.md`).
|
|
10
|
+
|
|
11
|
+
## Why it exists
|
|
12
|
+
|
|
13
|
+
`server/utils/types.ts` and `src/utils/types.ts` were byte-for-byte duplicates
|
|
14
|
+
kept in sync by hand, and the `isObj` guard alone had been re-typed in 18 files
|
|
15
|
+
across the bridges and relay. These guards are the definition of "general and
|
|
16
|
+
duplicated," so they live here once.
|
|
17
|
+
|
|
18
|
+
## Contents
|
|
19
|
+
|
|
20
|
+
| Guard | Narrows to | Notes |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| `isRecord(v)` | `Record<string, unknown>` | plain object; **arrays excluded** |
|
|
23
|
+
| `isObj(v)` | `object` | any non-null object; **arrays allowed** |
|
|
24
|
+
| `isNonEmptyString(v)` | `string` | non-empty **after trimming** |
|
|
25
|
+
| `isStringRecord(v)` | `Record<string, string>` | every value is a string |
|
|
26
|
+
| `isStringArray(v)` | `string[]` | every element is a string |
|
|
27
|
+
| `isUnknownArray(v)` | `unknown[]` | prefer over bare `Array.isArray` (which narrows to `any[]`) |
|
|
28
|
+
| `isErrorWithCode(v)` | `{ code: string; message?: string }` | Node.js fs-style errors |
|
|
29
|
+
| `hasStringProp(v, k)` | `Record<k, string>` | key present with a string value |
|
|
30
|
+
| `hasNumberProp(v, k)` | `Record<k, number>` | key present with a number value |
|
|
31
|
+
|
|
32
|
+
`isRecord` vs `isObj`: use `isRecord` whenever you go on to index string keys —
|
|
33
|
+
`isObj` lets arrays through, which is rarely what you want for a JSON payload.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** Narrow `unknown` to a plain object (not null, not array). */
|
|
2
|
+
export declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
3
|
+
/** Narrow `unknown` to any object (not null, arrays allowed).
|
|
4
|
+
* Use `isRecord` when you need to access string keys. */
|
|
5
|
+
export declare function isObj(value: unknown): value is object;
|
|
6
|
+
/** Non-empty string after trimming whitespace. */
|
|
7
|
+
export declare function isNonEmptyString(value: unknown): value is string;
|
|
8
|
+
/** Record whose values are all strings. */
|
|
9
|
+
export declare function isStringRecord(value: unknown): value is Record<string, string>;
|
|
10
|
+
/** String array (every element is a string). */
|
|
11
|
+
export declare function isStringArray(value: unknown): value is string[];
|
|
12
|
+
/** An array of unknowns. Prefer this over a bare `Array.isArray` in typed code:
|
|
13
|
+
* `Array.isArray(x: unknown)` narrows to `any[]`, silently reintroducing
|
|
14
|
+
* `any`, whereas this keeps the element type `unknown`. */
|
|
15
|
+
export declare function isUnknownArray(value: unknown): value is unknown[];
|
|
16
|
+
/** Error-like object with a `code` property (e.g. Node.js fs errors). */
|
|
17
|
+
export declare function isErrorWithCode(value: unknown): value is {
|
|
18
|
+
code: string;
|
|
19
|
+
message?: string;
|
|
20
|
+
};
|
|
21
|
+
/** Check that a record has a specific key with a string value. */
|
|
22
|
+
export declare function hasStringProp<K extends string>(value: unknown, key: K): value is Record<K, string> & Record<string, unknown>;
|
|
23
|
+
/** Check that a record has a specific key with a number value. */
|
|
24
|
+
export declare function hasNumberProp<K extends string>(value: unknown, key: K): value is Record<K, number> & Record<string, unknown>;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// General-purpose runtime type guards, shared across the MulmoClaude host,
|
|
2
|
+
// bridges, and plugins. This is a leaf package — pure and dependency-free — so
|
|
3
|
+
// any tier can import it without creating an uphill edge.
|
|
4
|
+
//
|
|
5
|
+
// These originated as `server/utils/types.ts` (#504), which centralised 40+
|
|
6
|
+
// hand-written inline `typeof x === "object"` checks. They are promoted here so
|
|
7
|
+
// the same guards stop being re-hand-written in every bridge and plugin too.
|
|
8
|
+
/** Narrow `unknown` to a plain object (not null, not array). */
|
|
9
|
+
export function isRecord(value) {
|
|
10
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
11
|
+
}
|
|
12
|
+
/** Narrow `unknown` to any object (not null, arrays allowed).
|
|
13
|
+
* Use `isRecord` when you need to access string keys. */
|
|
14
|
+
export function isObj(value) {
|
|
15
|
+
return typeof value === "object" && value !== null;
|
|
16
|
+
}
|
|
17
|
+
/** Non-empty string after trimming whitespace. */
|
|
18
|
+
export function isNonEmptyString(value) {
|
|
19
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
20
|
+
}
|
|
21
|
+
/** Record whose values are all strings. */
|
|
22
|
+
export function isStringRecord(value) {
|
|
23
|
+
if (!isRecord(value))
|
|
24
|
+
return false;
|
|
25
|
+
return Object.values(value).every((val) => typeof val === "string");
|
|
26
|
+
}
|
|
27
|
+
/** String array (every element is a string). */
|
|
28
|
+
export function isStringArray(value) {
|
|
29
|
+
return Array.isArray(value) && value.every((val) => typeof val === "string");
|
|
30
|
+
}
|
|
31
|
+
/** An array of unknowns. Prefer this over a bare `Array.isArray` in typed code:
|
|
32
|
+
* `Array.isArray(x: unknown)` narrows to `any[]`, silently reintroducing
|
|
33
|
+
* `any`, whereas this keeps the element type `unknown`. */
|
|
34
|
+
export function isUnknownArray(value) {
|
|
35
|
+
return Array.isArray(value);
|
|
36
|
+
}
|
|
37
|
+
/** Error-like object with a `code` property (e.g. Node.js fs errors). */
|
|
38
|
+
export function isErrorWithCode(value) {
|
|
39
|
+
return isRecord(value) && typeof value.code === "string";
|
|
40
|
+
}
|
|
41
|
+
/** Check that a record has a specific key with a string value. */
|
|
42
|
+
export function hasStringProp(value, key) {
|
|
43
|
+
return isRecord(value) && typeof value[key] === "string";
|
|
44
|
+
}
|
|
45
|
+
/** Check that a record has a specific key with a number value. */
|
|
46
|
+
export function hasNumberProp(value, key) {
|
|
47
|
+
return isRecord(value) && typeof value[key] === "number";
|
|
48
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mulmoclaude/common",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "General-purpose pure utilities (type guards, etc.) shared across the MulmoClaude host, bridges, and plugins",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"require": "./dist/index.js",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsc",
|
|
22
|
+
"prepack": "yarn build",
|
|
23
|
+
"typecheck": "tsc --noEmit",
|
|
24
|
+
"test": "tsx --test test/test_*.ts",
|
|
25
|
+
"lint": "eslint src test"
|
|
26
|
+
},
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"author": "Receptron Team",
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"typescript": "^6.0.3"
|
|
31
|
+
}
|
|
32
|
+
}
|