@ciderjs/gasnuki 0.3.0 → 0.3.2
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 +1 -1
- package/README.md +1 -1
- package/dist/cli.cjs +2 -2
- package/dist/cli.mjs +2 -2
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +2 -2
- package/dist/shared/{gasnuki.CxoM0Mts.cjs → gasnuki.BziruiRW.cjs} +26 -49
- package/dist/shared/{gasnuki.BYl_yopE.mjs → gasnuki.CS6ipBfD.mjs} +26 -49
- package/dist/vite.cjs +1 -1
- package/dist/vite.mjs +1 -1
- package/package.json +3 -2
- package/.docs/vite-plugin/design.md +0 -220
- package/.docs/vite-plugin/requirements.md +0 -72
package/README.ja.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# gasnuki
|
|
2
2
|
|
|
3
|
-
[](https://github.com/luthpg/gasnuki)
|
|
4
4
|
[](LICENSE)
|
|
5
5
|
[](https://www.npmjs.com/package/@ciderjs/gasnuki)
|
|
6
6
|
[](https://github.com/luthpg/gasnuki/issues)
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @ciderjs/gasnuki
|
|
2
2
|
|
|
3
|
-
[](https://github.com/luthpg/gasnuki)
|
|
4
4
|
[](LICENSE)
|
|
5
5
|
[](https://www.npmjs.com/package/@ciderjs/gasnuki)
|
|
6
6
|
[](https://github.com/luthpg/gasnuki/issues)
|
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.
|
|
7
|
+
const config = require('./shared/gasnuki.BziruiRW.cjs');
|
|
8
8
|
require('chokidar');
|
|
9
9
|
require('consola');
|
|
10
10
|
require('node:fs');
|
|
@@ -25,7 +25,7 @@ function _interopNamespaceCompat(e) {
|
|
|
25
25
|
|
|
26
26
|
const path__namespace = /*#__PURE__*/_interopNamespaceCompat(path);
|
|
27
27
|
|
|
28
|
-
const version = "0.3.
|
|
28
|
+
const version = "0.3.2";
|
|
29
29
|
|
|
30
30
|
const parseArgs = async (command) => {
|
|
31
31
|
const cliOpts = command.opts();
|
package/dist/cli.mjs
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
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.
|
|
5
|
+
import { l as loadConfig } from './shared/gasnuki.CS6ipBfD.mjs';
|
|
6
6
|
import 'chokidar';
|
|
7
7
|
import 'consola';
|
|
8
8
|
import 'node:fs';
|
|
9
9
|
import 'ts-morph';
|
|
10
10
|
import 'jiti';
|
|
11
11
|
|
|
12
|
-
const version = "0.3.
|
|
12
|
+
const version = "0.3.2";
|
|
13
13
|
|
|
14
14
|
const parseArgs = async (command) => {
|
|
15
15
|
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.
|
|
6
|
+
const config = require('./shared/gasnuki.BziruiRW.cjs');
|
|
7
7
|
require('node:fs');
|
|
8
8
|
require('ts-morph');
|
|
9
9
|
require('jiti');
|
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.
|
|
5
|
-
export { d as defineConfig } from './shared/gasnuki.
|
|
4
|
+
import { g as generateAppsScriptTypes } from './shared/gasnuki.CS6ipBfD.mjs';
|
|
5
|
+
export { d as defineConfig } from './shared/gasnuki.CS6ipBfD.mjs';
|
|
6
6
|
import 'node:fs';
|
|
7
7
|
import 'ts-morph';
|
|
8
8
|
import 'jiti';
|
|
@@ -92,8 +92,13 @@ const generateAppsScriptTypes = async ({
|
|
|
92
92
|
const methodDefinitions = [];
|
|
93
93
|
const exportedDeclarations = [];
|
|
94
94
|
const exportedDeclarationNames = /* @__PURE__ */ new Set();
|
|
95
|
-
const exportedFunctions = [];
|
|
96
95
|
for (const sourceFile of sourceFiles) {
|
|
96
|
+
const filePath = sourceFile.getFilePath().replace(/\\/g, "/");
|
|
97
|
+
const srcPath = absoluteSrcDir.replace(/\\/g, "/");
|
|
98
|
+
const projectRelativeSrcPath = path__namespace.join(projectPath, srcDir).replace(/\\/g, "/");
|
|
99
|
+
if (!filePath.startsWith(srcPath) && !filePath.startsWith(projectRelativeSrcPath)) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
97
102
|
for (const iface of sourceFile.getInterfaces()) {
|
|
98
103
|
if (!iface.getName()?.endsWith("_")) {
|
|
99
104
|
exportedDeclarations.push(iface);
|
|
@@ -112,7 +117,6 @@ const generateAppsScriptTypes = async ({
|
|
|
112
117
|
exportedDeclarations.push(func);
|
|
113
118
|
exportedDeclarationNames.add(name);
|
|
114
119
|
methodDefinitions.push(getInterfaceMethodDefinition_(name, func));
|
|
115
|
-
exportedFunctions.push(func);
|
|
116
120
|
}
|
|
117
121
|
}
|
|
118
122
|
for (const varStmt of sourceFile.getVariableStatements()) {
|
|
@@ -124,7 +128,6 @@ const generateAppsScriptTypes = async ({
|
|
|
124
128
|
exportedDeclarations.push(varDecl);
|
|
125
129
|
exportedDeclarationNames.add(name);
|
|
126
130
|
methodDefinitions.push(getInterfaceMethodDefinition_(name, funcExpr));
|
|
127
|
-
exportedFunctions.push(funcExpr);
|
|
128
131
|
}
|
|
129
132
|
}
|
|
130
133
|
}
|
|
@@ -156,38 +159,18 @@ const generateAppsScriptTypes = async ({
|
|
|
156
159
|
}
|
|
157
160
|
}
|
|
158
161
|
};
|
|
159
|
-
const returnValueSymbols = /* @__PURE__ */ new Set();
|
|
160
|
-
for (const func of exportedFunctions) {
|
|
161
|
-
collectSymbolsFromType(func.getReturnType(), returnValueSymbols);
|
|
162
|
-
}
|
|
163
162
|
const symbolsToProcess = /* @__PURE__ */ new Set();
|
|
164
163
|
for (const decl of exportedDeclarations) {
|
|
165
164
|
if (decl.getKind() === tsMorph.SyntaxKind.FunctionDeclaration || decl.getKind() === tsMorph.SyntaxKind.VariableDeclaration && (decl.getInitializer()?.getKind() === tsMorph.SyntaxKind.ArrowFunction || decl.getInitializer()?.getKind() === tsMorph.SyntaxKind.FunctionExpression)) {
|
|
166
165
|
const func = decl.getKind() === tsMorph.SyntaxKind.FunctionDeclaration ? decl : decl.getInitializer();
|
|
167
166
|
const parameters = func.getParameters();
|
|
168
167
|
for (const param of parameters) {
|
|
169
|
-
|
|
170
|
-
for (const typeRef of typeRefs) {
|
|
171
|
-
const symbol = typeRef.getType().getAliasSymbol() ?? typeRef.getType().getSymbol();
|
|
172
|
-
if (symbol) symbolsToProcess.add(symbol);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
const returnTypeNode = func.getReturnTypeNode();
|
|
176
|
-
if (returnTypeNode) {
|
|
177
|
-
const typeRefs = returnTypeNode.getDescendantsOfKind(
|
|
178
|
-
tsMorph.SyntaxKind.TypeReference
|
|
179
|
-
);
|
|
180
|
-
for (const typeRef of typeRefs) {
|
|
181
|
-
const symbol = typeRef.getType().getAliasSymbol() ?? typeRef.getType().getSymbol();
|
|
182
|
-
if (symbol) symbolsToProcess.add(symbol);
|
|
183
|
-
}
|
|
168
|
+
collectSymbolsFromType(param.getType(), symbolsToProcess);
|
|
184
169
|
}
|
|
170
|
+
const returnType = func.getReturnType();
|
|
171
|
+
collectSymbolsFromType(returnType, symbolsToProcess);
|
|
185
172
|
} else if (decl.getKind() === tsMorph.SyntaxKind.InterfaceDeclaration || decl.getKind() === tsMorph.SyntaxKind.TypeAliasDeclaration) {
|
|
186
|
-
|
|
187
|
-
for (const typeRef of typeRefs) {
|
|
188
|
-
const symbol = typeRef.getType().getAliasSymbol() ?? typeRef.getType().getSymbol();
|
|
189
|
-
if (symbol) symbolsToProcess.add(symbol);
|
|
190
|
-
}
|
|
173
|
+
collectSymbolsFromType(decl.getType(), symbolsToProcess);
|
|
191
174
|
}
|
|
192
175
|
}
|
|
193
176
|
const importsMap = /* @__PURE__ */ new Map();
|
|
@@ -210,31 +193,14 @@ const generateAppsScriptTypes = async ({
|
|
|
210
193
|
continue;
|
|
211
194
|
}
|
|
212
195
|
const sourceFile = declaration.getSourceFile();
|
|
213
|
-
|
|
196
|
+
const sourceFilePath = sourceFile.getFilePath();
|
|
197
|
+
if (sourceFilePath.includes("node_modules")) {
|
|
214
198
|
continue;
|
|
215
199
|
}
|
|
216
200
|
processedSymbols.add(symbolName);
|
|
217
|
-
const
|
|
218
|
-
if (
|
|
219
|
-
|
|
220
|
-
const declText = declaration.getText();
|
|
221
|
-
inlineDefinitions.set(symbolName, declText);
|
|
222
|
-
const tempSourceFile = project.createSourceFile(
|
|
223
|
-
`__temp_${symbolName}.ts`,
|
|
224
|
-
declText
|
|
225
|
-
);
|
|
226
|
-
for (const descendant of tempSourceFile.getDescendantsOfKind(
|
|
227
|
-
tsMorph.SyntaxKind.TypeReference
|
|
228
|
-
)) {
|
|
229
|
-
const newSymbol = descendant.getType().getAliasSymbol() ?? descendant.getType().getSymbol();
|
|
230
|
-
if (newSymbol) {
|
|
231
|
-
symbolsToProcess.add(newSymbol);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
tempSourceFile.delete();
|
|
235
|
-
}
|
|
236
|
-
} else {
|
|
237
|
-
let modulePath = path__namespace.relative(absoluteOutDir, sourceFile.getFilePath()).replace(/\\/g, "/");
|
|
201
|
+
const isExternal = !sourceFilePath.replace(/\\/g, "/").startsWith(absoluteSrcDir.replace(/\\/g, "/")) && !sourceFilePath.replace(/\\/g, "/").startsWith(path__namespace.join(projectPath, srcDir).replace(/\\/g, "/"));
|
|
202
|
+
if (isExternal) {
|
|
203
|
+
let modulePath = path__namespace.relative(absoluteOutDir, sourceFilePath).replace(/\\/g, "/");
|
|
238
204
|
modulePath = modulePath.replace(/\.(d\.)?ts$/, "");
|
|
239
205
|
if (modulePath.endsWith("/index")) {
|
|
240
206
|
modulePath = modulePath.slice(0, -6);
|
|
@@ -249,6 +215,17 @@ const generateAppsScriptTypes = async ({
|
|
|
249
215
|
importsMap.set(modulePath, /* @__PURE__ */ new Set());
|
|
250
216
|
}
|
|
251
217
|
importsMap.get(modulePath)?.add(symbolName);
|
|
218
|
+
} else {
|
|
219
|
+
const declText = declaration.getText();
|
|
220
|
+
inlineDefinitions.set(symbolName, declText);
|
|
221
|
+
}
|
|
222
|
+
for (const descendant of declaration.getDescendantsOfKind(
|
|
223
|
+
tsMorph.SyntaxKind.TypeReference
|
|
224
|
+
)) {
|
|
225
|
+
const newSymbol = descendant.getType().getAliasSymbol() ?? descendant.getType().getSymbol();
|
|
226
|
+
if (newSymbol) {
|
|
227
|
+
symbolsToProcess.add(newSymbol);
|
|
228
|
+
}
|
|
252
229
|
}
|
|
253
230
|
}
|
|
254
231
|
if (!fs__namespace.existsSync(absoluteOutDir)) {
|
|
@@ -75,8 +75,13 @@ const generateAppsScriptTypes = async ({
|
|
|
75
75
|
const methodDefinitions = [];
|
|
76
76
|
const exportedDeclarations = [];
|
|
77
77
|
const exportedDeclarationNames = /* @__PURE__ */ new Set();
|
|
78
|
-
const exportedFunctions = [];
|
|
79
78
|
for (const sourceFile of sourceFiles) {
|
|
79
|
+
const filePath = sourceFile.getFilePath().replace(/\\/g, "/");
|
|
80
|
+
const srcPath = absoluteSrcDir.replace(/\\/g, "/");
|
|
81
|
+
const projectRelativeSrcPath = path.join(projectPath, srcDir).replace(/\\/g, "/");
|
|
82
|
+
if (!filePath.startsWith(srcPath) && !filePath.startsWith(projectRelativeSrcPath)) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
80
85
|
for (const iface of sourceFile.getInterfaces()) {
|
|
81
86
|
if (!iface.getName()?.endsWith("_")) {
|
|
82
87
|
exportedDeclarations.push(iface);
|
|
@@ -95,7 +100,6 @@ const generateAppsScriptTypes = async ({
|
|
|
95
100
|
exportedDeclarations.push(func);
|
|
96
101
|
exportedDeclarationNames.add(name);
|
|
97
102
|
methodDefinitions.push(getInterfaceMethodDefinition_(name, func));
|
|
98
|
-
exportedFunctions.push(func);
|
|
99
103
|
}
|
|
100
104
|
}
|
|
101
105
|
for (const varStmt of sourceFile.getVariableStatements()) {
|
|
@@ -107,7 +111,6 @@ const generateAppsScriptTypes = async ({
|
|
|
107
111
|
exportedDeclarations.push(varDecl);
|
|
108
112
|
exportedDeclarationNames.add(name);
|
|
109
113
|
methodDefinitions.push(getInterfaceMethodDefinition_(name, funcExpr));
|
|
110
|
-
exportedFunctions.push(funcExpr);
|
|
111
114
|
}
|
|
112
115
|
}
|
|
113
116
|
}
|
|
@@ -139,38 +142,18 @@ const generateAppsScriptTypes = async ({
|
|
|
139
142
|
}
|
|
140
143
|
}
|
|
141
144
|
};
|
|
142
|
-
const returnValueSymbols = /* @__PURE__ */ new Set();
|
|
143
|
-
for (const func of exportedFunctions) {
|
|
144
|
-
collectSymbolsFromType(func.getReturnType(), returnValueSymbols);
|
|
145
|
-
}
|
|
146
145
|
const symbolsToProcess = /* @__PURE__ */ new Set();
|
|
147
146
|
for (const decl of exportedDeclarations) {
|
|
148
147
|
if (decl.getKind() === SyntaxKind.FunctionDeclaration || decl.getKind() === SyntaxKind.VariableDeclaration && (decl.getInitializer()?.getKind() === SyntaxKind.ArrowFunction || decl.getInitializer()?.getKind() === SyntaxKind.FunctionExpression)) {
|
|
149
148
|
const func = decl.getKind() === SyntaxKind.FunctionDeclaration ? decl : decl.getInitializer();
|
|
150
149
|
const parameters = func.getParameters();
|
|
151
150
|
for (const param of parameters) {
|
|
152
|
-
|
|
153
|
-
for (const typeRef of typeRefs) {
|
|
154
|
-
const symbol = typeRef.getType().getAliasSymbol() ?? typeRef.getType().getSymbol();
|
|
155
|
-
if (symbol) symbolsToProcess.add(symbol);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
const returnTypeNode = func.getReturnTypeNode();
|
|
159
|
-
if (returnTypeNode) {
|
|
160
|
-
const typeRefs = returnTypeNode.getDescendantsOfKind(
|
|
161
|
-
SyntaxKind.TypeReference
|
|
162
|
-
);
|
|
163
|
-
for (const typeRef of typeRefs) {
|
|
164
|
-
const symbol = typeRef.getType().getAliasSymbol() ?? typeRef.getType().getSymbol();
|
|
165
|
-
if (symbol) symbolsToProcess.add(symbol);
|
|
166
|
-
}
|
|
151
|
+
collectSymbolsFromType(param.getType(), symbolsToProcess);
|
|
167
152
|
}
|
|
153
|
+
const returnType = func.getReturnType();
|
|
154
|
+
collectSymbolsFromType(returnType, symbolsToProcess);
|
|
168
155
|
} else if (decl.getKind() === SyntaxKind.InterfaceDeclaration || decl.getKind() === SyntaxKind.TypeAliasDeclaration) {
|
|
169
|
-
|
|
170
|
-
for (const typeRef of typeRefs) {
|
|
171
|
-
const symbol = typeRef.getType().getAliasSymbol() ?? typeRef.getType().getSymbol();
|
|
172
|
-
if (symbol) symbolsToProcess.add(symbol);
|
|
173
|
-
}
|
|
156
|
+
collectSymbolsFromType(decl.getType(), symbolsToProcess);
|
|
174
157
|
}
|
|
175
158
|
}
|
|
176
159
|
const importsMap = /* @__PURE__ */ new Map();
|
|
@@ -193,31 +176,14 @@ const generateAppsScriptTypes = async ({
|
|
|
193
176
|
continue;
|
|
194
177
|
}
|
|
195
178
|
const sourceFile = declaration.getSourceFile();
|
|
196
|
-
|
|
179
|
+
const sourceFilePath = sourceFile.getFilePath();
|
|
180
|
+
if (sourceFilePath.includes("node_modules")) {
|
|
197
181
|
continue;
|
|
198
182
|
}
|
|
199
183
|
processedSymbols.add(symbolName);
|
|
200
|
-
const
|
|
201
|
-
if (
|
|
202
|
-
|
|
203
|
-
const declText = declaration.getText();
|
|
204
|
-
inlineDefinitions.set(symbolName, declText);
|
|
205
|
-
const tempSourceFile = project.createSourceFile(
|
|
206
|
-
`__temp_${symbolName}.ts`,
|
|
207
|
-
declText
|
|
208
|
-
);
|
|
209
|
-
for (const descendant of tempSourceFile.getDescendantsOfKind(
|
|
210
|
-
SyntaxKind.TypeReference
|
|
211
|
-
)) {
|
|
212
|
-
const newSymbol = descendant.getType().getAliasSymbol() ?? descendant.getType().getSymbol();
|
|
213
|
-
if (newSymbol) {
|
|
214
|
-
symbolsToProcess.add(newSymbol);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
tempSourceFile.delete();
|
|
218
|
-
}
|
|
219
|
-
} else {
|
|
220
|
-
let modulePath = path.relative(absoluteOutDir, sourceFile.getFilePath()).replace(/\\/g, "/");
|
|
184
|
+
const isExternal = !sourceFilePath.replace(/\\/g, "/").startsWith(absoluteSrcDir.replace(/\\/g, "/")) && !sourceFilePath.replace(/\\/g, "/").startsWith(path.join(projectPath, srcDir).replace(/\\/g, "/"));
|
|
185
|
+
if (isExternal) {
|
|
186
|
+
let modulePath = path.relative(absoluteOutDir, sourceFilePath).replace(/\\/g, "/");
|
|
221
187
|
modulePath = modulePath.replace(/\.(d\.)?ts$/, "");
|
|
222
188
|
if (modulePath.endsWith("/index")) {
|
|
223
189
|
modulePath = modulePath.slice(0, -6);
|
|
@@ -232,6 +198,17 @@ const generateAppsScriptTypes = async ({
|
|
|
232
198
|
importsMap.set(modulePath, /* @__PURE__ */ new Set());
|
|
233
199
|
}
|
|
234
200
|
importsMap.get(modulePath)?.add(symbolName);
|
|
201
|
+
} else {
|
|
202
|
+
const declText = declaration.getText();
|
|
203
|
+
inlineDefinitions.set(symbolName, declText);
|
|
204
|
+
}
|
|
205
|
+
for (const descendant of declaration.getDescendantsOfKind(
|
|
206
|
+
SyntaxKind.TypeReference
|
|
207
|
+
)) {
|
|
208
|
+
const newSymbol = descendant.getType().getAliasSymbol() ?? descendant.getType().getSymbol();
|
|
209
|
+
if (newSymbol) {
|
|
210
|
+
symbolsToProcess.add(newSymbol);
|
|
211
|
+
}
|
|
235
212
|
}
|
|
236
213
|
}
|
|
237
214
|
if (!fs.existsSync(absoluteOutDir)) {
|
package/dist/vite.cjs
CHANGED
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.
|
|
3
|
+
import { l as loadConfig, g as generateAppsScriptTypes } from './shared/gasnuki.CS6ipBfD.mjs';
|
|
4
4
|
import 'node:fs';
|
|
5
5
|
import 'ts-morph';
|
|
6
6
|
import 'jiti';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ciderjs/gasnuki",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
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",
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"test:coverage:update": "pnpm test:coverage && pnpm update-coverage-badge",
|
|
37
37
|
"prepublish": "pnpm run generate && pnpm run check && pnpm run test:coverage:update && pnpm run build",
|
|
38
38
|
"pg:react": "pnpm -C playground/react",
|
|
39
|
+
"pg:react-vite": "pnpm -C playground/react-with-vite-plugin",
|
|
39
40
|
"pg:vue": "pnpm -C playground/vue3"
|
|
40
41
|
},
|
|
41
42
|
"keywords": [
|
|
@@ -62,7 +63,7 @@
|
|
|
62
63
|
},
|
|
63
64
|
"devDependencies": {
|
|
64
65
|
"@biomejs/biome": "^2.2.6",
|
|
65
|
-
"@types/node": "^24.
|
|
66
|
+
"@types/node": "^24.8.1",
|
|
66
67
|
"@vitest/coverage-v8": "3.2.4",
|
|
67
68
|
"typescript": "^5.9.3",
|
|
68
69
|
"unbuild": "^3.6.1",
|
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
# `@ciderjs/gasnuki` Viteプラグイン 設計書
|
|
2
|
-
|
|
3
|
-
## 1. はじめに
|
|
4
|
-
|
|
5
|
-
### 1.1. 目的
|
|
6
|
-
|
|
7
|
-
本ドキュメントは、先に作成された「`@ciderjs/gasnuki` Viteプラグイン機能追加 要件定義書」に基づき、Viteプラグイン機能の具体的なアーキテクチャ、実装詳細、データ構造などを定義することを目的とする。
|
|
8
|
-
|
|
9
|
-
### 1.2. 対象読者
|
|
10
|
-
|
|
11
|
-
`@ciderjs/gasnuki` の開発者およびコントリビューターを対象とする。
|
|
12
|
-
|
|
13
|
-
## 2. アーキテクチャ概要
|
|
14
|
-
|
|
15
|
-
`@ciderjs/gasnuki` のViteプラグインは、Viteの開発サーバーのライフサイクルにフックすることで動作する。既存の型生成コアロジック (`generateAppsScriptTypes`) を再利用し、Viteの開発環境とシームレスに連携する。
|
|
16
|
-
|
|
17
|
-
### 2.1. 構成図
|
|
18
|
-
|
|
19
|
-
```mermaid
|
|
20
|
-
graph TD
|
|
21
|
-
subgraph Vite開発環境
|
|
22
|
-
A[vite.config.ts] --> B(Vite Dev Server);
|
|
23
|
-
B -- 起動 --> C{gasnuki Plugin};
|
|
24
|
-
B -- ファイル変更通知 --> C;
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
subgraph gasnuki Plugin
|
|
28
|
-
C -- configResolvedフック --> D[設定解決ロジック];
|
|
29
|
-
C -- configureServerフック --> E[初回生成 & ウォッチャー設定];
|
|
30
|
-
E -- ファイル変更イベント --> F[型再生成トリガー];
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
subgraph gasnuki コアモジュール
|
|
34
|
-
G[./modules/config.ts];
|
|
35
|
-
H[./modules/generate.ts];
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
D -- 読み込み --> G;
|
|
39
|
-
E -- 実行 --> H;
|
|
40
|
-
F -- 実行 --> H;
|
|
41
|
-
|
|
42
|
-
style Vite開発環境 fill:#e6f2ff,stroke:#b3d9ff
|
|
43
|
-
style gasnukiコアモジュール fill:#fff2e6,stroke:#ffdab3
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
### 2.2. 処理フロー
|
|
47
|
-
|
|
48
|
-
1. **設定解決**: Vite開発サーバー起動時、`configResolved` フックが発火。Viteの設定情報 (`config.root`) を元にプロジェクトルートを特定し、プラグインオプション、`gasnuki.config.ts`、デフォルト値をマージして最終的な設定を確定する。
|
|
49
|
-
2. **初回生成**: `configureServer` フックで、開発サーバーの起動処理の一環として、型定義の初回生成 (`generateAppsScriptTypes`) を実行する。
|
|
50
|
-
3. **ファイル監視と再生成**: 同じく `configureServer` フック内で、Viteのファイルウォッチャー (`server.watcher`) を利用して、設定されたソースディレクトリ (`srcDir`) を監視する。ファイルの追加・変更・削除を検知すると、再度 `generateAppsScriptTypes` を実行して型定義を更新する。
|
|
51
|
-
|
|
52
|
-
## 3. ファイル構成
|
|
53
|
-
|
|
54
|
-
| ファイルパス | 状態 | 役割 |
|
|
55
|
-
| :------------------- | :--- | :-------------------------------------------------------------------------------------------------- |
|
|
56
|
-
| `src/vite.ts` | 新規 | Viteプラグインのロジックを実装する。プラグインのファクトリ関数 `gasnuki()` をエクスポートする。 |
|
|
57
|
-
| `package.json` | 変更 | `exports` フィールドに `./vite` エントリーポイントを追加し、Viteプラグインを外部から利用可能にする。 |
|
|
58
|
-
| `build.config.ts` | 変更 | `unbuild` のビルド対象に `src/vite.ts` を追加する。 |
|
|
59
|
-
| `src/modules/generate.ts` | 変更 | (必要であれば) Vite環境でのロギングやエラーハンドリングを改善するために軽微な修正を行う可能性がある。 |
|
|
60
|
-
| `src/modules/config.ts` | 変更なし | 既存のコンフィグローダーをそのまま利用する。 |
|
|
61
|
-
|
|
62
|
-
## 4. 詳細設計
|
|
63
|
-
|
|
64
|
-
### 4.1. Viteプラグインエントリーポイント (`src/vite.ts`)
|
|
65
|
-
|
|
66
|
-
プラグインは `gasnuki(options?: UserConfig): Plugin` というファクトリ関数として提供する。
|
|
67
|
-
|
|
68
|
-
```typescript:gasnuki Vite Plugin:src/vite.ts
|
|
69
|
-
import type { Plugin, ResolvedConfig, ViteDevServer } from 'vite';
|
|
70
|
-
import * as path from 'node:path';
|
|
71
|
-
import { consola } from 'consola';
|
|
72
|
-
import { generateAppsScriptTypes } from './modules/generate';
|
|
73
|
-
import { loadConfig, type UserConfig } from './modules/config';
|
|
74
|
-
import type { GenerateOptions } from './index';
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* A factory function to create the gasnuki Vite plugin.
|
|
78
|
-
* @param options - The user-defined configuration for gasnuki.
|
|
79
|
-
* @returns The Vite plugin object.
|
|
80
|
-
*/
|
|
81
|
-
export function gasnuki(options?: UserConfig): Plugin {
|
|
82
|
-
let projectRoot: string;
|
|
83
|
-
let gasnukiOptions: Omit<GenerateOptions, 'watch' | 'project'>;
|
|
84
|
-
|
|
85
|
-
// Debounce mechanism to prevent rapid-fire regeneration
|
|
86
|
-
let debounceTimer: NodeJS.Timeout | null = null;
|
|
87
|
-
const debounce = (func: () => void, timeout = 300) => {
|
|
88
|
-
if (debounceTimer) {
|
|
89
|
-
clearTimeout(debounceTimer);
|
|
90
|
-
}
|
|
91
|
-
debounceTimer = setTimeout(func, timeout);
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
const runGeneration = (triggeredBy?: string) => {
|
|
95
|
-
debounce(async () => {
|
|
96
|
-
const reason = triggeredBy ? ` (triggered by: ${triggeredBy})` : '';
|
|
97
|
-
consola.info(`[gasnuki] Generating AppsScript types${reason}...`);
|
|
98
|
-
try {
|
|
99
|
-
await generateAppsScriptTypes({
|
|
100
|
-
...gasnukiOptions,
|
|
101
|
-
project: projectRoot,
|
|
102
|
-
});
|
|
103
|
-
consola.success('[gasnuki] Type generation complete.');
|
|
104
|
-
} catch (e) {
|
|
105
|
-
consola.error(`[gasnuki] Type generation failed: ${(e as Error).message}`);
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
return {
|
|
111
|
-
name: 'vite-plugin-gasnuki',
|
|
112
|
-
apply: 'serve', // Apply only in serve mode
|
|
113
|
-
|
|
114
|
-
async configResolved(config: ResolvedConfig) {
|
|
115
|
-
projectRoot = config.root;
|
|
116
|
-
const fileConfig = await loadConfig(projectRoot);
|
|
117
|
-
const defaultOptions: Partial<GenerateOptions> = {
|
|
118
|
-
srcDir: 'server',
|
|
119
|
-
outDir: 'types',
|
|
120
|
-
outputFile: 'appsscript.ts',
|
|
121
|
-
};
|
|
122
|
-
gasnukiOptions = {
|
|
123
|
-
...defaultOptions,
|
|
124
|
-
...fileConfig,
|
|
125
|
-
...(options || {}),
|
|
126
|
-
};
|
|
127
|
-
},
|
|
128
|
-
|
|
129
|
-
async configureServer(server: ViteDevServer) {
|
|
130
|
-
const targetDir = path.resolve(projectRoot, gasnukiOptions.srcDir);
|
|
131
|
-
|
|
132
|
-
// Initial generation on server startup
|
|
133
|
-
runGeneration('server startup');
|
|
134
|
-
|
|
135
|
-
// Watch for file changes
|
|
136
|
-
server.watcher.on('all', (event, filePath) => {
|
|
137
|
-
// Normalize paths for reliable comparison
|
|
138
|
-
const normalizedFilePath = path.normalize(filePath);
|
|
139
|
-
const normalizedTargetDir = path.normalize(targetDir);
|
|
140
|
-
|
|
141
|
-
if (normalizedFilePath.startsWith(normalizedTargetDir)) {
|
|
142
|
-
runGeneration(path.relative(projectRoot, filePath));
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
},
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
### 4.2. 設定解決ロジック (`configResolved` フック内)
|
|
151
|
-
|
|
152
|
-
1. `config.root` からプロジェクトのルートパスを取得する。
|
|
153
|
-
2. 既存の `loadConfig(projectRoot)` を呼び出し、`gasnuki.config.ts` の内容を読み込む。
|
|
154
|
-
3. 以下の優先順位で設定をマージし、`gasnukiOptions` として内部に保持する。
|
|
155
|
-
1. **高**: `vite.config.ts` でプラグインに渡された `options`
|
|
156
|
-
2. **中**: `gasnuki.config.ts` の内容
|
|
157
|
-
3. **低**: プラグイン内部で定義されたデフォルト値 (`srcDir`, `outDir`, `outputFile`)
|
|
158
|
-
|
|
159
|
-
### 4.3. ファイル監視ロジック (`configureServer` フック内)
|
|
160
|
-
|
|
161
|
-
- Viteの `server.watcher` を利用することで、`chokidar` を直接依存関係に追加する必要はない。
|
|
162
|
-
- `on('all', callback)` を使用し、ファイルの追加(`add`)、変更(`change`)、削除(`unlink`) すべてのイベントを捕捉する。
|
|
163
|
-
- イベントのコールバック内で、変更されたファイルパスが `gasnukiOptions.srcDir` 内に存在するかをチェックし、関係のないファイルの変更で再生成が走らないようにする。
|
|
164
|
-
- 頻繁なファイル変更による過剰な再生成を防ぐため、300ms程度のデバウンス処理を実装する。
|
|
165
|
-
|
|
166
|
-
## 5. データ構造・インターフェース
|
|
167
|
-
|
|
168
|
-
### 5.1. `UserConfig` (既存)
|
|
169
|
-
|
|
170
|
-
既存の `UserConfig` 型をそのままプラグインオプションの型として利用する。
|
|
171
|
-
|
|
172
|
-
```typescript
|
|
173
|
-
// src/modules/config.ts (既存)
|
|
174
|
-
export type UserConfig = Partial<Omit<GenerateOptions, 'watch' | 'project'>>;
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
## 6. シーケンス図
|
|
178
|
-
|
|
179
|
-
### 6.1. 開発サーバー起動時
|
|
180
|
-
|
|
181
|
-
```mermaid
|
|
182
|
-
sequenceDiagram
|
|
183
|
-
participant User
|
|
184
|
-
participant Vite
|
|
185
|
-
participant gasnukiPlugin as gasnuki Plugin
|
|
186
|
-
participant Core as gasnuki Core
|
|
187
|
-
|
|
188
|
-
User->>Vite: `vite dev` を実行
|
|
189
|
-
Vite->>gasnukiPlugin: configResolved フックを呼び出し
|
|
190
|
-
gasnukiPlugin->>Core: loadConfig()
|
|
191
|
-
Core-->>gasnukiPlugin: 設定ファイルを返す
|
|
192
|
-
gasnukiPlugin->>gasnukiPlugin: 設定をマージ
|
|
193
|
-
Vite->>gasnukiPlugin: configureServer フックを呼び出し
|
|
194
|
-
gasnukiPlugin->>gasnukiPlugin: runGeneration('server startup')
|
|
195
|
-
gasnukiPlugin->>Core: generateAppsScriptTypes()
|
|
196
|
-
Core-->>gasnukiPlugin: 生成完了
|
|
197
|
-
Note right of gasnukiPlugin: ファイルウォッチャーを設定
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
### 6.2. ファイル変更時
|
|
201
|
-
|
|
202
|
-
```mermaid
|
|
203
|
-
sequenceDiagram
|
|
204
|
-
participant User
|
|
205
|
-
participant ViteWatcher
|
|
206
|
-
participant gasnukiPlugin as gasnuki Plugin
|
|
207
|
-
participant Core as gasnuki Core
|
|
208
|
-
|
|
209
|
-
User->>ViteWatcher: ソースファイルを変更・保存
|
|
210
|
-
ViteWatcher->>gasnukiPlugin: 'all' イベントを発火
|
|
211
|
-
gasnukiPlugin->>gasnukiPlugin: runGeneration('path/to/file.ts')
|
|
212
|
-
Note right of gasnukiPlugin: (デバウンス処理)
|
|
213
|
-
gasnukiPlugin->>Core: generateAppsScriptTypes()
|
|
214
|
-
Core-->>gasnukiPlugin: 再生成完了
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
## 7. その他考慮事項
|
|
218
|
-
|
|
219
|
-
- **エラー表示**: `generateAppsScriptTypes` が例外をスローした場合、`consola.error` を使用してViteのコンソールにスタックトレースを含む詳細なエラー情報を出力する。これにより、開発者はエラーの原因を特定しやすくなる。
|
|
220
|
-
- **テスト**: Viteプラグインの動作を検証するための単体テスト・結合テストを追加する。`vite` を `devDependencies` に追加し、テスト環境内でViteサーバーをプログラム的に起動してプラグインの各フックが正しく動作するかを確認する。
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
# `@ciderjs/gasnuki` Viteプラグイン機能追加 要件定義書
|
|
2
|
-
|
|
3
|
-
## 1. 概要
|
|
4
|
-
|
|
5
|
-
本ドキュメントは、npmパッケージ `@ciderjs/gasnuki` にViteプラグイン機能を追加するための要件を定義するものである。
|
|
6
|
-
|
|
7
|
-
## 2. 背景・目的
|
|
8
|
-
|
|
9
|
-
`@ciderjs/gasnuki` は、Google Apps Script (GAS) のサーバーサイドコードからTypeScriptの型定義を生成するCLIツールである。現状では、開発者はCLIを単独で、または `--watch` モードで実行する必要がある。
|
|
10
|
-
|
|
11
|
-
Viteを利用したフロントエンド開発プロジェクトにおいて、`vite dev` コマンドによる開発サーバーのライフサイクルと `gasnuki` の型生成プロセスを連携させることで、以下の目的を達成する。
|
|
12
|
-
|
|
13
|
-
- **開発体験の向上**: 開発者は `vite dev` を実行するだけで、GASコードの変更が自動的にクライアントサイドの型定義に反映されるようになり、手動でのコマンド実行や別プロセスの管理が不要になる。
|
|
14
|
-
- **設定の統合**: `gasnuki` に関する設定を `vite.config.ts` 内に集約し、プロジェクト設定の一元管理を促進する。
|
|
15
|
-
- **シームレスな統合**: Viteの開発エコシステムに `gasnuki` をスムーズに統合し、導入のハードルを下げる。
|
|
16
|
-
|
|
17
|
-
## 3. スコープ
|
|
18
|
-
|
|
19
|
-
### 3.1. スコープ内
|
|
20
|
-
|
|
21
|
-
- Viteの開発サーバー (`vite dev` / `serve`) 実行時に動作するViteプラグインの開発。
|
|
22
|
-
- プラグイン経由での `gasnuki` の設定。
|
|
23
|
-
- 開発サーバー起動時の初回型定義生成。
|
|
24
|
-
- ソースファイルの変更を監視し、型定義を自動で再生成する機能。
|
|
25
|
-
|
|
26
|
-
### 3.2. スコープ外
|
|
27
|
-
|
|
28
|
-
- Viteのビルドプロセス (`vite build`) へのフック。`gasnuki` は開発時の型安全性を目的とするため、本番ビルドには関与しない。
|
|
29
|
-
- CLI機能の変更・廃止。既存のCLI機能はそのまま維持する。
|
|
30
|
-
|
|
31
|
-
## 4. 機能要件
|
|
32
|
-
|
|
33
|
-
| ID | 機能名 | 種別 | 概要 |
|
|
34
|
-
| :--- | :----------------------------- | :--- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
35
|
-
| F-01 | **プラグインインターフェース** | 新規 | `import { gasnuki } from '@ciderjs/gasnuki/vite'` のようにインポートできるエントリーポイントを提供する。<br>プラグインは `gasnuki(options?: UserConfig)` という形式のファクトリ関数として提供する。 |
|
|
36
|
-
| F-02 | **設定の解決** | 変更 | プラグインに `options` が渡された場合はその設定を優先する。<br>`options` がない場合は、プロジェクトルートの `gasnuki.config.ts` 等を自動で読み込む。<br>プロジェクトルートの特定にはViteのコンフィグを利用する。 |
|
|
37
|
-
| F-03 | **初回型定義生成** | 新規 | `vite dev` コマンドで開発サーバーが起動する際に、型定義の生成処理を一度実行する。 |
|
|
38
|
-
| F-04 | **ファイル変更時の自動再生成** | 新規 | 開発サーバーの起動中、設定された `srcDir` 内の `.ts` ファイルの変更(追加・更新・削除)を監視し、変更があった場合に型定義の再生成を自動で実行する。 |
|
|
39
|
-
| F-05 | **既存機能との連携** | 変更 | 型定義の生成ロジック (`generateAppsScriptTypes`) や設定ファイルの読み込みロジック (`loadConfig`) など、既存のコア機能を再利用して実装する。 |
|
|
40
|
-
|
|
41
|
-
## 5. 非機能要件
|
|
42
|
-
|
|
43
|
-
| ID | 要件項目 | 概要 |
|
|
44
|
-
| :---- | :----------------- | :----------------------------------------------------------------------------------------------------- |
|
|
45
|
-
| NF-01 | **パフォーマンス** | ファイル変更時の再生成処理が、開発サーバーの応答性やパフォーマンスに大きな影響を与えないこと。 |
|
|
46
|
-
| NF-02 | **ユーザビリティ** | `vite.config.ts` に数行追加するだけで導入できる、シンプルで分かりやすいAPIを提供すること。 |
|
|
47
|
-
| NF-03 | **フィードバック** | 型定義の生成・再生成の開始、成功、エラー発生時には、Viteのコンソールに適切なメッセージを出力すること。 |
|
|
48
|
-
| NF-04 | **互換性** | 既存のCLI機能とViteプラグイン機能が共存でき、互いに影響を与えないこと。 |
|
|
49
|
-
|
|
50
|
-
## 6. 実装方針
|
|
51
|
-
|
|
52
|
-
### 6.1. パッケージ構成
|
|
53
|
-
|
|
54
|
-
- プラグインのロジックを実装するファイル (例: `src/vite.ts`) を新設する。
|
|
55
|
-
- `package.json` の `exports` フィールドに、Viteプラグイン用のエントリーポイント (例: `./vite`) を追加する。
|
|
56
|
-
- ビルド設定 (`build.config.ts`) を更新し、Viteプラグイン用のファイルを成果物として出力する。
|
|
57
|
-
|
|
58
|
-
### 6.2. Viteプラグインフックの利用
|
|
59
|
-
|
|
60
|
-
- **`name`**: プラグインを識別するための一意な名前 (例: `vite-plugin-gasnuki`) を設定する。
|
|
61
|
-
- **`apply: 'serve'`**: 開発サーバーでのみプラグインが動作するように制限する。
|
|
62
|
-
- **`configResolved(config)`**: Viteの設定が解決された後に呼び出されるフック。`config.root` を基準にプロジェクトルートを特定し、`gasnuki` の最終的な設定オブジェクトをここで確定させる。
|
|
63
|
-
- **`configureServer(server)`**: 開発サーバーが構成された際に呼び出されるフック。
|
|
64
|
-
- サーバー起動処理の一環として、初回の型生成処理を非同期で実行する。
|
|
65
|
-
- `server.watcher` (Viteが内部で使用する `chokidar` インスタンス) を利用して、対象ソースファイルの変更イベントを購読する。
|
|
66
|
-
- ファイル変更イベント発生時に、型定義の再生成処理を呼び出す。
|
|
67
|
-
|
|
68
|
-
## 7. ドキュメント
|
|
69
|
-
|
|
70
|
-
- `README.md` および `README.ja.md` を更新し、「Viteプラグインとしての利用」のセクションを追加する。
|
|
71
|
-
- `vite.config.ts` への基本的な設定例を記載する。
|
|
72
|
-
- プラグインに渡せるオプションについて説明する。
|