@ciderjs/gasnuki 0.2.2 → 0.2.4

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,5 +1,10 @@
1
1
  # gasnuki
2
2
 
3
+ [![Test Coverage](https://img.shields.io/badge/test%20coverage-87.76%25-green)](https://github.com/luthpg/gasnuki)
4
+ [![License](https://img.shields.io/badge/license-ISC-blue.svg)](LICENSE)
5
+ [![npm version](https://img.shields.io/npm/v/@ciderjs/gasnuki.svg)](https://www.npmjs.com/package/@ciderjs/gasnuki)
6
+ [![GitHub issues](https://img.shields.io/github/issues/luthpg/gasnuki.svg)](https://github.com/luthpg/gasnuki/issues)
7
+
3
8
  Google Apps Script クライアントサイドAPIの型定義・ユーティリティ
4
9
 
5
10
  ## 概要
@@ -27,11 +32,22 @@ pnpm add @ciderjs/gasnuki
27
32
  npx @ciderjs/gasnuki
28
33
  ```
29
34
 
35
+ ... または、プロジェクトのnpmスクリプトを `package.json` に追加:
36
+
37
+ ```jsonc
38
+ {
39
+ // others...
40
+ "scripts": {
41
+ "gas": "gasnuki"
42
+ }
43
+ }
44
+ ```
45
+
30
46
  デフォルトでは `types` ディレクトリに型定義ファイルが生成されます。
31
47
 
32
48
  2. 生成されたディレクトリ(デフォルト: `types`)を `tsconfig.json` の `include` に追加してください:
33
49
 
34
- ```json
50
+ ```jsonc
35
51
  {
36
52
  "compilerOptions": {
37
53
  // ... your options ...
@@ -56,7 +72,7 @@ google.script.run
56
72
  .getContent('Sheet1');
57
73
  ```
58
74
 
59
- ## 提供機能
75
+ ## 機能
60
76
 
61
77
  - Google Apps Script クライアントAPIの型定義
62
78
  - サーバーサイド関数の戻り値型をvoidに変換するユーティリティ型
@@ -68,4 +84,4 @@ google.script.run
68
84
 
69
85
  ## ライセンス
70
86
 
71
- MIT
87
+ MIT
package/README.md CHANGED
@@ -1,4 +1,9 @@
1
- # gasnuki
1
+ # @ciderjs/gasnuki
2
+
3
+ [![Test Coverage](https://img.shields.io/badge/test%20coverage-87.76%25-green)](https://github.com/luthpg/gasnuki)
4
+ [![License](https://img.shields.io/badge/license-ISC-blue.svg)](LICENSE)
5
+ [![npm version](https://img.shields.io/npm/v/@ciderjs/gasnuki.svg)](https://www.npmjs.com/package/@ciderjs/gasnuki)
6
+ [![GitHub issues](https://img.shields.io/github/issues/luthpg/gasnuki.svg)](https://github.com/luthpg/gasnuki/issues)
2
7
 
3
8
  Type definitions and utilities for Google Apps Script client-side API
4
9
 
@@ -54,6 +59,7 @@ This will generate type definition files in the `types` directory by default.
54
59
  ```
55
60
 
56
61
  3. Then, you can use `google` with Type Definitions.
62
+
57
63
  ```ts
58
64
  // Type-safe access to google.script.run
59
65
  // Example: Call the server-side function getContent
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.D0Jm2dZh.cjs');
6
+ const index = require('./shared/gasnuki.CYh0jbl5.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.2";
27
+ const version = "0.2.4";
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.DjqKPcXI.mjs';
4
+ import { l as loadConfig, g as generateTypes } from './shared/gasnuki.DvpVGJ1U.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.2";
11
+ const version = "0.2.4";
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.D0Jm2dZh.cjs');
6
+ const index = require('./shared/gasnuki.CYh0jbl5.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.DjqKPcXI.mjs';
4
+ export { d as defineConfig, g as generateTypes } from './shared/gasnuki.DvpVGJ1U.mjs';
5
5
  import 'node:fs';
6
6
  import 'ts-morph';
7
7
  import 'jiti';
package/dist/promise.cjs CHANGED
@@ -1,23 +1,19 @@
1
1
  'use strict';
2
2
 
3
3
  const getPromisedServerScripts = (mockupFunctions = {}) => {
4
- const serverScripts = {
5
- ...mockupFunctions
6
- };
7
- if (!("google" in globalThis) || !google?.script?.run) {
8
- return serverScripts;
9
- }
10
- for (const method of Object.keys(google.script.run)) {
11
- if (["withSuccessHandler", "withFailureHandler", "withUserObject"].includes(
12
- String(method)
13
- )) {
14
- continue;
4
+ return new Proxy(mockupFunctions, {
5
+ get(target, method) {
6
+ if (!("google" in globalThis) || !google?.script?.run) {
7
+ return target[method];
8
+ }
9
+ if (!(method in google.script.run)) {
10
+ throw Error(`Method ${method} not found in AppsScript.`);
11
+ }
12
+ return (...args) => new Promise((resolve, reject) => {
13
+ google.script.run.withSuccessHandler(resolve).withFailureHandler(reject)[method](...args);
14
+ });
15
15
  }
16
- serverScripts[method] = (...args) => new Promise((resolve, reject) => {
17
- google.script.run.withSuccessHandler(resolve).withFailureHandler(reject)[method](...args);
18
- });
19
- }
20
- return serverScripts;
16
+ });
21
17
  };
22
18
 
23
19
  exports.getPromisedServerScripts = getPromisedServerScripts;
package/dist/promise.mjs CHANGED
@@ -1,21 +1,17 @@
1
1
  const getPromisedServerScripts = (mockupFunctions = {}) => {
2
- const serverScripts = {
3
- ...mockupFunctions
4
- };
5
- if (!("google" in globalThis) || !google?.script?.run) {
6
- return serverScripts;
7
- }
8
- for (const method of Object.keys(google.script.run)) {
9
- if (["withSuccessHandler", "withFailureHandler", "withUserObject"].includes(
10
- String(method)
11
- )) {
12
- continue;
2
+ return new Proxy(mockupFunctions, {
3
+ get(target, method) {
4
+ if (!("google" in globalThis) || !google?.script?.run) {
5
+ return target[method];
6
+ }
7
+ if (!(method in google.script.run)) {
8
+ throw Error(`Method ${method} not found in AppsScript.`);
9
+ }
10
+ return (...args) => new Promise((resolve, reject) => {
11
+ google.script.run.withSuccessHandler(resolve).withFailureHandler(reject)[method](...args);
12
+ });
13
13
  }
14
- serverScripts[method] = (...args) => new Promise((resolve, reject) => {
15
- google.script.run.withSuccessHandler(resolve).withFailureHandler(reject)[method](...args);
16
- });
17
- }
18
- return serverScripts;
14
+ });
19
15
  };
20
16
 
21
17
  export { getPromisedServerScripts };
@@ -74,6 +74,14 @@ const getInterfaceMethodDefinition_ = (name, node) => {
74
74
  }
75
75
  return `${jsDocString}${name}${typeParamsString}(${parameters}): ${returnType};`;
76
76
  };
77
+ const SIMPLE_TRIGGER_FUNCTION_NAMES = [
78
+ "onOpen",
79
+ "onEdit",
80
+ "onInstall",
81
+ "onSelectionChange",
82
+ "doGet",
83
+ "doPost"
84
+ ];
77
85
  const generateAppsScriptTypes = async ({
78
86
  project: projectPath,
79
87
  srcDir,
@@ -95,13 +103,44 @@ const generateAppsScriptTypes = async ({
95
103
  );
96
104
  const methodDefinitions = [];
97
105
  const globalTypeDefinitions = [];
106
+ const importStatements = /* @__PURE__ */ new Set();
98
107
  const sourceFiles = project.getSourceFiles();
99
108
  consola.consola.info(`Found ${sourceFiles.length} source file(s).`);
100
109
  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
+ }
101
132
  for (const iface of sourceFile.getInterfaces()) {
133
+ const name = iface?.getName?.();
134
+ if (name == null || name.endsWith("_")) {
135
+ continue;
136
+ }
102
137
  globalTypeDefinitions.push(iface.getText());
103
138
  }
104
139
  for (const typeAlias of sourceFile.getTypeAliases()) {
140
+ const name = typeAlias?.getName?.();
141
+ if (name == null || name.endsWith("_")) {
142
+ continue;
143
+ }
105
144
  globalTypeDefinitions.push(typeAlias.getText());
106
145
  }
107
146
  for (const statement of sourceFile.getStatements()) {
@@ -112,7 +151,7 @@ const generateAppsScriptTypes = async ({
112
151
  for (const funcDecl of sourceFile.getFunctions()) {
113
152
  if (!funcDecl.isAmbient()) {
114
153
  const name = funcDecl.getName();
115
- if (name != null && !name.endsWith("_")) {
154
+ if (name != null && !name.endsWith("_") && !SIMPLE_TRIGGER_FUNCTION_NAMES.includes(name)) {
116
155
  methodDefinitions.push(getInterfaceMethodDefinition_(name, funcDecl));
117
156
  }
118
157
  }
@@ -122,7 +161,7 @@ const generateAppsScriptTypes = async ({
122
161
  for (const varDecl of varStmt.getDeclarations()) {
123
162
  const initializer = varDecl.getInitializer();
124
163
  const varName = varDecl.getName();
125
- if (initializer != null && (initializer.getKind() === tsMorph.SyntaxKind.ArrowFunction || initializer.getKind() === tsMorph.SyntaxKind.FunctionExpression) && !varName.endsWith("_")) {
164
+ if (initializer != null && (initializer.getKind() === tsMorph.SyntaxKind.ArrowFunction || initializer.getKind() === tsMorph.SyntaxKind.FunctionExpression) && !varName.endsWith("_") && !SIMPLE_TRIGGER_FUNCTION_NAMES.includes(varName)) {
126
165
  methodDefinitions.push(
127
166
  getInterfaceMethodDefinition_(
128
167
  varName,
@@ -142,6 +181,11 @@ const generateAppsScriptTypes = async ({
142
181
  let outputContent = `// Auto-generated by ${generatorName}
143
182
  // Do NOT edit this file manually.
144
183
  `;
184
+ if (importStatements.size > 0) {
185
+ outputContent += `${[...importStatements].join("\n")}
186
+
187
+ `;
188
+ }
145
189
  if (globalTypeDefinitions.length > 0) {
146
190
  outputContent += `${globalTypeDefinitions.join("\n\n")}
147
191
 
@@ -159,7 +203,7 @@ ${formattedMethods}
159
203
  `Interface 'ServerScript' type definitions written to ${absoluteOutputFile} (${methodDefinitions.length} function(s), ${globalTypeDefinitions.length} type(s)).`
160
204
  );
161
205
  } else {
162
- outputContent = "export type ServerScripts = {}\n";
206
+ outputContent += "export type ServerScripts = {}\n";
163
207
  consola.consola.info(
164
208
  `Interface 'ServerScript' type definitions written to ${absoluteOutputFile} (no functions found).`
165
209
  );
@@ -56,6 +56,14 @@ const getInterfaceMethodDefinition_ = (name, node) => {
56
56
  }
57
57
  return `${jsDocString}${name}${typeParamsString}(${parameters}): ${returnType};`;
58
58
  };
59
+ const SIMPLE_TRIGGER_FUNCTION_NAMES = [
60
+ "onOpen",
61
+ "onEdit",
62
+ "onInstall",
63
+ "onSelectionChange",
64
+ "doGet",
65
+ "doPost"
66
+ ];
59
67
  const generateAppsScriptTypes = async ({
60
68
  project: projectPath,
61
69
  srcDir,
@@ -77,13 +85,44 @@ const generateAppsScriptTypes = async ({
77
85
  );
78
86
  const methodDefinitions = [];
79
87
  const globalTypeDefinitions = [];
88
+ const importStatements = /* @__PURE__ */ new Set();
80
89
  const sourceFiles = project.getSourceFiles();
81
90
  consola.info(`Found ${sourceFiles.length} source file(s).`);
82
91
  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
+ }
83
114
  for (const iface of sourceFile.getInterfaces()) {
115
+ const name = iface?.getName?.();
116
+ if (name == null || name.endsWith("_")) {
117
+ continue;
118
+ }
84
119
  globalTypeDefinitions.push(iface.getText());
85
120
  }
86
121
  for (const typeAlias of sourceFile.getTypeAliases()) {
122
+ const name = typeAlias?.getName?.();
123
+ if (name == null || name.endsWith("_")) {
124
+ continue;
125
+ }
87
126
  globalTypeDefinitions.push(typeAlias.getText());
88
127
  }
89
128
  for (const statement of sourceFile.getStatements()) {
@@ -94,7 +133,7 @@ const generateAppsScriptTypes = async ({
94
133
  for (const funcDecl of sourceFile.getFunctions()) {
95
134
  if (!funcDecl.isAmbient()) {
96
135
  const name = funcDecl.getName();
97
- if (name != null && !name.endsWith("_")) {
136
+ if (name != null && !name.endsWith("_") && !SIMPLE_TRIGGER_FUNCTION_NAMES.includes(name)) {
98
137
  methodDefinitions.push(getInterfaceMethodDefinition_(name, funcDecl));
99
138
  }
100
139
  }
@@ -104,7 +143,7 @@ const generateAppsScriptTypes = async ({
104
143
  for (const varDecl of varStmt.getDeclarations()) {
105
144
  const initializer = varDecl.getInitializer();
106
145
  const varName = varDecl.getName();
107
- if (initializer != null && (initializer.getKind() === SyntaxKind.ArrowFunction || initializer.getKind() === SyntaxKind.FunctionExpression) && !varName.endsWith("_")) {
146
+ if (initializer != null && (initializer.getKind() === SyntaxKind.ArrowFunction || initializer.getKind() === SyntaxKind.FunctionExpression) && !varName.endsWith("_") && !SIMPLE_TRIGGER_FUNCTION_NAMES.includes(varName)) {
108
147
  methodDefinitions.push(
109
148
  getInterfaceMethodDefinition_(
110
149
  varName,
@@ -124,6 +163,11 @@ const generateAppsScriptTypes = async ({
124
163
  let outputContent = `// Auto-generated by ${generatorName}
125
164
  // Do NOT edit this file manually.
126
165
  `;
166
+ if (importStatements.size > 0) {
167
+ outputContent += `${[...importStatements].join("\n")}
168
+
169
+ `;
170
+ }
127
171
  if (globalTypeDefinitions.length > 0) {
128
172
  outputContent += `${globalTypeDefinitions.join("\n\n")}
129
173
 
@@ -141,7 +185,7 @@ ${formattedMethods}
141
185
  `Interface 'ServerScript' type definitions written to ${absoluteOutputFile} (${methodDefinitions.length} function(s), ${globalTypeDefinitions.length} type(s)).`
142
186
  );
143
187
  } else {
144
- outputContent = "export type ServerScripts = {}\n";
188
+ outputContent += "export type ServerScripts = {}\n";
145
189
  consola.info(
146
190
  `Interface 'ServerScript' type definitions written to ${absoluteOutputFile} (no functions found).`
147
191
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ciderjs/gasnuki",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
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",
@@ -26,7 +26,10 @@
26
26
  "check": "biome check --write",
27
27
  "build": "unbuild",
28
28
  "test": "vitest run",
29
- "prepare": "pnpm run generate && pnpm run check && pnpm run test && pnpm run build",
29
+ "test:coverage": "vitest run --coverage",
30
+ "update-coverage-badge": "jiti scripts/update-coverage-badge.ts README.md README.ja.md",
31
+ "test:coverage:update": "pnpm test:coverage && pnpm update-coverage-badge",
32
+ "prepare": "pnpm run generate && pnpm run check && pnpm run test:coverage:update && pnpm run build",
30
33
  "pg:react": "pnpm -C playground/react",
31
34
  "pg:vue": "pnpm -C playground/vue3"
32
35
  },
@@ -1,53 +0,0 @@
1
- export type RemoveReturnType<T> = {
2
- [P in keyof T]: T[P] extends (...args: infer A) => any
3
- ? (...args: A) => void
4
- : T[P];
5
- };
6
-
7
- type _AppsScriptRun = {
8
- [key: string]: (...args: any[]) => any;
9
- withSuccessHandler: <T = string | number | boolean | undefined, U = any>(
10
- callback: (returnValues: T, userObject?: U) => void,
11
- ) => _AppsScriptRun;
12
- withFailureHandler: <U = any>(
13
- callback: (error: Error, userObject?: U) => void,
14
- ) => _AppsScriptRun;
15
- withUserObject: <U = any>(userObject: U) => _AppsScriptRun;
16
- };
17
-
18
- type _AppsScriptHistoryFunction = (
19
- stateObject: object,
20
- params: object,
21
- hash: string,
22
- ) => void;
23
-
24
- interface _WebAppLovacationType {
25
- hash: string;
26
- parameter: Record<string, string>;
27
- parameters: Record<string, string[]>;
28
- }
29
-
30
- export declare interface GoogleClientSideApi {
31
- script: {
32
- run: _AppsScriptRun;
33
- url: {
34
- getLocation: (
35
- callback: (location: _WebAppLovacationType) => void,
36
- ) => void;
37
- };
38
- history: {
39
- push: _AppsScriptHistoryFunction;
40
- replace: _AppsScriptHistoryFunction;
41
- setChangeHandler: (
42
- callback: (e: {
43
- state: object;
44
- location: _WebAppLovacationType;
45
- }) => void,
46
- ) => void;
47
- };
48
- };
49
- }
50
-
51
- declare global {
52
- const google: GoogleClientSideApi;
53
- }