@tuyau/core 0.0.5 → 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/LICENSE.md ADDED
@@ -0,0 +1,9 @@
1
+ # The MIT License
2
+
3
+ Copyright (c) 2023
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,15 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __decorateClass = (decorators, target, key, kind) => {
4
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
5
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
6
+ if (decorator = decorators[i])
7
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
8
+ if (kind && result)
9
+ __defProp(target, key, result);
10
+ return result;
11
+ };
12
+
13
+ export {
14
+ __decorateClass
15
+ };
@@ -1 +1 @@
1
- {"commands":[{"commandName":"tuyau:generate","description":"Tuyau generator command","help":"","namespace":"tuyau","aliases":[],"flags":[],"args":[],"options":{"startApp":true},"filePath":"generate.js","absoluteFilePath":"/home/julien/code/adonis/tuyau/packages/core/build/commands/generate.js"}],"version":1}
1
+ {"commands":[{"commandName":"tuyau:generate","description":"Tuyau generator command","help":"","namespace":"tuyau","aliases":[],"flags":[{"name":"verbose","flagName":"verbose","required":false,"type":"boolean","description":"Verbose logs","default":false,"alias":"v"}],"args":[],"options":{"startApp":true},"filePath":"generate.js","absoluteFilePath":"/home/julien/code/adonis/tuyau/packages/core/build/commands/generate.js"}],"version":1}
@@ -6,6 +6,7 @@ declare class CodegenTypes extends BaseCommand {
6
6
  static commandName: string;
7
7
  static description: string;
8
8
  static options: CommandOptions;
9
+ verbose: boolean;
9
10
  /**
10
11
  * Execute command
11
12
  */
@@ -1,12 +1,18 @@
1
+ import {
2
+ __decorateClass
3
+ } from "../chunk-3KNDPG6Y.js";
4
+
1
5
  // commands/generate.ts
2
6
  import { Project, QuoteKind } from "ts-morph";
3
- import { BaseCommand } from "@adonisjs/core/ace";
7
+ import { BaseCommand, flags } from "@adonisjs/core/ace";
4
8
 
5
9
  // src/codegen/api_types_generator.ts
6
10
  import { Node } from "ts-morph";
11
+ import matchit from "@poppinss/matchit";
7
12
  import { fileURLToPath } from "node:url";
8
13
  import { dirname, relative } from "node:path";
9
14
  import { existsSync, mkdirSync } from "node:fs";
15
+ import string from "@adonisjs/core/helpers/string";
10
16
  import { parseBindingReference } from "@adonisjs/core/helpers";
11
17
  var ApiTypesGenerator = class {
12
18
  #appRoot;
@@ -30,7 +36,7 @@ var ApiTypesGenerator = class {
30
36
  * Create the destination directory if it does not exists
31
37
  */
32
38
  #prepareDestination() {
33
- this.#destination = new URL("./.adonisjs/types/api.d.ts", this.#appRoot);
39
+ this.#destination = new URL("./.adonisjs/api.ts", this.#appRoot);
34
40
  const directory = this.#getDestinationDirectory();
35
41
  if (!existsSync(directory)) {
36
42
  mkdirSync(directory, { recursive: true });
@@ -72,7 +78,12 @@ var ApiTypesGenerator = class {
72
78
  const schema = validateUsingCallNode.getArguments()[0];
73
79
  if (!Node.isIdentifier(schema))
74
80
  return;
75
- const importPath = schema.getImplementations()[0].getSourceFile().getFilePath();
81
+ const implementation = schema.getImplementations().at(0);
82
+ if (!implementation) {
83
+ this.#logger.warning(`Unable to find the schema file for ${schema.getText()}`);
84
+ return;
85
+ }
86
+ const importPath = implementation.getSourceFile().getFilePath();
76
87
  const relativeImportPath = relative(this.#getDestinationDirectory(), importPath);
77
88
  return `InferInput<typeof import('${relativeImportPath}')['${schema.getText()}']>`;
78
89
  }
@@ -81,13 +92,13 @@ var ApiTypesGenerator = class {
81
92
  /**
82
93
  * Generate the final interface containing all routes, request, and response
83
94
  */
84
- #generateFinalInterface(types, indent = " ") {
95
+ #generateDefinitionInterface(types, indent = " ") {
85
96
  let interfaceContent = "";
86
97
  Object.entries(types).forEach(([key, value]) => {
87
98
  if (typeof value === "object") {
88
99
  interfaceContent += `${indent}'${key}': {
89
100
  `;
90
- interfaceContent += this.#generateFinalInterface(value, indent + " ");
101
+ interfaceContent += this.#generateDefinitionInterface(value, indent + " ");
91
102
  interfaceContent += `${indent}};
92
103
  `;
93
104
  } else {
@@ -97,24 +108,6 @@ var ApiTypesGenerator = class {
97
108
  });
98
109
  return interfaceContent;
99
110
  }
100
- /**
101
- * Write the final interface containing all routes, request, and response
102
- * in a routes.d.ts file
103
- */
104
- async #writeFinalInterface(types) {
105
- const file = this.#project.createSourceFile(fileURLToPath(this.#destination), "", {
106
- overwrite: true
107
- });
108
- if (!file)
109
- throw new Error("Unable to create the api.d.ts file");
110
- file?.removeText();
111
- file.insertText(0, (writer) => {
112
- writer.writeLine(
113
- `import type { MakeOptional, Serialize, Simplify, ConvertReturnTypeToRecordStatusResponse } from '@tuyau/utils/types'`
114
- ).writeLine(`import type { InferInput } from '@vinejs/vine/types'`).newLine().writeLine(`export interface AdonisApi {`).write(this.#generateFinalInterface(types, " ")).writeLine(`}`);
115
- });
116
- await file.save();
117
- }
118
111
  /**
119
112
  * Filter routes to generate based on the ignoreRoutes config
120
113
  */
@@ -134,8 +127,45 @@ var ApiTypesGenerator = class {
134
127
  return true;
135
128
  });
136
129
  }
130
+ #generateRoutesNameArray(routes) {
131
+ return routes.map(({ name, pattern, methods }) => {
132
+ const params = matchit.parse(pattern).filter((node) => node.type !== 0).map((node) => node.val);
133
+ const typeName = string.pascalCase(string.slug(pattern)) + string.pascalCase(methods.join(" "));
134
+ return { params, name, path: pattern, method: methods, types: typeName };
135
+ }).filter((route) => !!route.name);
136
+ }
137
+ async #writeApiFile(options) {
138
+ const path = fileURLToPath(this.#destination);
139
+ const file = this.#project.createSourceFile(path, "", { overwrite: true });
140
+ if (!file)
141
+ throw new Error("Unable to create the api.ts file");
142
+ file.removeText().insertText(0, (writer) => {
143
+ writer.writeLine(`import type { MakeTuyauRequest, MakeTuyauResponse } from '@tuyau/utils/types'`).writeLine(`import type { InferInput } from '@vinejs/vine/types'`).newLine();
144
+ Object.entries(options.typesByPattern).forEach(([key, value]) => {
145
+ writer.writeLine(`type ${key} = {`);
146
+ writer.writeLine(` request: ${value.request}`);
147
+ writer.writeLine(` response: ${value.response}`);
148
+ writer.writeLine(`}`);
149
+ });
150
+ writer.writeLine(`interface AdonisApi {`).write(this.#generateDefinitionInterface(options.definition, " ")).writeLine(`}`);
151
+ writer.writeLine(`const routes = [`);
152
+ for (const route of options.routesNameArray) {
153
+ writer.writeLine(` {`);
154
+ writer.writeLine(` params: ${JSON.stringify(route.params)},`);
155
+ writer.writeLine(` name: '${route.name}',`);
156
+ writer.writeLine(` path: '${route.path}',`);
157
+ writer.writeLine(` method: ${JSON.stringify(route.method)},`);
158
+ writer.writeLine(` types: {} as ${route.types},`);
159
+ writer.writeLine(` },`);
160
+ }
161
+ writer.writeLine(`] as const;`);
162
+ writer.writeLine(`export const api = {`).writeLine(` routes,`).writeLine(` definition: {} as AdonisApi`).writeLine(`}`);
163
+ });
164
+ await file.save();
165
+ }
137
166
  async generate() {
138
- const types = {};
167
+ const definition = {};
168
+ const typesByPattern = {};
139
169
  const sourcesFiles = this.#project.getSourceFiles();
140
170
  const routes = this.#filterRoutesToGenerate(this.#routes);
141
171
  for (const route of routes) {
@@ -158,25 +188,30 @@ var ApiTypesGenerator = class {
158
188
  const schemaImport = this.#extractRequest(handlerData);
159
189
  const methods = route.methods.map((method) => "$" + method.toLowerCase()).filter((method) => method !== "head");
160
190
  const segments = route.pattern.split("/").filter(Boolean);
161
- let currentLevel = types;
191
+ let currentLevel = definition;
162
192
  const relativePath = relative(this.#getDestinationDirectory(), file.getFilePath());
163
193
  segments.forEach((segment, i) => {
164
- if (!currentLevel[segment]) {
194
+ if (!currentLevel[segment])
165
195
  currentLevel[segment] = {};
166
- }
167
196
  currentLevel = currentLevel[segment];
168
- if (i === segments.length - 1) {
169
- currentLevel["$url"] = {};
170
- for (const method of methods) {
171
- currentLevel[method] = {
172
- request: schemaImport ? `MakeOptional<${schemaImport}>` : "unknown",
173
- response: `Simplify<Serialize<ConvertReturnTypeToRecordStatusResponse<Awaited<ReturnType<typeof import('${relativePath}').default['prototype']['${routeHandler.method}']>>>>>`
174
- };
175
- }
197
+ if (i !== segments.length - 1)
198
+ return;
199
+ const typeName = string.pascalCase(string.slug(route.pattern)) + string.pascalCase(methods.join(""));
200
+ typesByPattern[typeName] = {
201
+ request: schemaImport ? `MakeTuyauRequest<${schemaImport}>` : "unknown",
202
+ response: `MakeTuyauResponse<import('${relativePath}').default['${routeHandler.method}']>`
203
+ };
204
+ currentLevel.$url = {};
205
+ for (const method of methods) {
206
+ currentLevel[method] = `${string.pascalCase(typeName)}`;
176
207
  }
177
208
  });
178
209
  }
179
- await this.#writeFinalInterface(types);
210
+ await this.#writeApiFile({
211
+ definition,
212
+ typesByPattern,
213
+ routesNameArray: this.#generateRoutesNameArray(routes)
214
+ });
180
215
  }
181
216
  };
182
217
 
@@ -212,6 +247,9 @@ var CodegenTypes = class extends BaseCommand {
212
247
  this.logger.success("Types generated successfully");
213
248
  }
214
249
  };
250
+ __decorateClass([
251
+ flags.boolean({ description: "Verbose logs", default: false, alias: "v" })
252
+ ], CodegenTypes.prototype, "verbose", 2);
215
253
  export {
216
254
  CodegenTypes as default
217
255
  };
package/build/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ import "./chunk-3KNDPG6Y.js";
2
+
1
3
  // stubs/main.ts
2
4
  import { getDirname } from "@adonisjs/core/helpers";
3
5
  var stubsRoot = getDirname(import.meta.url);
@@ -1,3 +1,5 @@
1
+ import "../chunk-3KNDPG6Y.js";
2
+
1
3
  // providers/tuyau_provider.ts
2
4
  var TuyauProvider = class {
3
5
  constructor(app) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tuyau/core",
3
3
  "type": "module",
4
- "version": "0.0.5",
4
+ "version": "0.1.0",
5
5
  "description": "",
6
6
  "author": "",
7
7
  "license": "MIT",
@@ -18,20 +18,6 @@
18
18
  "engines": {
19
19
  "node": ">=20.6.0"
20
20
  },
21
- "scripts": {
22
- "clean": "del-cli build",
23
- "copy:templates": "copyfiles \"stubs/**/*.stub\" build",
24
- "typecheck": "tsc --noEmit",
25
- "format": "prettier --write .",
26
- "quick:test": "node --import=./tsnode.esm.js --enable-source-maps bin/test.ts",
27
- "test": "c8 npm run quick:test",
28
- "index:commands": "adonis-kit index build/commands",
29
- "prebuild": "npm run clean",
30
- "build": "pnpm clean && tsup-node && pnpm copy:templates && pnpm index:commands",
31
- "release": "pnpm build && pnpm release-it",
32
- "version": "npm run build",
33
- "prepublishOnly": "npm run build"
34
- },
35
21
  "peerDependencies": {
36
22
  "@adonisjs/core": "^6.2.0"
37
23
  },
@@ -39,14 +25,14 @@
39
25
  "ts-morph": "^22.0.0"
40
26
  },
41
27
  "devDependencies": {
42
- "@adonisjs/assembler": "^7.4.0",
43
- "@adonisjs/core": "^6.5.0",
28
+ "@adonisjs/assembler": "^7.5.1",
29
+ "@adonisjs/core": "^6.8.0",
44
30
  "@julr/tooling-configs": "^2.2.0",
45
31
  "@poppinss/cliui": "^6.4.1",
46
32
  "@poppinss/matchit": "^3.1.2",
47
- "@tuyau/client": "workspace:*",
48
- "@tuyau/utils": "workspace:*",
49
- "@types/node": "^20.12.7"
33
+ "@types/node": "^20.12.7",
34
+ "@tuyau/utils": "0.0.4",
35
+ "@tuyau/client": "0.1.0"
50
36
  },
51
37
  "publishConfig": {
52
38
  "access": "public",
@@ -61,18 +47,6 @@
61
47
  "tests/**"
62
48
  ]
63
49
  },
64
- "release-it": {
65
- "git": {
66
- "commitMessage": "chore(release): @tuyau/core@${version}",
67
- "tagAnnotation": "release ${version}",
68
- "tagName": "@tuyau/core@${version}"
69
- },
70
- "github": {
71
- "release": true,
72
- "releaseName": "@tuyau/core@${version}",
73
- "web": true
74
- }
75
- },
76
50
  "tsup": {
77
51
  "entry": [
78
52
  "./index.ts",
@@ -85,5 +59,17 @@
85
59
  "format": "esm",
86
60
  "dts": true,
87
61
  "target": "esnext"
62
+ },
63
+ "scripts": {
64
+ "clean": "del-cli build",
65
+ "copy:templates": "copyfiles \"stubs/**/*.stub\" build",
66
+ "typecheck": "tsc --noEmit",
67
+ "format": "prettier --write .",
68
+ "quick:test": "node --import=./tsnode.esm.js --enable-source-maps bin/test.ts",
69
+ "test": "c8 npm run quick:test",
70
+ "index:commands": "adonis-kit index build/commands",
71
+ "prebuild": "npm run clean",
72
+ "build": "pnpm clean && tsup-node && pnpm copy:templates && pnpm index:commands",
73
+ "version": "npm run build"
88
74
  }
89
- }
75
+ }