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.
Files changed (44) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +188 -0
  3. package/bin/sheets-deployer.mjs +169 -0
  4. package/libs/alasql.js +15577 -0
  5. package/libs/common/gas_response_helper.ts +147 -0
  6. package/libs/common/gaserror.ts +101 -0
  7. package/libs/common/gaslogger.ts +172 -0
  8. package/libs/db_ddl.ts +316 -0
  9. package/libs/libraries.json +56 -0
  10. package/libs/spreadsheets_db.ts +4406 -0
  11. package/libs/triggers.ts +113 -0
  12. package/package.json +73 -0
  13. package/scripts/build.mjs +513 -0
  14. package/scripts/clean.mjs +31 -0
  15. package/scripts/create.mjs +94 -0
  16. package/scripts/ddl-handler.mjs +232 -0
  17. package/scripts/describe.mjs +38 -0
  18. package/scripts/drop.mjs +39 -0
  19. package/scripts/init.mjs +465 -0
  20. package/scripts/lib/utils.mjs +1019 -0
  21. package/scripts/login.mjs +102 -0
  22. package/scripts/provision.mjs +35 -0
  23. package/scripts/refresh-cache.mjs +34 -0
  24. package/scripts/set-key.mjs +48 -0
  25. package/scripts/setup-trigger.mjs +95 -0
  26. package/scripts/setup.mjs +677 -0
  27. package/scripts/show.mjs +37 -0
  28. package/scripts/sync.mjs +35 -0
  29. package/scripts/whoami.mjs +36 -0
  30. package/src/api/ddl-handler-entry.ts +136 -0
  31. package/src/api/ddl.ts +321 -0
  32. package/src/templates/.clasp.json.ejs +1 -0
  33. package/src/templates/appsscript.json.ejs +16 -0
  34. package/src/templates/config.ts.ejs +14 -0
  35. package/src/templates/ddl-handler-config.ts.ejs +3 -0
  36. package/src/templates/ddl-handler-main.ts.ejs +56 -0
  37. package/src/templates/main.ts.ejs +288 -0
  38. package/src/templates/rbac.ts.ejs +148 -0
  39. package/src/templates/views.ts.ejs +92 -0
  40. package/templates/blank.json +33 -0
  41. package/templates/blog-cms.json +507 -0
  42. package/templates/crm.json +360 -0
  43. package/templates/e-commerce.json +424 -0
  44. 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
+ }