@ciderjs/gasbombe 0.2.1 → 0.2.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/dist/cli.cjs CHANGED
@@ -11,7 +11,7 @@ require('consola');
11
11
  require('ejs');
12
12
  require('glob');
13
13
 
14
- const version = "0.2.1";
14
+ const version = "0.2.2";
15
15
 
16
16
  async function main() {
17
17
  const program = new commander.Command();
package/dist/cli.mjs CHANGED
@@ -9,7 +9,7 @@ import 'consola';
9
9
  import 'ejs';
10
10
  import 'glob';
11
11
 
12
- const version = "0.2.1";
12
+ const version = "0.2.2";
13
13
 
14
14
  async function main() {
15
15
  const program = new Command();
package/dist/index.cjs CHANGED
@@ -18,8 +18,7 @@ async function runCommand(command, args, cwd, capture = false) {
18
18
  return new Promise((resolve, reject) => {
19
19
  const child = node_child_process.spawn(command, args, {
20
20
  cwd,
21
- stdio: capture ? "pipe" : "inherit",
22
- shell: true
21
+ stdio: capture ? "pipe" : "inherit"
23
22
  });
24
23
  let stdout = "";
25
24
  let stderr = "";
package/dist/index.mjs CHANGED
@@ -19,8 +19,7 @@ async function runCommand(command, args, cwd, capture = false) {
19
19
  return new Promise((resolve, reject) => {
20
20
  const child = spawn(command, args, {
21
21
  cwd,
22
- stdio: capture ? "pipe" : "inherit",
23
- shell: true
22
+ stdio: capture ? "pipe" : "inherit"
24
23
  });
25
24
  let stdout = "";
26
25
  let stderr = "";
package/package.json CHANGED
@@ -1,16 +1,17 @@
1
1
  {
2
2
  "name": "@ciderjs/gasbombe",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "A TypeScript Project Generator for GoogleAppsScript, available as CLI",
5
5
  "type": "module",
6
- "main": "src/index.ts",
6
+ "main": "dist/index.cjs",
7
7
  "bin": {
8
8
  "gasbombe": "dist/cli.cjs"
9
9
  },
10
10
  "files": [
11
11
  "dist",
12
12
  "LICENSE",
13
- "README.md"
13
+ "README.md",
14
+ "README.ja.md"
14
15
  ],
15
16
  "module": "dist/index.mjs",
16
17
  "types": "dist/index.d.ts",
@@ -20,8 +21,7 @@
20
21
  "check": "biome check --write",
21
22
  "generate": "jiti scripts/copyTemplates",
22
23
  "test": "vitest run --coverage",
23
- "build": "pnpm run tsc && pnpm run test --silent && unbuild && pnpm run generate",
24
- "postinstall": "pnpm run generate"
24
+ "build": "pnpm run tsc && pnpm run test --silent && unbuild && pnpm run generate"
25
25
  },
26
26
  "keywords": [
27
27
  "googleappsscript",
package/src/index.ts DELETED
@@ -1,325 +0,0 @@
1
- import { spawn } from 'node:child_process';
2
- import fs from 'node:fs/promises';
3
- import path from 'node:path';
4
- import { select } from '@inquirer/prompts';
5
- import { consola } from 'consola';
6
- import ejs from 'ejs';
7
- import { glob } from 'glob';
8
- import type { ProjectOptions } from '../types';
9
-
10
- export async function runCommand(
11
- command: string,
12
- args: string[],
13
- cwd: string,
14
- capture = false,
15
- ): Promise<string> {
16
- return new Promise((resolve, reject) => {
17
- const child = spawn(command, args, {
18
- cwd,
19
- stdio: capture ? 'pipe' : 'inherit',
20
- shell: true,
21
- });
22
-
23
- let stdout = '';
24
- let stderr = '';
25
-
26
- if (capture) {
27
- child.stdout?.on('data', (data) => {
28
- stdout += data.toString();
29
- });
30
- child.stderr?.on('data', (data) => {
31
- stderr += data.toString();
32
- });
33
- }
34
-
35
- child.on('close', (code) => {
36
- if (code === 0) {
37
- resolve(stdout.trim());
38
- } else {
39
- const errorMsg = `Command failed with exit code ${code}${stderr ? `:\n${stderr}` : ''}`;
40
- reject(new Error(errorMsg));
41
- }
42
- });
43
-
44
- child.on('error', (err) => {
45
- reject(err);
46
- });
47
- });
48
- }
49
-
50
- async function handleClaspSetup(
51
- claspOption: ProjectOptions['clasp'],
52
- projectName: string,
53
- outputDir: string,
54
- claspProjectId: string | undefined,
55
- packageManager: ProjectOptions['packageManager'] = 'npm',
56
- ): Promise<void> {
57
- if (claspOption === 'skip') {
58
- return;
59
- }
60
-
61
- const npxLikeCommand =
62
- packageManager === 'npm'
63
- ? 'npx'
64
- : packageManager === 'pnpm'
65
- ? 'pnpx'
66
- : 'yarn';
67
-
68
- consola.start(
69
- `Setting up .clasp.json with \`${npxLikeCommand} @google/clasp\`...`,
70
- );
71
-
72
- if (claspOption === 'create' || claspOption === 'list') {
73
- try {
74
- await runCommand(npxLikeCommand, ['@google/clasp', 'status'], outputDir);
75
- } catch {
76
- consola.error(
77
- `It seems you are not logged in to clasp. Please run \`${npxLikeCommand} @google/clasp login\` and try again.`,
78
- );
79
- return;
80
- }
81
- }
82
-
83
- let scriptId: string | undefined;
84
- let existingClaspJson: { scriptId: string; [key: string]: string | string[] } | null = null;
85
-
86
- switch (claspOption) {
87
- case 'create':
88
- try {
89
- const claspJsonPath = path.join(outputDir, '.clasp.json');
90
- try {
91
- const existingContent = await fs.readFile(claspJsonPath, 'utf-8');
92
- existingClaspJson = JSON.parse(existingContent);
93
- await fs.unlink(claspJsonPath);
94
- } catch {
95
- // No existing .clasp.json, which is fine.
96
- }
97
-
98
- const result = await runCommand(
99
- npxLikeCommand,
100
- [
101
- '@google/clasp',
102
- 'create',
103
- '--title',
104
- `"${projectName}"`,
105
- '--type',
106
- 'standalone',
107
- ],
108
- outputDir,
109
- true,
110
- );
111
- const match = result.match(/Created new script: .+\/d\/(.+)\/edit/);
112
- if (match?.[1]) {
113
- scriptId = match[1];
114
- consola.info(`Created new Apps Script project with ID: ${scriptId}`);
115
- } else {
116
- throw new Error('Could not parse scriptId from clasp output.');
117
- }
118
- } catch (e) {
119
- consola.error('Failed to create new Apps Script project.', e);
120
- return;
121
- }
122
- break;
123
-
124
- case 'list':
125
- try {
126
- const listOutput = await runCommand(
127
- npxLikeCommand,
128
- ['@google/clasp', 'list'],
129
- outputDir,
130
- true,
131
- );
132
- const projects = listOutput
133
- .split('\n')
134
- .slice(1) // Skip header
135
- .map((line) => {
136
- const parts = line.split(' - ');
137
- if (parts.length >= 2) {
138
- const name = parts[0]?.trim();
139
- const url = parts[1]?.trim();
140
- if (!name || !url) return null;
141
-
142
- const match = url.match(/\/d\/(.+)\/edit/);
143
- const scriptId = match?.[1];
144
-
145
- if (scriptId) {
146
- return { name, value: scriptId };
147
- }
148
- }
149
- return null;
150
- })
151
- .filter((p): p is { name: string; value: string } => p !== null);
152
-
153
- if (projects.length === 0) {
154
- consola.warn(
155
- 'No existing Apps Script projects found. Please create one first.',
156
- );
157
- return;
158
- }
159
-
160
- scriptId = await select({
161
- message: 'Choose an existing Apps Script project:',
162
- choices: projects,
163
- });
164
- } catch (e) {
165
- consola.error('Failed to list Apps Script projects.', e);
166
- return;
167
- }
168
- break;
169
-
170
- case 'input':
171
- scriptId = claspProjectId;
172
- break;
173
- }
174
-
175
- if (scriptId) {
176
- const claspJsonPath = path.join(outputDir, '.clasp.json');
177
- let claspJson: { scriptId: string; [key: string]: string | string[] } = {
178
- scriptId,
179
- };
180
- let successMessage = `.clasp.json created successfully with scriptId: ${scriptId}`;
181
-
182
- if (existingClaspJson) {
183
- claspJson = { ...existingClaspJson, scriptId };
184
- successMessage = `.clasp.json updated successfully with scriptId: ${scriptId}`;
185
- } else {
186
- try {
187
- const existingContent = await fs.readFile(claspJsonPath, 'utf-8');
188
- const currentClaspJson = JSON.parse(existingContent);
189
- claspJson = { ...currentClaspJson, scriptId };
190
- successMessage = `.clasp.json updated successfully with scriptId: ${scriptId}`;
191
- } catch {
192
- // If file doesn't exist or is invalid, we'll just create a new one.
193
- }
194
- }
195
-
196
- const claspJsonContent = JSON.stringify(claspJson, null, 2);
197
- await fs.writeFile(claspJsonPath, claspJsonContent, { encoding: 'utf-8' });
198
- consola.success(successMessage);
199
- }
200
- }
201
-
202
- export async function generateProject({
203
- projectName,
204
- packageManager,
205
- templateType,
206
- clasp,
207
- claspProjectId,
208
- install,
209
- }: ProjectOptions): Promise<void> {
210
- const outputDir = path.resolve(process.cwd(), projectName);
211
- const templateBaseDir = path.resolve(__dirname, '..', 'dist', 'templates');
212
- const commonTemplateDir = path.resolve(templateBaseDir, 'common');
213
- const specificTemplateDir = path.resolve(templateBaseDir, templateType);
214
-
215
- consola.start(
216
- `Creating a new Project for GoogleAppsScript in ${outputDir}...`,
217
- );
218
-
219
- if (projectName === '.') {
220
- try {
221
- const files = await fs.readdir(outputDir);
222
- const relevantFiles = files.filter((file) => !file.startsWith('.'));
223
-
224
- if (relevantFiles.length > 0) {
225
- const proceed = await confirm(
226
- 'Current directory is not empty. Proceed anyway?',
227
- );
228
-
229
- if (!proceed) {
230
- consola.warn('Operation cancelled.');
231
- process.exit(0);
232
- }
233
- }
234
- } catch {
235
- // Directory does not exist, then mkdir will create it.
236
- }
237
- } else {
238
- try {
239
- await fs.access(outputDir);
240
- consola.error(`Directory ${projectName} already exists.`);
241
- process.exit(1);
242
- } catch {
243
- // Directory does not exist, which is what we want.
244
- }
245
- }
246
-
247
- await fs.mkdir(outputDir, { recursive: true });
248
- consola.info(`Generating project files from template '${templateType}'...`);
249
-
250
- const ejsData = { projectName };
251
- const templateDirs = [commonTemplateDir, specificTemplateDir];
252
- for (const dir of templateDirs) {
253
- const files = await glob('./**/*', {
254
- cwd: dir,
255
- nodir: true,
256
- dot: true,
257
- });
258
-
259
- for (const file of files) {
260
- const relativePath = path.relative(dir, path.resolve(dir, file));
261
- const templatePath = path.join(dir, relativePath);
262
- const outputPath = path.join(outputDir, relativePath.replace('.ejs', ''));
263
-
264
- await fs.mkdir(path.dirname(outputPath), { recursive: true });
265
-
266
- const templateContent = await fs.readFile(templatePath, {
267
- encoding: 'utf-8',
268
- });
269
- const renderedContent = ejs.render(templateContent, ejsData);
270
- await fs.writeFile(outputPath, renderedContent, { encoding: 'utf-8' });
271
- }
272
- }
273
-
274
- await handleClaspSetup(
275
- clasp,
276
- projectName,
277
- outputDir,
278
- claspProjectId,
279
- packageManager,
280
- );
281
-
282
- if (install) {
283
- consola.start(`Installing dependencies with ${packageManager}...`);
284
- try {
285
- await runCommand(packageManager, ['install'], outputDir);
286
- consola.success(`Dependencies installed successfully.`);
287
- } catch (e) {
288
- consola.fail('Failed to install dependencies. Please do it manually.');
289
- consola.error(e);
290
- }
291
- }
292
-
293
- consola.start(`Initializing Git repository...`);
294
- try {
295
- await runCommand('git', ['init'], outputDir);
296
- await runCommand('git', ['add', '-A'], outputDir);
297
- await runCommand(
298
- 'git',
299
- ['commit', '-m', '"Initial commit from gasbombe"'],
300
- outputDir,
301
- );
302
- consola.success(`Git repository initialized successfully.`);
303
- } catch (e) {
304
- consola.fail('Failed to initialize Git repository. Please do it manually.');
305
- consola.error(e);
306
- }
307
-
308
- consola.success(`Project '${projectName}' created successfully!`);
309
-
310
- const messages: string[] = [];
311
- projectName !== '.' && messages.push(` cd ${projectName}`);
312
- !install && messages.push(` ${packageManager} install`);
313
- templateType !== 'vanilla-ts' && messages.push(` ${packageManager} dev`);
314
-
315
- if (messages.length > 0) {
316
- consola.log(`\nTo get started, run:\n`);
317
- for (const message of messages) {
318
- consola.log(message);
319
- }
320
- consola.log('');
321
- consola.log(`...and write your GAS code!`);
322
- } else {
323
- consola.log(`\nTo get started, write your GAS code in \`src/\`!`);
324
- }
325
- }