nsa-sheets-db-builder 4.0.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/LICENSE +21 -0
- package/README.md +188 -0
- package/bin/sheets-deployer.mjs +169 -0
- package/libs/alasql.js +15577 -0
- package/libs/common/gas_response_helper.ts +147 -0
- package/libs/common/gaserror.ts +101 -0
- package/libs/common/gaslogger.ts +172 -0
- package/libs/db_ddl.ts +316 -0
- package/libs/libraries.json +56 -0
- package/libs/spreadsheets_db.ts +4406 -0
- package/libs/triggers.ts +113 -0
- package/package.json +73 -0
- package/scripts/build.mjs +513 -0
- package/scripts/clean.mjs +31 -0
- package/scripts/create.mjs +94 -0
- package/scripts/ddl-handler.mjs +232 -0
- package/scripts/describe.mjs +38 -0
- package/scripts/drop.mjs +39 -0
- package/scripts/init.mjs +465 -0
- package/scripts/lib/utils.mjs +1019 -0
- package/scripts/login.mjs +102 -0
- package/scripts/provision.mjs +35 -0
- package/scripts/refresh-cache.mjs +34 -0
- package/scripts/set-key.mjs +48 -0
- package/scripts/setup-trigger.mjs +95 -0
- package/scripts/setup.mjs +677 -0
- package/scripts/show.mjs +37 -0
- package/scripts/sync.mjs +35 -0
- package/scripts/whoami.mjs +36 -0
- package/src/api/ddl-handler-entry.ts +136 -0
- package/src/api/ddl.ts +321 -0
- package/src/templates/.clasp.json.ejs +1 -0
- package/src/templates/appsscript.json.ejs +16 -0
- package/src/templates/config.ts.ejs +14 -0
- package/src/templates/ddl-handler-config.ts.ejs +3 -0
- package/src/templates/ddl-handler-main.ts.ejs +56 -0
- package/src/templates/main.ts.ejs +288 -0
- package/src/templates/rbac.ts.ejs +148 -0
- package/src/templates/views.ts.ejs +92 -0
- package/templates/blank.json +33 -0
- package/templates/blog-cms.json +507 -0
- package/templates/crm.json +360 -0
- package/templates/e-commerce.json +424 -0
- package/templates/inventory.json +307 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Clean built output for nsa-sheets-db-builder.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* node scripts/clean.mjs --db <name> # Clean dist/<name>/
|
|
8
|
+
* node scripts/clean.mjs # Clean all of dist/
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import fs from 'fs';
|
|
12
|
+
import { parseArgs, getDistDir, DIST_DIR } from './lib/utils.mjs';
|
|
13
|
+
|
|
14
|
+
const args = parseArgs();
|
|
15
|
+
|
|
16
|
+
if (args.db) {
|
|
17
|
+
const distDir = getDistDir(args.db);
|
|
18
|
+
if (fs.existsSync(distDir)) {
|
|
19
|
+
fs.rmSync(distDir, { recursive: true });
|
|
20
|
+
console.log(`Cleaned dist/${args.db}/`);
|
|
21
|
+
} else {
|
|
22
|
+
console.log(`dist/${args.db}/ does not exist, nothing to clean.`);
|
|
23
|
+
}
|
|
24
|
+
} else {
|
|
25
|
+
if (fs.existsSync(DIST_DIR)) {
|
|
26
|
+
fs.rmSync(DIST_DIR, { recursive: true });
|
|
27
|
+
console.log('Cleaned dist/ (all DBs)');
|
|
28
|
+
} else {
|
|
29
|
+
console.log('dist/ does not exist, nothing to clean.');
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Set up a new DB project: Drive folder + system spreadsheet + data spreadsheet + trigger.
|
|
5
|
+
* After creation, updates tables.json to replace __new__ spreadsheetIds with real IDs.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* node scripts/create.mjs --db <name> [--env <env>] [--instance <type>]
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { parseArgs, requireDb, loadDbConfig, getEnvConfig, getDistDirForInstance, claspRun, loadTables, saveTables, saveProjectConfig, requireInstance, ensureAuthenticated } from './lib/utils.mjs';
|
|
12
|
+
|
|
13
|
+
const args = parseArgs();
|
|
14
|
+
const dbName = requireDb(args, 'create.mjs');
|
|
15
|
+
const config = loadDbConfig(dbName);
|
|
16
|
+
const { env, envConfig } = getEnvConfig(config, args.env);
|
|
17
|
+
const instance = requireInstance(args, envConfig);
|
|
18
|
+
const distDir = getDistDirForInstance(dbName, instance.type);
|
|
19
|
+
|
|
20
|
+
if (envConfig.systemSpreadsheetId) {
|
|
21
|
+
console.log(`Environment "${env}" already set up:`);
|
|
22
|
+
console.log(` systemSpreadsheetId: ${envConfig.systemSpreadsheetId}`);
|
|
23
|
+
console.log(` driveFolderId: ${envConfig.driveFolderId}`);
|
|
24
|
+
console.log('\nTo recreate, clear systemSpreadsheetId in project.json first.');
|
|
25
|
+
process.exit(0);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Auth enforcement
|
|
29
|
+
const userProfile = await ensureAuthenticated(dbName, args, envConfig, env);
|
|
30
|
+
|
|
31
|
+
// 1. Setup: create Drive folder + system spreadsheet + trigger
|
|
32
|
+
const folderName = `${config.name}-${env}`;
|
|
33
|
+
console.log(`Setting up ${dbName} (${env})...`);
|
|
34
|
+
console.log(` Creating Drive folder: ${folderName}`);
|
|
35
|
+
|
|
36
|
+
const setupResult = claspRun(distDir, 'ddlSetup', [{
|
|
37
|
+
name: folderName,
|
|
38
|
+
driveFolderId: envConfig.driveFolderId || undefined
|
|
39
|
+
}], { userProfile });
|
|
40
|
+
|
|
41
|
+
if (!setupResult?.systemSpreadsheetId) {
|
|
42
|
+
console.error('\nSetup failed:', JSON.stringify(setupResult, null, 2));
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
envConfig.driveFolderId = setupResult.folderId;
|
|
47
|
+
envConfig.systemSpreadsheetId = setupResult.systemSpreadsheetId;
|
|
48
|
+
|
|
49
|
+
console.log(` Drive folder: ${setupResult.folderUrl}`);
|
|
50
|
+
console.log(` System spreadsheet: ${setupResult.systemSpreadsheetId}`);
|
|
51
|
+
|
|
52
|
+
// 2. Check tables.json for __new__ spreadsheetIds and create data spreadsheets
|
|
53
|
+
const tables = loadTables(dbName);
|
|
54
|
+
let createdCount = 0;
|
|
55
|
+
|
|
56
|
+
// Find tables that need a new spreadsheet
|
|
57
|
+
const needsNew = Object.entries(tables).filter(([, t]) => t.spreadsheetId === '__new__');
|
|
58
|
+
|
|
59
|
+
if (needsNew.length > 0) {
|
|
60
|
+
const dataName = `${config.name}-data`;
|
|
61
|
+
console.log(` Creating data spreadsheet: ${dataName}`);
|
|
62
|
+
|
|
63
|
+
const dataResult = claspRun(distDir, 'ddlCreateDataSpreadsheet', [{
|
|
64
|
+
name: dataName,
|
|
65
|
+
folderId: setupResult.folderId
|
|
66
|
+
}], { userProfile });
|
|
67
|
+
|
|
68
|
+
if (dataResult?.spreadsheetId) {
|
|
69
|
+
console.log(` Data spreadsheet: ${dataResult.spreadsheetId}`);
|
|
70
|
+
|
|
71
|
+
// Replace __new__ with real spreadsheet ID in tables.json
|
|
72
|
+
for (const [name, table] of Object.entries(tables)) {
|
|
73
|
+
if (table.spreadsheetId === '__new__') {
|
|
74
|
+
table.spreadsheetId = dataResult.spreadsheetId;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
saveTables(dbName, tables);
|
|
78
|
+
createdCount++;
|
|
79
|
+
|
|
80
|
+
console.log(` Updated tables.json: replaced __new__ → ${dataResult.spreadsheetId}`);
|
|
81
|
+
} else {
|
|
82
|
+
console.warn(' Warning: data spreadsheet creation result:', JSON.stringify(dataResult, null, 2));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// 3. Save project config
|
|
87
|
+
saveProjectConfig(dbName, config);
|
|
88
|
+
|
|
89
|
+
console.log(`\nSetup complete for ${dbName} (${env}).`);
|
|
90
|
+
console.log(` Written to dbs/${dbName}/project.json`);
|
|
91
|
+
if (createdCount > 0) {
|
|
92
|
+
console.log(` Updated dbs/${dbName}/tables.json with spreadsheet IDs`);
|
|
93
|
+
}
|
|
94
|
+
console.log(`\nNext: nsa-sheets-db-builder provision --db ${dbName}`);
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Standalone DDL handler management.
|
|
5
|
+
*
|
|
6
|
+
* The DDL handler is a separate, generic Apps Script project deployed
|
|
7
|
+
* once per Google account. It handles schema operations (create folders,
|
|
8
|
+
* spreadsheets, provision tables, etc.) via HTTP POST.
|
|
9
|
+
*
|
|
10
|
+
* This script can be used independently of setup.mjs to:
|
|
11
|
+
* - Build the DDL handler
|
|
12
|
+
* - Push it to Apps Script
|
|
13
|
+
* - Deploy it as a web app
|
|
14
|
+
*
|
|
15
|
+
* The DDL handler reference is stored in .nsaproject.json (root config)
|
|
16
|
+
* under environments.<env>.ddlHandler.
|
|
17
|
+
*
|
|
18
|
+
* Usage:
|
|
19
|
+
* node scripts/ddl-handler.mjs [--build] [--push] [--deploy]
|
|
20
|
+
* --db <name> DB project (for auth profile resolution)
|
|
21
|
+
* --env <env> Environment (default: dev)
|
|
22
|
+
* --force Skip account validation
|
|
23
|
+
* --inherit Use default clasp credentials
|
|
24
|
+
*
|
|
25
|
+
* Examples:
|
|
26
|
+
* # Build + push + deploy (default: does all three):
|
|
27
|
+
* nsa-sheets-db-builder ddl-handler --db my-app
|
|
28
|
+
*
|
|
29
|
+
* # Just rebuild (e.g. after updating libs):
|
|
30
|
+
* nsa-sheets-db-builder ddl-handler --db my-app --build
|
|
31
|
+
*
|
|
32
|
+
* # Push + update existing deployment:
|
|
33
|
+
* nsa-sheets-db-builder ddl-handler --db my-app --push --deploy
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
import fs from 'fs';
|
|
37
|
+
import os from 'os';
|
|
38
|
+
import path from 'path';
|
|
39
|
+
import crypto from 'crypto';
|
|
40
|
+
import { execSync } from 'child_process';
|
|
41
|
+
import {
|
|
42
|
+
parseArgs, requireDb, loadDbConfig, getEnvConfig,
|
|
43
|
+
ensureAuthenticated, resolveAccount,
|
|
44
|
+
loadRootConfig, saveRootConfig,
|
|
45
|
+
getDdlHandlerDistDir
|
|
46
|
+
} from './lib/utils.mjs';
|
|
47
|
+
import { buildDdlHandler } from './build.mjs';
|
|
48
|
+
|
|
49
|
+
// ────────────────────────────────────────
|
|
50
|
+
// Helpers
|
|
51
|
+
// ────────────────────────────────────────
|
|
52
|
+
|
|
53
|
+
function parseDeploymentId(output) {
|
|
54
|
+
const match = output.match(/(?:^Deployed |^- )(\S+) @/m);
|
|
55
|
+
return match ? match[1] : null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function userFlag(profile) {
|
|
59
|
+
return profile ? ` --user ${profile}` : '';
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function generateAdminKey() {
|
|
63
|
+
return crypto.randomBytes(24).toString('hex');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ────────────────────────────────────────
|
|
67
|
+
// Main
|
|
68
|
+
// ────────────────────────────────────────
|
|
69
|
+
|
|
70
|
+
async function main() {
|
|
71
|
+
const args = parseArgs();
|
|
72
|
+
const dbName = requireDb(args, 'ddl-handler.mjs');
|
|
73
|
+
|
|
74
|
+
const config = loadDbConfig(dbName);
|
|
75
|
+
const { env, envConfig } = getEnvConfig(config, args.env);
|
|
76
|
+
|
|
77
|
+
const account = resolveAccount(envConfig, env);
|
|
78
|
+
if (!account) {
|
|
79
|
+
console.error('ERROR: account not set.');
|
|
80
|
+
console.error(`Set "account" in .nsaproject.json → environments.${env}`);
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
console.log(`\nDDL Handler — account: ${account} (via ${dbName}/${env})`);
|
|
85
|
+
console.log('='.repeat(50));
|
|
86
|
+
|
|
87
|
+
const userProfile = await ensureAuthenticated(dbName, args, envConfig, env);
|
|
88
|
+
|
|
89
|
+
// Default: if no flags provided, do all three
|
|
90
|
+
const doBuild = args.build || (!args.build && !args.push && !args.deploy);
|
|
91
|
+
const doPush = args.push || (!args.build && !args.push && !args.deploy);
|
|
92
|
+
const doDeploy = args.deploy || (!args.build && !args.push && !args.deploy);
|
|
93
|
+
|
|
94
|
+
// Load existing handler state from root config
|
|
95
|
+
let rootConfig = loadRootConfig();
|
|
96
|
+
let rootEnv = rootConfig.environments?.[env] || {};
|
|
97
|
+
let handler = rootEnv.ddlHandler || {};
|
|
98
|
+
|
|
99
|
+
const ddlAdminKey = handler.ddlAdminKey || generateAdminKey();
|
|
100
|
+
let scriptId = handler.scriptId || '';
|
|
101
|
+
let deploymentId = handler.deploymentId || '';
|
|
102
|
+
|
|
103
|
+
// ── Create GAS project if needed ──
|
|
104
|
+
|
|
105
|
+
if (!scriptId) {
|
|
106
|
+
const title = `ddl-handler-${account.split('@')[0]}`;
|
|
107
|
+
console.log(`\nCreating GAS project: ${title}`);
|
|
108
|
+
|
|
109
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'nsa-sheets-db-builder-ddl-'));
|
|
110
|
+
try {
|
|
111
|
+
execSync(
|
|
112
|
+
`npx --prefer-offline @google/clasp create --type webapp --title "${title}" --rootDir .${userFlag(userProfile)}`,
|
|
113
|
+
{ cwd: tmpDir, stdio: 'pipe' }
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
const claspJson = JSON.parse(fs.readFileSync(path.join(tmpDir, '.clasp.json'), 'utf8'));
|
|
117
|
+
scriptId = claspJson.scriptId;
|
|
118
|
+
|
|
119
|
+
if (!scriptId) {
|
|
120
|
+
console.error('ERROR: clasp create succeeded but no scriptId found.');
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
console.log(` scriptId: ${scriptId}`);
|
|
125
|
+
} catch (err) {
|
|
126
|
+
const stderr = err.stderr?.toString() || '';
|
|
127
|
+
const stdout = err.stdout?.toString() || '';
|
|
128
|
+
console.error('\nclasp create failed for DDL handler:');
|
|
129
|
+
if (stderr) console.error(stderr);
|
|
130
|
+
if (stdout) console.error(stdout);
|
|
131
|
+
process.exit(1);
|
|
132
|
+
} finally {
|
|
133
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
134
|
+
}
|
|
135
|
+
} else {
|
|
136
|
+
console.log(`\nUsing existing scriptId: ${scriptId}`);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ── Build ──
|
|
140
|
+
|
|
141
|
+
if (doBuild) {
|
|
142
|
+
console.log('\n-- Build --');
|
|
143
|
+
const loggingVerbosity = config.settings?.loggingVerbosity ?? 2;
|
|
144
|
+
const projectId = rootEnv.projectId || '';
|
|
145
|
+
buildDdlHandler(ddlAdminKey, loggingVerbosity, scriptId, projectId);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// ── Push ──
|
|
149
|
+
|
|
150
|
+
if (doPush) {
|
|
151
|
+
console.log('\n-- Push --');
|
|
152
|
+
const ddlDistDir = getDdlHandlerDistDir();
|
|
153
|
+
|
|
154
|
+
if (!fs.existsSync(path.join(ddlDistDir, '.clasp.json'))) {
|
|
155
|
+
console.error('ERROR: DDL handler not built yet. Run with --build first.');
|
|
156
|
+
process.exit(1);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
console.log(' Pushing DDL handler...');
|
|
160
|
+
try {
|
|
161
|
+
execSync(`npx --prefer-offline @google/clasp push --force${userFlag(userProfile)}`, {
|
|
162
|
+
cwd: ddlDistDir,
|
|
163
|
+
stdio: 'inherit'
|
|
164
|
+
});
|
|
165
|
+
} catch {
|
|
166
|
+
console.error(' clasp push failed for DDL handler.');
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// ── Deploy ──
|
|
172
|
+
|
|
173
|
+
if (doDeploy) {
|
|
174
|
+
console.log('\n-- Deploy --');
|
|
175
|
+
const ddlDistDir = getDdlHandlerDistDir();
|
|
176
|
+
|
|
177
|
+
if (deploymentId) {
|
|
178
|
+
console.log(` Updating deployment: ${deploymentId}`);
|
|
179
|
+
execSync(
|
|
180
|
+
`npx --prefer-offline @google/clasp update-deployment ${deploymentId} --description 'DDL Handler'${userFlag(userProfile)}`,
|
|
181
|
+
{ cwd: ddlDistDir, stdio: 'inherit' }
|
|
182
|
+
);
|
|
183
|
+
} else {
|
|
184
|
+
console.log(' Creating new deployment...');
|
|
185
|
+
const output = execSync(
|
|
186
|
+
`npx --prefer-offline @google/clasp deploy --description 'DDL Handler'${userFlag(userProfile)}`,
|
|
187
|
+
{ cwd: ddlDistDir, encoding: 'utf8' }
|
|
188
|
+
);
|
|
189
|
+
deploymentId = parseDeploymentId(output);
|
|
190
|
+
if (!deploymentId) {
|
|
191
|
+
console.error(' ERROR: could not parse deployment ID from clasp output:');
|
|
192
|
+
console.error(output);
|
|
193
|
+
process.exit(1);
|
|
194
|
+
}
|
|
195
|
+
console.log(` deploymentId: ${deploymentId}`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// ── Save state to .nsaproject.json ──
|
|
200
|
+
|
|
201
|
+
rootConfig = loadRootConfig();
|
|
202
|
+
if (!rootConfig.environments) rootConfig.environments = {};
|
|
203
|
+
if (!rootConfig.environments[env]) rootConfig.environments[env] = {};
|
|
204
|
+
rootConfig.environments[env].ddlHandler = {
|
|
205
|
+
scriptId,
|
|
206
|
+
deploymentId,
|
|
207
|
+
ddlAdminKey
|
|
208
|
+
};
|
|
209
|
+
saveRootConfig(rootConfig);
|
|
210
|
+
|
|
211
|
+
// ── Summary ──
|
|
212
|
+
|
|
213
|
+
console.log('\n-- DDL Handler --');
|
|
214
|
+
console.log(` Account: ${account}`);
|
|
215
|
+
console.log(` Script: https://script.google.com/d/${scriptId}/edit`);
|
|
216
|
+
if (deploymentId) {
|
|
217
|
+
console.log(` Web app: https://script.google.com/macros/s/${deploymentId}/exec`);
|
|
218
|
+
}
|
|
219
|
+
console.log(` Admin key: ${ddlAdminKey.substring(0, 8)}...`);
|
|
220
|
+
console.log(` Saved to: .nsaproject.json`);
|
|
221
|
+
|
|
222
|
+
if (doDeploy && !handler.deploymentId) {
|
|
223
|
+
console.log(`\n NOTE: Authorize the DDL handler in the Apps Script editor:`);
|
|
224
|
+
console.log(` https://script.google.com/d/${scriptId}/edit`);
|
|
225
|
+
console.log(` Open the editor → Run any function → Approve permissions.`);
|
|
226
|
+
console.log(` This only needs to be done ONCE per Google account.`);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
console.log('\nDone.');
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
main();
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Describe a table's columns.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* node scripts/describe.mjs --db <name> --table <table> [--env <env>] [--instance <type>]
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { parseArgs, requireDb, loadDbConfig, getEnvConfig, getDistDirForInstance, claspRun, loadTables, requireDataSpreadsheet, requireInstance, ensureAuthenticated } from './lib/utils.mjs';
|
|
11
|
+
|
|
12
|
+
const args = parseArgs();
|
|
13
|
+
const dbName = requireDb(args, 'describe.mjs');
|
|
14
|
+
|
|
15
|
+
if (!args.table) {
|
|
16
|
+
console.error('Usage: node scripts/describe.mjs --db <name> --table <table> [--env <env>] [--instance <type>]');
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const config = loadDbConfig(dbName);
|
|
21
|
+
const { env, envConfig } = getEnvConfig(config, args.env);
|
|
22
|
+
const instance = requireInstance(args, envConfig);
|
|
23
|
+
const distDir = getDistDirForInstance(dbName, instance.type);
|
|
24
|
+
|
|
25
|
+
const tables = loadTables(dbName);
|
|
26
|
+
const spreadsheetId = requireDataSpreadsheet(tables, dbName);
|
|
27
|
+
|
|
28
|
+
// Auth enforcement
|
|
29
|
+
const userProfile = await ensureAuthenticated(dbName, args, envConfig, env);
|
|
30
|
+
|
|
31
|
+
console.log(`Describing table "${args.table}" for ${dbName} (${env}, ${instance.type})...`);
|
|
32
|
+
|
|
33
|
+
const result = claspRun(distDir, 'ddlDescribeTable', [{
|
|
34
|
+
spreadsheetId,
|
|
35
|
+
table: args.table
|
|
36
|
+
}], { userProfile });
|
|
37
|
+
|
|
38
|
+
console.log('\nResult:', JSON.stringify(result, null, 2));
|
package/scripts/drop.mjs
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Drop a table from a data spreadsheet.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* node scripts/drop.mjs --db <name> --table <table> [--env <env>] [--instance <type>]
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { parseArgs, requireDb, loadDbConfig, getEnvConfig, getDistDirForInstance, claspRun, loadTables, requireDataSpreadsheet, requireInstance, ensureAuthenticated } from './lib/utils.mjs';
|
|
11
|
+
|
|
12
|
+
const args = parseArgs();
|
|
13
|
+
const dbName = requireDb(args, 'drop.mjs');
|
|
14
|
+
|
|
15
|
+
if (!args.table) {
|
|
16
|
+
console.error('Usage: node scripts/drop.mjs --db <name> --table <table> [--env <env>] [--instance <type>]');
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const config = loadDbConfig(dbName);
|
|
21
|
+
const { env, envConfig } = getEnvConfig(config, args.env);
|
|
22
|
+
const instance = requireInstance(args, envConfig);
|
|
23
|
+
const distDir = getDistDirForInstance(dbName, instance.type);
|
|
24
|
+
|
|
25
|
+
const tables = loadTables(dbName);
|
|
26
|
+
const spreadsheetId = requireDataSpreadsheet(tables, dbName);
|
|
27
|
+
|
|
28
|
+
// Auth enforcement
|
|
29
|
+
const userProfile = await ensureAuthenticated(dbName, args, envConfig, env);
|
|
30
|
+
|
|
31
|
+
console.log(`Dropping table "${args.table}" from ${dbName} (${env}, ${instance.type})...`);
|
|
32
|
+
console.log(` Data spreadsheet: ${spreadsheetId}`);
|
|
33
|
+
|
|
34
|
+
const result = claspRun(distDir, 'ddlDropTable', [{
|
|
35
|
+
spreadsheetId,
|
|
36
|
+
table: args.table
|
|
37
|
+
}], { userProfile });
|
|
38
|
+
|
|
39
|
+
console.log('\nResult:', JSON.stringify(result, null, 2));
|