@ciderjs/gasnuki 0.3.7 → 0.4.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/README.ja.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # @ciderjs/gasnuki
2
2
 
3
3
  [![README-en](https://img.shields.io/badge/English-blue?logo=ReadMe)](./README.md)
4
- [![Test Coverage](https://img.shields.io/badge/test%20coverage-93.77%25-brightgreen)](https://github.com/luthpg/gasnuki)
4
+ [![Test Coverage](https://img.shields.io/badge/test%20coverage-93.7%25-brightgreen)](https://github.com/luthpg/gasnuki)
5
5
  [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
6
6
  [![npm version](https://img.shields.io/npm/v/@ciderjs/gasnuki.svg)](https://www.npmjs.com/package/@ciderjs/gasnuki)
7
7
  [![GitHub issues](https://img.shields.io/github/issues/luthpg/gasnuki.svg)](https://github.com/luthpg/gasnuki/issues)
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # @ciderjs/gasnuki
2
2
 
3
3
  [![README-ja](https://img.shields.io/badge/日本語-blue?logo=ReadMe)](./README.ja.md)
4
- [![Test Coverage](https://img.shields.io/badge/test%20coverage-93.77%25-brightgreen)](https://github.com/luthpg/gasnuki)
4
+ [![Test Coverage](https://img.shields.io/badge/test%20coverage-93.7%25-brightgreen)](https://github.com/luthpg/gasnuki)
5
5
  [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
6
6
  [![npm version](https://img.shields.io/npm/v/@ciderjs/gasnuki.svg)](https://www.npmjs.com/package/@ciderjs/gasnuki)
7
7
  [![GitHub issues](https://img.shields.io/github/issues/luthpg/gasnuki.svg)](https://github.com/luthpg/gasnuki/issues)
package/dist/cli.cjs CHANGED
@@ -4,9 +4,10 @@
4
4
  const path = require('node:path');
5
5
  const commander = require('commander');
6
6
  const index = require('./index.cjs');
7
- const config = require('./shared/gasnuki.CooUv3Bz.cjs');
7
+ const config = require('./shared/gasnuki.DfLTmLhN.cjs');
8
8
  require('chokidar');
9
9
  require('consola');
10
+ require('node:crypto');
10
11
  require('node:fs');
11
12
  require('ts-morph');
12
13
  require('jiti');
@@ -25,7 +26,7 @@ function _interopNamespaceCompat(e) {
25
26
 
26
27
  const path__namespace = /*#__PURE__*/_interopNamespaceCompat(path);
27
28
 
28
- const version = "0.3.7";
29
+ const version = "0.4.0";
29
30
 
30
31
  const parseArgs = async (command) => {
31
32
  const cliOpts = command.opts();
@@ -69,7 +70,7 @@ const runCli = async () => {
69
70
  "-o, --outDir <dir>",
70
71
  "Output directory name (relative to project root)",
71
72
  "types"
72
- ).option("-f, --outputFile <file>", "Output file name", "appsscript.ts").option("-w, --watch", "Watch for changes and re-generate types", false);
73
+ ).option("-f, --outputFile <file>", "Output file name", "appsscript.ts").option("-w, --watch", "Watch for changes and re-generate types", false).option("--cache", "Enable checking generation cache", true).option("--no-cache", "Disable checking generation cache", true);
73
74
  await program.parseAsync(process.argv);
74
75
  };
75
76
  const isMainModule = typeof require !== "undefined" && require.main === module;
package/dist/cli.mjs CHANGED
@@ -2,14 +2,15 @@
2
2
  import * as path from 'node:path';
3
3
  import { Command } from 'commander';
4
4
  import { generateTypes } from './index.mjs';
5
- import { l as loadConfig } from './shared/gasnuki.Md02V2Fd.mjs';
5
+ import { l as loadConfig } from './shared/gasnuki.SJQVcSIQ.mjs';
6
6
  import 'chokidar';
7
7
  import 'consola';
8
+ import 'node:crypto';
8
9
  import 'node:fs';
9
10
  import 'ts-morph';
10
11
  import 'jiti';
11
12
 
12
- const version = "0.3.7";
13
+ const version = "0.4.0";
13
14
 
14
15
  const parseArgs = async (command) => {
15
16
  const cliOpts = command.opts();
@@ -53,7 +54,7 @@ const runCli = async () => {
53
54
  "-o, --outDir <dir>",
54
55
  "Output directory name (relative to project root)",
55
56
  "types"
56
- ).option("-f, --outputFile <file>", "Output file name", "appsscript.ts").option("-w, --watch", "Watch for changes and re-generate types", false);
57
+ ).option("-f, --outputFile <file>", "Output file name", "appsscript.ts").option("-w, --watch", "Watch for changes and re-generate types", false).option("--cache", "Enable checking generation cache", true).option("--no-cache", "Disable checking generation cache", true);
57
58
  await program.parseAsync(process.argv);
58
59
  };
59
60
  const isMainModule = typeof require !== "undefined" && require.main === module;
package/dist/index.cjs CHANGED
@@ -3,7 +3,8 @@
3
3
  const path = require('node:path');
4
4
  const chokidar = require('chokidar');
5
5
  const consola = require('consola');
6
- const config = require('./shared/gasnuki.CooUv3Bz.cjs');
6
+ const config = require('./shared/gasnuki.DfLTmLhN.cjs');
7
+ require('node:crypto');
7
8
  require('node:fs');
8
9
  require('ts-morph');
9
10
  require('jiti');
@@ -28,13 +29,23 @@ const generateTypes = async ({
28
29
  srcDir,
29
30
  outDir,
30
31
  outputFile,
31
- watch
32
+ watch,
33
+ cache
32
34
  }) => {
35
+ if (cache === false) {
36
+ consola.consola.info("Generation cache is disabled");
37
+ }
33
38
  const runGeneration = async (triggeredBy) => {
34
39
  const reason = triggeredBy ? ` (${triggeredBy})` : "";
35
40
  consola.consola.info(`Generating AppsScript types${reason}...`);
36
41
  try {
37
- await config.generateAppsScriptTypes({ project, srcDir, outDir, outputFile });
42
+ await config.generateAppsScriptTypes({
43
+ project,
44
+ srcDir,
45
+ outDir,
46
+ outputFile,
47
+ cache
48
+ });
38
49
  consola.consola.info("Type generation complete.");
39
50
  } catch (e) {
40
51
  consola.consola.error(`Type generation failed: ${e.message}`, e);
package/dist/index.d.cts CHANGED
@@ -16,8 +16,9 @@ interface GenerateOptions {
16
16
  outDir: string;
17
17
  outputFile: string;
18
18
  watch: boolean;
19
+ cache?: boolean;
19
20
  }
20
- declare const generateTypes: ({ project, srcDir, outDir, outputFile, watch, }: GenerateOptions) => Promise<void>;
21
+ declare const generateTypes: ({ project, srcDir, outDir, outputFile, watch, cache, }: GenerateOptions) => Promise<void>;
21
22
 
22
23
  export { defineConfig, generateTypes };
23
24
  export type { GenerateOptions, UserConfig };
package/dist/index.d.mts CHANGED
@@ -16,8 +16,9 @@ interface GenerateOptions {
16
16
  outDir: string;
17
17
  outputFile: string;
18
18
  watch: boolean;
19
+ cache?: boolean;
19
20
  }
20
- declare const generateTypes: ({ project, srcDir, outDir, outputFile, watch, }: GenerateOptions) => Promise<void>;
21
+ declare const generateTypes: ({ project, srcDir, outDir, outputFile, watch, cache, }: GenerateOptions) => Promise<void>;
21
22
 
22
23
  export { defineConfig, generateTypes };
23
24
  export type { GenerateOptions, UserConfig };
package/dist/index.d.ts CHANGED
@@ -16,8 +16,9 @@ interface GenerateOptions {
16
16
  outDir: string;
17
17
  outputFile: string;
18
18
  watch: boolean;
19
+ cache?: boolean;
19
20
  }
20
- declare const generateTypes: ({ project, srcDir, outDir, outputFile, watch, }: GenerateOptions) => Promise<void>;
21
+ declare const generateTypes: ({ project, srcDir, outDir, outputFile, watch, cache, }: GenerateOptions) => Promise<void>;
21
22
 
22
23
  export { defineConfig, generateTypes };
23
24
  export type { GenerateOptions, UserConfig };
package/dist/index.mjs CHANGED
@@ -1,8 +1,9 @@
1
1
  import * as path from 'node:path';
2
2
  import * as chokidar from 'chokidar';
3
3
  import { consola } from 'consola';
4
- import { g as generateAppsScriptTypes } from './shared/gasnuki.Md02V2Fd.mjs';
5
- export { d as defineConfig } from './shared/gasnuki.Md02V2Fd.mjs';
4
+ import { g as generateAppsScriptTypes } from './shared/gasnuki.SJQVcSIQ.mjs';
5
+ export { d as defineConfig } from './shared/gasnuki.SJQVcSIQ.mjs';
6
+ import 'node:crypto';
6
7
  import 'node:fs';
7
8
  import 'ts-morph';
8
9
  import 'jiti';
@@ -12,13 +13,23 @@ const generateTypes = async ({
12
13
  srcDir,
13
14
  outDir,
14
15
  outputFile,
15
- watch
16
+ watch,
17
+ cache
16
18
  }) => {
19
+ if (cache === false) {
20
+ consola.info("Generation cache is disabled");
21
+ }
17
22
  const runGeneration = async (triggeredBy) => {
18
23
  const reason = triggeredBy ? ` (${triggeredBy})` : "";
19
24
  consola.info(`Generating AppsScript types${reason}...`);
20
25
  try {
21
- await generateAppsScriptTypes({ project, srcDir, outDir, outputFile });
26
+ await generateAppsScriptTypes({
27
+ project,
28
+ srcDir,
29
+ outDir,
30
+ outputFile,
31
+ cache
32
+ });
22
33
  consola.info("Type generation complete.");
23
34
  } catch (e) {
24
35
  consola.error(`Type generation failed: ${e.message}`, e);
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ const crypto = require('node:crypto');
3
4
  const fs = require('node:fs');
4
5
  const path = require('node:path');
5
6
  const consola = require('consola');
@@ -18,11 +19,24 @@ function _interopNamespaceCompat(e) {
18
19
  return n;
19
20
  }
20
21
 
22
+ const crypto__namespace = /*#__PURE__*/_interopNamespaceCompat(crypto);
21
23
  const fs__namespace = /*#__PURE__*/_interopNamespaceCompat(fs);
22
24
  const path__namespace = /*#__PURE__*/_interopNamespaceCompat(path);
23
25
 
24
26
  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 _WebAppLocationType {\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: (callback: (location: _WebAppLocationType) => void) => void;\n };\n history: {\n push: _AppsScriptHistoryFunction;\n replace: _AppsScriptHistoryFunction;\n setChangeHandler: (\n callback: (e: { state: object; location: _WebAppLocationType }) => void,\n ) => void;\n };\n };\n}\n\ndeclare global {\n const google: GoogleClientSideApi;\n}\n";
25
27
 
28
+ const generationCache = /* @__PURE__ */ new Map();
29
+ const computeSourceHash = (sourceFiles) => {
30
+ const hash = crypto__namespace.createHash("md5");
31
+ const sortedFiles = [...sourceFiles].sort(
32
+ (a, b) => a.getFilePath().localeCompare(b.getFilePath())
33
+ );
34
+ for (const file of sortedFiles) {
35
+ hash.update(file.getFilePath());
36
+ hash.update(file.getFullText());
37
+ }
38
+ return hash.digest("hex");
39
+ };
26
40
  const getInterfaceMethodDefinition_ = (name, node) => {
27
41
  const typeParameters = node.getTypeParameters?.() ?? [];
28
42
  const typeParamsString = typeParameters.length > 0 ? `<${typeParameters.map((tp) => tp.getText()).join(", ")}>` : "";
@@ -103,7 +117,9 @@ const generateAppsScriptTypes = async ({
103
117
  srcDir,
104
118
  outDir,
105
119
  outputFile,
106
- projectInstance
120
+ projectInstance,
121
+ cache = true
122
+ // Default to true
107
123
  }) => {
108
124
  const absoluteSrcDir = path__namespace.resolve(projectPath, srcDir);
109
125
  const absoluteOutDir = path__namespace.resolve(projectPath, outDir);
@@ -120,6 +136,16 @@ const generateAppsScriptTypes = async ({
120
136
  project.addSourceFilesAtPaths([sourceFilesPattern, testFilesPattern]);
121
137
  const sourceFiles = project.getSourceFiles();
122
138
  consola.consola.info(`Found ${sourceFiles.length} source file(s).`);
139
+ if (cache) {
140
+ const currentHash = computeSourceHash(sourceFiles);
141
+ const cacheKey = absoluteOutputFile;
142
+ if (generationCache.get(cacheKey) === currentHash && fs__namespace.existsSync(absoluteOutputFile)) {
143
+ consola.consola.success(
144
+ `Skipping generation: Source files have not changed (Hash: ${currentHash.slice(0, 8)}).`
145
+ );
146
+ return;
147
+ }
148
+ }
123
149
  const methodDefinitions = [];
124
150
  const exportedDeclarations = [];
125
151
  const exportedDeclarationNames = /* @__PURE__ */ new Set();
@@ -354,24 +380,9 @@ const generateAppsScriptTypes = async ({
354
380
  // Do NOT edit this file manually.
355
381
 
356
382
  `;
357
- const sortedModulePaths = [...importsMap.keys()].sort((a, b) => {
358
- const aIsRelative = a.startsWith(".");
359
- const bIsRelative = b.startsWith(".");
360
- if (aIsRelative !== bIsRelative) return aIsRelative ? 1 : -1;
361
- return a.localeCompare(b);
362
- });
363
- if (sortedModulePaths.length > 0) {
364
- const importStatements = sortedModulePaths.map((modulePath) => {
365
- const imports = [...importsMap.get(modulePath) ?? []].sort();
366
- const finalModulePath = modulePath === "." ? "./index" : modulePath;
367
- return `import type { ${imports.join(", ")} } from '${finalModulePath}';`;
368
- });
369
- outputContent += `${importStatements.join("\n")}
370
-
371
- `;
372
- }
383
+ let bodyContent = "";
373
384
  if (inlineDefinitions.size > 0) {
374
- outputContent += `${[...inlineDefinitions.values()].join("\n\n")}
385
+ bodyContent += `${[...inlineDefinitions.values()].join("\n\n")}
375
386
 
376
387
  `;
377
388
  }
@@ -379,7 +390,7 @@ const generateAppsScriptTypes = async ({
379
390
  (d) => d.getKind() === tsMorph.SyntaxKind.InterfaceDeclaration || d.getKind() === tsMorph.SyntaxKind.TypeAliasDeclaration
380
391
  ).map((decl) => decl.getText());
381
392
  if (exportedTypeDefinitions.length > 0) {
382
- outputContent += `${exportedTypeDefinitions.join("\n\n")}
393
+ bodyContent += `${exportedTypeDefinitions.join("\n\n")}
383
394
 
384
395
  `;
385
396
  }
@@ -387,7 +398,7 @@ const generateAppsScriptTypes = async ({
387
398
  const formattedMethods = methodDefinitions.map(
388
399
  (method) => method.split("\n").map((line) => ` ${line}`).join("\n")
389
400
  ).join("\n\n");
390
- outputContent += `export type ServerScripts = {
401
+ bodyContent += `export type ServerScripts = {
391
402
  ${formattedMethods}
392
403
  }
393
404
  `;
@@ -395,16 +406,45 @@ ${formattedMethods}
395
406
  `Interface 'ServerScript' type definitions written to ${absoluteOutputFile} (${methodDefinitions.length} function(s), ${exportedTypeDefinitions.length + inlineDefinitions.size} type(s)).`
396
407
  );
397
408
  } else {
398
- outputContent += "export type ServerScripts = {}\n";
409
+ bodyContent += "export type ServerScripts = {}\n";
399
410
  consola.consola.info(
400
411
  `Interface 'ServerScript' type definitions written to ${absoluteOutputFile} (no functions found).`
401
412
  );
402
413
  }
403
- outputContent += `
414
+ bodyContent += `
404
415
  // Auto-generated Types for GoogleAppsScript in client-side code
405
416
 
406
417
  ${text}`;
418
+ const sortedModulePaths = [...importsMap.keys()].sort((a, b) => {
419
+ const aIsRelative = a.startsWith(".");
420
+ const bIsRelative = b.startsWith(".");
421
+ if (aIsRelative !== bIsRelative) return aIsRelative ? 1 : -1;
422
+ return a.localeCompare(b);
423
+ });
424
+ if (sortedModulePaths.length > 0) {
425
+ const importStatements = sortedModulePaths.map((modulePath) => {
426
+ const imports = [...importsMap.get(modulePath) ?? []].sort().filter((importName) => {
427
+ const regex = new RegExp(`\\b${importName}\\b`);
428
+ return regex.test(bodyContent);
429
+ });
430
+ if (imports.length === 0) {
431
+ return null;
432
+ }
433
+ const finalModulePath = modulePath === "." ? "./index" : modulePath;
434
+ return `import type { ${imports.join(", ")} } from '${finalModulePath}';`;
435
+ }).filter((s) => s !== null);
436
+ if (importStatements.length > 0) {
437
+ outputContent += `${importStatements.join("\n")}
438
+
439
+ `;
440
+ }
441
+ }
442
+ outputContent += bodyContent;
407
443
  fs__namespace.writeFileSync(absoluteOutputFile, outputContent);
444
+ if (cache) {
445
+ const currentHash = computeSourceHash(sourceFiles);
446
+ generationCache.set(absoluteOutputFile, currentHash);
447
+ }
408
448
  };
409
449
 
410
450
  function defineConfig(config) {
@@ -1,3 +1,4 @@
1
+ import * as crypto from 'node:crypto';
1
2
  import * as fs from 'node:fs';
2
3
  import * as path from 'node:path';
3
4
  import { consola } from 'consola';
@@ -6,6 +7,18 @@ import { createJiti } from 'jiti';
6
7
 
7
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 _WebAppLocationType {\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: (callback: (location: _WebAppLocationType) => void) => void;\n };\n history: {\n push: _AppsScriptHistoryFunction;\n replace: _AppsScriptHistoryFunction;\n setChangeHandler: (\n callback: (e: { state: object; location: _WebAppLocationType }) => void,\n ) => void;\n };\n };\n}\n\ndeclare global {\n const google: GoogleClientSideApi;\n}\n";
8
9
 
10
+ const generationCache = /* @__PURE__ */ new Map();
11
+ const computeSourceHash = (sourceFiles) => {
12
+ const hash = crypto.createHash("md5");
13
+ const sortedFiles = [...sourceFiles].sort(
14
+ (a, b) => a.getFilePath().localeCompare(b.getFilePath())
15
+ );
16
+ for (const file of sortedFiles) {
17
+ hash.update(file.getFilePath());
18
+ hash.update(file.getFullText());
19
+ }
20
+ return hash.digest("hex");
21
+ };
9
22
  const getInterfaceMethodDefinition_ = (name, node) => {
10
23
  const typeParameters = node.getTypeParameters?.() ?? [];
11
24
  const typeParamsString = typeParameters.length > 0 ? `<${typeParameters.map((tp) => tp.getText()).join(", ")}>` : "";
@@ -86,7 +99,9 @@ const generateAppsScriptTypes = async ({
86
99
  srcDir,
87
100
  outDir,
88
101
  outputFile,
89
- projectInstance
102
+ projectInstance,
103
+ cache = true
104
+ // Default to true
90
105
  }) => {
91
106
  const absoluteSrcDir = path.resolve(projectPath, srcDir);
92
107
  const absoluteOutDir = path.resolve(projectPath, outDir);
@@ -103,6 +118,16 @@ const generateAppsScriptTypes = async ({
103
118
  project.addSourceFilesAtPaths([sourceFilesPattern, testFilesPattern]);
104
119
  const sourceFiles = project.getSourceFiles();
105
120
  consola.info(`Found ${sourceFiles.length} source file(s).`);
121
+ if (cache) {
122
+ const currentHash = computeSourceHash(sourceFiles);
123
+ const cacheKey = absoluteOutputFile;
124
+ if (generationCache.get(cacheKey) === currentHash && fs.existsSync(absoluteOutputFile)) {
125
+ consola.success(
126
+ `Skipping generation: Source files have not changed (Hash: ${currentHash.slice(0, 8)}).`
127
+ );
128
+ return;
129
+ }
130
+ }
106
131
  const methodDefinitions = [];
107
132
  const exportedDeclarations = [];
108
133
  const exportedDeclarationNames = /* @__PURE__ */ new Set();
@@ -337,24 +362,9 @@ const generateAppsScriptTypes = async ({
337
362
  // Do NOT edit this file manually.
338
363
 
339
364
  `;
340
- const sortedModulePaths = [...importsMap.keys()].sort((a, b) => {
341
- const aIsRelative = a.startsWith(".");
342
- const bIsRelative = b.startsWith(".");
343
- if (aIsRelative !== bIsRelative) return aIsRelative ? 1 : -1;
344
- return a.localeCompare(b);
345
- });
346
- if (sortedModulePaths.length > 0) {
347
- const importStatements = sortedModulePaths.map((modulePath) => {
348
- const imports = [...importsMap.get(modulePath) ?? []].sort();
349
- const finalModulePath = modulePath === "." ? "./index" : modulePath;
350
- return `import type { ${imports.join(", ")} } from '${finalModulePath}';`;
351
- });
352
- outputContent += `${importStatements.join("\n")}
353
-
354
- `;
355
- }
365
+ let bodyContent = "";
356
366
  if (inlineDefinitions.size > 0) {
357
- outputContent += `${[...inlineDefinitions.values()].join("\n\n")}
367
+ bodyContent += `${[...inlineDefinitions.values()].join("\n\n")}
358
368
 
359
369
  `;
360
370
  }
@@ -362,7 +372,7 @@ const generateAppsScriptTypes = async ({
362
372
  (d) => d.getKind() === SyntaxKind.InterfaceDeclaration || d.getKind() === SyntaxKind.TypeAliasDeclaration
363
373
  ).map((decl) => decl.getText());
364
374
  if (exportedTypeDefinitions.length > 0) {
365
- outputContent += `${exportedTypeDefinitions.join("\n\n")}
375
+ bodyContent += `${exportedTypeDefinitions.join("\n\n")}
366
376
 
367
377
  `;
368
378
  }
@@ -370,7 +380,7 @@ const generateAppsScriptTypes = async ({
370
380
  const formattedMethods = methodDefinitions.map(
371
381
  (method) => method.split("\n").map((line) => ` ${line}`).join("\n")
372
382
  ).join("\n\n");
373
- outputContent += `export type ServerScripts = {
383
+ bodyContent += `export type ServerScripts = {
374
384
  ${formattedMethods}
375
385
  }
376
386
  `;
@@ -378,16 +388,45 @@ ${formattedMethods}
378
388
  `Interface 'ServerScript' type definitions written to ${absoluteOutputFile} (${methodDefinitions.length} function(s), ${exportedTypeDefinitions.length + inlineDefinitions.size} type(s)).`
379
389
  );
380
390
  } else {
381
- outputContent += "export type ServerScripts = {}\n";
391
+ bodyContent += "export type ServerScripts = {}\n";
382
392
  consola.info(
383
393
  `Interface 'ServerScript' type definitions written to ${absoluteOutputFile} (no functions found).`
384
394
  );
385
395
  }
386
- outputContent += `
396
+ bodyContent += `
387
397
  // Auto-generated Types for GoogleAppsScript in client-side code
388
398
 
389
399
  ${text}`;
400
+ const sortedModulePaths = [...importsMap.keys()].sort((a, b) => {
401
+ const aIsRelative = a.startsWith(".");
402
+ const bIsRelative = b.startsWith(".");
403
+ if (aIsRelative !== bIsRelative) return aIsRelative ? 1 : -1;
404
+ return a.localeCompare(b);
405
+ });
406
+ if (sortedModulePaths.length > 0) {
407
+ const importStatements = sortedModulePaths.map((modulePath) => {
408
+ const imports = [...importsMap.get(modulePath) ?? []].sort().filter((importName) => {
409
+ const regex = new RegExp(`\\b${importName}\\b`);
410
+ return regex.test(bodyContent);
411
+ });
412
+ if (imports.length === 0) {
413
+ return null;
414
+ }
415
+ const finalModulePath = modulePath === "." ? "./index" : modulePath;
416
+ return `import type { ${imports.join(", ")} } from '${finalModulePath}';`;
417
+ }).filter((s) => s !== null);
418
+ if (importStatements.length > 0) {
419
+ outputContent += `${importStatements.join("\n")}
420
+
421
+ `;
422
+ }
423
+ }
424
+ outputContent += bodyContent;
390
425
  fs.writeFileSync(absoluteOutputFile, outputContent);
426
+ if (cache) {
427
+ const currentHash = computeSourceHash(sourceFiles);
428
+ generationCache.set(absoluteOutputFile, currentHash);
429
+ }
391
430
  };
392
431
 
393
432
  function defineConfig(config) {
package/dist/vite.cjs CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  const path = require('node:path');
4
4
  const consola = require('consola');
5
- const config = require('./shared/gasnuki.CooUv3Bz.cjs');
5
+ const config = require('./shared/gasnuki.DfLTmLhN.cjs');
6
+ require('node:crypto');
6
7
  require('node:fs');
7
8
  require('ts-morph');
8
9
  require('jiti');
package/dist/vite.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  import * as path from 'node:path';
2
2
  import { consola } from 'consola';
3
- import { l as loadConfig, g as generateAppsScriptTypes } from './shared/gasnuki.Md02V2Fd.mjs';
3
+ import { l as loadConfig, g as generateAppsScriptTypes } from './shared/gasnuki.SJQVcSIQ.mjs';
4
+ import 'node:crypto';
4
5
  import 'node:fs';
5
6
  import 'ts-morph';
6
7
  import 'jiti';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ciderjs/gasnuki",
3
- "version": "0.3.7",
3
+ "version": "0.4.0",
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",