@ciderjs/gasnuki 0.5.1 → 0.5.3

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-92.76%25-brightgreen)](https://github.com/luthpg/gasnuki)
4
+ [![Test Coverage](https://img.shields.io/badge/test%20coverage-89.02%25-green)](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
  ![NPM Downloads](https://img.shields.io/npm/dw/@ciderjs/gasnuki)
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-92.76%25-brightgreen)](https://github.com/luthpg/gasnuki)
4
+ [![Test Coverage](https://img.shields.io/badge/test%20coverage-89.02%25-green)](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
  ![NPM Downloads](https://img.shields.io/npm/dw/@ciderjs/gasnuki)
package/dist/cli.cjs CHANGED
@@ -4,7 +4,7 @@
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.Co0-wxJi.cjs');
7
+ const config = require('./shared/gasnuki.CDe7f-cZ.cjs');
8
8
  require('chokidar');
9
9
  require('consola');
10
10
  require('node:crypto');
@@ -26,7 +26,7 @@ function _interopNamespaceCompat(e) {
26
26
 
27
27
  const path__namespace = /*#__PURE__*/_interopNamespaceCompat(path);
28
28
 
29
- const version = "0.5.1";
29
+ const version = "0.5.3";
30
30
 
31
31
  const parseArgs = async (command) => {
32
32
  const cliOpts = command.opts();
package/dist/cli.mjs CHANGED
@@ -2,7 +2,7 @@
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.DePJgSg9.mjs';
5
+ import { l as loadConfig } from './shared/gasnuki.BAmTBfMa.mjs';
6
6
  import 'chokidar';
7
7
  import 'consola';
8
8
  import 'node:crypto';
@@ -10,7 +10,7 @@ import 'node:fs';
10
10
  import 'ts-morph';
11
11
  import 'jiti';
12
12
 
13
- const version = "0.5.1";
13
+ const version = "0.5.3";
14
14
 
15
15
  const parseArgs = async (command) => {
16
16
  const cliOpts = command.opts();
package/dist/index.cjs CHANGED
@@ -3,7 +3,7 @@
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.Co0-wxJi.cjs');
6
+ const config = require('./shared/gasnuki.CDe7f-cZ.cjs');
7
7
  require('node:crypto');
8
8
  require('node:fs');
9
9
  require('ts-morph');
package/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
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.DePJgSg9.mjs';
5
- export { d as defineConfig } from './shared/gasnuki.DePJgSg9.mjs';
4
+ import { g as generateAppsScriptTypes } from './shared/gasnuki.BAmTBfMa.mjs';
5
+ export { d as defineConfig } from './shared/gasnuki.BAmTBfMa.mjs';
6
6
  import 'node:crypto';
7
7
  import 'node:fs';
8
8
  import 'ts-morph';
@@ -2,7 +2,7 @@ import * as crypto from 'node:crypto';
2
2
  import * as fs from 'node:fs';
3
3
  import * as path from 'node:path';
4
4
  import { consola } from 'consola';
5
- import { Project, SyntaxKind, SymbolFlags } from 'ts-morph';
5
+ import { Project, SyntaxKind, SymbolFlags, Node } 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 _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";
@@ -72,27 +72,86 @@ const SIMPLE_TRIGGER_FUNCTION_NAMES = [
72
72
  "doGet",
73
73
  "doPost"
74
74
  ];
75
- const getPackageNameFromNodeModulesPath_ = (filePath) => {
76
- const normalizedPath = filePath.replace(/\\/g, "/");
77
- const nodeModulesIndex = normalizedPath.lastIndexOf("node_modules/");
78
- if (nodeModulesIndex === -1) {
79
- return null;
75
+ const packageJsonCache = /* @__PURE__ */ new Map();
76
+ const findPackageJson_ = (startDir) => {
77
+ let currentDir = startDir;
78
+ while (true) {
79
+ if (packageJsonCache.has(currentDir)) {
80
+ return packageJsonCache.get(currentDir);
81
+ }
82
+ const pkgPath = path.join(currentDir, "package.json");
83
+ if (fs.existsSync(pkgPath)) {
84
+ try {
85
+ const content = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
86
+ const result = { path: pkgPath, content };
87
+ packageJsonCache.set(currentDir, result);
88
+ if (currentDir !== startDir) {
89
+ packageJsonCache.set(startDir, result);
90
+ }
91
+ return result;
92
+ } catch {
93
+ }
94
+ }
95
+ const parentDir = path.dirname(currentDir);
96
+ if (parentDir === currentDir) {
97
+ packageJsonCache.set(currentDir, null);
98
+ if (currentDir !== startDir) {
99
+ packageJsonCache.set(startDir, null);
100
+ }
101
+ break;
102
+ }
103
+ currentDir = parentDir;
80
104
  }
81
- const afterNodeModules = normalizedPath.slice(
82
- nodeModulesIndex + "node_modules/".length
83
- );
84
- const parts = afterNodeModules.split("/");
85
- if (parts.length === 0) {
86
- return null;
105
+ return null;
106
+ };
107
+ const matchesExportValue_ = (node, targetPath) => {
108
+ if (typeof node === "string") {
109
+ return node === targetPath || node === targetPath.replace(/\.d\.ts$/, ".js");
87
110
  }
88
- if (parts[0].startsWith("@") && parts.length >= 2) {
89
- const scopedName = `${parts[0]}/${parts[1]}`;
90
- if (parts[0] === "@types") {
91
- return parts[1];
111
+ if (typeof node === "object" && node !== null) {
112
+ if (node.types && node.types === targetPath) {
113
+ return true;
114
+ }
115
+ for (const key in node) {
116
+ if (matchesExportValue_(node[key], targetPath)) {
117
+ return true;
118
+ }
92
119
  }
93
- return scopedName;
94
120
  }
95
- return parts[0];
121
+ return false;
122
+ };
123
+ const resolveNodeModuleSpecifier_ = (filePath) => {
124
+ const pkg = findPackageJson_(path.dirname(filePath));
125
+ if (!pkg) return null;
126
+ let packageName = pkg.content.name;
127
+ if (packageName.startsWith("@types/")) {
128
+ packageName = packageName.slice(7);
129
+ }
130
+ const packageRoot = path.dirname(pkg.path);
131
+ let relativePath = path.relative(packageRoot, filePath).replace(/\\/g, "/");
132
+ if (!relativePath.startsWith(".")) {
133
+ relativePath = `./${relativePath}`;
134
+ }
135
+ if (pkg.content.exports) {
136
+ for (const key in pkg.content.exports) {
137
+ const exportValue = pkg.content.exports[key];
138
+ if (matchesExportValue_(exportValue, relativePath)) {
139
+ if (key === ".") return packageName;
140
+ return path.posix.join(packageName, key);
141
+ }
142
+ }
143
+ }
144
+ const mainTypes = pkg.content.types || pkg.content.typings;
145
+ if (mainTypes) {
146
+ let normalizedMain = mainTypes.replace(/\\/g, "/");
147
+ if (!normalizedMain.startsWith(".")) {
148
+ normalizedMain = `./${normalizedMain}`;
149
+ }
150
+ if (normalizedMain === relativePath) {
151
+ return packageName;
152
+ }
153
+ }
154
+ return packageName;
96
155
  };
97
156
  const generateAppsScriptTypes = async ({
98
157
  project: projectPath,
@@ -109,8 +168,12 @@ const generateAppsScriptTypes = async ({
109
168
  consola.info("Starting AppsScript type generation with gasnuki...");
110
169
  consola.info(` AppsScript Source Directory: ${absoluteSrcDir}`);
111
170
  consola.info(` Output File: ${absoluteOutputFile}`);
171
+ let tsConfigFilePath = path.resolve(projectPath, "tsconfig.json");
172
+ if (fs.existsSync(path.resolve(projectPath, "tsconfig.app.json"))) {
173
+ tsConfigFilePath = path.resolve(projectPath, "tsconfig.app.json");
174
+ }
112
175
  const project = projectInstance ?? new Project({
113
- tsConfigFilePath: path.resolve(projectPath, "tsconfig.json"),
176
+ tsConfigFilePath,
114
177
  skipAddingFilesFromTsConfig: true
115
178
  });
116
179
  const sourceFilesPattern = path.join(absoluteSrcDir, "**/*.ts").replace(/\\/g, "/");
@@ -407,7 +470,17 @@ const generateAppsScriptTypes = async ({
407
470
  if (!functionSignatureSymbols.has(symbol)) {
408
471
  continue;
409
472
  }
410
- const packageName = getPackageNameFromNodeModulesPath_(sourceFilePath);
473
+ const hasExportModifier = sourceFile.getStatements().some((stmt) => {
474
+ if (Node.isExportable(stmt)) {
475
+ return stmt.isExported();
476
+ }
477
+ return false;
478
+ });
479
+ const isGlobal = sourceFile.getImportDeclarations().length === 0 && sourceFile.getExportDeclarations().length === 0 && sourceFile.getExportAssignments().length === 0 && !hasExportModifier;
480
+ if (isGlobal) {
481
+ continue;
482
+ }
483
+ const packageName = resolveNodeModuleSpecifier_(sourceFilePath);
411
484
  if (packageName) {
412
485
  processedSymbols.add(symbolName);
413
486
  if (!importsMap.has(packageName)) {
@@ -90,27 +90,86 @@ const SIMPLE_TRIGGER_FUNCTION_NAMES = [
90
90
  "doGet",
91
91
  "doPost"
92
92
  ];
93
- const getPackageNameFromNodeModulesPath_ = (filePath) => {
94
- const normalizedPath = filePath.replace(/\\/g, "/");
95
- const nodeModulesIndex = normalizedPath.lastIndexOf("node_modules/");
96
- if (nodeModulesIndex === -1) {
97
- return null;
93
+ const packageJsonCache = /* @__PURE__ */ new Map();
94
+ const findPackageJson_ = (startDir) => {
95
+ let currentDir = startDir;
96
+ while (true) {
97
+ if (packageJsonCache.has(currentDir)) {
98
+ return packageJsonCache.get(currentDir);
99
+ }
100
+ const pkgPath = path__namespace.join(currentDir, "package.json");
101
+ if (fs__namespace.existsSync(pkgPath)) {
102
+ try {
103
+ const content = JSON.parse(fs__namespace.readFileSync(pkgPath, "utf-8"));
104
+ const result = { path: pkgPath, content };
105
+ packageJsonCache.set(currentDir, result);
106
+ if (currentDir !== startDir) {
107
+ packageJsonCache.set(startDir, result);
108
+ }
109
+ return result;
110
+ } catch {
111
+ }
112
+ }
113
+ const parentDir = path__namespace.dirname(currentDir);
114
+ if (parentDir === currentDir) {
115
+ packageJsonCache.set(currentDir, null);
116
+ if (currentDir !== startDir) {
117
+ packageJsonCache.set(startDir, null);
118
+ }
119
+ break;
120
+ }
121
+ currentDir = parentDir;
98
122
  }
99
- const afterNodeModules = normalizedPath.slice(
100
- nodeModulesIndex + "node_modules/".length
101
- );
102
- const parts = afterNodeModules.split("/");
103
- if (parts.length === 0) {
104
- return null;
123
+ return null;
124
+ };
125
+ const matchesExportValue_ = (node, targetPath) => {
126
+ if (typeof node === "string") {
127
+ return node === targetPath || node === targetPath.replace(/\.d\.ts$/, ".js");
105
128
  }
106
- if (parts[0].startsWith("@") && parts.length >= 2) {
107
- const scopedName = `${parts[0]}/${parts[1]}`;
108
- if (parts[0] === "@types") {
109
- return parts[1];
129
+ if (typeof node === "object" && node !== null) {
130
+ if (node.types && node.types === targetPath) {
131
+ return true;
132
+ }
133
+ for (const key in node) {
134
+ if (matchesExportValue_(node[key], targetPath)) {
135
+ return true;
136
+ }
110
137
  }
111
- return scopedName;
112
138
  }
113
- return parts[0];
139
+ return false;
140
+ };
141
+ const resolveNodeModuleSpecifier_ = (filePath) => {
142
+ const pkg = findPackageJson_(path__namespace.dirname(filePath));
143
+ if (!pkg) return null;
144
+ let packageName = pkg.content.name;
145
+ if (packageName.startsWith("@types/")) {
146
+ packageName = packageName.slice(7);
147
+ }
148
+ const packageRoot = path__namespace.dirname(pkg.path);
149
+ let relativePath = path__namespace.relative(packageRoot, filePath).replace(/\\/g, "/");
150
+ if (!relativePath.startsWith(".")) {
151
+ relativePath = `./${relativePath}`;
152
+ }
153
+ if (pkg.content.exports) {
154
+ for (const key in pkg.content.exports) {
155
+ const exportValue = pkg.content.exports[key];
156
+ if (matchesExportValue_(exportValue, relativePath)) {
157
+ if (key === ".") return packageName;
158
+ return path__namespace.posix.join(packageName, key);
159
+ }
160
+ }
161
+ }
162
+ const mainTypes = pkg.content.types || pkg.content.typings;
163
+ if (mainTypes) {
164
+ let normalizedMain = mainTypes.replace(/\\/g, "/");
165
+ if (!normalizedMain.startsWith(".")) {
166
+ normalizedMain = `./${normalizedMain}`;
167
+ }
168
+ if (normalizedMain === relativePath) {
169
+ return packageName;
170
+ }
171
+ }
172
+ return packageName;
114
173
  };
115
174
  const generateAppsScriptTypes = async ({
116
175
  project: projectPath,
@@ -127,8 +186,12 @@ const generateAppsScriptTypes = async ({
127
186
  consola.consola.info("Starting AppsScript type generation with gasnuki...");
128
187
  consola.consola.info(` AppsScript Source Directory: ${absoluteSrcDir}`);
129
188
  consola.consola.info(` Output File: ${absoluteOutputFile}`);
189
+ let tsConfigFilePath = path__namespace.resolve(projectPath, "tsconfig.json");
190
+ if (fs__namespace.existsSync(path__namespace.resolve(projectPath, "tsconfig.app.json"))) {
191
+ tsConfigFilePath = path__namespace.resolve(projectPath, "tsconfig.app.json");
192
+ }
130
193
  const project = projectInstance ?? new tsMorph.Project({
131
- tsConfigFilePath: path__namespace.resolve(projectPath, "tsconfig.json"),
194
+ tsConfigFilePath,
132
195
  skipAddingFilesFromTsConfig: true
133
196
  });
134
197
  const sourceFilesPattern = path__namespace.join(absoluteSrcDir, "**/*.ts").replace(/\\/g, "/");
@@ -425,7 +488,17 @@ const generateAppsScriptTypes = async ({
425
488
  if (!functionSignatureSymbols.has(symbol)) {
426
489
  continue;
427
490
  }
428
- const packageName = getPackageNameFromNodeModulesPath_(sourceFilePath);
491
+ const hasExportModifier = sourceFile.getStatements().some((stmt) => {
492
+ if (tsMorph.Node.isExportable(stmt)) {
493
+ return stmt.isExported();
494
+ }
495
+ return false;
496
+ });
497
+ const isGlobal = sourceFile.getImportDeclarations().length === 0 && sourceFile.getExportDeclarations().length === 0 && sourceFile.getExportAssignments().length === 0 && !hasExportModifier;
498
+ if (isGlobal) {
499
+ continue;
500
+ }
501
+ const packageName = resolveNodeModuleSpecifier_(sourceFilePath);
429
502
  if (packageName) {
430
503
  processedSymbols.add(symbolName);
431
504
  if (!importsMap.has(packageName)) {
package/dist/vite.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  const path = require('node:path');
4
4
  const consola = require('consola');
5
- const config = require('./shared/gasnuki.Co0-wxJi.cjs');
5
+ const config = require('./shared/gasnuki.CDe7f-cZ.cjs');
6
6
  require('node:crypto');
7
7
  require('node:fs');
8
8
  require('ts-morph');
package/dist/vite.mjs CHANGED
@@ -1,6 +1,6 @@
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.DePJgSg9.mjs';
3
+ import { l as loadConfig, g as generateAppsScriptTypes } from './shared/gasnuki.BAmTBfMa.mjs';
4
4
  import 'node:crypto';
5
5
  import 'node:fs';
6
6
  import 'ts-morph';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ciderjs/gasnuki",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
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",
@@ -68,12 +68,12 @@
68
68
  },
69
69
  "devDependencies": {
70
70
  "@biomejs/biome": "^2.3.11",
71
- "@types/node": "^25.0.5",
72
- "@vitest/coverage-v8": "4.0.16",
71
+ "@types/node": "^25.0.9",
72
+ "@vitest/coverage-v8": "4.0.17",
73
73
  "typescript": "^5.9.3",
74
74
  "unbuild": "^3.6.1",
75
75
  "vite": "^7.3.1",
76
- "vitest": "4.0.16"
76
+ "vitest": "4.0.17"
77
77
  },
78
78
  "peerDependencies": {
79
79
  "vite": "^7"