@effect-app/eslint-codegen-model 0.59.0 → 0.59.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/presets/model.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAsBnD,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB,CAyFA,CAAA"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/presets/model.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAqBnD,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB,CAiDA,CAAA"}
@@ -27,100 +27,72 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  exports.model = void 0;
30
+ /* eslint-disable @typescript-eslint/no-explicit-any */
30
31
  const generator_1 = __importDefault(require("@babel/generator"));
31
32
  const parser_1 = require("@babel/parser");
32
33
  const fs = __importStar(require("fs"));
33
- const compiler_1 = require("../compiler");
34
34
  function normalise(str) {
35
35
  try {
36
36
  return (0, generator_1.default)((0, parser_1.parse)(str, { sourceType: "module", plugins: ["typescript"] }))
37
37
  .code;
38
38
  // .replace(/'/g, `"`)
39
39
  // .replace(/\/index/g, "")
40
- //.replace(/([\n\s]+ \|)/g, " |").replaceAll(": |", ":")
41
- //.replaceAll(/[\s\n]+\|/g, " |")
42
- //.replaceAll("\n", ";")
43
- //.replaceAll(" ", "")
40
+ // .replace(/([\n\s]+ \|)/g, " |").replaceAll(": |", ":")
41
+ // .replaceAll(/[\s\n]+\|/g, " |")
42
+ // .replaceAll("\n", ";")
43
+ // .replaceAll(" ", "")
44
44
  // TODO: remove all \n and whitespace?
45
45
  }
46
46
  catch (e) {
47
47
  return str;
48
48
  }
49
49
  }
50
- const utils_1 = require("@typescript-eslint/utils");
51
- const model = ({ meta, options }, context) => {
52
- if (!context.parserOptions.project) {
53
- console.warn(`${meta.filename}: Cannot run ESLint Model plugin, because no TS Compiler is enabled`);
54
- return meta.existingContent;
55
- }
56
- const writeFullTypes = !!options.writeFullTypes;
50
+ const model = ({ meta }) => {
57
51
  try {
58
- // option to exclude some methods
59
- //const exclude = (options.exclude || "").split(",")
60
- // checks and reads the file
52
+ const targetContent = fs.readFileSync(meta.filename).toString();
53
+ const processed = [];
61
54
  const sourcePath = meta.filename;
62
55
  if (!fs.existsSync(sourcePath) || !fs.statSync(sourcePath).isFile()) {
63
56
  throw Error(`Source path is not a file: ${sourcePath}`);
64
57
  }
65
- // const cfgFile = ts.findConfigFile(sourcePath, (fn) => fs.existsSync(fn))
66
- // if (!cfgFile) {
67
- // throw new Error("No TS config file found")
68
- // }
69
- // const cfg = ts.readConfigFile(cfgFile, (fn) => fs.readFileSync(fn, "utf-8"))
70
- // const basePath = path.dirname(cfgFile); // equal to "getDirectoryPath" from ts, at least in our case.
71
- // const parsedConfig = ts.parseJsonConfigFileContent(cfg.config, ts.sys, basePath);
72
- // const program = ts.createProgram([sourcePath], parsedConfig.options)
73
- const { program } = utils_1.ESLintUtils.getParserServices(context);
74
- //console.log("$$ processing", sourcePath)
75
- // create and parse the AST
76
- const sourceFile = program.getSourceFile(sourcePath);
77
- // collect data-first declarations
78
- // const dataFirstDeclarations = sourceFile.statements
79
- // .filter(ts.isFunctionDeclaration)
80
- // // .filter(
81
- // // (node) =>
82
- // // node.modifiers &&
83
- // // node.modifiers.filter(
84
- // // (modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword
85
- // // ).length > 0
86
- // // )
87
- // // .filter((node) => !!node.name)
88
- // // .filter((node) => node.parameters.length >= 2)
89
- // // .filter((node) => node.name!.getText(sourceFile).endsWith("_"))
90
- // // .map((node) => ({
91
- // // functionName: node.name!.getText(sourceFile),
92
- // // typeParameters: node.typeParameters || ts.factory.createNodeArray(),
93
- // // parameters: node.parameters || ts.factory.createNodeArray(),
94
- // // type: node.type!,
95
- // // implemented: !!node.body,
96
- // // jsDoc: getJSDoc(node)
97
- // // }))
98
- // // .filter((decl) => exclude.indexOf(decl.functionName) === -1)
99
- // // create the actual AST nodes
100
- // const nodes = dataFirstDeclarations.map(createPipeableFunctionDeclaration)
101
- // const expectedContent = nodes.map((node) => printNode(node, sourceFile)).join("\n")
102
- const pn = (0, compiler_1.processNode)(program.getTypeChecker(), sourceFile, writeFullTypes);
103
- let abc = [];
104
- // TODO: must return void, cannot use getChildren() etc, or it wont work, no idea why!
105
- sourceFile.forEachChild(c => { abc = abc.concat(pn(c)); });
58
+ const clss = targetContent.matchAll(/^export class (\w+)[^{]*(Extended(Tagged)?Class)|ExtendedTaggedRequest/g);
59
+ const them = [];
60
+ for (const cls of clss) {
61
+ let modelName = null;
62
+ if (cls && cls[1]) {
63
+ modelName = cls[1];
64
+ }
65
+ else
66
+ continue;
67
+ if (processed.includes(modelName))
68
+ continue;
69
+ processed.push(modelName);
70
+ them.push([
71
+ `export namespace ${modelName} {`,
72
+ ` export class From extends S.FromClass<typeof ${modelName}>() {}`,
73
+ "}"
74
+ ]);
75
+ }
106
76
  const expectedContent = [
107
77
  "//",
108
78
  `/* eslint-disable */`,
109
- ...abc.filter((x) => !!x),
79
+ ...them.flat().filter((x) => !!x),
110
80
  `/* eslint-enable */`,
111
81
  "//"
112
- ].join("\n");
82
+ ]
83
+ .join("\n");
113
84
  // do not re-emit in a different style, or a loop will occur
114
- if (normalise(meta.existingContent) === normalise(expectedContent))
85
+ if (normalise(meta.existingContent) === normalise(expectedContent)) {
115
86
  return meta.existingContent;
87
+ }
116
88
  return expectedContent;
117
89
  }
118
90
  catch (e) {
119
- return ("/** Got exception: " +
120
- ("stack" in e ? e.stack : "") +
121
- JSON.stringify(e) +
122
- "*/");
91
+ return ("/** Got exception: "
92
+ + ("stack" in e ? e.stack : "")
93
+ + JSON.stringify(e)
94
+ + "*/");
123
95
  }
124
96
  };
125
97
  exports.model = model;
126
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kZWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcHJlc2V0cy9tb2RlbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLGlFQUF1QztBQUN2QywwQ0FBcUM7QUFFckMsdUNBQXdCO0FBQ3hCLDBDQUF5QztBQUN6QyxTQUFTLFNBQVMsQ0FBQyxHQUFXO0lBQzVCLElBQUksQ0FBQztRQUNILE9BQU8sSUFBQSxtQkFBUSxFQUNiLElBQUEsY0FBSyxFQUFDLEdBQUcsRUFBRSxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBUSxDQUNyRTthQUNFLElBQUksQ0FBQTtRQUNMLHNCQUFzQjtRQUN0QiwyQkFBMkI7UUFDM0Isd0RBQXdEO1FBQ3hELGlDQUFpQztRQUNqQyx3QkFBd0I7UUFDeEIsc0JBQXNCO1FBQ3RCLHNDQUFzQztJQUMxQyxDQUFDO0lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUNYLE9BQU8sR0FBRyxDQUFBO0lBQ1osQ0FBQztBQUNILENBQUM7QUFFRCxvREFBc0Q7QUFDL0MsTUFBTSxLQUFLLEdBRWIsQ0FBQyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsRUFBRSxPQUFZLEVBQUUsRUFBRTtJQUN2QyxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNuQyxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLFFBQVEscUVBQXFFLENBQUMsQ0FBQTtRQUNuRyxPQUFPLElBQUksQ0FBQyxlQUFlLENBQUE7SUFDN0IsQ0FBQztJQUVELE1BQU0sY0FBYyxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFBO0lBRS9DLElBQUksQ0FBQztRQUNILGlDQUFpQztRQUNqQyxvREFBb0Q7UUFFcEQsNEJBQTRCO1FBQzVCLE1BQU0sVUFBVSxHQUFHLElBQUks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
98
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kZWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcHJlc2V0cy9tb2RlbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLHVEQUF1RDtBQUN2RCxpRUFBdUM7QUFDdkMsMENBQXFDO0FBRXJDLHVDQUF3QjtBQUV4QixTQUFTLFNBQVMsQ0FBQyxHQUFXO0lBQzVCLElBQUksQ0FBQztRQUNILE9BQU8sSUFBQSxtQkFBUSxFQUNiLElBQUEsY0FBSyxFQUFDLEdBQUcsRUFBRSxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBUSxDQUNyRTthQUNFLElBQUksQ0FBQTtRQUNQLHNCQUFzQjtRQUN0QiwyQkFBMkI7UUFDM0IseURBQXlEO1FBQ3pELGtDQUFrQztRQUNsQyx5QkFBeUI7UUFDekIsdUJBQXVCO1FBQ3ZCLHNDQUFzQztJQUN4QyxDQUFDO0lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUNYLE9BQU8sR0FBRyxDQUFBO0lBQ1osQ0FBQztBQUNILENBQUM7QUFFTSxNQUFNLEtBQUssR0FFYixDQUFDLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRTtJQUNoQixJQUFJLENBQUM7UUFDSCxNQUFNLGFBQWEsR0FBRyxFQUFFLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQTtRQUUvRCxNQUFNLFNBQVMsR0FBYSxFQUFFLENBQUE7UUFFOUIsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQTtRQUNoQyxJQUFJLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQztZQUNwRSxNQUFNLEtBQUssQ0FBQyw4QkFBOEIsVUFBVSxFQUFFLENBQUMsQ0FBQTtRQUN6RCxDQUFDO1FBRUQsTUFBTSxJQUFJLEdBQUcsYUFBYSxDQUFDLFFBQVEsQ0FBQyx5RUFBeUUsQ0FBQyxDQUFBO1FBQzlHLE1BQU0sSUFBSSxHQUFHLEVBQUUsQ0FBQTtRQUNmLEtBQUssTUFBTSxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7WUFDdkIsSUFBSSxTQUFTLEdBQUcsSUFBSSxDQUFBO1lBQ3BCLElBQUksR0FBRyxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO2dCQUNsQixTQUFTLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFBO1lBQ3BCLENBQUM7O2dCQUFNLFNBQVE7WUFDZixJQUFJLFNBQVMsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDO2dCQUFFLFNBQVE7WUFDM0MsU0FBUyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQTtZQUV6QixJQUFJLENBQUMsSUFBSSxDQUFDO2dCQUNSLG9CQUFvQixTQUFTLElBQUk7Z0JBQ2pDLGtEQUFrRCxTQUFTLFFBQVE7Z0JBQ25FLEdBQUc7YUFDSixDQUFDLENBQUE7UUFDSixDQUFDO1FBQ0QsTUFBTSxlQUFlLEdBQUc7WUFDdEIsSUFBSTtZQUNKLHNCQUFzQjtZQUN0QixHQUFHLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQWUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDOUMscUJBQXFCO1lBQ3JCLElBQUk7U0FDTDthQUNFLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUViLDREQUE0RDtRQUM1RCxJQUFJLFNBQVMsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLEtBQUssU0FBUyxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUM7WUFDbkUsT0FBTyxJQUFJLENBQUMsZUFBZSxDQUFBO1FBQzdCLENBQUM7UUFDRCxPQUFPLGVBQWUsQ0FBQTtJQUN4QixDQUFDO0lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUNYLE9BQU8sQ0FDTCxxQkFBcUI7Y0FDbkIsQ0FBQyxPQUFPLElBQUssQ0FBUyxDQUFDLENBQUMsQ0FBRSxDQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7Y0FDL0MsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7Y0FDakIsSUFBSSxDQUNQLENBQUE7SUFDSCxDQUFDO0FBQ0gsQ0FBQyxDQUFBO0FBbkRZLFFBQUEsS0FBSyxTQW1EakIifQ==
package/package.json CHANGED
@@ -2,11 +2,11 @@
2
2
  "name": "@effect-app/eslint-codegen-model",
3
3
  "description": "Contains eslint helpers",
4
4
  "sideEffects": false,
5
- "version": "0.59.0",
5
+ "version": "0.59.2",
6
6
  "dependencies": {
7
7
  "@babel/generator": "7.23.6",
8
8
  "@babel/parser": "7.24.0",
9
- "@typescript-eslint/utils": "7.1.0",
9
+ "@typescript-eslint/utils": "7.1.1",
10
10
  "eslint-plugin-codegen": "0.17.0",
11
11
  "glob": "8.1.0",
12
12
  "io-ts": "2.2.21",
@@ -1,116 +1,76 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  import generate from "@babel/generator"
2
3
  import { parse } from "@babel/parser"
3
4
  import type { Preset } from "eslint-plugin-codegen"
4
5
  import * as fs from "fs"
5
- import { processNode } from "../compiler"
6
+
6
7
  function normalise(str: string) {
7
8
  try {
8
9
  return generate(
9
10
  parse(str, { sourceType: "module", plugins: ["typescript"] }) as any
10
11
  )
11
12
  .code
12
- // .replace(/'/g, `"`)
13
- // .replace(/\/index/g, "")
14
- //.replace(/([\n\s]+ \|)/g, " |").replaceAll(": |", ":")
15
- //.replaceAll(/[\s\n]+\|/g, " |")
16
- //.replaceAll("\n", ";")
17
- //.replaceAll(" ", "")
18
- // TODO: remove all \n and whitespace?
13
+ // .replace(/'/g, `"`)
14
+ // .replace(/\/index/g, "")
15
+ // .replace(/([\n\s]+ \|)/g, " |").replaceAll(": |", ":")
16
+ // .replaceAll(/[\s\n]+\|/g, " |")
17
+ // .replaceAll("\n", ";")
18
+ // .replaceAll(" ", "")
19
+ // TODO: remove all \n and whitespace?
19
20
  } catch (e) {
20
21
  return str
21
22
  }
22
23
  }
23
24
 
24
- import { ESLintUtils } from "@typescript-eslint/utils"
25
25
  export const model: Preset<{
26
26
  writeFullTypes?: boolean
27
- }> = ({ meta, options }, context: any) => {
28
- if (!context.parserOptions.project) {
29
- console.warn(`${meta.filename}: Cannot run ESLint Model plugin, because no TS Compiler is enabled`)
30
- return meta.existingContent
31
- }
32
-
33
- const writeFullTypes = !!options.writeFullTypes
34
-
27
+ }> = ({ meta }) => {
35
28
  try {
36
- // option to exclude some methods
37
- //const exclude = (options.exclude || "").split(",")
29
+ const targetContent = fs.readFileSync(meta.filename).toString()
30
+
31
+ const processed: string[] = []
38
32
 
39
- // checks and reads the file
40
33
  const sourcePath = meta.filename
41
34
  if (!fs.existsSync(sourcePath) || !fs.statSync(sourcePath).isFile()) {
42
35
  throw Error(`Source path is not a file: ${sourcePath}`)
43
36
  }
44
- // const cfgFile = ts.findConfigFile(sourcePath, (fn) => fs.existsSync(fn))
45
- // if (!cfgFile) {
46
- // throw new Error("No TS config file found")
47
- // }
48
-
49
- // const cfg = ts.readConfigFile(cfgFile, (fn) => fs.readFileSync(fn, "utf-8"))
50
- // const basePath = path.dirname(cfgFile); // equal to "getDirectoryPath" from ts, at least in our case.
51
- // const parsedConfig = ts.parseJsonConfigFileContent(cfg.config, ts.sys, basePath);
52
-
53
- // const program = ts.createProgram([sourcePath], parsedConfig.options)
54
37
 
38
+ const clss = targetContent.matchAll(/^export class (\w+)[^{]*(Extended(Tagged)?Class)|ExtendedTaggedRequest/g)
39
+ const them = []
40
+ for (const cls of clss) {
41
+ let modelName = null
42
+ if (cls && cls[1]) {
43
+ modelName = cls[1]
44
+ } else continue
45
+ if (processed.includes(modelName)) continue
46
+ processed.push(modelName)
55
47
 
56
- const { program } = ESLintUtils.getParserServices(context);
57
-
58
- //console.log("$$ processing", sourcePath)
59
-
60
- // create and parse the AST
61
- const sourceFile = program.getSourceFile(
62
- sourcePath,
63
- )!
64
-
65
- // collect data-first declarations
66
- // const dataFirstDeclarations = sourceFile.statements
67
- // .filter(ts.isFunctionDeclaration)
68
- // // .filter(
69
- // // (node) =>
70
- // // node.modifiers &&
71
- // // node.modifiers.filter(
72
- // // (modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword
73
- // // ).length > 0
74
- // // )
75
- // // .filter((node) => !!node.name)
76
- // // .filter((node) => node.parameters.length >= 2)
77
- // // .filter((node) => node.name!.getText(sourceFile).endsWith("_"))
78
- // // .map((node) => ({
79
- // // functionName: node.name!.getText(sourceFile),
80
- // // typeParameters: node.typeParameters || ts.factory.createNodeArray(),
81
- // // parameters: node.parameters || ts.factory.createNodeArray(),
82
- // // type: node.type!,
83
- // // implemented: !!node.body,
84
- // // jsDoc: getJSDoc(node)
85
- // // }))
86
- // // .filter((decl) => exclude.indexOf(decl.functionName) === -1)
87
-
88
- // // create the actual AST nodes
89
- // const nodes = dataFirstDeclarations.map(createPipeableFunctionDeclaration)
90
- // const expectedContent = nodes.map((node) => printNode(node, sourceFile)).join("\n")
91
-
92
- const pn = processNode(program.getTypeChecker(), sourceFile, writeFullTypes)
93
- let abc: (string[] | undefined)[] = []
94
- // TODO: must return void, cannot use getChildren() etc, or it wont work, no idea why!
95
- sourceFile.forEachChild(c => {abc = abc.concat(pn(c))})
48
+ them.push([
49
+ `export namespace ${modelName} {`,
50
+ ` export class From extends S.FromClass<typeof ${modelName}>() {}`,
51
+ "}"
52
+ ])
53
+ }
96
54
  const expectedContent = [
97
55
  "//",
98
- `/* eslint-disable */`,
99
- ...abc.filter((x): x is string[] => !!x),
56
+ `/* eslint-disable */`,
57
+ ...them.flat().filter((x): x is string => !!x),
100
58
  `/* eslint-enable */`,
101
59
  "//"
102
- ].join("\n")
60
+ ]
61
+ .join("\n")
103
62
 
104
63
  // do not re-emit in a different style, or a loop will occur
105
- if (normalise(meta.existingContent) === normalise(expectedContent))
64
+ if (normalise(meta.existingContent) === normalise(expectedContent)) {
106
65
  return meta.existingContent
66
+ }
107
67
  return expectedContent
108
68
  } catch (e) {
109
69
  return (
110
- "/** Got exception: " +
111
- ("stack" in (e as any) ? (e as any).stack : "") +
112
- JSON.stringify(e) +
113
- "*/"
70
+ "/** Got exception: "
71
+ + ("stack" in (e as any) ? (e as any).stack : "")
72
+ + JSON.stringify(e)
73
+ + "*/"
114
74
  )
115
75
  }
116
76
  }
package/src/compiler.ts DELETED
@@ -1,246 +0,0 @@
1
- import ts, { SyntaxKind } from "typescript"
2
-
3
- const sortUnion = (a: string, b: string) => {
4
- if (a !== "null" && a!== "undefined" && (b === "null" || b === "undefined")) {
5
- return -1
6
- }
7
- if (b !== "null" && b !== "undefined" && (a === "null" || a === "undefined")) {
8
- return 1
9
- }
10
- if(a < b) { return -1; }
11
- if(a > b) { return 1; }
12
- return 0;
13
- }
14
-
15
- const sortAlpha = (a: string, b: string) => {
16
- if(a < b) { return -1; }
17
- if(a > b) { return 1; }
18
- return 0;
19
- }
20
-
21
- // TODO: we don't support string literals with spaces in them currently.
22
- const rx = /(([^\s\<\>\,\[\(]+)? \| ([^\s\<\>\,\]\)]+))+/
23
-
24
- function sortIt(str: string) {
25
- return str.split(" | ").sort(sortUnion).join(" | ")
26
- }
27
-
28
- const debug = false // true
29
-
30
- export function processNode(tc: ts.TypeChecker, root: ts.Node, writeFullTypes = false) {
31
- const processed: any[] = []
32
- return (n: ts.Node) => {
33
- if (/*ts.isClassDeclaration(n) || ts.isTypeAliasDeclaration(n)*/ true) {
34
-
35
- let modelName = null
36
- if (ts.isClassDeclaration(n)) {
37
- if (n.getText().match(/(Extended(Tagged)?Class)|ExtendedTaggedRequest/)) {
38
- modelName = (n.name as any)?.escapedText
39
- }
40
- }
41
- if (!modelName) {
42
- const constructorName = (n as any).name?.escapedText
43
- // TODO: Remove requirement
44
- if (!constructorName?.endsWith("Constructor")) {
45
- //console.log("$$$constructorName doesnt end with Constructor", constructorName)
46
- return
47
- }
48
- modelName = constructorName.replace("Constructor", "")
49
- }
50
- if (processed.includes(modelName)) { return }
51
- processed.push(modelName)
52
-
53
- if (!writeFullTypes) {
54
- return [
55
- `export namespace ${modelName} {`,
56
- ` export class From extends S.FromClass<typeof ${modelName}>() {}`,
57
- // ` export const From: FromOps = { $: {} }`,
58
- // ` export interface FromAspects {}`,
59
- "}",
60
- ]
61
- }
62
-
63
- //console.log("$$$ constructorName", constructorName)
64
-
65
- const t = tc.getTypeAtLocation(n)
66
-
67
- const result = { encoded: [] as string[], parsed: [] as string[] }
68
- const unions: Record<string, string> = {}
69
-
70
- //console.log("$$$ fields", t.getProperties().map(x => x.escapedName))
71
- t.getProperties().forEach((c) => {
72
- const method = c.name
73
- if (method === "encoded" || method === "parsed") {
74
- //console.log("$$$ method", method)
75
- //console.log(c.members)
76
- const tt = tc.getTypeOfSymbolAtLocation(c, n)
77
- // const s = tc.getReturnTypeOfSignature(tt.getCallSignatures()[0])
78
-
79
- // const type = tc.getReturnTypeOfSignature(s! as any /* TODO */)
80
-
81
-
82
- tt.getProperties().forEach(p => {
83
- const isLookup = debug && p.escapedName === "carrier"
84
-
85
- //kind = 207,
86
- //arguments[0].escapedText === "HosterRole"
87
- //console.log("$$$p", p.escapedName)
88
- //if (p.escapedName === "opposite") {
89
- //console.log("$$$ a union!", p.declarations?.map(x => x.forEachChild(c => {
90
-
91
- // TODO: have to find nullable, array, set, map, etc.
92
- // TODO: "From"
93
- // but also should find fully custom sets like PurchaseOrderModulesSet - we should be able to just use those directly, incl PurchaseOrderModulesSet.From
94
- // for now just skip them?
95
- p.declarations?.map(x => x.forEachChild(c => {
96
- if (isLookup) {
97
- console.log("$$$ lookup", c.kind, c)
98
- }
99
- if (c.kind === SyntaxKind.CallExpression) { // 207 -- SyntaxKind.ElementAccessExpression) {
100
- let it = (c as any).arguments[0]
101
- //const isState = p.escapedName === "state"
102
- if (isLookup) {
103
- console.log("$$$ state it", it)
104
- }
105
- const isNullable = it.expression?.escapedText === "nullable"
106
- const isIt = it.arguments && it.arguments[0] //it.expression?.escapedText === "nullable"
107
- if (isIt) {
108
- //console.log("$$ nullable", it.arguments[0])
109
- // TODO: usually the union is on the last input, we need to support all elements individually however
110
- it = it.arguments[it.arguments.length - 1]
111
- }
112
- //console.log("$args", it)
113
- //tc.getTypeAtLocation(it)
114
- const tt = tc.getTypeAtLocation(c) //tc.getTypeOfSymbolAtLocation(it.parent, n)
115
- const typeDecl = tc.typeToString(
116
- tt,
117
- root,
118
- ts.TypeFormatFlags.NoTruncation
119
- //ts.TypeFormatFlags.None
120
- //ts.TypeFormatFlags.AddUndefined |
121
- // | ts.TypeFormatFlags.NoTypeReduction
122
- // | ts.TypeFormatFlags.MultilineObjectLiterals
123
- //| ts.TypeFormatFlags.InTypeAlias
124
- | ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope // prevents import(*)
125
- // | ts.TypeFormatFlags.UseStructuralFallback
126
- )
127
- if (isLookup) {
128
- console.log("$$ type", typeDecl)
129
- }
130
- const matches = typeDecl.match(rx)
131
- if (isLookup) {
132
- console.log("$$ matches", matches)
133
- }
134
- const isOptional = typeDecl.match(/\>, "optional"/)
135
- if (matches) {
136
- let replaced = matches[0]!.replace(rx, (match) => sortIt(match))
137
- replaced = sortIt(isOptional ? isNullable ? replaced.replace(" | null", " | undefined | null") : replaced + " | undefined" : replaced)
138
- //console.log("$$ replaced", replaced, it.escapedText, matches)
139
- // if (it.escapedText === "TaskState") {
140
- // console.log("Help", it)
141
- // }
142
- if (isLookup) {
143
- console.log("$$$ replaced", it.escapedText, replaced)
144
- }
145
- if (it.escapedText && !it.escapedText.endsWith("Set") /* skip the "Set" problem */ && replaced.replace(" | null", "").includes("|")) {
146
- const replacement = it.escapedText + (isNullable ? " | null" : "") + (isOptional ? " | undefined" : "")
147
- // if (it.escapedText === "TaskState") {
148
- // console.log("$$$", { replaced, replacement })
149
- // unions[replaced] = replacement
150
- // } else {
151
- unions[replaced] = replacement
152
- if (isLookup) {
153
- console.log("$$ repl", { replaced, replacement})
154
- }
155
- //}
156
- } else {
157
- // if (isIt) {
158
- // console.log("$$ no name found", it.escapedText)
159
- // }
160
- // console.log("$$ no name found??", it)
161
- }
162
- }
163
-
164
- }
165
- //c.kind === 346 ? console.log(c) : null
166
- //console.log((c as any).flowNode?.node?.name)
167
- }))
168
- //}
169
- })
170
-
171
- if (debug && Object.keys(unions).length) {
172
- console.log("$$$ unions to replace", unions)
173
- }
174
-
175
- const typeDecl = tc.typeToString(
176
- tt,
177
- root,
178
- ts.TypeFormatFlags.NoTruncation
179
- //ts.TypeFormatFlags.None
180
- //ts.TypeFormatFlags.AddUndefined |
181
- // | ts.TypeFormatFlags.NoTypeReduction
182
- // | ts.TypeFormatFlags.MultilineObjectLiterals
183
- //| ts.TypeFormatFlags.InTypeAlias
184
- | ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope // prevents import(*)
185
- // | ts.TypeFormatFlags.UseStructuralFallback
186
- )
187
- const str = typeDecl === "{}" ? [] :
188
- // drop leading { and trailing }
189
- typeDecl.substring(2, typeDecl.length - 2)
190
- .split(";")
191
- .map(l => l.trim())
192
- // todo; skip the first split, as its the property
193
- .map(l => l.replace(rx, (match) => {
194
- const rpl = sortIt(match)
195
- //if (debug) { console.log("Searching for", rpl, { unions}) }
196
- if (rpl.endsWith(" | undefined")) {
197
- const sub = unions[rpl.replace(" | undefined", "")]
198
- return sub ? sub + " | undefined" : unions[rpl] ?? rpl
199
- }
200
-
201
- const sub = unions[rpl]
202
- return (sub ? sub : rpl)
203
- })
204
- .replaceAll(" Array<", " ReadonlyArray<") // .replaceAll(/(Array|Set|Map)\</", "ReadonlyArray<") //
205
- .replaceAll(" Set<", " ReadonlySet<")
206
- .replaceAll(" Map<", " ReadonlyMap<")
207
- .replaceAll("(Array<", "(ReadonlyArray<") // .replaceAll(/(Array|Set|Map)\</", "ReadonlyArray<") //
208
- .replaceAll("(Set<", "(ReadonlySet<")
209
- .replaceAll("(Map<", "(ReadonlyMap<")
210
- .replaceAll(" Array.Array<", " ReadonlyArray<") // .replaceAll(/(Array|Set|Map)\</", "ReadonlyArray<") //
211
- .replaceAll(" Set.Set<", " ReadonlySet<")
212
- .replaceAll(" Map.Map<", " ReadonlyMap<")
213
- )
214
- // we sort for now, because otherwise we have sometimes multiple times changing back and forth between editor and console.
215
- .sort(sortAlpha)
216
- // Taken care of by "ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope"
217
- //.replaceAll(/import\("[^"]+"\)\./g, "")
218
-
219
- result[method] = str
220
- }
221
- })
222
-
223
- if (!("parsed" in result)) {
224
- throw new Error("No parsed result")
225
- }
226
- if (!("encoded" in result)) {
227
- throw new Error("No encoded result")
228
- }
229
-
230
-
231
- const encoded = result.encoded.filter(x => !!x)
232
- const parsed = result.parsed.filter(x => !!x)
233
-
234
- return [
235
- `export interface ${modelName} {${parsed.length ? "\n" + parsed.map(l => " " + l).join("\n") + "\n" : ""}}`,
236
- `export namespace ${modelName} {`,
237
- ` export interface From {${encoded.length ? "\n" + encoded.map(l => " " + l).join("\n") + "\n " : ""}}`,
238
- ` export const From: FromOps = {}`,
239
- // ` export const From: FromOps = { $: {} }`,
240
- // ` export interface FromAspects {}`,
241
- ` export interface FromOps {}`,
242
- "}",
243
- ]
244
- }
245
- }
246
- }