@ciderjs/gasnuki 0.2.4 → 0.2.5

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.ja.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # gasnuki
2
2
 
3
- [![Test Coverage](https://img.shields.io/badge/test%20coverage-87.76%25-green)](https://github.com/luthpg/gasnuki)
3
+ [![Test Coverage](https://img.shields.io/badge/test%20coverage-83.65%25-green)](https://github.com/luthpg/gasnuki)
4
4
  [![License](https://img.shields.io/badge/license-ISC-blue.svg)](LICENSE)
5
5
  [![npm version](https://img.shields.io/npm/v/@ciderjs/gasnuki.svg)](https://www.npmjs.com/package/@ciderjs/gasnuki)
6
6
  [![GitHub issues](https://img.shields.io/github/issues/luthpg/gasnuki.svg)](https://github.com/luthpg/gasnuki/issues)
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @ciderjs/gasnuki
2
2
 
3
- [![Test Coverage](https://img.shields.io/badge/test%20coverage-87.76%25-green)](https://github.com/luthpg/gasnuki)
3
+ [![Test Coverage](https://img.shields.io/badge/test%20coverage-83.65%25-green)](https://github.com/luthpg/gasnuki)
4
4
  [![License](https://img.shields.io/badge/license-ISC-blue.svg)](LICENSE)
5
5
  [![npm version](https://img.shields.io/npm/v/@ciderjs/gasnuki.svg)](https://www.npmjs.com/package/@ciderjs/gasnuki)
6
6
  [![GitHub issues](https://img.shields.io/github/issues/luthpg/gasnuki.svg)](https://github.com/luthpg/gasnuki/issues)
package/dist/cli.cjs CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  const path = require('node:path');
5
5
  const commander = require('commander');
6
- const index = require('./shared/gasnuki.CYh0jbl5.cjs');
6
+ const index = require('./shared/gasnuki.Ce9vzQ2b.cjs');
7
7
  require('chokidar');
8
8
  require('consola');
9
9
  require('node:fs');
@@ -24,7 +24,7 @@ function _interopNamespaceCompat(e) {
24
24
 
25
25
  const path__namespace = /*#__PURE__*/_interopNamespaceCompat(path);
26
26
 
27
- const version = "0.2.4";
27
+ const version = "0.2.5";
28
28
 
29
29
  const parseArgs = async (command) => {
30
30
  const cliOpts = command.opts();
package/dist/cli.mjs CHANGED
@@ -1,14 +1,14 @@
1
1
  #! /usr/bin/env node
2
2
  import * as path from 'node:path';
3
3
  import { Command } from 'commander';
4
- import { l as loadConfig, g as generateTypes } from './shared/gasnuki.DvpVGJ1U.mjs';
4
+ import { l as loadConfig, g as generateTypes } from './shared/gasnuki.DJCCMztm.mjs';
5
5
  import 'chokidar';
6
6
  import 'consola';
7
7
  import 'node:fs';
8
8
  import 'ts-morph';
9
9
  import 'jiti';
10
10
 
11
- const version = "0.2.4";
11
+ const version = "0.2.5";
12
12
 
13
13
  const parseArgs = async (command) => {
14
14
  const cliOpts = command.opts();
package/dist/index.cjs CHANGED
@@ -3,7 +3,7 @@
3
3
  require('node:path');
4
4
  require('chokidar');
5
5
  require('consola');
6
- const index = require('./shared/gasnuki.CYh0jbl5.cjs');
6
+ const index = require('./shared/gasnuki.Ce9vzQ2b.cjs');
7
7
  require('node:fs');
8
8
  require('ts-morph');
9
9
  require('jiti');
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import 'node:path';
2
2
  import 'chokidar';
3
3
  import 'consola';
4
- export { d as defineConfig, g as generateTypes } from './shared/gasnuki.DvpVGJ1U.mjs';
4
+ export { d as defineConfig, g as generateTypes } from './shared/gasnuki.DJCCMztm.mjs';
5
5
  import 'node:fs';
6
6
  import 'ts-morph';
7
7
  import 'jiti';
@@ -47,29 +47,17 @@ const getInterfaceMethodDefinition_ = (name, node) => {
47
47
  }
48
48
  }
49
49
  let jsDocString = "";
50
- const jsDocOwner = "getJsDocs" in node ? node : "getParantOrThrow" in node && // @ts-expect-error variable declaration
50
+ const jsDocOwner = "getJsDocs" in node ? node : "getParentOrThrow" in node && // @ts-expect-error variable declaration
51
51
  node.getParentOrThrow().getKind() === tsMorph.SyntaxKind.VariableDeclaration ? (
52
52
  // @ts-expect-error variable declaration
53
53
  node.getParentOrThrow()
54
54
  ) : null;
55
55
  if (jsDocOwner != null) {
56
- const jsDocs = "getJsDocs" in jsDocOwner ? jsDocOwner.getJsDocs() : null;
57
- if (jsDocs != null && jsDocs.length > 0) {
58
- const rawConmmentText = jsDocs.map((doc) => doc.getFullText()).join("\n");
59
- if (rawConmmentText.includes("@deprecated")) {
60
- const deprecatedDoc = jsDocs.find(
61
- (doc) => doc.getFullText().includes("@deprecated")
62
- );
63
- jsDocString = `${deprecatedDoc != null ? deprecatedDoc.getFullText().trim() : "/**\n * @deprecated\n */"}
56
+ const jsDocs = "getJsDocs" in jsDocOwner ? jsDocOwner.getJsDocs() : [];
57
+ if (jsDocs.length > 0) {
58
+ const firstDoc = jsDocs[0];
59
+ jsDocString = `${firstDoc.getFullText().trim()}
64
60
  `;
65
- } else {
66
- const firstDoc = jsDocs[0];
67
- const description = firstDoc.getDescription().trim();
68
- if (description != null || firstDoc.getTags().length > 0) {
69
- jsDocString = `${firstDoc.getFullText().trim()}
70
- `;
71
- }
72
- }
73
61
  }
74
62
  }
75
63
  return `${jsDocString}${name}${typeParamsString}(${parameters}): ${returnType};`;
@@ -98,77 +86,90 @@ const generateAppsScriptTypes = async ({
98
86
  tsConfigFilePath: path__namespace.resolve(projectPath, "tsconfig.json"),
99
87
  skipAddingFilesFromTsConfig: true
100
88
  });
101
- project.addSourceFilesAtPaths(
102
- path__namespace.join(absoluteSrcDir, "**/*.ts").replace(/\\/g, "/")
103
- );
104
- const methodDefinitions = [];
105
- const globalTypeDefinitions = [];
106
- const importStatements = /* @__PURE__ */ new Set();
89
+ const sourceFilesPattern = path__namespace.join(absoluteSrcDir, "**/*.ts").replace(/\\/g, "/");
90
+ const testFilesPattern = `!${path__namespace.join(absoluteSrcDir, "**/*.{test,spec}.ts").replace(/\\/g, "/")}`;
91
+ project.addSourceFilesAtPaths([sourceFilesPattern, testFilesPattern]);
107
92
  const sourceFiles = project.getSourceFiles();
108
93
  consola.consola.info(`Found ${sourceFiles.length} source file(s).`);
94
+ const methodDefinitions = [];
95
+ const localDeclarations = [];
96
+ const localDeclarationNames = /* @__PURE__ */ new Set();
109
97
  for (const sourceFile of sourceFiles) {
110
- const importDeclarations = sourceFile.getImportDeclarations?.();
111
- if (importDeclarations != null && importDeclarations.length > 0) {
112
- for (const importDeclaration of importDeclarations) {
113
- const moduleSpecifier = importDeclaration.getModuleSpecifierSourceFile();
114
- if (moduleSpecifier) {
115
- const importedFilePath = moduleSpecifier.getFilePath();
116
- let relativePath = path__namespace.relative(path__namespace.dirname(absoluteOutputFile), importedFilePath).replace(/\\/g, "/");
117
- relativePath = relativePath.replace(/\.(ts|tsx|d\.ts)$/, "");
118
- if (!relativePath.startsWith(".") && !relativePath.startsWith("..")) {
119
- relativePath = `./${relativePath}`;
120
- }
121
- const originalText = importDeclaration.getText();
122
- const newImportText = originalText.replace(
123
- importDeclaration.getModuleSpecifierValue(),
124
- relativePath
125
- );
126
- importStatements.add(newImportText);
127
- } else {
128
- importStatements.add(importDeclaration.getText());
129
- }
130
- }
131
- }
132
98
  for (const iface of sourceFile.getInterfaces()) {
133
- const name = iface?.getName?.();
134
- if (name == null || name.endsWith("_")) {
135
- continue;
99
+ const name = iface.getName?.();
100
+ if (name && !name.endsWith("_")) {
101
+ localDeclarations.push(iface);
102
+ localDeclarationNames.add(name);
136
103
  }
137
- globalTypeDefinitions.push(iface.getText());
138
104
  }
139
105
  for (const typeAlias of sourceFile.getTypeAliases()) {
140
- const name = typeAlias?.getName?.();
141
- if (name == null || name.endsWith("_")) {
142
- continue;
106
+ const name = typeAlias.getName();
107
+ if (name && !name.endsWith("_")) {
108
+ localDeclarations.push(typeAlias);
109
+ localDeclarationNames.add(name);
143
110
  }
144
- globalTypeDefinitions.push(typeAlias.getText());
145
111
  }
146
- for (const statement of sourceFile.getStatements()) {
147
- if (statement.getKind() === tsMorph.SyntaxKind.ModuleDeclaration) {
148
- globalTypeDefinitions.push(statement.getText());
112
+ for (const func of sourceFile.getFunctions()) {
113
+ const name = func.getName();
114
+ if (name && !func.isAmbient() && !name.endsWith("_") && !SIMPLE_TRIGGER_FUNCTION_NAMES.includes(name)) {
115
+ localDeclarations.push(func);
116
+ localDeclarationNames.add(name);
117
+ methodDefinitions.push(getInterfaceMethodDefinition_(name, func));
149
118
  }
150
119
  }
151
- for (const funcDecl of sourceFile.getFunctions()) {
152
- if (!funcDecl.isAmbient()) {
153
- const name = funcDecl.getName();
154
- if (name != null && !name.endsWith("_") && !SIMPLE_TRIGGER_FUNCTION_NAMES.includes(name)) {
155
- methodDefinitions.push(getInterfaceMethodDefinition_(name, funcDecl));
120
+ for (const varStmt of sourceFile.getVariableStatements()) {
121
+ if (varStmt.isAmbient()) continue;
122
+ for (const varDecl of varStmt.getDeclarations()) {
123
+ const name = varDecl.getName();
124
+ const initializer = varDecl.getInitializer();
125
+ if (!name.endsWith("_") && !SIMPLE_TRIGGER_FUNCTION_NAMES.includes(name) && initializer && (initializer.getKind() === tsMorph.SyntaxKind.ArrowFunction || initializer.getKind() === tsMorph.SyntaxKind.FunctionExpression)) {
126
+ localDeclarations.push(varDecl);
127
+ localDeclarationNames.add(name);
128
+ methodDefinitions.push(
129
+ getInterfaceMethodDefinition_(
130
+ name,
131
+ initializer
132
+ )
133
+ );
156
134
  }
157
135
  }
158
136
  }
159
- for (const varStmt of sourceFile.getVariableStatements()) {
160
- if (!varStmt.isAmbient()) {
161
- for (const varDecl of varStmt.getDeclarations()) {
162
- const initializer = varDecl.getInitializer();
163
- const varName = varDecl.getName();
164
- if (initializer != null && (initializer.getKind() === tsMorph.SyntaxKind.ArrowFunction || initializer.getKind() === tsMorph.SyntaxKind.FunctionExpression) && !varName.endsWith("_") && !SIMPLE_TRIGGER_FUNCTION_NAMES.includes(varName)) {
165
- methodDefinitions.push(
166
- getInterfaceMethodDefinition_(
167
- varName,
168
- initializer
169
- )
170
- );
137
+ }
138
+ const importsMap = /* @__PURE__ */ new Map();
139
+ for (const decl of localDeclarations) {
140
+ const descendants = decl.getDescendantsOfKind?.(tsMorph.SyntaxKind.TypeReference) ?? [];
141
+ for (const descendant of descendants) {
142
+ const symbol = descendant.getType().getAliasSymbol() ?? descendant.getType().getSymbol();
143
+ if (symbol) {
144
+ const symbolFlags = symbol.getFlags();
145
+ if (symbolFlags & tsMorph.SymbolFlags.TypeParameter) {
146
+ continue;
147
+ }
148
+ const symbolName = symbol.getName();
149
+ if (localDeclarationNames.has(symbolName) || symbolName === "__type") {
150
+ continue;
151
+ }
152
+ const declaration = symbol.getDeclarations()[0];
153
+ if (declaration) {
154
+ const declarationSourceFile = declaration.getSourceFile();
155
+ if (declarationSourceFile.getFilePath().includes("node_modules")) {
156
+ continue;
157
+ }
158
+ let modulePath = path__namespace.relative(absoluteOutDir, declarationSourceFile.getFilePath()).replace(/\\/g, "/");
159
+ modulePath = modulePath.replace(/\.(d\.)?ts$/, "");
160
+ if (modulePath.endsWith("/index")) {
161
+ modulePath = modulePath.slice(0, -6);
162
+ }
163
+ if (modulePath === "index" || modulePath === "") {
164
+ modulePath = ".";
171
165
  }
166
+ if (!modulePath.startsWith(".")) {
167
+ modulePath = `./${modulePath}`;
168
+ }
169
+ if (!importsMap.has(modulePath)) {
170
+ importsMap.set(modulePath, /* @__PURE__ */ new Set());
171
+ }
172
+ importsMap.get(modulePath)?.add(symbolName);
172
173
  }
173
174
  }
174
175
  }
@@ -180,12 +181,27 @@ const generateAppsScriptTypes = async ({
180
181
  const generatorName = "gasnuki";
181
182
  let outputContent = `// Auto-generated by ${generatorName}
182
183
  // Do NOT edit this file manually.
184
+
183
185
  `;
184
- if (importStatements.size > 0) {
185
- outputContent += `${[...importStatements].join("\n")}
186
+ const sortedModulePaths = [...importsMap.keys()].sort((a, b) => {
187
+ const aIsRelative = a.startsWith(".");
188
+ const bIsRelative = b.startsWith(".");
189
+ if (aIsRelative !== bIsRelative) return aIsRelative ? 1 : -1;
190
+ return a.localeCompare(b);
191
+ });
192
+ if (sortedModulePaths.length > 0) {
193
+ const importStatements = sortedModulePaths.map((modulePath) => {
194
+ const imports = [...importsMap.get(modulePath) ?? []].sort();
195
+ const finalModulePath = modulePath === "." ? "./index" : modulePath;
196
+ return `import type { ${imports.join(", ")} } from '${finalModulePath}';`;
197
+ });
198
+ outputContent += `${importStatements.join("\n")}
186
199
 
187
200
  `;
188
201
  }
202
+ const globalTypeDefinitions = localDeclarations.filter(
203
+ (d) => d.getKind?.() === tsMorph.SyntaxKind.InterfaceDeclaration || d.getKind?.() === tsMorph.SyntaxKind.TypeAliasDeclaration
204
+ ).map((decl) => decl.getText?.());
189
205
  if (globalTypeDefinitions.length > 0) {
190
206
  outputContent += `${globalTypeDefinitions.join("\n\n")}
191
207
 
@@ -2,7 +2,7 @@ import * as path from 'node:path';
2
2
  import * as chokidar from 'chokidar';
3
3
  import { consola } from 'consola';
4
4
  import * as fs from 'node:fs';
5
- import { Project, SyntaxKind } from 'ts-morph';
5
+ import { Project, SyntaxKind, SymbolFlags } from 'ts-morph';
6
6
  import { createJiti } from 'jiti';
7
7
 
8
8
  const text = "export type RemoveReturnType<T> = {\n [P in keyof T]: T[P] extends (...args: infer A) => any\n ? (...args: A) => void\n : T[P];\n};\n\ntype _AppsScriptRun = RemoveReturnType<ServerScripts> & {\n [key: string]: (...args: any[]) => any;\n withSuccessHandler: <T = string | number | boolean | undefined, U = any>(\n callback: (returnValues: T, userObject?: U) => void,\n ) => _AppsScriptRun;\n withFailureHandler: <U = any>(\n callback: (error: Error, userObject?: U) => void,\n ) => _AppsScriptRun;\n withUserObject: <U = any>(userObject: U) => _AppsScriptRun;\n};\n\ntype _AppsScriptHistoryFunction = (\n stateObject: object,\n params: object,\n hash: string,\n) => void;\n\ninterface _WebAppLovacationType {\n hash: string;\n parameter: Record<string, string>;\n parameters: Record<string, string[]>;\n}\n\nexport declare interface GoogleClientSideApi {\n script: {\n run: _AppsScriptRun;\n url: {\n getLocation: (\n callback: (location: _WebAppLovacationType) => void,\n ) => void;\n };\n history: {\n push: _AppsScriptHistoryFunction;\n replace: _AppsScriptHistoryFunction;\n setChangeHandler: (\n callback: (e: {\n state: object;\n location: _WebAppLovacationType;\n }) => void,\n ) => void;\n };\n };\n}\n\ndeclare global {\n const google: GoogleClientSideApi;\n}\n";
@@ -29,29 +29,17 @@ const getInterfaceMethodDefinition_ = (name, node) => {
29
29
  }
30
30
  }
31
31
  let jsDocString = "";
32
- const jsDocOwner = "getJsDocs" in node ? node : "getParantOrThrow" in node && // @ts-expect-error variable declaration
32
+ const jsDocOwner = "getJsDocs" in node ? node : "getParentOrThrow" in node && // @ts-expect-error variable declaration
33
33
  node.getParentOrThrow().getKind() === SyntaxKind.VariableDeclaration ? (
34
34
  // @ts-expect-error variable declaration
35
35
  node.getParentOrThrow()
36
36
  ) : null;
37
37
  if (jsDocOwner != null) {
38
- const jsDocs = "getJsDocs" in jsDocOwner ? jsDocOwner.getJsDocs() : null;
39
- if (jsDocs != null && jsDocs.length > 0) {
40
- const rawConmmentText = jsDocs.map((doc) => doc.getFullText()).join("\n");
41
- if (rawConmmentText.includes("@deprecated")) {
42
- const deprecatedDoc = jsDocs.find(
43
- (doc) => doc.getFullText().includes("@deprecated")
44
- );
45
- jsDocString = `${deprecatedDoc != null ? deprecatedDoc.getFullText().trim() : "/**\n * @deprecated\n */"}
38
+ const jsDocs = "getJsDocs" in jsDocOwner ? jsDocOwner.getJsDocs() : [];
39
+ if (jsDocs.length > 0) {
40
+ const firstDoc = jsDocs[0];
41
+ jsDocString = `${firstDoc.getFullText().trim()}
46
42
  `;
47
- } else {
48
- const firstDoc = jsDocs[0];
49
- const description = firstDoc.getDescription().trim();
50
- if (description != null || firstDoc.getTags().length > 0) {
51
- jsDocString = `${firstDoc.getFullText().trim()}
52
- `;
53
- }
54
- }
55
43
  }
56
44
  }
57
45
  return `${jsDocString}${name}${typeParamsString}(${parameters}): ${returnType};`;
@@ -80,77 +68,90 @@ const generateAppsScriptTypes = async ({
80
68
  tsConfigFilePath: path.resolve(projectPath, "tsconfig.json"),
81
69
  skipAddingFilesFromTsConfig: true
82
70
  });
83
- project.addSourceFilesAtPaths(
84
- path.join(absoluteSrcDir, "**/*.ts").replace(/\\/g, "/")
85
- );
86
- const methodDefinitions = [];
87
- const globalTypeDefinitions = [];
88
- const importStatements = /* @__PURE__ */ new Set();
71
+ const sourceFilesPattern = path.join(absoluteSrcDir, "**/*.ts").replace(/\\/g, "/");
72
+ const testFilesPattern = `!${path.join(absoluteSrcDir, "**/*.{test,spec}.ts").replace(/\\/g, "/")}`;
73
+ project.addSourceFilesAtPaths([sourceFilesPattern, testFilesPattern]);
89
74
  const sourceFiles = project.getSourceFiles();
90
75
  consola.info(`Found ${sourceFiles.length} source file(s).`);
76
+ const methodDefinitions = [];
77
+ const localDeclarations = [];
78
+ const localDeclarationNames = /* @__PURE__ */ new Set();
91
79
  for (const sourceFile of sourceFiles) {
92
- const importDeclarations = sourceFile.getImportDeclarations?.();
93
- if (importDeclarations != null && importDeclarations.length > 0) {
94
- for (const importDeclaration of importDeclarations) {
95
- const moduleSpecifier = importDeclaration.getModuleSpecifierSourceFile();
96
- if (moduleSpecifier) {
97
- const importedFilePath = moduleSpecifier.getFilePath();
98
- let relativePath = path.relative(path.dirname(absoluteOutputFile), importedFilePath).replace(/\\/g, "/");
99
- relativePath = relativePath.replace(/\.(ts|tsx|d\.ts)$/, "");
100
- if (!relativePath.startsWith(".") && !relativePath.startsWith("..")) {
101
- relativePath = `./${relativePath}`;
102
- }
103
- const originalText = importDeclaration.getText();
104
- const newImportText = originalText.replace(
105
- importDeclaration.getModuleSpecifierValue(),
106
- relativePath
107
- );
108
- importStatements.add(newImportText);
109
- } else {
110
- importStatements.add(importDeclaration.getText());
111
- }
112
- }
113
- }
114
80
  for (const iface of sourceFile.getInterfaces()) {
115
- const name = iface?.getName?.();
116
- if (name == null || name.endsWith("_")) {
117
- continue;
81
+ const name = iface.getName?.();
82
+ if (name && !name.endsWith("_")) {
83
+ localDeclarations.push(iface);
84
+ localDeclarationNames.add(name);
118
85
  }
119
- globalTypeDefinitions.push(iface.getText());
120
86
  }
121
87
  for (const typeAlias of sourceFile.getTypeAliases()) {
122
- const name = typeAlias?.getName?.();
123
- if (name == null || name.endsWith("_")) {
124
- continue;
88
+ const name = typeAlias.getName();
89
+ if (name && !name.endsWith("_")) {
90
+ localDeclarations.push(typeAlias);
91
+ localDeclarationNames.add(name);
125
92
  }
126
- globalTypeDefinitions.push(typeAlias.getText());
127
93
  }
128
- for (const statement of sourceFile.getStatements()) {
129
- if (statement.getKind() === SyntaxKind.ModuleDeclaration) {
130
- globalTypeDefinitions.push(statement.getText());
94
+ for (const func of sourceFile.getFunctions()) {
95
+ const name = func.getName();
96
+ if (name && !func.isAmbient() && !name.endsWith("_") && !SIMPLE_TRIGGER_FUNCTION_NAMES.includes(name)) {
97
+ localDeclarations.push(func);
98
+ localDeclarationNames.add(name);
99
+ methodDefinitions.push(getInterfaceMethodDefinition_(name, func));
131
100
  }
132
101
  }
133
- for (const funcDecl of sourceFile.getFunctions()) {
134
- if (!funcDecl.isAmbient()) {
135
- const name = funcDecl.getName();
136
- if (name != null && !name.endsWith("_") && !SIMPLE_TRIGGER_FUNCTION_NAMES.includes(name)) {
137
- methodDefinitions.push(getInterfaceMethodDefinition_(name, funcDecl));
102
+ for (const varStmt of sourceFile.getVariableStatements()) {
103
+ if (varStmt.isAmbient()) continue;
104
+ for (const varDecl of varStmt.getDeclarations()) {
105
+ const name = varDecl.getName();
106
+ const initializer = varDecl.getInitializer();
107
+ if (!name.endsWith("_") && !SIMPLE_TRIGGER_FUNCTION_NAMES.includes(name) && initializer && (initializer.getKind() === SyntaxKind.ArrowFunction || initializer.getKind() === SyntaxKind.FunctionExpression)) {
108
+ localDeclarations.push(varDecl);
109
+ localDeclarationNames.add(name);
110
+ methodDefinitions.push(
111
+ getInterfaceMethodDefinition_(
112
+ name,
113
+ initializer
114
+ )
115
+ );
138
116
  }
139
117
  }
140
118
  }
141
- for (const varStmt of sourceFile.getVariableStatements()) {
142
- if (!varStmt.isAmbient()) {
143
- for (const varDecl of varStmt.getDeclarations()) {
144
- const initializer = varDecl.getInitializer();
145
- const varName = varDecl.getName();
146
- if (initializer != null && (initializer.getKind() === SyntaxKind.ArrowFunction || initializer.getKind() === SyntaxKind.FunctionExpression) && !varName.endsWith("_") && !SIMPLE_TRIGGER_FUNCTION_NAMES.includes(varName)) {
147
- methodDefinitions.push(
148
- getInterfaceMethodDefinition_(
149
- varName,
150
- initializer
151
- )
152
- );
119
+ }
120
+ const importsMap = /* @__PURE__ */ new Map();
121
+ for (const decl of localDeclarations) {
122
+ const descendants = decl.getDescendantsOfKind?.(SyntaxKind.TypeReference) ?? [];
123
+ for (const descendant of descendants) {
124
+ const symbol = descendant.getType().getAliasSymbol() ?? descendant.getType().getSymbol();
125
+ if (symbol) {
126
+ const symbolFlags = symbol.getFlags();
127
+ if (symbolFlags & SymbolFlags.TypeParameter) {
128
+ continue;
129
+ }
130
+ const symbolName = symbol.getName();
131
+ if (localDeclarationNames.has(symbolName) || symbolName === "__type") {
132
+ continue;
133
+ }
134
+ const declaration = symbol.getDeclarations()[0];
135
+ if (declaration) {
136
+ const declarationSourceFile = declaration.getSourceFile();
137
+ if (declarationSourceFile.getFilePath().includes("node_modules")) {
138
+ continue;
139
+ }
140
+ let modulePath = path.relative(absoluteOutDir, declarationSourceFile.getFilePath()).replace(/\\/g, "/");
141
+ modulePath = modulePath.replace(/\.(d\.)?ts$/, "");
142
+ if (modulePath.endsWith("/index")) {
143
+ modulePath = modulePath.slice(0, -6);
144
+ }
145
+ if (modulePath === "index" || modulePath === "") {
146
+ modulePath = ".";
153
147
  }
148
+ if (!modulePath.startsWith(".")) {
149
+ modulePath = `./${modulePath}`;
150
+ }
151
+ if (!importsMap.has(modulePath)) {
152
+ importsMap.set(modulePath, /* @__PURE__ */ new Set());
153
+ }
154
+ importsMap.get(modulePath)?.add(symbolName);
154
155
  }
155
156
  }
156
157
  }
@@ -162,12 +163,27 @@ const generateAppsScriptTypes = async ({
162
163
  const generatorName = "gasnuki";
163
164
  let outputContent = `// Auto-generated by ${generatorName}
164
165
  // Do NOT edit this file manually.
166
+
165
167
  `;
166
- if (importStatements.size > 0) {
167
- outputContent += `${[...importStatements].join("\n")}
168
+ const sortedModulePaths = [...importsMap.keys()].sort((a, b) => {
169
+ const aIsRelative = a.startsWith(".");
170
+ const bIsRelative = b.startsWith(".");
171
+ if (aIsRelative !== bIsRelative) return aIsRelative ? 1 : -1;
172
+ return a.localeCompare(b);
173
+ });
174
+ if (sortedModulePaths.length > 0) {
175
+ const importStatements = sortedModulePaths.map((modulePath) => {
176
+ const imports = [...importsMap.get(modulePath) ?? []].sort();
177
+ const finalModulePath = modulePath === "." ? "./index" : modulePath;
178
+ return `import type { ${imports.join(", ")} } from '${finalModulePath}';`;
179
+ });
180
+ outputContent += `${importStatements.join("\n")}
168
181
 
169
182
  `;
170
183
  }
184
+ const globalTypeDefinitions = localDeclarations.filter(
185
+ (d) => d.getKind?.() === SyntaxKind.InterfaceDeclaration || d.getKind?.() === SyntaxKind.TypeAliasDeclaration
186
+ ).map((decl) => decl.getText?.());
171
187
  if (globalTypeDefinitions.length > 0) {
172
188
  outputContent += `${globalTypeDefinitions.join("\n\n")}
173
189
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ciderjs/gasnuki",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "Type definitions and utilities for Google Apps Script client-side API",
5
5
  "main": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",
@@ -21,7 +21,7 @@
21
21
  },
22
22
  "scripts": {
23
23
  "generate": "jiti .bin/generate.ts",
24
- "dev": "pnpm prebuild && jiti src/cli.ts -p playground/react -s src/server",
24
+ "dev": "pnpm run generate && jiti src/cli.ts -p playground/react -s src/server",
25
25
  "start": "node dist/cli.mjs -p playground/react -s src/server",
26
26
  "check": "biome check --write",
27
27
  "build": "unbuild",