Comparing version 0.0.0 to 0.0.1
@@ -25,4 +25,4 @@ declare function required<T>(arg: T): [`required`, T]; | ||
type ToPath<S extends string, D extends string> = S extends `${infer T extends string}${D}${infer U extends string}` ? T extends `$${string}` ? [string & {}, ...ToPath<U, D>] : [T, ...ToPath<U, D>] : S extends `$${string}` ? [string & {}] : [S]; | ||
type MySplit = ToPath<`hello/$world/good/morning`, `/`>; | ||
declare function isTreePath<T extends Tree>(tree: T, maybePath: unknown[]): maybePath is TreePath<T>; | ||
export { type Flat, type Join, type MySplit, type OptionalTree, type RequiredTree, type ToPath, type Tree, type TreeContents, type TreeMap, type TreePath, type TreePathName, optional, required }; | ||
export { type Flat, type Join, type OptionalTree, type RequiredTree, type ToPath, type Tree, type TreeContents, type TreeMap, type TreePath, type TreePathName, isTreePath, optional, required }; |
@@ -8,11 +8,31 @@ // src/treetrunks.ts | ||
} | ||
var myTree = required({ | ||
hello: optional({ | ||
world: null, | ||
$name: optional({ good: required({ morning: null }) }) | ||
}) | ||
}); | ||
function isTreePath(tree, maybePath) { | ||
let currentTreeNode = tree; | ||
for (const segment of maybePath) { | ||
if (currentTreeNode === null) { | ||
return false; | ||
} | ||
if (typeof segment !== `string`) { | ||
return false; | ||
} | ||
if (segment in currentTreeNode[1]) { | ||
currentTreeNode = currentTreeNode[1][segment]; | ||
} else { | ||
return false; | ||
} | ||
} | ||
if (currentTreeNode === null) { | ||
return true; | ||
} | ||
switch (currentTreeNode[0]) { | ||
case `required`: | ||
return false; | ||
case `optional`: | ||
return true; | ||
} | ||
} | ||
export { | ||
required, | ||
optional | ||
optional, | ||
isTreePath | ||
}; |
{ | ||
"name": "treetrunks", | ||
"version": "0.0.0", | ||
"license": "MIT", | ||
"author": { | ||
"name": "Jeremy Banka", | ||
"email": "hello@jeremybanka.com" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"type": "module", | ||
"files": ["dist", "src"], | ||
"main": "dist/treetrunks.js", | ||
"scripts": { | ||
"build:js": "bun build --outdir dist -- src/treetrunks.ts", | ||
"build:dts": "tsup", | ||
"build": "rimraf dist && concurrently \"bun:build:*\"", | ||
"lint:biome": "biome check -- .", | ||
"lint:eslint": "eslint --flag unstable_ts_config -- .", | ||
"lint:types": "tsc --noEmit", | ||
"lint:types:watch": "tsc --watch --noEmit", | ||
"lint": "bun run lint:biome && bun run lint:eslint && bun run lint:types", | ||
"test": "vitest", | ||
"test:once": "vitest run", | ||
"test:coverage": "echo no test coverage yet", | ||
"postversion": "biome format --write package.json" | ||
}, | ||
"devDependencies": { | ||
"concurrently": "9.0.1", | ||
"rimraf": "6.0.1", | ||
"tsup": "8.3.0", | ||
"vitest": "2.1.2" | ||
} | ||
} | ||
"name": "treetrunks", | ||
"version": "0.0.1", | ||
"license": "MIT", | ||
"author": { | ||
"name": "Jeremy Banka", | ||
"email": "hello@jeremybanka.com" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"type": "module", | ||
"files": [ | ||
"dist", | ||
"src" | ||
], | ||
"main": "dist/treetrunks.js", | ||
"devDependencies": { | ||
"concurrently": "9.0.1", | ||
"rimraf": "6.0.1", | ||
"tsup": "8.3.0", | ||
"vitest": "2.1.3" | ||
}, | ||
"scripts": { | ||
"build:js": "bun build --outdir dist -- src/treetrunks.ts", | ||
"build:dts": "tsup", | ||
"build": "rimraf dist && concurrently \"bun:build:*\"", | ||
"lint:biome": "biome check -- .", | ||
"lint:eslint": "eslint --flag unstable_ts_config -- .", | ||
"lint:types": "tsc --noEmit", | ||
"lint:types:watch": "tsc --watch --noEmit", | ||
"lint": "bun run lint:biome && bun run lint:eslint && bun run lint:types", | ||
"test": "vitest", | ||
"test:once": "echo no tests yet", | ||
"test:coverage": "echo no test coverage yet", | ||
"postversion": "biome format --write package.json" | ||
} | ||
} |
@@ -63,15 +63,29 @@ export function required<T>(arg: T): [`required`, T] { | ||
export type MySplit = ToPath<`hello/$world/good/morning`, `/`> | ||
const myTree = required({ | ||
hello: optional({ | ||
world: null, | ||
$name: optional({ good: required({ morning: null }) }), | ||
}), | ||
}) | ||
type MyTreePath = TreePath<typeof myTree> | ||
type MyTreeMap = TreeMap<typeof myTree, null> | ||
type MyTreePathsJoined = Join<MyTreePath, `/`> | ||
// type MyTreePathsJoined$ = Join<MyTreePath$, `/`> | ||
export function isTreePath<T extends Tree>( | ||
tree: T, | ||
maybePath: unknown[], | ||
): maybePath is TreePath<T> { | ||
let currentTreeNode: Tree | null = tree | ||
for (const segment of maybePath) { | ||
if (currentTreeNode === null) { | ||
return false | ||
} | ||
if (typeof segment !== `string`) { | ||
return false | ||
} | ||
if (segment in currentTreeNode[1]) { | ||
currentTreeNode = currentTreeNode[1][segment] | ||
} else { | ||
return false | ||
} | ||
} | ||
if (currentTreeNode === null) { | ||
return true | ||
} | ||
switch (currentTreeNode[0]) { | ||
case `required`: | ||
return false | ||
case `optional`: | ||
return true | ||
} | ||
} |
9047
146