@ciderjs/gasnuki 0.2.3 → 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-93.43%25-brightgreen)](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-93.43%25-brightgreen)](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.s61ETQvI.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.3";
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.y-_vxcPh.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.3";
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.s61ETQvI.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.y-_vxcPh.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,33 +47,29 @@ 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};`;
76
64
  };
65
+ const SIMPLE_TRIGGER_FUNCTION_NAMES = [
66
+ "onOpen",
67
+ "onEdit",
68
+ "onInstall",
69
+ "onSelectionChange",
70
+ "doGet",
71
+ "doPost"
72
+ ];
77
73
  const generateAppsScriptTypes = async ({
78
74
  project: projectPath,
79
75
  srcDir,
@@ -90,54 +86,90 @@ const generateAppsScriptTypes = async ({
90
86
  tsConfigFilePath: path__namespace.resolve(projectPath, "tsconfig.json"),
91
87
  skipAddingFilesFromTsConfig: true
92
88
  });
93
- project.addSourceFilesAtPaths(
94
- path__namespace.join(absoluteSrcDir, "**/*.ts").replace(/\\/g, "/")
95
- );
96
- const methodDefinitions = [];
97
- const globalTypeDefinitions = [];
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]);
98
92
  const sourceFiles = project.getSourceFiles();
99
93
  consola.consola.info(`Found ${sourceFiles.length} source file(s).`);
94
+ const methodDefinitions = [];
95
+ const localDeclarations = [];
96
+ const localDeclarationNames = /* @__PURE__ */ new Set();
100
97
  for (const sourceFile of sourceFiles) {
101
98
  for (const iface of sourceFile.getInterfaces()) {
102
- const name = iface?.getName?.();
103
- if (name == null || name.endsWith("_")) {
104
- continue;
99
+ const name = iface.getName?.();
100
+ if (name && !name.endsWith("_")) {
101
+ localDeclarations.push(iface);
102
+ localDeclarationNames.add(name);
105
103
  }
106
- globalTypeDefinitions.push(iface.getText());
107
104
  }
108
105
  for (const typeAlias of sourceFile.getTypeAliases()) {
109
- const name = typeAlias?.getName?.();
110
- if (name == null || name.endsWith("_")) {
111
- continue;
106
+ const name = typeAlias.getName();
107
+ if (name && !name.endsWith("_")) {
108
+ localDeclarations.push(typeAlias);
109
+ localDeclarationNames.add(name);
112
110
  }
113
- globalTypeDefinitions.push(typeAlias.getText());
114
111
  }
115
- for (const statement of sourceFile.getStatements()) {
116
- if (statement.getKind() === tsMorph.SyntaxKind.ModuleDeclaration) {
117
- 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));
118
118
  }
119
119
  }
120
- for (const funcDecl of sourceFile.getFunctions()) {
121
- if (!funcDecl.isAmbient()) {
122
- const name = funcDecl.getName();
123
- if (name != null && !name.endsWith("_")) {
124
- 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
+ );
125
134
  }
126
135
  }
127
136
  }
128
- for (const varStmt of sourceFile.getVariableStatements()) {
129
- if (!varStmt.isAmbient()) {
130
- for (const varDecl of varStmt.getDeclarations()) {
131
- const initializer = varDecl.getInitializer();
132
- const varName = varDecl.getName();
133
- if (initializer != null && (initializer.getKind() === tsMorph.SyntaxKind.ArrowFunction || initializer.getKind() === tsMorph.SyntaxKind.FunctionExpression) && !varName.endsWith("_")) {
134
- methodDefinitions.push(
135
- getInterfaceMethodDefinition_(
136
- varName,
137
- initializer
138
- )
139
- );
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;
140
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 = ".";
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);
141
173
  }
142
174
  }
143
175
  }
@@ -149,7 +181,27 @@ const generateAppsScriptTypes = async ({
149
181
  const generatorName = "gasnuki";
150
182
  let outputContent = `// Auto-generated by ${generatorName}
151
183
  // Do NOT edit this file manually.
184
+
152
185
  `;
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")}
199
+
200
+ `;
201
+ }
202
+ const globalTypeDefinitions = localDeclarations.filter(
203
+ (d) => d.getKind?.() === tsMorph.SyntaxKind.InterfaceDeclaration || d.getKind?.() === tsMorph.SyntaxKind.TypeAliasDeclaration
204
+ ).map((decl) => decl.getText?.());
153
205
  if (globalTypeDefinitions.length > 0) {
154
206
  outputContent += `${globalTypeDefinitions.join("\n\n")}
155
207
 
@@ -167,7 +219,7 @@ ${formattedMethods}
167
219
  `Interface 'ServerScript' type definitions written to ${absoluteOutputFile} (${methodDefinitions.length} function(s), ${globalTypeDefinitions.length} type(s)).`
168
220
  );
169
221
  } else {
170
- outputContent = "export type ServerScripts = {}\n";
222
+ outputContent += "export type ServerScripts = {}\n";
171
223
  consola.consola.info(
172
224
  `Interface 'ServerScript' type definitions written to ${absoluteOutputFile} (no functions found).`
173
225
  );
@@ -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,33 +29,29 @@ 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};`;
58
46
  };
47
+ const SIMPLE_TRIGGER_FUNCTION_NAMES = [
48
+ "onOpen",
49
+ "onEdit",
50
+ "onInstall",
51
+ "onSelectionChange",
52
+ "doGet",
53
+ "doPost"
54
+ ];
59
55
  const generateAppsScriptTypes = async ({
60
56
  project: projectPath,
61
57
  srcDir,
@@ -72,54 +68,90 @@ const generateAppsScriptTypes = async ({
72
68
  tsConfigFilePath: path.resolve(projectPath, "tsconfig.json"),
73
69
  skipAddingFilesFromTsConfig: true
74
70
  });
75
- project.addSourceFilesAtPaths(
76
- path.join(absoluteSrcDir, "**/*.ts").replace(/\\/g, "/")
77
- );
78
- const methodDefinitions = [];
79
- const globalTypeDefinitions = [];
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]);
80
74
  const sourceFiles = project.getSourceFiles();
81
75
  consola.info(`Found ${sourceFiles.length} source file(s).`);
76
+ const methodDefinitions = [];
77
+ const localDeclarations = [];
78
+ const localDeclarationNames = /* @__PURE__ */ new Set();
82
79
  for (const sourceFile of sourceFiles) {
83
80
  for (const iface of sourceFile.getInterfaces()) {
84
- const name = iface?.getName?.();
85
- if (name == null || name.endsWith("_")) {
86
- continue;
81
+ const name = iface.getName?.();
82
+ if (name && !name.endsWith("_")) {
83
+ localDeclarations.push(iface);
84
+ localDeclarationNames.add(name);
87
85
  }
88
- globalTypeDefinitions.push(iface.getText());
89
86
  }
90
87
  for (const typeAlias of sourceFile.getTypeAliases()) {
91
- const name = typeAlias?.getName?.();
92
- if (name == null || name.endsWith("_")) {
93
- continue;
88
+ const name = typeAlias.getName();
89
+ if (name && !name.endsWith("_")) {
90
+ localDeclarations.push(typeAlias);
91
+ localDeclarationNames.add(name);
94
92
  }
95
- globalTypeDefinitions.push(typeAlias.getText());
96
93
  }
97
- for (const statement of sourceFile.getStatements()) {
98
- if (statement.getKind() === SyntaxKind.ModuleDeclaration) {
99
- 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));
100
100
  }
101
101
  }
102
- for (const funcDecl of sourceFile.getFunctions()) {
103
- if (!funcDecl.isAmbient()) {
104
- const name = funcDecl.getName();
105
- if (name != null && !name.endsWith("_")) {
106
- 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
+ );
107
116
  }
108
117
  }
109
118
  }
110
- for (const varStmt of sourceFile.getVariableStatements()) {
111
- if (!varStmt.isAmbient()) {
112
- for (const varDecl of varStmt.getDeclarations()) {
113
- const initializer = varDecl.getInitializer();
114
- const varName = varDecl.getName();
115
- if (initializer != null && (initializer.getKind() === SyntaxKind.ArrowFunction || initializer.getKind() === SyntaxKind.FunctionExpression) && !varName.endsWith("_")) {
116
- methodDefinitions.push(
117
- getInterfaceMethodDefinition_(
118
- varName,
119
- initializer
120
- )
121
- );
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;
122
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 = ".";
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);
123
155
  }
124
156
  }
125
157
  }
@@ -131,7 +163,27 @@ const generateAppsScriptTypes = async ({
131
163
  const generatorName = "gasnuki";
132
164
  let outputContent = `// Auto-generated by ${generatorName}
133
165
  // Do NOT edit this file manually.
166
+
134
167
  `;
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")}
181
+
182
+ `;
183
+ }
184
+ const globalTypeDefinitions = localDeclarations.filter(
185
+ (d) => d.getKind?.() === SyntaxKind.InterfaceDeclaration || d.getKind?.() === SyntaxKind.TypeAliasDeclaration
186
+ ).map((decl) => decl.getText?.());
135
187
  if (globalTypeDefinitions.length > 0) {
136
188
  outputContent += `${globalTypeDefinitions.join("\n\n")}
137
189
 
@@ -149,7 +201,7 @@ ${formattedMethods}
149
201
  `Interface 'ServerScript' type definitions written to ${absoluteOutputFile} (${methodDefinitions.length} function(s), ${globalTypeDefinitions.length} type(s)).`
150
202
  );
151
203
  } else {
152
- outputContent = "export type ServerScripts = {}\n";
204
+ outputContent += "export type ServerScripts = {}\n";
153
205
  consola.info(
154
206
  `Interface 'ServerScript' type definitions written to ${absoluteOutputFile} (no functions found).`
155
207
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ciderjs/gasnuki",
3
- "version": "0.2.3",
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",