gasup 0.2.1 → 0.3.1

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.md ADDED
@@ -0,0 +1,121 @@
1
+ # Gasup
2
+
3
+ Gasup is a command-line interface (CLI) tool designed to simplify the process.
4
+
5
+ - building
6
+ - bundling
7
+ - pushing
8
+ - deploying
9
+ - change development, staging, production
10
+
11
+ It offers an easy way to automate tasks and manage your deployments without the need to manually interact with the Apps Script dashboard.
12
+
13
+ ## Installation
14
+
15
+ To get started with gasup, you need clasp first.
16
+
17
+ Then you can install gasup like below.
18
+
19
+ ```
20
+ npm i -g gasup
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ ### Build
26
+
27
+ Simple build.
28
+
29
+ ```
30
+ gasup --build
31
+ ```
32
+
33
+ This command compiles your code with tsc.
34
+
35
+ ### Bundle
36
+
37
+ Bundle with esbuild into one file. This allows you to use libraries that are not natively available in Google Apps Script.
38
+
39
+ ```
40
+ gasup --bundle
41
+ ```
42
+
43
+ ### Push
44
+
45
+ Simply push using "clasp push".
46
+
47
+ ```
48
+ gasup --push
49
+ ```
50
+
51
+ ### Deploy
52
+
53
+ Deploy to the latest deployment. If no previous deployments exist, a new deployment will be created.
54
+
55
+ ```
56
+ gasup --deploy
57
+ ```
58
+
59
+ ### Change Environment
60
+
61
+ If you need to switch between different environments (e.g., development, staging, production), you can use the --env flag to modify the appsscript.json file accordingly.
62
+
63
+ ```
64
+ gasup --env <target>
65
+ ```
66
+
67
+ Target options:
68
+
69
+ - dev : Development environment
70
+ - stag : Staging environment
71
+ - prod : Production environment
72
+
73
+ Default environment files:
74
+
75
+ .env, .env.staging, .env.production
76
+
77
+ Environment file details:
78
+
79
+ ```env
80
+ GASUP_SCRIPT_ID=xxx
81
+ GASUP_PARENT_ID=yyy,zzz
82
+ ```
83
+
84
+ ### Chain
85
+
86
+ Chan command is available like below.
87
+
88
+ ```
89
+ gasup --env dev --build --push --deploy
90
+ ```
91
+
92
+ ### Config
93
+
94
+ The config file will below.
95
+
96
+ ```ts
97
+ // gasup.config.ts
98
+ import { Config } from 'gasup';
99
+
100
+ const config:Config = {
101
+ srcDir: './src';
102
+ }
103
+
104
+ export default config;
105
+ ```
106
+
107
+ ```ts
108
+ export interface Config {
109
+ envPaths?: Record<Env, string>;
110
+ claspJsonPath?: string;
111
+ appsScriptJsonPath?: string;
112
+ bundleEntries?: string[];
113
+ bundleOutfile?: string;
114
+ srcDir?: string;
115
+ distDir?: string;
116
+ }
117
+ ```
118
+
119
+ ## License
120
+
121
+ MIT
package/dist/Config.d.ts CHANGED
@@ -1,13 +1,15 @@
1
- export type Env = 'dev' | 'stag' | 'prod';
2
- export interface Config {
3
- envPaths?: Record<Env, string>;
1
+ import { Config } from './types.js';
2
+ export declare const config: {
3
+ envPaths: {
4
+ dev: string;
5
+ stag: string;
6
+ prod: string;
7
+ };
4
8
  claspJsonPath?: string;
5
9
  appsScriptJsonPath?: string;
6
10
  bundleEntries?: string[];
7
11
  bundleOutfile?: string;
8
12
  srcDir?: string;
9
13
  distDir?: string;
10
- }
14
+ };
11
15
  export declare const defaultConfig: Config;
12
- export declare function initConfig(): void;
13
- export declare function getConfig(): Config;
package/dist/Config.js CHANGED
@@ -1,7 +1,8 @@
1
- import { readFileSync } from 'fs';
2
1
  import fs from 'fs-extra';
3
2
  import path from 'path';
4
- const configPath = 'gasup.json';
3
+ import tsnode from 'ts-node';
4
+ const configFileName = 'gasup.config.ts';
5
+ export const config = loadConfigWithDefault();
5
6
  export const defaultConfig = {
6
7
  envPaths: {
7
8
  dev: '.env',
@@ -15,21 +16,28 @@ export const defaultConfig = {
15
16
  srcDir: 'src',
16
17
  distDir: 'dist',
17
18
  };
18
- export function initConfig() {
19
- const config = getConfig();
20
- fs.writeFileSync(path.join(process.cwd(), configPath), JSON.stringify(config, null, 2));
19
+ function loadConfigWithDefault() {
20
+ const configPath = path.join(process.cwd(), configFileName);
21
+ const config = loadConfig(configPath);
22
+ return {
23
+ ...defaultConfig,
24
+ ...config,
25
+ envPaths: { ...defaultConfig.envPaths, ...(config.envPaths ?? {}) },
26
+ };
21
27
  }
22
- export function getConfig() {
28
+ function loadConfig(configPath) {
23
29
  try {
24
- const res = readFileSync(path.join(process.cwd(), configPath));
25
- const data = JSON.parse(res.toString());
26
- return {
27
- ...defaultConfig,
28
- ...data,
29
- envPaths: { ...defaultConfig.envPaths, ...(data.envPaths ?? {}) },
30
- };
30
+ const configString = fs.readFileSync(configPath, 'utf-8');
31
+ const compiledPath = path.join(__dirname, '__config_compiled.js');
32
+ const compiledCode = tsnode
33
+ .create()
34
+ .compile(configString, 'config_dummy.ts');
35
+ fs.writeFileSync(compiledPath, compiledCode);
36
+ const data = require(compiledPath);
37
+ fs.unlinkSync(compiledPath);
38
+ return data.default;
31
39
  }
32
- catch (e) {
33
- return defaultConfig;
40
+ catch (err) {
41
+ return {};
34
42
  }
35
43
  }
@@ -1,13 +1,11 @@
1
1
  import { copyFileSync } from 'fs';
2
- import { getConfig } from './config.js';
3
2
  import fs from 'fs-extra';
4
3
  import path from 'path';
4
+ import { config } from './config.js';
5
5
  export function getAppsScript() {
6
- const config = getConfig();
7
6
  const json = fs.readFileSync(config.appsScriptJsonPath, 'utf-8');
8
7
  return JSON.parse(json ?? '{}');
9
8
  }
10
9
  export function copyAppsScript() {
11
- const config = getConfig();
12
10
  copyFileSync(config.appsScriptJsonPath, path.join(config.distDir, 'appsscript.json'));
13
11
  }
package/dist/bin/gasup.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { program } from 'commander';
2
2
  import { build } from '../build.js';
3
3
  import { bundle } from '../bundle.js';
4
- import { changeEnv } from '../changeEnv.js';
4
+ import { changeEnv } from '../envFile/changeEnv.js';
5
5
  import { init } from '../init.js';
6
6
  import inquirer from 'inquirer';
7
7
  import { execSync } from 'child_process';
package/dist/build.js CHANGED
@@ -1,9 +1,8 @@
1
1
  import { execSync } from 'child_process';
2
2
  import { copyFileSync } from 'fs';
3
3
  import path from 'path';
4
- import { getConfig } from './config.js';
4
+ import { config } from './config.js';
5
5
  export function build() {
6
6
  execSync('tsc', { stdio: 'inherit' });
7
- const config = getConfig();
8
7
  copyFileSync(config.appsScriptJsonPath, path.join(config.distDir, 'appsscript.json'));
9
8
  }
package/dist/bundle.js CHANGED
@@ -1,10 +1,9 @@
1
- import { getConfig } from './config.js';
2
1
  import esbuild from 'esbuild';
3
2
  import { GasPlugin } from 'esbuild-gas-plugin';
4
3
  import fs from 'fs-extra';
5
4
  import path from 'path';
5
+ import { config } from './config.js';
6
6
  export async function bundle() {
7
- const config = getConfig();
8
7
  await esbuild.build({
9
8
  entryPoints: config.bundleEntries,
10
9
  bundle: true,
package/dist/changeEnv.js CHANGED
@@ -1,6 +1,6 @@
1
- import dotenv from 'dotenv';
2
1
  import fs from 'fs-extra';
3
2
  import { getConfig } from './config.js';
3
+ import { getEnvData } from './envFile/envFile.js';
4
4
  export function changeEnv(env = 'dev') {
5
5
  const config = getConfig();
6
6
  const envPath = config.envPaths[env];
@@ -13,14 +13,15 @@ export function changeEnv(env = 'dev') {
13
13
  throw new Error(`${path} not found`);
14
14
  }
15
15
  }
16
- dotenv.config({ path: envPath });
17
- const scriptId = process.env.GASUP_SCRIPT_ID;
16
+ const envData = getEnvData(envPath);
17
+ const scriptId = envData.GASUP_SCRIPT_ID;
18
18
  if (!scriptId) {
19
19
  throw new Error(`GASUP_SCRIPT_ID not found on ${envPath}`);
20
20
  }
21
21
  const data = {
22
22
  scriptId,
23
23
  rootDir: config.distDir,
24
+ parentId: envData.GASUP_PARENT_ID,
24
25
  };
25
26
  fs.writeFileSync(claspJsonPath, JSON.stringify(data, null, 2));
26
27
  }
@@ -1 +1,6 @@
1
- export declare function getClaspJson(): any;
1
+ export interface ClaspJson {
2
+ scriptId?: string;
3
+ rootDir?: string;
4
+ parentId?: string[];
5
+ }
6
+ export declare function getClaspJson(): ClaspJson;
package/dist/claspJson.js CHANGED
@@ -1,7 +1,6 @@
1
- import { getConfig } from './config.js';
2
1
  import fs from 'fs-extra';
2
+ import { config } from './config.js';
3
3
  export function getClaspJson() {
4
- const config = getConfig();
5
4
  const json = fs.readFileSync(config.claspJsonPath, 'utf-8');
6
5
  return JSON.parse(json ?? '{}');
7
6
  }
@@ -0,0 +1 @@
1
+ export declare function addToEnvString(envString: string, _items: Record<string, string>): string;
@@ -0,0 +1,39 @@
1
+ // 環境変数を変更する
2
+ export function addToEnvString(envString, _items) {
3
+ const items = { ..._items };
4
+ const newLines = [];
5
+ for (const line of envString.split('\n')) {
6
+ if (isCommentLine(line)) {
7
+ newLines.push(line);
8
+ }
9
+ else {
10
+ const { key, value } = parseLine(line);
11
+ if (key) {
12
+ if (items[key]) {
13
+ newLines.push(`${key}=${items[key]}`);
14
+ delete items[key];
15
+ }
16
+ else {
17
+ newLines.push(`${key}=${value}`);
18
+ }
19
+ }
20
+ else {
21
+ newLines.push('');
22
+ }
23
+ }
24
+ }
25
+ newLines.push('');
26
+ for (const [key, value] of Object.entries(items)) {
27
+ if (!key)
28
+ continue;
29
+ newLines.push(`${key}=${value}`);
30
+ }
31
+ return newLines.join('\n');
32
+ }
33
+ function isCommentLine(line) {
34
+ return line.startsWith('#');
35
+ }
36
+ function parseLine(line) {
37
+ const [key, ...values] = line.split('=');
38
+ return { key, value: values.join('=') };
39
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,56 @@
1
+ import { addToEnvString } from './addToEnvString.js';
2
+ import { describe, it, expect } from 'vitest';
3
+ describe('addToEnvString', () => {
4
+ const mockEnvString = `
5
+ # This is a comment
6
+ KEY1=value1
7
+ KEY2=value2
8
+ `.trim();
9
+ it('should add new keys to the env string and overwrite existing ones', () => {
10
+ const itemsToAdd = {
11
+ KEY3: 'value3',
12
+ KEY1: 'newValue1', // 既存のKEY1を上書きしない
13
+ };
14
+ const result = addToEnvString(mockEnvString, itemsToAdd);
15
+ // 新しい環境変数を含んだ結果を確認
16
+ const expectedContent = `
17
+ # This is a comment
18
+ KEY1=value1
19
+ KEY2=value2
20
+
21
+ KEY3=value3
22
+ `.trim();
23
+ console.log({ mockEnvString, result, expectedContent });
24
+ expect(result).toBe(expectedContent);
25
+ });
26
+ it('should add only new keys if not already in the string', () => {
27
+ const itemsToAdd = {
28
+ KEY3: 'value3',
29
+ KEY4: 'value4',
30
+ };
31
+ const result = addToEnvString(mockEnvString, itemsToAdd);
32
+ // 新しい環境変数を含んだ結果を確認
33
+ const expectedContent = `
34
+ # This is a comment
35
+ KEY1=value1
36
+ KEY2=value2
37
+
38
+ KEY3=value3
39
+ KEY4=value4
40
+ `.trim();
41
+ expect(result).toBe(expectedContent);
42
+ });
43
+ it('should handle an empty env string', () => {
44
+ const itemsToAdd = {
45
+ KEY1: 'value1',
46
+ KEY2: 'value2',
47
+ };
48
+ const result = addToEnvString('', itemsToAdd);
49
+ // 空の環境変数文字列に対して追加された内容を確認
50
+ const expectedContent = `
51
+ KEY1=value1
52
+ KEY2=value2
53
+ `.trim();
54
+ expect(result.trim()).toBe(expectedContent);
55
+ });
56
+ });
@@ -0,0 +1,2 @@
1
+ import { Env } from '../types.js';
2
+ export declare function changeEnv(env?: Env): void;
@@ -0,0 +1,26 @@
1
+ import fs from 'fs-extra';
2
+ import { config } from '../config.js';
3
+ import { getEnvData } from './envFile.js';
4
+ export function changeEnv(env = 'dev') {
5
+ const envPath = config.envPaths[env];
6
+ if (!envPath) {
7
+ throw new Error(`envPath not found on ${envPath}`);
8
+ }
9
+ const claspJsonPath = config.claspJsonPath;
10
+ for (const path of [envPath, claspJsonPath]) {
11
+ if (!fs.existsSync(path)) {
12
+ throw new Error(`${path} not found`);
13
+ }
14
+ }
15
+ const envData = getEnvData(envPath);
16
+ const scriptId = envData.GASUP_SCRIPT_ID;
17
+ if (!scriptId) {
18
+ throw new Error(`GASUP_SCRIPT_ID not found on ${envPath}`);
19
+ }
20
+ const data = {
21
+ scriptId,
22
+ rootDir: config.distDir,
23
+ parentId: envData.GASUP_PARENT_ID,
24
+ };
25
+ fs.writeFileSync(claspJsonPath, JSON.stringify(data, null, 2));
26
+ }
@@ -0,0 +1,4 @@
1
+ import { EnvObject } from '../types.js';
2
+ export declare function initEnvFiles(): void;
3
+ export declare function getEnvData(envPath: string): EnvObject;
4
+ export declare function addToEnvFile(envPath: string, _items: Record<string, string>): void;
@@ -0,0 +1,36 @@
1
+ import dotenv from 'dotenv';
2
+ import fs from 'fs-extra';
3
+ import { config } from '../config.js';
4
+ import { getClaspJson } from './../claspJson.js';
5
+ import { addToEnvString } from './addToEnvString.js';
6
+ export function initEnvFiles() {
7
+ const claspJson = getClaspJson();
8
+ const envPath = config.envPaths['dev'];
9
+ console.log({ claspJson });
10
+ addToEnvFile(envPath, {
11
+ GASUP_SCRIPT_ID: claspJson.scriptId,
12
+ GASUP_PARENT_ID: claspJson.parentId?.join(','),
13
+ });
14
+ }
15
+ export function getEnvData(envPath) {
16
+ try {
17
+ const envString = fs.readFileSync(envPath, 'utf-8');
18
+ const data = dotenv.parse(envString);
19
+ return {
20
+ GASUP_SCRIPT_ID: data.GASUP_SCRIPT_ID,
21
+ GASUP_PARENT_ID: data.GASUP_PARENT_ID?.split(','),
22
+ };
23
+ }
24
+ catch (err) {
25
+ return {};
26
+ }
27
+ }
28
+ export function addToEnvFile(envPath, _items) {
29
+ let envString = '';
30
+ try {
31
+ envString = fs.readFileSync(envPath, 'utf-8');
32
+ }
33
+ catch (e) { }
34
+ const newEnvString = addToEnvString(envString.trim(), _items);
35
+ fs.writeFileSync(envPath, newEnvString);
36
+ }
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './bundle.js';
2
- export * from './changeEnv.js';
2
+ export * from './envFile/changeEnv.js';
3
3
  export * from './config.js';
4
+ export * from './types.js';
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './bundle.js';
2
- export * from './changeEnv.js';
2
+ export * from './envFile/changeEnv.js';
3
3
  export * from './config.js';
4
+ export * from './types.js';
package/dist/init.js CHANGED
@@ -1,8 +1,6 @@
1
- import { initConfig } from './config.js';
2
- import { initEnvFiles } from './envFile.js';
1
+ import { initEnvFiles } from './envFile/envFile.js';
3
2
  import { addGitIgnores } from './gitignore.js';
4
3
  export function init() {
5
- initConfig();
6
4
  initEnvFiles();
7
5
  addGitIgnores();
8
6
  }
@@ -0,0 +1,14 @@
1
+ export type Env = 'dev' | 'stag' | 'prod';
2
+ export interface Config {
3
+ envPaths?: Record<Env, string>;
4
+ claspJsonPath?: string;
5
+ appsScriptJsonPath?: string;
6
+ bundleEntries?: string[];
7
+ bundleOutfile?: string;
8
+ srcDir?: string;
9
+ distDir?: string;
10
+ }
11
+ export interface EnvObject {
12
+ GASUP_SCRIPT_ID?: string;
13
+ GASUP_PARENT_ID?: string[];
14
+ }
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gasup",
3
- "version": "0.2.1",
3
+ "version": "0.3.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "gasup": "./dist/bin/gasup.js"