@ciderjs/gasnuki 0.1.4 → 0.2.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/bin/typedef/clientside.d.ts +1 -0
- package/dist/cli.cjs +40 -5
- package/dist/cli.mjs +26 -5
- package/dist/index.cjs +9 -220
- package/dist/index.d.cts +14 -2
- package/dist/index.d.mts +14 -2
- package/dist/index.d.ts +14 -2
- package/dist/index.mjs +7 -207
- package/dist/promise.cjs +18 -0
- package/dist/promise.d.cts +6 -0
- package/dist/promise.d.mts +6 -0
- package/dist/promise.d.ts +6 -0
- package/dist/promise.mjs +16 -0
- package/dist/shared/gasnuki.C-MvXA42.mjs +244 -0
- package/dist/shared/gasnuki.Yj84yCWz.cjs +264 -0
- package/package.json +10 -5
|
@@ -5,6 +5,7 @@ type RemoveReturnType<T> = {
|
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
type _AppsScriptRun = RemoveReturnType<ServerScripts> & {
|
|
8
|
+
[key: string]: (...args: any[]) => any;
|
|
8
9
|
withSuccessHandler: <T = string | number | boolean | undefined, U = any>(
|
|
9
10
|
callback: (returnValues: T, userObject?: U) => void,
|
|
10
11
|
) => _AppsScriptRun;
|
package/dist/cli.cjs
CHANGED
|
@@ -1,19 +1,54 @@
|
|
|
1
1
|
#! /usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
+
const path = require('node:path');
|
|
4
5
|
const commander = require('commander');
|
|
5
|
-
const index = require('./
|
|
6
|
-
require('node:path');
|
|
6
|
+
const index = require('./shared/gasnuki.Yj84yCWz.cjs');
|
|
7
7
|
require('chokidar');
|
|
8
8
|
require('consola');
|
|
9
9
|
require('node:fs');
|
|
10
10
|
require('ts-morph');
|
|
11
|
+
require('jiti');
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
function _interopNamespaceCompat(e) {
|
|
14
|
+
if (e && typeof e === 'object' && 'default' in e) return e;
|
|
15
|
+
const n = Object.create(null);
|
|
16
|
+
if (e) {
|
|
17
|
+
for (const k in e) {
|
|
18
|
+
n[k] = e[k];
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
n.default = e;
|
|
22
|
+
return n;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const path__namespace = /*#__PURE__*/_interopNamespaceCompat(path);
|
|
26
|
+
|
|
27
|
+
const version = "0.2.0";
|
|
13
28
|
|
|
14
29
|
const parseArgs = async (command) => {
|
|
15
|
-
const
|
|
16
|
-
await index.
|
|
30
|
+
const cliOpts = command.opts();
|
|
31
|
+
const fileConfig = await index.loadConfig(path__namespace.resolve(cliOpts.project));
|
|
32
|
+
const defaultOpts = {};
|
|
33
|
+
for (const option of command.options) {
|
|
34
|
+
const key = option.attributeName();
|
|
35
|
+
defaultOpts[key] = option.defaultValue;
|
|
36
|
+
}
|
|
37
|
+
const explicitCliOpts = {};
|
|
38
|
+
for (const option of command.options) {
|
|
39
|
+
const key = option.attributeName();
|
|
40
|
+
if (command.getOptionValueSource(key) === "cli") {
|
|
41
|
+
explicitCliOpts[key] = cliOpts[key];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const finalOptions = {
|
|
45
|
+
...defaultOpts,
|
|
46
|
+
...fileConfig,
|
|
47
|
+
...explicitCliOpts,
|
|
48
|
+
project: cliOpts.project,
|
|
49
|
+
watch: cliOpts.watch
|
|
50
|
+
};
|
|
51
|
+
await index.generateTypes(finalOptions);
|
|
17
52
|
};
|
|
18
53
|
const cli = async () => {
|
|
19
54
|
const program = new commander.Command();
|
package/dist/cli.mjs
CHANGED
|
@@ -1,17 +1,38 @@
|
|
|
1
1
|
#! /usr/bin/env node
|
|
2
|
+
import * as path from 'node:path';
|
|
2
3
|
import { Command } from 'commander';
|
|
3
|
-
import { generateTypes } from './
|
|
4
|
-
import 'node:path';
|
|
4
|
+
import { l as loadConfig, g as generateTypes } from './shared/gasnuki.C-MvXA42.mjs';
|
|
5
5
|
import 'chokidar';
|
|
6
6
|
import 'consola';
|
|
7
7
|
import 'node:fs';
|
|
8
8
|
import 'ts-morph';
|
|
9
|
+
import 'jiti';
|
|
9
10
|
|
|
10
|
-
const version = "0.
|
|
11
|
+
const version = "0.2.0";
|
|
11
12
|
|
|
12
13
|
const parseArgs = async (command) => {
|
|
13
|
-
const
|
|
14
|
-
await
|
|
14
|
+
const cliOpts = command.opts();
|
|
15
|
+
const fileConfig = await loadConfig(path.resolve(cliOpts.project));
|
|
16
|
+
const defaultOpts = {};
|
|
17
|
+
for (const option of command.options) {
|
|
18
|
+
const key = option.attributeName();
|
|
19
|
+
defaultOpts[key] = option.defaultValue;
|
|
20
|
+
}
|
|
21
|
+
const explicitCliOpts = {};
|
|
22
|
+
for (const option of command.options) {
|
|
23
|
+
const key = option.attributeName();
|
|
24
|
+
if (command.getOptionValueSource(key) === "cli") {
|
|
25
|
+
explicitCliOpts[key] = cliOpts[key];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const finalOptions = {
|
|
29
|
+
...defaultOpts,
|
|
30
|
+
...fileConfig,
|
|
31
|
+
...explicitCliOpts,
|
|
32
|
+
project: cliOpts.project,
|
|
33
|
+
watch: cliOpts.watch
|
|
34
|
+
};
|
|
35
|
+
await generateTypes(finalOptions);
|
|
15
36
|
};
|
|
16
37
|
const cli = async () => {
|
|
17
38
|
const program = new Command();
|
package/dist/index.cjs
CHANGED
|
@@ -1,225 +1,14 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
3
|
+
require('node:path');
|
|
4
|
+
require('chokidar');
|
|
5
|
+
require('consola');
|
|
6
|
+
const index = require('./shared/gasnuki.Yj84yCWz.cjs');
|
|
7
|
+
require('node:fs');
|
|
8
|
+
require('ts-morph');
|
|
9
|
+
require('jiti');
|
|
8
10
|
|
|
9
|
-
function _interopNamespaceCompat(e) {
|
|
10
|
-
if (e && typeof e === 'object' && 'default' in e) return e;
|
|
11
|
-
const n = Object.create(null);
|
|
12
|
-
if (e) {
|
|
13
|
-
for (const k in e) {
|
|
14
|
-
n[k] = e[k];
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
n.default = e;
|
|
18
|
-
return n;
|
|
19
|
-
}
|
|
20
11
|
|
|
21
|
-
const path__namespace = /*#__PURE__*/_interopNamespaceCompat(path);
|
|
22
|
-
const chokidar__namespace = /*#__PURE__*/_interopNamespaceCompat(chokidar);
|
|
23
|
-
const fs__namespace = /*#__PURE__*/_interopNamespaceCompat(fs);
|
|
24
12
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const getInterfaceMethodDefinition_ = (name, node) => {
|
|
28
|
-
const typeParameters = node.getTypeParameters?.() ?? [];
|
|
29
|
-
const typeParamsString = typeParameters.length > 0 ? `<${typeParameters.map((tp) => tp.getText()).join(", ")}>` : "";
|
|
30
|
-
const parameters = node.getParameters().map((param) => {
|
|
31
|
-
const paramName = param.getName();
|
|
32
|
-
const type = param.getTypeNode()?.getText() ?? param.getType().getText(node) ?? "any";
|
|
33
|
-
const questionToken = param.hasQuestionToken() ? "?" : "";
|
|
34
|
-
return `${paramName}${questionToken}: ${type}`;
|
|
35
|
-
}).join(", ");
|
|
36
|
-
const returnTypeNode = node.getReturnTypeNode();
|
|
37
|
-
let returnType;
|
|
38
|
-
if (returnTypeNode != null) {
|
|
39
|
-
returnType = returnTypeNode.getText();
|
|
40
|
-
} else {
|
|
41
|
-
const inferredReturnType = node.getReturnType();
|
|
42
|
-
if (inferredReturnType.isVoid()) {
|
|
43
|
-
returnType = "void";
|
|
44
|
-
} else {
|
|
45
|
-
returnType = inferredReturnType.getText(node);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
let jsDocString = "";
|
|
49
|
-
const jsDocOwner = "getJsDocs" in node ? node : "getParantOrThrow" in node && // @ts-expect-error variable declaration
|
|
50
|
-
node.getParentOrThrow().getKind() === tsMorph.SyntaxKind.VariableDeclaration ? (
|
|
51
|
-
// @ts-expect-error variable declaration
|
|
52
|
-
node.getParentOrThrow()
|
|
53
|
-
) : null;
|
|
54
|
-
if (jsDocOwner != null) {
|
|
55
|
-
const jsDocs = "getJsDocs" in jsDocOwner ? jsDocOwner.getJsDocs() : null;
|
|
56
|
-
if (jsDocs != null && jsDocs.length > 0) {
|
|
57
|
-
const rawConmmentText = jsDocs.map((doc) => doc.getFullText()).join("\n");
|
|
58
|
-
if (rawConmmentText.includes("@deprecated")) {
|
|
59
|
-
const deprecatedDoc = jsDocs.find(
|
|
60
|
-
(doc) => doc.getFullText().includes("@deprecated")
|
|
61
|
-
);
|
|
62
|
-
jsDocString = `${deprecatedDoc != null ? deprecatedDoc.getFullText().trim() : "/**\n * @deprecated\n */"}
|
|
63
|
-
`;
|
|
64
|
-
} else {
|
|
65
|
-
const firstDoc = jsDocs[0];
|
|
66
|
-
const description = firstDoc.getDescription().trim();
|
|
67
|
-
if (description != null || firstDoc.getTags().length > 0) {
|
|
68
|
-
jsDocString = `${firstDoc.getFullText().trim()}
|
|
69
|
-
`;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
return `${jsDocString}${name}${typeParamsString}(${parameters}): ${returnType};`;
|
|
75
|
-
};
|
|
76
|
-
const generateAppsScriptTypes = async ({
|
|
77
|
-
project: projectPath,
|
|
78
|
-
srcDir,
|
|
79
|
-
outDir,
|
|
80
|
-
outputFile
|
|
81
|
-
}) => {
|
|
82
|
-
const absoluteSrcDir = path__namespace.resolve(projectPath, srcDir);
|
|
83
|
-
const absoluteOutDir = path__namespace.resolve(projectPath, outDir);
|
|
84
|
-
const absoluteOutputFile = path__namespace.resolve(absoluteOutDir, outputFile);
|
|
85
|
-
consola.consola.info("Starting AppsScript type generation with gasnuki...");
|
|
86
|
-
consola.consola.info(` AppsScript Source Directory: ${absoluteSrcDir}`);
|
|
87
|
-
consola.consola.info(` Output File: ${absoluteOutputFile}`);
|
|
88
|
-
const project = new tsMorph.Project({
|
|
89
|
-
tsConfigFilePath: path__namespace.resolve(projectPath, "tsconfig.json"),
|
|
90
|
-
skipAddingFilesFromTsConfig: true
|
|
91
|
-
});
|
|
92
|
-
project.addSourceFilesAtPaths(
|
|
93
|
-
path__namespace.join(absoluteSrcDir, "**/*.ts").replace(/\\/g, "/")
|
|
94
|
-
);
|
|
95
|
-
const methodDefinitions = [];
|
|
96
|
-
const globalTypeDefinitions = [];
|
|
97
|
-
const sourceFiles = project.getSourceFiles();
|
|
98
|
-
consola.consola.info(`Found ${sourceFiles.length} source file(s).`);
|
|
99
|
-
for (const sourceFile of sourceFiles) {
|
|
100
|
-
for (const iface of sourceFile.getInterfaces()) {
|
|
101
|
-
globalTypeDefinitions.push(iface.getText());
|
|
102
|
-
}
|
|
103
|
-
for (const typeAlias of sourceFile.getTypeAliases()) {
|
|
104
|
-
globalTypeDefinitions.push(typeAlias.getText());
|
|
105
|
-
}
|
|
106
|
-
for (const statement of sourceFile.getStatements()) {
|
|
107
|
-
if (statement.getKind() === tsMorph.SyntaxKind.ModuleDeclaration) {
|
|
108
|
-
globalTypeDefinitions.push(statement.getText());
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
for (const funcDecl of sourceFile.getFunctions()) {
|
|
112
|
-
if (!funcDecl.isAmbient()) {
|
|
113
|
-
const name = funcDecl.getName();
|
|
114
|
-
if (name != null && !name.endsWith("_")) {
|
|
115
|
-
methodDefinitions.push(getInterfaceMethodDefinition_(name, funcDecl));
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
for (const varStmt of sourceFile.getVariableStatements()) {
|
|
120
|
-
if (!varStmt.isAmbient()) {
|
|
121
|
-
for (const varDecl of varStmt.getDeclarations()) {
|
|
122
|
-
const initializer = varDecl.getInitializer();
|
|
123
|
-
const varName = varDecl.getName();
|
|
124
|
-
if (initializer != null && (initializer.getKind() === tsMorph.SyntaxKind.ArrowFunction || initializer.getKind() === tsMorph.SyntaxKind.FunctionExpression) && !varName.endsWith("_")) {
|
|
125
|
-
methodDefinitions.push(
|
|
126
|
-
getInterfaceMethodDefinition_(
|
|
127
|
-
varName,
|
|
128
|
-
initializer
|
|
129
|
-
)
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
if (!fs__namespace.existsSync(absoluteOutDir)) {
|
|
137
|
-
fs__namespace.mkdirSync(absoluteOutDir, { recursive: true });
|
|
138
|
-
consola.consola.info(`Created output directory: ${absoluteOutDir}`);
|
|
139
|
-
}
|
|
140
|
-
const generatorName = "gasnuki";
|
|
141
|
-
let outputContent = `// Auto-generated by ${generatorName}
|
|
142
|
-
// Do NOT edit this file manually.
|
|
143
|
-
`;
|
|
144
|
-
if (globalTypeDefinitions.length > 0) {
|
|
145
|
-
outputContent += `${globalTypeDefinitions.join("\n\n")}
|
|
146
|
-
|
|
147
|
-
`;
|
|
148
|
-
}
|
|
149
|
-
if (methodDefinitions.length > 0) {
|
|
150
|
-
const formattedMethods = methodDefinitions.map(
|
|
151
|
-
(method) => method.split("\n").map((line) => ` ${line}`).join("\n")
|
|
152
|
-
).join("\n\n");
|
|
153
|
-
outputContent += `export type ServerScripts = {
|
|
154
|
-
${formattedMethods}
|
|
155
|
-
}
|
|
156
|
-
`;
|
|
157
|
-
consola.consola.info(
|
|
158
|
-
`Interface 'ServerScript' type definitions written to ${absoluteOutputFile} (${methodDefinitions.length} function(s), ${globalTypeDefinitions.length} type(s)).`
|
|
159
|
-
);
|
|
160
|
-
} else {
|
|
161
|
-
outputContent = "export type ServerScripts = {}\n";
|
|
162
|
-
consola.consola.info(
|
|
163
|
-
`Interface 'ServerScript' type definitions written to ${absoluteOutputFile} (no functions found).`
|
|
164
|
-
);
|
|
165
|
-
}
|
|
166
|
-
outputContent += `
|
|
167
|
-
// Auto-generated Types for GoogleAppsScript in client-side code
|
|
168
|
-
|
|
169
|
-
${text}`;
|
|
170
|
-
fs__namespace.writeFileSync(absoluteOutputFile, outputContent);
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
const generateTypes = async ({
|
|
174
|
-
project,
|
|
175
|
-
srcDir,
|
|
176
|
-
outDir,
|
|
177
|
-
outputFile,
|
|
178
|
-
watch
|
|
179
|
-
}) => {
|
|
180
|
-
const runGeneration = async (triggeredBy) => {
|
|
181
|
-
const reason = triggeredBy ? ` (${triggeredBy})` : "";
|
|
182
|
-
consola.consola.info(`Generating AppsScript types${reason}...`);
|
|
183
|
-
try {
|
|
184
|
-
await generateAppsScriptTypes({ project, srcDir, outDir, outputFile });
|
|
185
|
-
consola.consola.info("Type generation complete.");
|
|
186
|
-
} catch (e) {
|
|
187
|
-
consola.consola.error(`Type generation failed: ${e.message}`, e);
|
|
188
|
-
}
|
|
189
|
-
};
|
|
190
|
-
await runGeneration();
|
|
191
|
-
if (watch) {
|
|
192
|
-
const sourcePathToWatch = path__namespace.resolve(project, srcDir).replace(/\\/g, "/");
|
|
193
|
-
consola.consola.info(
|
|
194
|
-
`Watching for changes in ${sourcePathToWatch}... (Press Ctrl+C to stop)`
|
|
195
|
-
);
|
|
196
|
-
const watcher = chokidar__namespace.watch(sourcePathToWatch, {
|
|
197
|
-
ignored: ["node_modules", "dist"],
|
|
198
|
-
persistent: true,
|
|
199
|
-
ignoreInitial: true
|
|
200
|
-
});
|
|
201
|
-
const eventHandler = async (filePath, eventName) => {
|
|
202
|
-
consola.consola.info(`Watcher is called triggered on ${eventName}`);
|
|
203
|
-
const relativePath = path__namespace.relative(project, filePath);
|
|
204
|
-
await runGeneration(relativePath);
|
|
205
|
-
};
|
|
206
|
-
watcher.on("ready", async () => {
|
|
207
|
-
console.log("...waiting...");
|
|
208
|
-
watcher.on("all", async (event, path2) => {
|
|
209
|
-
consola.consola.info(`Watcher is called triggered on ${event}: ${path2}`);
|
|
210
|
-
await eventHandler(path2, event);
|
|
211
|
-
});
|
|
212
|
-
});
|
|
213
|
-
for (const signal of ["SIGINT", "SIGTERM"]) {
|
|
214
|
-
process.on(signal, async () => {
|
|
215
|
-
await watcher.close();
|
|
216
|
-
consola.consola.info("Watcher is closed.");
|
|
217
|
-
process.exit(0);
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
} else {
|
|
221
|
-
process.exit(0);
|
|
222
|
-
}
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
exports.generateTypes = generateTypes;
|
|
13
|
+
exports.defineConfig = index.defineConfig;
|
|
14
|
+
exports.generateTypes = index.generateTypes;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User-defined configuration for gasnuki.
|
|
3
|
+
* `project` and `watch` options are excluded as they are runtime flags.
|
|
4
|
+
*/
|
|
5
|
+
type UserConfig = Partial<Omit<GenerateOptions, 'watch' | 'project'>>;
|
|
6
|
+
/**
|
|
7
|
+
* A helper function to define the gasnuki configuration with type safety.
|
|
8
|
+
* @param config The configuration object.
|
|
9
|
+
* @returns The configuration object.
|
|
10
|
+
*/
|
|
11
|
+
declare function defineConfig(config: UserConfig): UserConfig;
|
|
12
|
+
|
|
1
13
|
interface GenerateOptions {
|
|
2
14
|
project: string;
|
|
3
15
|
srcDir: string;
|
|
@@ -7,5 +19,5 @@ interface GenerateOptions {
|
|
|
7
19
|
}
|
|
8
20
|
declare const generateTypes: ({ project, srcDir, outDir, outputFile, watch, }: GenerateOptions) => Promise<void>;
|
|
9
21
|
|
|
10
|
-
export { generateTypes };
|
|
11
|
-
export type { GenerateOptions };
|
|
22
|
+
export { defineConfig, generateTypes };
|
|
23
|
+
export type { GenerateOptions, UserConfig };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User-defined configuration for gasnuki.
|
|
3
|
+
* `project` and `watch` options are excluded as they are runtime flags.
|
|
4
|
+
*/
|
|
5
|
+
type UserConfig = Partial<Omit<GenerateOptions, 'watch' | 'project'>>;
|
|
6
|
+
/**
|
|
7
|
+
* A helper function to define the gasnuki configuration with type safety.
|
|
8
|
+
* @param config The configuration object.
|
|
9
|
+
* @returns The configuration object.
|
|
10
|
+
*/
|
|
11
|
+
declare function defineConfig(config: UserConfig): UserConfig;
|
|
12
|
+
|
|
1
13
|
interface GenerateOptions {
|
|
2
14
|
project: string;
|
|
3
15
|
srcDir: string;
|
|
@@ -7,5 +19,5 @@ interface GenerateOptions {
|
|
|
7
19
|
}
|
|
8
20
|
declare const generateTypes: ({ project, srcDir, outDir, outputFile, watch, }: GenerateOptions) => Promise<void>;
|
|
9
21
|
|
|
10
|
-
export { generateTypes };
|
|
11
|
-
export type { GenerateOptions };
|
|
22
|
+
export { defineConfig, generateTypes };
|
|
23
|
+
export type { GenerateOptions, UserConfig };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User-defined configuration for gasnuki.
|
|
3
|
+
* `project` and `watch` options are excluded as they are runtime flags.
|
|
4
|
+
*/
|
|
5
|
+
type UserConfig = Partial<Omit<GenerateOptions, 'watch' | 'project'>>;
|
|
6
|
+
/**
|
|
7
|
+
* A helper function to define the gasnuki configuration with type safety.
|
|
8
|
+
* @param config The configuration object.
|
|
9
|
+
* @returns The configuration object.
|
|
10
|
+
*/
|
|
11
|
+
declare function defineConfig(config: UserConfig): UserConfig;
|
|
12
|
+
|
|
1
13
|
interface GenerateOptions {
|
|
2
14
|
project: string;
|
|
3
15
|
srcDir: string;
|
|
@@ -7,5 +19,5 @@ interface GenerateOptions {
|
|
|
7
19
|
}
|
|
8
20
|
declare const generateTypes: ({ project, srcDir, outDir, outputFile, watch, }: GenerateOptions) => Promise<void>;
|
|
9
21
|
|
|
10
|
-
export { generateTypes };
|
|
11
|
-
export type { GenerateOptions };
|
|
22
|
+
export { defineConfig, generateTypes };
|
|
23
|
+
export type { GenerateOptions, UserConfig };
|
package/dist/index.mjs
CHANGED
|
@@ -1,207 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const getInterfaceMethodDefinition_ = (name, node) => {
|
|
10
|
-
const typeParameters = node.getTypeParameters?.() ?? [];
|
|
11
|
-
const typeParamsString = typeParameters.length > 0 ? `<${typeParameters.map((tp) => tp.getText()).join(", ")}>` : "";
|
|
12
|
-
const parameters = node.getParameters().map((param) => {
|
|
13
|
-
const paramName = param.getName();
|
|
14
|
-
const type = param.getTypeNode()?.getText() ?? param.getType().getText(node) ?? "any";
|
|
15
|
-
const questionToken = param.hasQuestionToken() ? "?" : "";
|
|
16
|
-
return `${paramName}${questionToken}: ${type}`;
|
|
17
|
-
}).join(", ");
|
|
18
|
-
const returnTypeNode = node.getReturnTypeNode();
|
|
19
|
-
let returnType;
|
|
20
|
-
if (returnTypeNode != null) {
|
|
21
|
-
returnType = returnTypeNode.getText();
|
|
22
|
-
} else {
|
|
23
|
-
const inferredReturnType = node.getReturnType();
|
|
24
|
-
if (inferredReturnType.isVoid()) {
|
|
25
|
-
returnType = "void";
|
|
26
|
-
} else {
|
|
27
|
-
returnType = inferredReturnType.getText(node);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
let jsDocString = "";
|
|
31
|
-
const jsDocOwner = "getJsDocs" in node ? node : "getParantOrThrow" in node && // @ts-expect-error variable declaration
|
|
32
|
-
node.getParentOrThrow().getKind() === SyntaxKind.VariableDeclaration ? (
|
|
33
|
-
// @ts-expect-error variable declaration
|
|
34
|
-
node.getParentOrThrow()
|
|
35
|
-
) : null;
|
|
36
|
-
if (jsDocOwner != null) {
|
|
37
|
-
const jsDocs = "getJsDocs" in jsDocOwner ? jsDocOwner.getJsDocs() : null;
|
|
38
|
-
if (jsDocs != null && jsDocs.length > 0) {
|
|
39
|
-
const rawConmmentText = jsDocs.map((doc) => doc.getFullText()).join("\n");
|
|
40
|
-
if (rawConmmentText.includes("@deprecated")) {
|
|
41
|
-
const deprecatedDoc = jsDocs.find(
|
|
42
|
-
(doc) => doc.getFullText().includes("@deprecated")
|
|
43
|
-
);
|
|
44
|
-
jsDocString = `${deprecatedDoc != null ? deprecatedDoc.getFullText().trim() : "/**\n * @deprecated\n */"}
|
|
45
|
-
`;
|
|
46
|
-
} else {
|
|
47
|
-
const firstDoc = jsDocs[0];
|
|
48
|
-
const description = firstDoc.getDescription().trim();
|
|
49
|
-
if (description != null || firstDoc.getTags().length > 0) {
|
|
50
|
-
jsDocString = `${firstDoc.getFullText().trim()}
|
|
51
|
-
`;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return `${jsDocString}${name}${typeParamsString}(${parameters}): ${returnType};`;
|
|
57
|
-
};
|
|
58
|
-
const generateAppsScriptTypes = async ({
|
|
59
|
-
project: projectPath,
|
|
60
|
-
srcDir,
|
|
61
|
-
outDir,
|
|
62
|
-
outputFile
|
|
63
|
-
}) => {
|
|
64
|
-
const absoluteSrcDir = path.resolve(projectPath, srcDir);
|
|
65
|
-
const absoluteOutDir = path.resolve(projectPath, outDir);
|
|
66
|
-
const absoluteOutputFile = path.resolve(absoluteOutDir, outputFile);
|
|
67
|
-
consola.info("Starting AppsScript type generation with gasnuki...");
|
|
68
|
-
consola.info(` AppsScript Source Directory: ${absoluteSrcDir}`);
|
|
69
|
-
consola.info(` Output File: ${absoluteOutputFile}`);
|
|
70
|
-
const project = new Project({
|
|
71
|
-
tsConfigFilePath: path.resolve(projectPath, "tsconfig.json"),
|
|
72
|
-
skipAddingFilesFromTsConfig: true
|
|
73
|
-
});
|
|
74
|
-
project.addSourceFilesAtPaths(
|
|
75
|
-
path.join(absoluteSrcDir, "**/*.ts").replace(/\\/g, "/")
|
|
76
|
-
);
|
|
77
|
-
const methodDefinitions = [];
|
|
78
|
-
const globalTypeDefinitions = [];
|
|
79
|
-
const sourceFiles = project.getSourceFiles();
|
|
80
|
-
consola.info(`Found ${sourceFiles.length} source file(s).`);
|
|
81
|
-
for (const sourceFile of sourceFiles) {
|
|
82
|
-
for (const iface of sourceFile.getInterfaces()) {
|
|
83
|
-
globalTypeDefinitions.push(iface.getText());
|
|
84
|
-
}
|
|
85
|
-
for (const typeAlias of sourceFile.getTypeAliases()) {
|
|
86
|
-
globalTypeDefinitions.push(typeAlias.getText());
|
|
87
|
-
}
|
|
88
|
-
for (const statement of sourceFile.getStatements()) {
|
|
89
|
-
if (statement.getKind() === SyntaxKind.ModuleDeclaration) {
|
|
90
|
-
globalTypeDefinitions.push(statement.getText());
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
for (const funcDecl of sourceFile.getFunctions()) {
|
|
94
|
-
if (!funcDecl.isAmbient()) {
|
|
95
|
-
const name = funcDecl.getName();
|
|
96
|
-
if (name != null && !name.endsWith("_")) {
|
|
97
|
-
methodDefinitions.push(getInterfaceMethodDefinition_(name, funcDecl));
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
for (const varStmt of sourceFile.getVariableStatements()) {
|
|
102
|
-
if (!varStmt.isAmbient()) {
|
|
103
|
-
for (const varDecl of varStmt.getDeclarations()) {
|
|
104
|
-
const initializer = varDecl.getInitializer();
|
|
105
|
-
const varName = varDecl.getName();
|
|
106
|
-
if (initializer != null && (initializer.getKind() === SyntaxKind.ArrowFunction || initializer.getKind() === SyntaxKind.FunctionExpression) && !varName.endsWith("_")) {
|
|
107
|
-
methodDefinitions.push(
|
|
108
|
-
getInterfaceMethodDefinition_(
|
|
109
|
-
varName,
|
|
110
|
-
initializer
|
|
111
|
-
)
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
if (!fs.existsSync(absoluteOutDir)) {
|
|
119
|
-
fs.mkdirSync(absoluteOutDir, { recursive: true });
|
|
120
|
-
consola.info(`Created output directory: ${absoluteOutDir}`);
|
|
121
|
-
}
|
|
122
|
-
const generatorName = "gasnuki";
|
|
123
|
-
let outputContent = `// Auto-generated by ${generatorName}
|
|
124
|
-
// Do NOT edit this file manually.
|
|
125
|
-
`;
|
|
126
|
-
if (globalTypeDefinitions.length > 0) {
|
|
127
|
-
outputContent += `${globalTypeDefinitions.join("\n\n")}
|
|
128
|
-
|
|
129
|
-
`;
|
|
130
|
-
}
|
|
131
|
-
if (methodDefinitions.length > 0) {
|
|
132
|
-
const formattedMethods = methodDefinitions.map(
|
|
133
|
-
(method) => method.split("\n").map((line) => ` ${line}`).join("\n")
|
|
134
|
-
).join("\n\n");
|
|
135
|
-
outputContent += `export type ServerScripts = {
|
|
136
|
-
${formattedMethods}
|
|
137
|
-
}
|
|
138
|
-
`;
|
|
139
|
-
consola.info(
|
|
140
|
-
`Interface 'ServerScript' type definitions written to ${absoluteOutputFile} (${methodDefinitions.length} function(s), ${globalTypeDefinitions.length} type(s)).`
|
|
141
|
-
);
|
|
142
|
-
} else {
|
|
143
|
-
outputContent = "export type ServerScripts = {}\n";
|
|
144
|
-
consola.info(
|
|
145
|
-
`Interface 'ServerScript' type definitions written to ${absoluteOutputFile} (no functions found).`
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
outputContent += `
|
|
149
|
-
// Auto-generated Types for GoogleAppsScript in client-side code
|
|
150
|
-
|
|
151
|
-
${text}`;
|
|
152
|
-
fs.writeFileSync(absoluteOutputFile, outputContent);
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
const generateTypes = async ({
|
|
156
|
-
project,
|
|
157
|
-
srcDir,
|
|
158
|
-
outDir,
|
|
159
|
-
outputFile,
|
|
160
|
-
watch
|
|
161
|
-
}) => {
|
|
162
|
-
const runGeneration = async (triggeredBy) => {
|
|
163
|
-
const reason = triggeredBy ? ` (${triggeredBy})` : "";
|
|
164
|
-
consola.info(`Generating AppsScript types${reason}...`);
|
|
165
|
-
try {
|
|
166
|
-
await generateAppsScriptTypes({ project, srcDir, outDir, outputFile });
|
|
167
|
-
consola.info("Type generation complete.");
|
|
168
|
-
} catch (e) {
|
|
169
|
-
consola.error(`Type generation failed: ${e.message}`, e);
|
|
170
|
-
}
|
|
171
|
-
};
|
|
172
|
-
await runGeneration();
|
|
173
|
-
if (watch) {
|
|
174
|
-
const sourcePathToWatch = path.resolve(project, srcDir).replace(/\\/g, "/");
|
|
175
|
-
consola.info(
|
|
176
|
-
`Watching for changes in ${sourcePathToWatch}... (Press Ctrl+C to stop)`
|
|
177
|
-
);
|
|
178
|
-
const watcher = chokidar.watch(sourcePathToWatch, {
|
|
179
|
-
ignored: ["node_modules", "dist"],
|
|
180
|
-
persistent: true,
|
|
181
|
-
ignoreInitial: true
|
|
182
|
-
});
|
|
183
|
-
const eventHandler = async (filePath, eventName) => {
|
|
184
|
-
consola.info(`Watcher is called triggered on ${eventName}`);
|
|
185
|
-
const relativePath = path.relative(project, filePath);
|
|
186
|
-
await runGeneration(relativePath);
|
|
187
|
-
};
|
|
188
|
-
watcher.on("ready", async () => {
|
|
189
|
-
console.log("...waiting...");
|
|
190
|
-
watcher.on("all", async (event, path2) => {
|
|
191
|
-
consola.info(`Watcher is called triggered on ${event}: ${path2}`);
|
|
192
|
-
await eventHandler(path2, event);
|
|
193
|
-
});
|
|
194
|
-
});
|
|
195
|
-
for (const signal of ["SIGINT", "SIGTERM"]) {
|
|
196
|
-
process.on(signal, async () => {
|
|
197
|
-
await watcher.close();
|
|
198
|
-
consola.info("Watcher is closed.");
|
|
199
|
-
process.exit(0);
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
} else {
|
|
203
|
-
process.exit(0);
|
|
204
|
-
}
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
export { generateTypes };
|
|
1
|
+
import 'node:path';
|
|
2
|
+
import 'chokidar';
|
|
3
|
+
import 'consola';
|
|
4
|
+
export { d as defineConfig, g as generateTypes } from './shared/gasnuki.C-MvXA42.mjs';
|
|
5
|
+
import 'node:fs';
|
|
6
|
+
import 'ts-morph';
|
|
7
|
+
import 'jiti';
|
package/dist/promise.cjs
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const ServerScripts = () => {
|
|
4
|
+
const serverScripts = {};
|
|
5
|
+
for (const method of Object.keys(google.script.run)) {
|
|
6
|
+
if (["withSuccessHandler", "withFailureHandler", "withUserObject"].includes(
|
|
7
|
+
String(method)
|
|
8
|
+
)) {
|
|
9
|
+
continue;
|
|
10
|
+
}
|
|
11
|
+
serverScripts[method] = (...args) => new Promise((resolve, reject) => {
|
|
12
|
+
google.script.run.withSuccessHandler(resolve).withFailureHandler(reject)[method](...args);
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
return serverScripts;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
exports.ServerScripts = ServerScripts;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
type Promised<T> = {
|
|
2
|
+
[K in keyof T]: T[K] extends (...args: infer A) => infer R ? (...args: A) => Promise<R> : T[K];
|
|
3
|
+
};
|
|
4
|
+
declare const ServerScripts: <T extends Record<string, (...args: any[]) => any> = Omit<Omit<Omit<typeof google.script.run, "withSuccessHandler">, "withFailureHandler">, "withUserObject">>() => Promised<T>;
|
|
5
|
+
|
|
6
|
+
export { ServerScripts };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
type Promised<T> = {
|
|
2
|
+
[K in keyof T]: T[K] extends (...args: infer A) => infer R ? (...args: A) => Promise<R> : T[K];
|
|
3
|
+
};
|
|
4
|
+
declare const ServerScripts: <T extends Record<string, (...args: any[]) => any> = Omit<Omit<Omit<typeof google.script.run, "withSuccessHandler">, "withFailureHandler">, "withUserObject">>() => Promised<T>;
|
|
5
|
+
|
|
6
|
+
export { ServerScripts };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
type Promised<T> = {
|
|
2
|
+
[K in keyof T]: T[K] extends (...args: infer A) => infer R ? (...args: A) => Promise<R> : T[K];
|
|
3
|
+
};
|
|
4
|
+
declare const ServerScripts: <T extends Record<string, (...args: any[]) => any> = Omit<Omit<Omit<typeof google.script.run, "withSuccessHandler">, "withFailureHandler">, "withUserObject">>() => Promised<T>;
|
|
5
|
+
|
|
6
|
+
export { ServerScripts };
|
package/dist/promise.mjs
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const ServerScripts = () => {
|
|
2
|
+
const serverScripts = {};
|
|
3
|
+
for (const method of Object.keys(google.script.run)) {
|
|
4
|
+
if (["withSuccessHandler", "withFailureHandler", "withUserObject"].includes(
|
|
5
|
+
String(method)
|
|
6
|
+
)) {
|
|
7
|
+
continue;
|
|
8
|
+
}
|
|
9
|
+
serverScripts[method] = (...args) => new Promise((resolve, reject) => {
|
|
10
|
+
google.script.run.withSuccessHandler(resolve).withFailureHandler(reject)[method](...args);
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
return serverScripts;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export { ServerScripts };
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import * as path from 'node:path';
|
|
2
|
+
import * as chokidar from 'chokidar';
|
|
3
|
+
import { consola } from 'consola';
|
|
4
|
+
import * as fs from 'node:fs';
|
|
5
|
+
import { Project, SyntaxKind } from 'ts-morph';
|
|
6
|
+
import { createJiti } from 'jiti';
|
|
7
|
+
|
|
8
|
+
const text = "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";
|
|
9
|
+
|
|
10
|
+
const getInterfaceMethodDefinition_ = (name, node) => {
|
|
11
|
+
const typeParameters = node.getTypeParameters?.() ?? [];
|
|
12
|
+
const typeParamsString = typeParameters.length > 0 ? `<${typeParameters.map((tp) => tp.getText()).join(", ")}>` : "";
|
|
13
|
+
const parameters = node.getParameters().map((param) => {
|
|
14
|
+
const paramName = param.getName();
|
|
15
|
+
const type = param.getTypeNode()?.getText() ?? param.getType().getText(node) ?? "any";
|
|
16
|
+
const questionToken = param.hasQuestionToken() ? "?" : "";
|
|
17
|
+
return `${paramName}${questionToken}: ${type}`;
|
|
18
|
+
}).join(", ");
|
|
19
|
+
const returnTypeNode = node.getReturnTypeNode();
|
|
20
|
+
let returnType;
|
|
21
|
+
if (returnTypeNode != null) {
|
|
22
|
+
returnType = returnTypeNode.getText();
|
|
23
|
+
} else {
|
|
24
|
+
const inferredReturnType = node.getReturnType();
|
|
25
|
+
if (inferredReturnType.isVoid()) {
|
|
26
|
+
returnType = "void";
|
|
27
|
+
} else {
|
|
28
|
+
returnType = inferredReturnType.getText(node);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
let jsDocString = "";
|
|
32
|
+
const jsDocOwner = "getJsDocs" in node ? node : "getParantOrThrow" in node && // @ts-expect-error variable declaration
|
|
33
|
+
node.getParentOrThrow().getKind() === SyntaxKind.VariableDeclaration ? (
|
|
34
|
+
// @ts-expect-error variable declaration
|
|
35
|
+
node.getParentOrThrow()
|
|
36
|
+
) : null;
|
|
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 */"}
|
|
46
|
+
`;
|
|
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
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return `${jsDocString}${name}${typeParamsString}(${parameters}): ${returnType};`;
|
|
58
|
+
};
|
|
59
|
+
const generateAppsScriptTypes = async ({
|
|
60
|
+
project: projectPath,
|
|
61
|
+
srcDir,
|
|
62
|
+
outDir,
|
|
63
|
+
outputFile
|
|
64
|
+
}) => {
|
|
65
|
+
const absoluteSrcDir = path.resolve(projectPath, srcDir);
|
|
66
|
+
const absoluteOutDir = path.resolve(projectPath, outDir);
|
|
67
|
+
const absoluteOutputFile = path.resolve(absoluteOutDir, outputFile);
|
|
68
|
+
consola.info("Starting AppsScript type generation with gasnuki...");
|
|
69
|
+
consola.info(` AppsScript Source Directory: ${absoluteSrcDir}`);
|
|
70
|
+
consola.info(` Output File: ${absoluteOutputFile}`);
|
|
71
|
+
const project = new Project({
|
|
72
|
+
tsConfigFilePath: path.resolve(projectPath, "tsconfig.json"),
|
|
73
|
+
skipAddingFilesFromTsConfig: true
|
|
74
|
+
});
|
|
75
|
+
project.addSourceFilesAtPaths(
|
|
76
|
+
path.join(absoluteSrcDir, "**/*.ts").replace(/\\/g, "/")
|
|
77
|
+
);
|
|
78
|
+
const methodDefinitions = [];
|
|
79
|
+
const globalTypeDefinitions = [];
|
|
80
|
+
const sourceFiles = project.getSourceFiles();
|
|
81
|
+
consola.info(`Found ${sourceFiles.length} source file(s).`);
|
|
82
|
+
for (const sourceFile of sourceFiles) {
|
|
83
|
+
for (const iface of sourceFile.getInterfaces()) {
|
|
84
|
+
globalTypeDefinitions.push(iface.getText());
|
|
85
|
+
}
|
|
86
|
+
for (const typeAlias of sourceFile.getTypeAliases()) {
|
|
87
|
+
globalTypeDefinitions.push(typeAlias.getText());
|
|
88
|
+
}
|
|
89
|
+
for (const statement of sourceFile.getStatements()) {
|
|
90
|
+
if (statement.getKind() === SyntaxKind.ModuleDeclaration) {
|
|
91
|
+
globalTypeDefinitions.push(statement.getText());
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
for (const funcDecl of sourceFile.getFunctions()) {
|
|
95
|
+
if (!funcDecl.isAmbient()) {
|
|
96
|
+
const name = funcDecl.getName();
|
|
97
|
+
if (name != null && !name.endsWith("_")) {
|
|
98
|
+
methodDefinitions.push(getInterfaceMethodDefinition_(name, funcDecl));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
for (const varStmt of sourceFile.getVariableStatements()) {
|
|
103
|
+
if (!varStmt.isAmbient()) {
|
|
104
|
+
for (const varDecl of varStmt.getDeclarations()) {
|
|
105
|
+
const initializer = varDecl.getInitializer();
|
|
106
|
+
const varName = varDecl.getName();
|
|
107
|
+
if (initializer != null && (initializer.getKind() === SyntaxKind.ArrowFunction || initializer.getKind() === SyntaxKind.FunctionExpression) && !varName.endsWith("_")) {
|
|
108
|
+
methodDefinitions.push(
|
|
109
|
+
getInterfaceMethodDefinition_(
|
|
110
|
+
varName,
|
|
111
|
+
initializer
|
|
112
|
+
)
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (!fs.existsSync(absoluteOutDir)) {
|
|
120
|
+
fs.mkdirSync(absoluteOutDir, { recursive: true });
|
|
121
|
+
consola.info(`Created output directory: ${absoluteOutDir}`);
|
|
122
|
+
}
|
|
123
|
+
const generatorName = "gasnuki";
|
|
124
|
+
let outputContent = `// Auto-generated by ${generatorName}
|
|
125
|
+
// Do NOT edit this file manually.
|
|
126
|
+
`;
|
|
127
|
+
if (globalTypeDefinitions.length > 0) {
|
|
128
|
+
outputContent += `${globalTypeDefinitions.join("\n\n")}
|
|
129
|
+
|
|
130
|
+
`;
|
|
131
|
+
}
|
|
132
|
+
if (methodDefinitions.length > 0) {
|
|
133
|
+
const formattedMethods = methodDefinitions.map(
|
|
134
|
+
(method) => method.split("\n").map((line) => ` ${line}`).join("\n")
|
|
135
|
+
).join("\n\n");
|
|
136
|
+
outputContent += `export type ServerScripts = {
|
|
137
|
+
${formattedMethods}
|
|
138
|
+
}
|
|
139
|
+
`;
|
|
140
|
+
consola.info(
|
|
141
|
+
`Interface 'ServerScript' type definitions written to ${absoluteOutputFile} (${methodDefinitions.length} function(s), ${globalTypeDefinitions.length} type(s)).`
|
|
142
|
+
);
|
|
143
|
+
} else {
|
|
144
|
+
outputContent = "export type ServerScripts = {}\n";
|
|
145
|
+
consola.info(
|
|
146
|
+
`Interface 'ServerScript' type definitions written to ${absoluteOutputFile} (no functions found).`
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
outputContent += `
|
|
150
|
+
// Auto-generated Types for GoogleAppsScript in client-side code
|
|
151
|
+
|
|
152
|
+
${text}`;
|
|
153
|
+
fs.writeFileSync(absoluteOutputFile, outputContent);
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
function defineConfig(config) {
|
|
157
|
+
return config;
|
|
158
|
+
}
|
|
159
|
+
async function loadConfig(projectRoot) {
|
|
160
|
+
const configFileExtensions = [".ts", ".mts", ".cts", ".js", ".mjs", ".cjs"];
|
|
161
|
+
let foundConfigPath;
|
|
162
|
+
let foundConfigFileName;
|
|
163
|
+
for (const configFileExtension of configFileExtensions) {
|
|
164
|
+
const configFile = `gasnuki.config${configFileExtension}`;
|
|
165
|
+
const fullPath = path.resolve(projectRoot, configFile);
|
|
166
|
+
if (fs.existsSync(fullPath)) {
|
|
167
|
+
foundConfigPath = fullPath;
|
|
168
|
+
foundConfigFileName = configFile;
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (!foundConfigPath || !foundConfigFileName) {
|
|
173
|
+
return {};
|
|
174
|
+
}
|
|
175
|
+
try {
|
|
176
|
+
const jiti = createJiti(projectRoot, {
|
|
177
|
+
fsCache: false,
|
|
178
|
+
moduleCache: false,
|
|
179
|
+
interopDefault: true
|
|
180
|
+
});
|
|
181
|
+
const configModule = await jiti.import(foundConfigPath, {
|
|
182
|
+
default: true
|
|
183
|
+
});
|
|
184
|
+
consola.success(`Loaded configuration from ${foundConfigFileName}`);
|
|
185
|
+
return configModule;
|
|
186
|
+
} catch (error) {
|
|
187
|
+
consola.error(`Error loading ${foundConfigFileName}:`, error);
|
|
188
|
+
return {};
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const generateTypes = async ({
|
|
193
|
+
project,
|
|
194
|
+
srcDir,
|
|
195
|
+
outDir,
|
|
196
|
+
outputFile,
|
|
197
|
+
watch
|
|
198
|
+
}) => {
|
|
199
|
+
const runGeneration = async (triggeredBy) => {
|
|
200
|
+
const reason = triggeredBy ? ` (${triggeredBy})` : "";
|
|
201
|
+
consola.info(`Generating AppsScript types${reason}...`);
|
|
202
|
+
try {
|
|
203
|
+
await generateAppsScriptTypes({ project, srcDir, outDir, outputFile });
|
|
204
|
+
consola.info("Type generation complete.");
|
|
205
|
+
} catch (e) {
|
|
206
|
+
consola.error(`Type generation failed: ${e.message}`, e);
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
await runGeneration();
|
|
210
|
+
if (watch) {
|
|
211
|
+
const sourcePathToWatch = path.resolve(project, srcDir).replace(/\\/g, "/");
|
|
212
|
+
consola.info(
|
|
213
|
+
`Watching for changes in ${sourcePathToWatch}... (Press Ctrl+C to stop)`
|
|
214
|
+
);
|
|
215
|
+
const watcher = chokidar.watch(sourcePathToWatch, {
|
|
216
|
+
ignored: ["node_modules", "dist"],
|
|
217
|
+
persistent: true,
|
|
218
|
+
ignoreInitial: true
|
|
219
|
+
});
|
|
220
|
+
const eventHandler = async (filePath, eventName) => {
|
|
221
|
+
consola.info(`Watcher is called triggered on ${eventName}`);
|
|
222
|
+
const relativePath = path.relative(project, filePath);
|
|
223
|
+
await runGeneration(relativePath);
|
|
224
|
+
};
|
|
225
|
+
watcher.on("ready", async () => {
|
|
226
|
+
console.log("...waiting...");
|
|
227
|
+
watcher.on("all", async (event, path2) => {
|
|
228
|
+
consola.info(`Watcher is called triggered on ${event}: ${path2}`);
|
|
229
|
+
await eventHandler(path2, event);
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
for (const signal of ["SIGINT", "SIGTERM"]) {
|
|
233
|
+
process.on(signal, async () => {
|
|
234
|
+
await watcher.close();
|
|
235
|
+
consola.info("Watcher is closed.");
|
|
236
|
+
process.exit(0);
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
} else {
|
|
240
|
+
process.exit(0);
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
export { defineConfig as d, generateTypes as g, loadConfig as l };
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const chokidar = require('chokidar');
|
|
5
|
+
const consola = require('consola');
|
|
6
|
+
const fs = require('node:fs');
|
|
7
|
+
const tsMorph = require('ts-morph');
|
|
8
|
+
const jiti = require('jiti');
|
|
9
|
+
|
|
10
|
+
function _interopNamespaceCompat(e) {
|
|
11
|
+
if (e && typeof e === 'object' && 'default' in e) return e;
|
|
12
|
+
const n = Object.create(null);
|
|
13
|
+
if (e) {
|
|
14
|
+
for (const k in e) {
|
|
15
|
+
n[k] = e[k];
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
n.default = e;
|
|
19
|
+
return n;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const path__namespace = /*#__PURE__*/_interopNamespaceCompat(path);
|
|
23
|
+
const chokidar__namespace = /*#__PURE__*/_interopNamespaceCompat(chokidar);
|
|
24
|
+
const fs__namespace = /*#__PURE__*/_interopNamespaceCompat(fs);
|
|
25
|
+
|
|
26
|
+
const text = "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";
|
|
27
|
+
|
|
28
|
+
const getInterfaceMethodDefinition_ = (name, node) => {
|
|
29
|
+
const typeParameters = node.getTypeParameters?.() ?? [];
|
|
30
|
+
const typeParamsString = typeParameters.length > 0 ? `<${typeParameters.map((tp) => tp.getText()).join(", ")}>` : "";
|
|
31
|
+
const parameters = node.getParameters().map((param) => {
|
|
32
|
+
const paramName = param.getName();
|
|
33
|
+
const type = param.getTypeNode()?.getText() ?? param.getType().getText(node) ?? "any";
|
|
34
|
+
const questionToken = param.hasQuestionToken() ? "?" : "";
|
|
35
|
+
return `${paramName}${questionToken}: ${type}`;
|
|
36
|
+
}).join(", ");
|
|
37
|
+
const returnTypeNode = node.getReturnTypeNode();
|
|
38
|
+
let returnType;
|
|
39
|
+
if (returnTypeNode != null) {
|
|
40
|
+
returnType = returnTypeNode.getText();
|
|
41
|
+
} else {
|
|
42
|
+
const inferredReturnType = node.getReturnType();
|
|
43
|
+
if (inferredReturnType.isVoid()) {
|
|
44
|
+
returnType = "void";
|
|
45
|
+
} else {
|
|
46
|
+
returnType = inferredReturnType.getText(node);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
let jsDocString = "";
|
|
50
|
+
const jsDocOwner = "getJsDocs" in node ? node : "getParantOrThrow" in node && // @ts-expect-error variable declaration
|
|
51
|
+
node.getParentOrThrow().getKind() === tsMorph.SyntaxKind.VariableDeclaration ? (
|
|
52
|
+
// @ts-expect-error variable declaration
|
|
53
|
+
node.getParentOrThrow()
|
|
54
|
+
) : null;
|
|
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 */"}
|
|
64
|
+
`;
|
|
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
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return `${jsDocString}${name}${typeParamsString}(${parameters}): ${returnType};`;
|
|
76
|
+
};
|
|
77
|
+
const generateAppsScriptTypes = async ({
|
|
78
|
+
project: projectPath,
|
|
79
|
+
srcDir,
|
|
80
|
+
outDir,
|
|
81
|
+
outputFile
|
|
82
|
+
}) => {
|
|
83
|
+
const absoluteSrcDir = path__namespace.resolve(projectPath, srcDir);
|
|
84
|
+
const absoluteOutDir = path__namespace.resolve(projectPath, outDir);
|
|
85
|
+
const absoluteOutputFile = path__namespace.resolve(absoluteOutDir, outputFile);
|
|
86
|
+
consola.consola.info("Starting AppsScript type generation with gasnuki...");
|
|
87
|
+
consola.consola.info(` AppsScript Source Directory: ${absoluteSrcDir}`);
|
|
88
|
+
consola.consola.info(` Output File: ${absoluteOutputFile}`);
|
|
89
|
+
const project = new tsMorph.Project({
|
|
90
|
+
tsConfigFilePath: path__namespace.resolve(projectPath, "tsconfig.json"),
|
|
91
|
+
skipAddingFilesFromTsConfig: true
|
|
92
|
+
});
|
|
93
|
+
project.addSourceFilesAtPaths(
|
|
94
|
+
path__namespace.join(absoluteSrcDir, "**/*.ts").replace(/\\/g, "/")
|
|
95
|
+
);
|
|
96
|
+
const methodDefinitions = [];
|
|
97
|
+
const globalTypeDefinitions = [];
|
|
98
|
+
const sourceFiles = project.getSourceFiles();
|
|
99
|
+
consola.consola.info(`Found ${sourceFiles.length} source file(s).`);
|
|
100
|
+
for (const sourceFile of sourceFiles) {
|
|
101
|
+
for (const iface of sourceFile.getInterfaces()) {
|
|
102
|
+
globalTypeDefinitions.push(iface.getText());
|
|
103
|
+
}
|
|
104
|
+
for (const typeAlias of sourceFile.getTypeAliases()) {
|
|
105
|
+
globalTypeDefinitions.push(typeAlias.getText());
|
|
106
|
+
}
|
|
107
|
+
for (const statement of sourceFile.getStatements()) {
|
|
108
|
+
if (statement.getKind() === tsMorph.SyntaxKind.ModuleDeclaration) {
|
|
109
|
+
globalTypeDefinitions.push(statement.getText());
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
for (const funcDecl of sourceFile.getFunctions()) {
|
|
113
|
+
if (!funcDecl.isAmbient()) {
|
|
114
|
+
const name = funcDecl.getName();
|
|
115
|
+
if (name != null && !name.endsWith("_")) {
|
|
116
|
+
methodDefinitions.push(getInterfaceMethodDefinition_(name, funcDecl));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
for (const varStmt of sourceFile.getVariableStatements()) {
|
|
121
|
+
if (!varStmt.isAmbient()) {
|
|
122
|
+
for (const varDecl of varStmt.getDeclarations()) {
|
|
123
|
+
const initializer = varDecl.getInitializer();
|
|
124
|
+
const varName = varDecl.getName();
|
|
125
|
+
if (initializer != null && (initializer.getKind() === tsMorph.SyntaxKind.ArrowFunction || initializer.getKind() === tsMorph.SyntaxKind.FunctionExpression) && !varName.endsWith("_")) {
|
|
126
|
+
methodDefinitions.push(
|
|
127
|
+
getInterfaceMethodDefinition_(
|
|
128
|
+
varName,
|
|
129
|
+
initializer
|
|
130
|
+
)
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (!fs__namespace.existsSync(absoluteOutDir)) {
|
|
138
|
+
fs__namespace.mkdirSync(absoluteOutDir, { recursive: true });
|
|
139
|
+
consola.consola.info(`Created output directory: ${absoluteOutDir}`);
|
|
140
|
+
}
|
|
141
|
+
const generatorName = "gasnuki";
|
|
142
|
+
let outputContent = `// Auto-generated by ${generatorName}
|
|
143
|
+
// Do NOT edit this file manually.
|
|
144
|
+
`;
|
|
145
|
+
if (globalTypeDefinitions.length > 0) {
|
|
146
|
+
outputContent += `${globalTypeDefinitions.join("\n\n")}
|
|
147
|
+
|
|
148
|
+
`;
|
|
149
|
+
}
|
|
150
|
+
if (methodDefinitions.length > 0) {
|
|
151
|
+
const formattedMethods = methodDefinitions.map(
|
|
152
|
+
(method) => method.split("\n").map((line) => ` ${line}`).join("\n")
|
|
153
|
+
).join("\n\n");
|
|
154
|
+
outputContent += `export type ServerScripts = {
|
|
155
|
+
${formattedMethods}
|
|
156
|
+
}
|
|
157
|
+
`;
|
|
158
|
+
consola.consola.info(
|
|
159
|
+
`Interface 'ServerScript' type definitions written to ${absoluteOutputFile} (${methodDefinitions.length} function(s), ${globalTypeDefinitions.length} type(s)).`
|
|
160
|
+
);
|
|
161
|
+
} else {
|
|
162
|
+
outputContent = "export type ServerScripts = {}\n";
|
|
163
|
+
consola.consola.info(
|
|
164
|
+
`Interface 'ServerScript' type definitions written to ${absoluteOutputFile} (no functions found).`
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
outputContent += `
|
|
168
|
+
// Auto-generated Types for GoogleAppsScript in client-side code
|
|
169
|
+
|
|
170
|
+
${text}`;
|
|
171
|
+
fs__namespace.writeFileSync(absoluteOutputFile, outputContent);
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
function defineConfig(config) {
|
|
175
|
+
return config;
|
|
176
|
+
}
|
|
177
|
+
async function loadConfig(projectRoot) {
|
|
178
|
+
const configFileExtensions = [".ts", ".mts", ".cts", ".js", ".mjs", ".cjs"];
|
|
179
|
+
let foundConfigPath;
|
|
180
|
+
let foundConfigFileName;
|
|
181
|
+
for (const configFileExtension of configFileExtensions) {
|
|
182
|
+
const configFile = `gasnuki.config${configFileExtension}`;
|
|
183
|
+
const fullPath = path__namespace.resolve(projectRoot, configFile);
|
|
184
|
+
if (fs__namespace.existsSync(fullPath)) {
|
|
185
|
+
foundConfigPath = fullPath;
|
|
186
|
+
foundConfigFileName = configFile;
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (!foundConfigPath || !foundConfigFileName) {
|
|
191
|
+
return {};
|
|
192
|
+
}
|
|
193
|
+
try {
|
|
194
|
+
const jiti$1 = jiti.createJiti(projectRoot, {
|
|
195
|
+
fsCache: false,
|
|
196
|
+
moduleCache: false,
|
|
197
|
+
interopDefault: true
|
|
198
|
+
});
|
|
199
|
+
const configModule = await jiti$1.import(foundConfigPath, {
|
|
200
|
+
default: true
|
|
201
|
+
});
|
|
202
|
+
consola.consola.success(`Loaded configuration from ${foundConfigFileName}`);
|
|
203
|
+
return configModule;
|
|
204
|
+
} catch (error) {
|
|
205
|
+
consola.consola.error(`Error loading ${foundConfigFileName}:`, error);
|
|
206
|
+
return {};
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const generateTypes = async ({
|
|
211
|
+
project,
|
|
212
|
+
srcDir,
|
|
213
|
+
outDir,
|
|
214
|
+
outputFile,
|
|
215
|
+
watch
|
|
216
|
+
}) => {
|
|
217
|
+
const runGeneration = async (triggeredBy) => {
|
|
218
|
+
const reason = triggeredBy ? ` (${triggeredBy})` : "";
|
|
219
|
+
consola.consola.info(`Generating AppsScript types${reason}...`);
|
|
220
|
+
try {
|
|
221
|
+
await generateAppsScriptTypes({ project, srcDir, outDir, outputFile });
|
|
222
|
+
consola.consola.info("Type generation complete.");
|
|
223
|
+
} catch (e) {
|
|
224
|
+
consola.consola.error(`Type generation failed: ${e.message}`, e);
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
await runGeneration();
|
|
228
|
+
if (watch) {
|
|
229
|
+
const sourcePathToWatch = path__namespace.resolve(project, srcDir).replace(/\\/g, "/");
|
|
230
|
+
consola.consola.info(
|
|
231
|
+
`Watching for changes in ${sourcePathToWatch}... (Press Ctrl+C to stop)`
|
|
232
|
+
);
|
|
233
|
+
const watcher = chokidar__namespace.watch(sourcePathToWatch, {
|
|
234
|
+
ignored: ["node_modules", "dist"],
|
|
235
|
+
persistent: true,
|
|
236
|
+
ignoreInitial: true
|
|
237
|
+
});
|
|
238
|
+
const eventHandler = async (filePath, eventName) => {
|
|
239
|
+
consola.consola.info(`Watcher is called triggered on ${eventName}`);
|
|
240
|
+
const relativePath = path__namespace.relative(project, filePath);
|
|
241
|
+
await runGeneration(relativePath);
|
|
242
|
+
};
|
|
243
|
+
watcher.on("ready", async () => {
|
|
244
|
+
console.log("...waiting...");
|
|
245
|
+
watcher.on("all", async (event, path2) => {
|
|
246
|
+
consola.consola.info(`Watcher is called triggered on ${event}: ${path2}`);
|
|
247
|
+
await eventHandler(path2, event);
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
for (const signal of ["SIGINT", "SIGTERM"]) {
|
|
251
|
+
process.on(signal, async () => {
|
|
252
|
+
await watcher.close();
|
|
253
|
+
consola.consola.info("Watcher is closed.");
|
|
254
|
+
process.exit(0);
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
} else {
|
|
258
|
+
process.exit(0);
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
exports.defineConfig = defineConfig;
|
|
263
|
+
exports.generateTypes = generateTypes;
|
|
264
|
+
exports.loadConfig = loadConfig;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ciderjs/gasnuki",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "",
|
|
3
|
+
"version": "0.2.0",
|
|
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",
|
|
7
7
|
"bin": {
|
|
@@ -12,14 +12,19 @@
|
|
|
12
12
|
"types": "./dist/index.d.ts",
|
|
13
13
|
"import": "./dist/index.mjs",
|
|
14
14
|
"require": "./dist/index.cjs"
|
|
15
|
+
},
|
|
16
|
+
"./promise": {
|
|
17
|
+
"types": "./dist/promise.d.ts",
|
|
18
|
+
"import": "./dist/promise.mjs",
|
|
19
|
+
"require": "./dist/promise.cjs"
|
|
15
20
|
}
|
|
16
21
|
},
|
|
17
22
|
"scripts": {
|
|
18
23
|
"prebuild": "jiti bin/generate.ts",
|
|
19
|
-
"dev": "pnpm prebuild && jiti src/cli.ts -p playground/react
|
|
24
|
+
"dev": "pnpm prebuild && jiti src/cli.ts -p playground/react",
|
|
20
25
|
"start": "node dist/cli.mjs -p playground/react -s src/server",
|
|
21
26
|
"check": "biome check --write",
|
|
22
|
-
"build": "
|
|
27
|
+
"build": "unbuild",
|
|
23
28
|
"test": "vitest run",
|
|
24
29
|
"prepare": "pnpm run check && pnpm run build"
|
|
25
30
|
},
|
|
@@ -39,12 +44,12 @@
|
|
|
39
44
|
"chokidar": "^4.0.3",
|
|
40
45
|
"commander": "^14.0.0",
|
|
41
46
|
"consola": "^3.4.2",
|
|
47
|
+
"jiti": "^2.4.2",
|
|
42
48
|
"ts-morph": "^26.0.0"
|
|
43
49
|
},
|
|
44
50
|
"devDependencies": {
|
|
45
51
|
"@biomejs/biome": "^1.9.4",
|
|
46
52
|
"@types/node": "^22.15.29",
|
|
47
|
-
"jiti": "^2.4.2",
|
|
48
53
|
"typescript": "^5.8.3",
|
|
49
54
|
"unbuild": "^3.5.0",
|
|
50
55
|
"vitest": "^3.2.1"
|