Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .dependency-cruiser.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ module.exports = {
path: "^src/utils/",
},
to: {
path: "^src/classses/",
path: "^src/classes/",
},
},
//
Expand Down Expand Up @@ -153,7 +153,7 @@ module.exports = {
"section of your package.json. If this module is development only - add it to the " +
"from.pathNot re of the not-to-dev-dep rule in the dependency-cruiser configuration",
from: {
path: "^(src/classses)",
path: "^(src/classes)",
pathNot: "[.](?:spec|test)[.](?:js|mjs|cjs|jsx|ts|mts|cts|tsx)$",
},
to: {
Expand Down Expand Up @@ -384,7 +384,7 @@ module.exports = {
attributes: { fillcolor: "#FFA726", fontcolor: "black" },
},
{
criteria: { source: "classses" },
criteria: { source: "classes" },
attributes: { fillcolor: "#EF5350", fontcolor: "black" },
},
{
Expand All @@ -402,7 +402,7 @@ module.exports = {
],
dependencies: [
{
criteria: { resolved: "classses" },
criteria: { resolved: "classes" },
attributes: { color: "#EF5350" },
},
{
Expand Down
1,318 changes: 752 additions & 566 deletions index.html

Large diffs are not rendered by default.

19 changes: 8 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"scripts": {
"build:types": "nodemon --watch src --ext ts --exec \"tsx ./src/buildTypes.ts\"",
"build:findTypeDeclarations": "nodemon --watch src --ext ts --exec \"tsx ./scripts/findTypeDeclarations.ts\"",
"build:typeMirror": "nodemon --watch src --ext ts --exec \"npx tsx src/scripts/generateTypeMirrorClass\"",
"graph:build": "depcruise src --output-type dot | dot -T svg | depcruise-wrap-stream-in-html > index.html",
"graph:test": "depcruise src",
"graph:watch": "nodemon --watch src --ext ts --exec \"npm run graph:build\"",
Expand All @@ -32,6 +33,7 @@
},
"dependencies": {
"@eslint/js": "^9.25.1",
"@types/node": "^24.0.3",
"@types/ramda": "^0.30.2",
"eslint-config-prettier": "^10.1.2",
"globals": "^16.0.0",
Expand Down
7 changes: 3 additions & 4 deletions scripts/findTypeDeclarations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@ import { findTypeDeclarations } from "../src/tsc"
// printer.printNode(ts.EmitHint.Unspecified, typeStringAlias, ts.createSourceFile("", "", ts.ScriptTarget.Latest)),
// )

const rootDir = "./src"
const dirsToScan = ["./src", "./tests", "./lib"]
const myType = "ValidateFlatTuple$"
const declarationPaths = findTypeDeclarations(rootDir, dirsToScan, myType)
const dirsToScan = "./src"
const typesToFind = ["ValidateFlatTuple$", "ReTypeError"]
const declarationPaths = findTypeDeclarations(dirsToScan, typesToFind)

console.log("declarationPaths", declarationPaths)
4 changes: 2 additions & 2 deletions src/buildTypes.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Lax } from "classses/Lax"
import { Strict } from "classses/Strict"
import { Lax } from "classes/Lax"
import { Strict } from "classes/Strict"
import fs from "node:fs"
import { toPairs } from "ramda"
import { ImportRegistry } from "services/ImportRegistry"
Expand Down
File renamed without changes.
16 changes: 9 additions & 7 deletions src/classses/Lax/index.ts → src/classes/Lax/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { resolveEitherName, resolveLaxName } from "classses/utils"
import { resolveEitherName, resolveLaxName } from "classes/utils"
import { prop } from "ramda"
import { createJsDocs } from "utils/createJsDocs"
import type { PARSED_TYPE_DECLARATION } from "utils/parseTypeDeclarations"
import { parseTypeDeclaration } from "utils/parseTypeDeclarations"
import type { WITH_CONTEXT } from "utils/resolveGenerics"
import { resolveGenerics } from "utils/resolveGenerics"
import { typeBuilder } from "utils/typeBuilder"
import { eitherBody } from "utils/typeBuilder/eitherBody"
import type { Brand } from "utilTypes"
import type { WITH_COMMENTS } from "../types"

export type LAX_BODY = Brand<string, "LAX_BODY">

export class Lax {
protected parsedType: PARSED_TYPE_DECLARATION

Expand Down Expand Up @@ -48,9 +52,7 @@ export class Lax {
currentTypeName: typeName,
})

const body = `[_Error] extends [never]
? ${typeInvocation}
: _Error`
const body = eitherBody(typeInvocation)

return typeBuilder.typeDeclaration({
docs,
Expand All @@ -62,7 +64,7 @@ export class Lax {

// --- PROTECTED ----------------------------------------------------------------------

protected makeLaxBody({ withContext, withComments }: WITH_COMMENTS & WITH_CONTEXT): string {
protected makeLaxBody({ withContext, withComments }: WITH_COMMENTS & WITH_CONTEXT): LAX_BODY {
// TODO: mismatch error could be more detailed and reuse validation (what it should be)
// TODO: inside validation missing (before return)

Expand All @@ -82,15 +84,15 @@ export class Lax {
generics: resolveGenerics({ withContext, generics }),
// currentTypeName: "laxName",
}),
)
) as LAX_BODY

if (withComments) {
return (
// prettier-ignore
`
// --- ${laxName} START ---
${conditionalTypeBody}
// --- ${laxName} END ---`
// --- ${laxName} END ---` as LAX_BODY
)
}

Expand Down
File renamed without changes.
9 changes: 6 additions & 3 deletions src/classses/Strict/index.ts → src/classes/Strict/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { rejectContext, resolveEitherLaxName, resolveStrictLaxName } from "classses/utils"
import { rejectContext, resolveEitherLaxName, resolveStrictLaxName } from "classes/utils"
import { ImportRegistry } from "services/ImportRegistry"
import { createJsDocs } from "utils/createJsDocs"
import type { PARSED_TYPE_DECLARATION } from "utils/parseTypeDeclarations"
Expand All @@ -8,6 +8,9 @@ import { resolveGenerics } from "utils/resolveGenerics"
import type { CurrentTypeName } from "utils/reTypeError/trace"
import { trace } from "utils/reTypeError/trace"
import { typeBuilder } from "utils/typeBuilder"
import type { Brand } from "utilTypes"

export type STRICT_LAX_BODY = Brand<string, "STRICT_LAX_BODY">

export class Strict {
protected parsedType: PARSED_TYPE_DECLARATION
Expand All @@ -34,7 +37,7 @@ export class Strict {
}

// TODO: import validation modules keys
protected makeStrictLaxBody({ currentTypeName }: { currentTypeName: CurrentTypeName }): string {
protected makeStrictLaxBody({ currentTypeName }: { currentTypeName: CurrentTypeName }): STRICT_LAX_BODY {
// TODO: mismatch error could be more detailed and reuse validation (what it should be)
// TODO: Kamils class
const ValidationType = "ValidateFlatTuple$"
Expand All @@ -57,7 +60,7 @@ export class Strict {
>,
// Pass original generics
${genericsInvocationWithoutContext}
>`
>` as STRICT_LAX_BODY

return typeDef
}
Expand Down
File renamed without changes.
File renamed without changes.
34 changes: 17 additions & 17 deletions src/coreTypes/errors/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const ERROR_TYPE = {
export type ErrorType = ValueOf<typeof ERROR_TYPE>

// TODO: do we need js here?
export const ERRORS_LOOKUP = {
export const ErrorsLookup = {
// input --------------------------------
OpenTypeError: {
msg: "input: is open types (any, unknown, never)",
Expand Down Expand Up @@ -60,36 +60,36 @@ export const ERRORS_LOOKUP = {
{ msg: string; url: string }
>

export type ErrorsLookup = typeof ERRORS_LOOKUP
export type ERRORS_LOOKUP = typeof ErrorsLookup

// TODO: js docs
export type ReTypeError<
_ErrorType extends keyof ErrorsLookup,
_ErrorType extends keyof ERRORS_LOOKUP,
Context extends string,
Value,
Constraint = unknown
_Constraint = "TODO:unknown"
> = {
__type: _ErrorType
__message: ErrorsLookup[_ErrorType]["msg"]
__context: Context
__value: Value & {} // TODO: pretty
__constraint?: Constraint & {} // TODO: pretty
__url: ErrorsLookup[_ErrorType]["url"]
readonly __type: _ErrorType
readonly __message: ERRORS_LOOKUP[_ErrorType]["msg"]
readonly __context: Context
readonly __value: Value & {} // TODO: pretty
readonly __constraint?: _Constraint & {} // TODO: pretty
readonly __url: ERRORS_LOOKUP[_ErrorType]["url"]
}

// -----------------------

// prettier-ignore
export type NeverError <CX extends string, T, Constraint = unknown> = ReTypeError<"NeverError", Trace<CX, "NeverError">, T, Constraint>
export type NeverError <CX extends string, T, _Constraint = "TODO:unknown"> = ReTypeError<"NeverError", Trace<CX, "NeverError">, T, _Constraint>
// prettier-ignore
export type AnyError <CX extends string, T, Constraint = unknown> = ReTypeError<"AnyError", Trace<CX, "AnyError">, T, Constraint>
export type AnyError <CX extends string, T, _Constraint = "TODO:unknown"> = ReTypeError<"AnyError", Trace<CX, "AnyError">, T, _Constraint>
// prettier-ignore
export type UnknownError <CX extends string, T, Constraint = unknown> = ReTypeError<"UnknownError", Trace<CX, "UnknownError">, T, Constraint>
export type UnknownError <CX extends string, T, _Constraint = "TODO:unknown"> = ReTypeError<"UnknownError", Trace<CX, "UnknownError">, T, _Constraint>
// prettier-ignore
export type MismatchError <CX extends string, T, Constraint = unknown> = ReTypeError<"MismatchError", Trace<CX, "MismatchError">, T, Constraint>
export type MismatchError <CX extends string, T, _Constraint = "TODO:unknown"> = ReTypeError<"MismatchError", Trace<CX, "MismatchError">, T, _Constraint>
// prettier-ignore
export type NonLiteralError <CX extends string, T, Constraint = unknown> = ReTypeError<"NonLiteralError", Trace<CX, "NonLiteralError">, T, Constraint>
export type NonLiteralError <CX extends string, T, _Constraint = "TODO:unknown"> = ReTypeError<"NonLiteralError", Trace<CX, "NonLiteralError">, T, _Constraint>
// prettier-ignore
export type EmptyStringError<CX extends string, T, Constraint = unknown> = ReTypeError<"EmptyStringError", Trace<CX, "EmptyStringError">, T, Constraint>
export type EmptyStringError<CX extends string, T, _Constraint = "TODO:unknown"> = ReTypeError<"EmptyStringError", Trace<CX, "EmptyStringError">, T, _Constraint>
// prettier-ignore
export type OpenTypeError <CX extends string, T, Constraint = unknown> = ReTypeError<"OpenTypeError", Trace<CX, "OpenTypeError">, T, Constraint>
export type OpenTypeError <CX extends string, T, _Constraint = "TODO:unknown"> = ReTypeError<"OpenTypeError", Trace<CX, "OpenTypeError">, T, _Constraint>
12 changes: 6 additions & 6 deletions src/coreTypes/errors/utils.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import type {
ErrorsLookup,
ERRORS_LOOKUP,
NeverError,
} from "./errors"

export type GENERIC_ERROR = {
__type: keyof ErrorsLookup
__message: ErrorsLookup[keyof ErrorsLookup]["msg"]
__url: ErrorsLookup[keyof ErrorsLookup]["url"]
__context: string
readonly __type: keyof ERRORS_LOOKUP
readonly __message: ERRORS_LOOKUP[keyof ERRORS_LOOKUP]["msg"]
readonly __url: ERRORS_LOOKUP[keyof ERRORS_LOOKUP]["url"]
readonly __context: string
// eslint-disable-next-line @typescript-eslint/no-explicit-any
__value: any
readonly __value: any
}

// -----------------------------------------------------------------
Expand Down
3 changes: 2 additions & 1 deletion src/regexes/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export const regexes = {
extractTypesAndValidations: /type ([\w$]*)<([^<>]*)>\s*=\s*(.*)/,
blockComment: /\/\*\*[\s\S]*?\*\//g,
lineComment: /\/\/.*/g,
}
2 changes: 1 addition & 1 deletion src/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ async function analyzeTypeScriptFiles(): Promise<void> {
console.log("🔍 Analyzing TypeScript files in the project...")

// Find all TypeScript files in the classes directory
const classesDir = path.resolve(process.cwd(), "src", "classses")
const classesDir = path.resolve(process.cwd(), "src", "classes")
const tsFiles = await findAllTsFiles(classesDir)

console.log(`Found ${tsFiles.length} TypeScript files`)
Expand Down
56 changes: 56 additions & 0 deletions src/scripts/generateTypeMirrorClass/codegen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { ImportRegistry } from "services/ImportRegistry"
import { findTypeDeclarations } from "tsc"
import type { GENERIC, PARSED_TYPE_DECLARATION } from "utils/parseTypeDeclarations"
import { deconstructConstraint, isPrimitiveConstraint } from "./utils/import"

// import type { ErrorsLookup } from "coreTypes/errors" // TODO: Hardcoded path, should be replaced with a dynamic import
// import type { BYPASS_MODES } from "coreTypes/validators"

export const generateParamsDeclaration = (generics: GENERIC[]): string =>
generics
.map((g) => `${g.name}${g.constraint ? `: ${g.constraint}` : ""}${g.defaultValue ? ` = ${g.defaultValue}` : ""}`)
// .map((g) => `${g.name}`) // ${g.constraint}`)
.join(", ")

export const generateParamsInterpolation = (generics: GENERIC[]): string =>
generics.map((g) => `\${${g.name}}`).join(", ")

export const generateMethod = ({ typeName, generics }: PARSED_TYPE_DECLARATION): string => {
const paramsDecl = generateParamsDeclaration(generics)
const paramsInterp = generateParamsInterpolation(generics)

generics.forEach(({ constraint: _constraint }) => {
if (_constraint) {
const constraint = deconstructConstraint(_constraint)

if (!isPrimitiveConstraint(constraint)) {
ImportRegistry.addImport(constraint)
}
}
})

return `
${typeName}(${paramsDecl}): string {
return \`${typeName}<${paramsInterp}>\`
}`
}

export const generateClassBody = (methods: PARSED_TYPE_DECLARATION[]): string => methods.map(generateMethod).join("\n")

export const generateOutput = (methods: PARSED_TYPE_DECLARATION[]): string => {
const utilClass = `export class TypeUtils {
${generateClassBody(methods)}
}`

const imports = ImportRegistry.getImports()
console.log("imports --->", imports)

const declarations = findTypeDeclarations("./src", imports)

console.log("declarations --->", declarations)

return `
${declarations.join("\n")}
${utilClass}
`
}
23 changes: 23 additions & 0 deletions src/scripts/generateTypeMirrorClass/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as fs from "fs"
import * as path from "path"

import { pipe } from "ramda"
import { collectTsFilePaths } from "tsc/collectTsFilePaths"
import { generateOutput } from "./codegen"
import { processAllFiles } from "./typeProcessing/processing"

const main = (dirToScan: string, outputFilePath: string): void => {
pipe(
//
collectTsFilePaths,
processAllFiles,
generateOutput,
(code: string) => fs.writeFileSync(outputFilePath, code),
)(dirToScan)
}

main(
//
path.resolve(process.cwd(), "src/coreTypes"),
path.resolve(process.cwd(), "dist/TypeMirror.ts"),
)
Loading