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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 NoStackApps
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# sheets-deployer
|
|
2
|
+
|
|
3
|
+
DDL provisioner for Google Sheets — treats spreadsheets as databases with tables, schemas, and migrations.
|
|
4
|
+
|
|
5
|
+
## What it does
|
|
6
|
+
|
|
7
|
+
- Creates Google Drive folders and spreadsheets as database containers
|
|
8
|
+
- Provisions tables (sheets) with typed column headers from a schema definition
|
|
9
|
+
- Builds and pushes Google Apps Script code via clasp
|
|
10
|
+
- Per-project Google account credentials with environment isolation
|
|
11
|
+
- Configurable library bundling (logger, error handler, response helper)
|
|
12
|
+
- Schema drift detection and sync
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install -g sheets-deployer
|
|
18
|
+
# or
|
|
19
|
+
npx sheets-deployer <command>
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Requirements
|
|
23
|
+
|
|
24
|
+
- Node.js >= 18
|
|
25
|
+
- [@google/clasp](https://github.com/google/clasp) >= 2.4.0
|
|
26
|
+
|
|
27
|
+
## Quick start
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# 1. Init a new project from a template
|
|
31
|
+
sheets-deployer init --db my-shop --template e-commerce
|
|
32
|
+
|
|
33
|
+
# 2. Set your GAS script ID in dbs/my-shop/db.config.json
|
|
34
|
+
|
|
35
|
+
# 3. Login (stores creds per project)
|
|
36
|
+
sheets-deployer login --db my-shop
|
|
37
|
+
|
|
38
|
+
# 4. Build + push to Google Apps Script
|
|
39
|
+
sheets-deployer push --db my-shop
|
|
40
|
+
|
|
41
|
+
# 5. Create Drive folder + spreadsheets
|
|
42
|
+
sheets-deployer create --db my-shop
|
|
43
|
+
|
|
44
|
+
# 6. Provision tables from schema
|
|
45
|
+
sheets-deployer provision --db my-shop
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Commands
|
|
49
|
+
|
|
50
|
+
| Command | Description |
|
|
51
|
+
|---------|-------------|
|
|
52
|
+
| `init` | Initialize a new DB project from a template |
|
|
53
|
+
| `build` | Build GAS output for a DB project |
|
|
54
|
+
| `push` | Build + push to Google Apps Script |
|
|
55
|
+
| `deploy` | Build + push + deploy as web app |
|
|
56
|
+
| `clean` | Clean build output |
|
|
57
|
+
| `create` | Create Drive folder + system/data spreadsheets |
|
|
58
|
+
| `provision` | Provision tables from schema.ts |
|
|
59
|
+
| `show` | List tables in data spreadsheet |
|
|
60
|
+
| `describe` | Describe a table's columns |
|
|
61
|
+
| `drop` | Drop a table |
|
|
62
|
+
| `sync` | Detect drift between schema and live sheets |
|
|
63
|
+
| `status` | Show tables with status info |
|
|
64
|
+
| `set-key` | Set the DDL API key |
|
|
65
|
+
| `rotate-key` | Generate + set a random API key |
|
|
66
|
+
| `refresh-cache` | Refresh the `__sys__tables__` cache |
|
|
67
|
+
| `setup-trigger` | Set up time-based cache refresh trigger |
|
|
68
|
+
| `remove-trigger` | Remove cache refresh trigger |
|
|
69
|
+
| `login` | Login to Google for a DB project |
|
|
70
|
+
| `whoami` | Check current Google account |
|
|
71
|
+
|
|
72
|
+
All commands accept `--db <name>` and most accept `--env <env>` (defaults to `dev`).
|
|
73
|
+
|
|
74
|
+
## Templates
|
|
75
|
+
|
|
76
|
+
Start from a pre-built schema:
|
|
77
|
+
|
|
78
|
+
| Template | Tables | Use case |
|
|
79
|
+
|----------|--------|----------|
|
|
80
|
+
| `blank` | 1 | Minimal starter |
|
|
81
|
+
| `blog-cms` | 8 | Content management (posts, categories, tags, media) |
|
|
82
|
+
| `crm` | — | Customer relationship management |
|
|
83
|
+
| `e-commerce` | — | Products, orders, customers |
|
|
84
|
+
| `inventory` | — | Stock tracking |
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
sheets-deployer init --db my-app --template blog-cms
|
|
88
|
+
sheets-deployer init --db my-app --template blank --minimal # core libs only
|
|
89
|
+
sheets-deployer init --db my-app --template crm --libs gaslogger,gaserror # pick specific libs
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Authentication
|
|
93
|
+
|
|
94
|
+
Each DB project can have its own Google account credentials, preventing accidental pushes to the wrong environment.
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# Login stores creds in dbs/<name>/.clasprc.json
|
|
98
|
+
sheets-deployer login --db my-app
|
|
99
|
+
|
|
100
|
+
# Check who's logged in
|
|
101
|
+
sheets-deployer whoami --db my-app
|
|
102
|
+
|
|
103
|
+
# Use global ~/.clasprc.json instead
|
|
104
|
+
sheets-deployer push --db my-app --inherit
|
|
105
|
+
|
|
106
|
+
# Skip account validation
|
|
107
|
+
sheets-deployer push --db my-app --force
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Account enforcement: if `db.config.json` has an `account` field per environment, push/deploy will block on mismatch.
|
|
111
|
+
|
|
112
|
+
## Project structure
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
dbs/
|
|
116
|
+
my-app/
|
|
117
|
+
db.config.json # Project config (scriptId, env settings, lib selection)
|
|
118
|
+
schema.ts # Table definitions
|
|
119
|
+
.clasprc.json # Per-project Google credentials (gitignored)
|
|
120
|
+
dist/
|
|
121
|
+
my-app/ # Built GAS output (gitignored)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### db.config.json
|
|
125
|
+
|
|
126
|
+
```json
|
|
127
|
+
{
|
|
128
|
+
"name": "my-app",
|
|
129
|
+
"libs": ["gaslogger", "gaserror", "gas_response_helper", "spreadsheets_db", "db_ddl"],
|
|
130
|
+
"settings": { "loggingVerbosity": 2 },
|
|
131
|
+
"environments": {
|
|
132
|
+
"dev": {
|
|
133
|
+
"scriptId": "YOUR_SCRIPT_ID",
|
|
134
|
+
"account": "dev@gmail.com",
|
|
135
|
+
"driveFolderId": "",
|
|
136
|
+
"systemSpreadsheetId": "",
|
|
137
|
+
"spreadsheetIds": [],
|
|
138
|
+
"deploymentId": ""
|
|
139
|
+
},
|
|
140
|
+
"prod": { ... }
|
|
141
|
+
},
|
|
142
|
+
"activeEnv": "dev"
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Libraries
|
|
147
|
+
|
|
148
|
+
The build bundles libraries into numbered `.gs` files for Google Apps Script.
|
|
149
|
+
|
|
150
|
+
**Core** (always required):
|
|
151
|
+
- `spreadsheets_db` — Database abstraction layer for Google Sheets
|
|
152
|
+
- `db_ddl` — Schema provisioning (DDL) operations
|
|
153
|
+
|
|
154
|
+
**Optional** (from [gas-common-libs](../common)):
|
|
155
|
+
- `gaslogger` — Structured logging with verbosity levels
|
|
156
|
+
- `gaserror` — Error wrapping with context, trace IDs, and stack chains
|
|
157
|
+
- `gas_response_helper` — Standardized API response formatting
|
|
158
|
+
|
|
159
|
+
Use `--minimal` to skip optional libs, or `--libs` to pick specific ones.
|
|
160
|
+
|
|
161
|
+
## Environment defaults
|
|
162
|
+
|
|
163
|
+
Create `.env.dev` or `.env.prod` at the project root for shared defaults:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
DEFAULT_ACCOUNT=dev@gmail.com
|
|
167
|
+
DRIVE_ROOT_FOLDER_ID=1abc...
|
|
168
|
+
DEFAULT_LOGGING_VERBOSITY=2
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
These are used as fallbacks when initializing new DB projects.
|
|
172
|
+
|
|
173
|
+
## Build pipeline
|
|
174
|
+
|
|
175
|
+
The build concatenates everything into numbered `.gs` files:
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
000-098 Library dependencies (from libs/ and common/)
|
|
179
|
+
099 Config template (env, scriptId, logging level)
|
|
180
|
+
100 Schema bundle (schema.ts → stripped of TS types)
|
|
181
|
+
101+ API source files (src/api/*.ts → stripped of TS + imports)
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Plus `appsscript.json` and `.clasp.json` manifests.
|
|
185
|
+
|
|
186
|
+
## License
|
|
187
|
+
|
|
188
|
+
MIT
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* CLI dispatcher for nsa-sheets-db-builder.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* nsa-sheets-db-builder <command> [options]
|
|
8
|
+
* npx nsa-sheets-db-builder <command> [options]
|
|
9
|
+
*
|
|
10
|
+
* Commands:
|
|
11
|
+
* init Initialize a new DB project from a template
|
|
12
|
+
* build Build GAS output for a DB project
|
|
13
|
+
* push Build + push to Google Apps Script
|
|
14
|
+
* deploy Build + push + deploy
|
|
15
|
+
* clean Clean build output
|
|
16
|
+
* create Create Drive folder + spreadsheets
|
|
17
|
+
* provision Provision tables from schema
|
|
18
|
+
* show Show tables in data spreadsheet
|
|
19
|
+
* describe Describe a table's columns
|
|
20
|
+
* drop Drop a table
|
|
21
|
+
* sync Sync schema — detect drift
|
|
22
|
+
* status Show tables + status info
|
|
23
|
+
* set-key Set DDL API key
|
|
24
|
+
* rotate-key Generate + set random API key
|
|
25
|
+
* refresh-cache Refresh __sys__tables__ cache
|
|
26
|
+
* setup-trigger Set up cache refresh trigger
|
|
27
|
+
* remove-trigger Remove cache refresh trigger
|
|
28
|
+
* login Login to Google for a DB project
|
|
29
|
+
* whoami Check current Google account
|
|
30
|
+
* setup Full first-time setup (create → build → deploy)
|
|
31
|
+
* ddl-handler Build, push, deploy the shared DDL handler
|
|
32
|
+
*
|
|
33
|
+
* Global options:
|
|
34
|
+
* --db <name> DB project name (required for most commands)
|
|
35
|
+
* --env <env> Target environment (default: activeEnv from config)
|
|
36
|
+
* --instance <name> Target instance (auto-selected if only one exists)
|
|
37
|
+
* --force Skip account validation
|
|
38
|
+
* --inherit Use default clasp credentials
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
import { execSync } from 'child_process';
|
|
42
|
+
import path from 'path';
|
|
43
|
+
import { fileURLToPath } from 'url';
|
|
44
|
+
|
|
45
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
46
|
+
const scriptsDir = path.resolve(__dirname, '..', 'scripts');
|
|
47
|
+
|
|
48
|
+
// Command → script mapping
|
|
49
|
+
const COMMANDS = {
|
|
50
|
+
'init': 'init.mjs',
|
|
51
|
+
'build': 'build.mjs',
|
|
52
|
+
'push': ['build.mjs', '--push'],
|
|
53
|
+
'deploy': ['build.mjs', '--push', '--deploy'],
|
|
54
|
+
'clean': 'clean.mjs',
|
|
55
|
+
'create': 'create.mjs',
|
|
56
|
+
'provision': 'provision.mjs',
|
|
57
|
+
'show': 'show.mjs',
|
|
58
|
+
'describe': 'describe.mjs',
|
|
59
|
+
'drop': 'drop.mjs',
|
|
60
|
+
'sync': 'sync.mjs',
|
|
61
|
+
'status': ['show.mjs', '--status'],
|
|
62
|
+
'set-key': 'set-key.mjs',
|
|
63
|
+
'rotate-key': ['set-key.mjs', '--rotate'],
|
|
64
|
+
'refresh-cache': 'refresh-cache.mjs',
|
|
65
|
+
'setup-trigger': 'setup-trigger.mjs',
|
|
66
|
+
'remove-trigger': ['setup-trigger.mjs', '--remove'],
|
|
67
|
+
'login': 'login.mjs',
|
|
68
|
+
'whoami': 'whoami.mjs',
|
|
69
|
+
'setup': 'setup.mjs',
|
|
70
|
+
'ddl-handler': 'ddl-handler.mjs'
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const command = process.argv[2];
|
|
74
|
+
const restArgs = process.argv.slice(3);
|
|
75
|
+
|
|
76
|
+
if (!command || command === '--help' || command === '-h') {
|
|
77
|
+
console.log('nsa-sheets-db-builder v4.0.0 — Google Sheets database provisioner\n');
|
|
78
|
+
console.log('Usage: nsa-sheets-db-builder <command> [options]\n');
|
|
79
|
+
console.log('Commands:');
|
|
80
|
+
const maxLen = Math.max(...Object.keys(COMMANDS).map(k => k.length));
|
|
81
|
+
for (const cmd of Object.keys(COMMANDS)) {
|
|
82
|
+
console.log(` ${cmd.padEnd(maxLen + 2)} ${getDescription(cmd)}`);
|
|
83
|
+
}
|
|
84
|
+
console.log('\nGlobal options:');
|
|
85
|
+
console.log(' --db <name> DB project name (required for most commands)');
|
|
86
|
+
console.log(' --env <env> Target environment (default: activeEnv from config)');
|
|
87
|
+
console.log(' --instance <type> Target instance: rw, r, w (or full name / scriptId)');
|
|
88
|
+
console.log(' --force Skip account validation');
|
|
89
|
+
console.log(' --inherit Use default clasp credentials');
|
|
90
|
+
console.log('\nInstance type aliases:');
|
|
91
|
+
console.log(' rw = read-write Full CRUD + locking');
|
|
92
|
+
console.log(' r = read-only Read operations only, no locking');
|
|
93
|
+
console.log(' w = write-only Write operations only');
|
|
94
|
+
console.log('\nFeature flags (init only):');
|
|
95
|
+
console.log(' --rbac <mode> Enable RBAC (mode: request | workspace)');
|
|
96
|
+
console.log(' --views Enable SQL views support');
|
|
97
|
+
console.log('\nProject layout:');
|
|
98
|
+
console.log(' dbs/<name>/project.json Project config (all-in-one)');
|
|
99
|
+
console.log(' dbs/<name>/tables.json Table definitions (schema)');
|
|
100
|
+
console.log(' dbs/<name>/customMethods.json Custom method declarations');
|
|
101
|
+
console.log(' dbs/<name>/libs/ Library source files (.ts)');
|
|
102
|
+
console.log(' dbs/<name>/overrides/ Custom method handler files (.ts)');
|
|
103
|
+
console.log(' dbs/<name>/rbac.json RBAC config (if enabled)');
|
|
104
|
+
console.log(' dbs/<name>/views.json SQL view definitions (if enabled)');
|
|
105
|
+
console.log('\nExamples:');
|
|
106
|
+
console.log(' nsa-sheets-db-builder init --db my-app --template blog-cms');
|
|
107
|
+
console.log(' nsa-sheets-db-builder init --db my-app --instances r,w');
|
|
108
|
+
console.log(' nsa-sheets-db-builder init --db my-app --rbac request --views');
|
|
109
|
+
console.log(' nsa-sheets-db-builder build --db my-app');
|
|
110
|
+
console.log(' nsa-sheets-db-builder push --db my-app --instance rw');
|
|
111
|
+
console.log(' nsa-sheets-db-builder deploy --db my-app --instance r');
|
|
112
|
+
process.exit(0);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (!COMMANDS[command]) {
|
|
116
|
+
console.error(`Unknown command: "${command}"`);
|
|
117
|
+
console.error(`Run "nsa-sheets-db-builder --help" for available commands.`);
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Resolve script + any built-in args
|
|
122
|
+
const mapping = COMMANDS[command];
|
|
123
|
+
const scriptFile = Array.isArray(mapping) ? mapping[0] : mapping;
|
|
124
|
+
const builtinArgs = Array.isArray(mapping) ? mapping.slice(1) : [];
|
|
125
|
+
|
|
126
|
+
const scriptPath = path.join(scriptsDir, scriptFile);
|
|
127
|
+
const allArgs = [...builtinArgs, ...restArgs];
|
|
128
|
+
|
|
129
|
+
// Set PROJECT_ROOT to cwd so dbs/ and dist/ resolve relative to user's directory
|
|
130
|
+
const env = {
|
|
131
|
+
...process.env,
|
|
132
|
+
NSA_SHEETS_DB_BUILDER_ROOT: process.cwd()
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
execSync(`node "${scriptPath}" ${allArgs.map(a => `"${a}"`).join(' ')}`, {
|
|
137
|
+
stdio: 'inherit',
|
|
138
|
+
env
|
|
139
|
+
});
|
|
140
|
+
} catch {
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function getDescription(cmd) {
|
|
145
|
+
const descriptions = {
|
|
146
|
+
'init': 'Initialize a new DB project from a template',
|
|
147
|
+
'build': 'Build GAS output for a DB project (all instances)',
|
|
148
|
+
'push': 'Build + push instance to Google Apps Script',
|
|
149
|
+
'deploy': 'Build + push + deploy instance',
|
|
150
|
+
'clean': 'Clean build output',
|
|
151
|
+
'create': 'Create Drive folder + spreadsheets',
|
|
152
|
+
'provision': 'Provision tables from schema',
|
|
153
|
+
'show': 'Show tables in data spreadsheet',
|
|
154
|
+
'describe': 'Describe a table\'s columns',
|
|
155
|
+
'drop': 'Drop a table',
|
|
156
|
+
'sync': 'Sync schema — detect drift',
|
|
157
|
+
'status': 'Show tables + status info',
|
|
158
|
+
'set-key': 'Set DDL API key (per instance)',
|
|
159
|
+
'rotate-key': 'Generate + set random API key (per instance)',
|
|
160
|
+
'refresh-cache': 'Refresh __sys__tables__ cache',
|
|
161
|
+
'setup-trigger': 'Set up cache refresh trigger',
|
|
162
|
+
'remove-trigger': 'Remove cache refresh trigger',
|
|
163
|
+
'login': 'Login to Google for a DB project',
|
|
164
|
+
'whoami': 'Check current Google account',
|
|
165
|
+
'setup': 'Full first-time setup: create GAS projects, build, push, deploy',
|
|
166
|
+
'ddl-handler': 'Build, push, deploy the shared DDL handler'
|
|
167
|
+
};
|
|
168
|
+
return descriptions[cmd] || '';
|
|
169
|
+
}
|