@t1mmen/srtd 0.2.2 → 0.4.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/README.md +170 -146
- package/dist/__tests__/vitest.setup.js +41 -25
- package/dist/__tests__/vitest.setup.js.map +1 -1
- package/dist/__tests__/watch.test.js +0 -1
- package/dist/__tests__/watch.test.js.map +1 -1
- package/dist/cli.js +3 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/_app.js +31 -3
- package/dist/commands/_app.js.map +1 -1
- package/dist/commands/apply.d.ts +13 -1
- package/dist/commands/apply.js +19 -6
- package/dist/commands/apply.js.map +1 -1
- package/dist/commands/build.d.ts +13 -1
- package/dist/commands/build.js +14 -4
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/clear.d.ts +2 -0
- package/dist/commands/clear.js +45 -0
- package/dist/commands/clear.js.map +1 -0
- package/dist/commands/index.js +25 -10
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/register.js +9 -6
- package/dist/commands/register.js.map +1 -1
- package/dist/commands/watch.js +121 -117
- package/dist/commands/watch.js.map +1 -1
- package/dist/components/Branding.js +5 -4
- package/dist/components/Branding.js.map +1 -1
- package/dist/components/Quittable.d.ts +6 -0
- package/dist/components/Quittable.js +36 -0
- package/dist/components/Quittable.js.map +1 -0
- package/dist/hooks/useDatabaseConnection.d.ts +7 -0
- package/dist/hooks/useDatabaseConnection.js +68 -0
- package/dist/hooks/useDatabaseConnection.js.map +1 -0
- package/dist/hooks/useTemplateManager.d.ts +22 -0
- package/dist/hooks/useTemplateManager.js +124 -0
- package/dist/hooks/useTemplateManager.js.map +1 -0
- package/dist/lib/templateManager.d.ts +12 -5
- package/dist/lib/templateManager.js +166 -60
- package/dist/lib/templateManager.js.map +1 -1
- package/dist/lib/templateManager.test.js +452 -15
- package/dist/lib/templateManager.test.js.map +1 -1
- package/dist/types.d.ts +2 -1
- package/dist/utils/config.d.ts +2 -0
- package/dist/utils/config.js +27 -40
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/databaseConnection.d.ts +5 -1
- package/dist/utils/databaseConnection.js +40 -9
- package/dist/utils/databaseConnection.js.map +1 -1
- package/dist/utils/logger.d.ts +1 -0
- package/package.json +12 -7
- package/dist/commands/help.d.ts +0 -1
- package/dist/commands/help.js +0 -2
- package/dist/commands/help.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,17 +1,27 @@
|
|
|
1
1
|
# `srtd` 🪄 Supabase Repeatable Template Definitions
|
|
2
2
|
|
|
3
|
-
Live-reloading SQL templates for [Supabase](https://supabase.com) projects. DX supercharged! 🚀
|
|
4
3
|
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
> Live-reloading SQL templates for [Supabase](https://supabase.com) projects. DX supercharged! 🚀
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
[](https://www.npmjs.com/package/@t1mmen/srtd)
|
|
8
|
+
[](https://opensource.org/licenses/MIT)
|
|
9
|
+
[](https://github.com/t1mmen/srtd/actions/workflows/ci.yml)
|
|
10
|
+
[](https://codecov.io/gh/t1mmen/srtd)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
[](./readme-screenshot.png)
|
|
14
|
+
|
|
15
|
+
`srtd` enhances the [Supabase](https://supabase.com) DX by adding live-reloading SQL templates into local db. The single-source-of-truth template ➡️ migrations system brings sanity to code reviews, making `git blame` useful.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
**Read the introductory blog post: [Introducing `srtd`: Live-Reloading SQL Templates for Supabase](https://timm.stokke.me/blog/srtd-live-reloading-and-sql-templates-for-supabase)**
|
|
9
19
|
|
|
10
20
|
## Why This Exists 🤔
|
|
11
21
|
|
|
12
22
|
While building [Timely](https://www.timely.com)'s next-generation [Memory Engine](https://www.timely.com/memory-app) on [Supabase](https://supabase.com), we found ourselves facing two major annoyances:
|
|
13
23
|
|
|
14
|
-
1. Code reviews were painful - function changes showed up as complete rewrites
|
|
24
|
+
1. Code reviews were painful - function changes showed up as complete rewrites, `git blame` was useless
|
|
15
25
|
2. Designing and iterating on database changes locally meant constant friction, like the dance around copy-pasting into SQL console
|
|
16
26
|
|
|
17
27
|
After over a year of looking-but-not-finding a better way, I paired up with [Claude](https://claude.ai) to eliminate these annoyances. Say hello to `srtd`.
|
|
@@ -19,10 +29,12 @@ After over a year of looking-but-not-finding a better way, I paired up with [Cla
|
|
|
19
29
|
## Key Features ✨
|
|
20
30
|
|
|
21
31
|
- **Live Reload**: Changes to your SQL templates instantly update your local database
|
|
22
|
-
- **Single Source of Truth**: Templates are the source of all (non-mutable) database objects,
|
|
23
|
-
- **
|
|
32
|
+
- **Single Source of Truth**: Templates are the source of all (non-mutable) database objects, improving code-review clarity
|
|
33
|
+
- **Just SQL**: Templates build as standard [Supabase](https://supabase.com) migrations when you're ready to deploy
|
|
24
34
|
- **Developer Friendly**: Interactive CLI with visual feedback for all operations
|
|
25
35
|
|
|
36
|
+
Built specifically for projects using the standard [Supabase](https://supabase.com) stack (but probably works alright for other Postgres-based projects, too).
|
|
37
|
+
|
|
26
38
|
## Requirements
|
|
27
39
|
|
|
28
40
|
- Node.js v20.x or higher
|
|
@@ -31,24 +43,29 @@ After over a year of looking-but-not-finding a better way, I paired up with [Cla
|
|
|
31
43
|
|
|
32
44
|
## Quick Start 🚀
|
|
33
45
|
|
|
34
|
-
|
|
46
|
+
### Installation
|
|
35
47
|
|
|
36
48
|
```bash
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
#
|
|
41
|
-
|
|
49
|
+
# Global installation
|
|
50
|
+
npm install -g @t1mmen/srtd
|
|
51
|
+
|
|
52
|
+
# Project installation
|
|
53
|
+
npm install --save-dev @t1mmen/srtd
|
|
54
|
+
|
|
55
|
+
# Or run directly
|
|
56
|
+
npx @t1mmen/srtd
|
|
42
57
|
```
|
|
43
58
|
|
|
44
|
-
|
|
59
|
+
### Setup
|
|
45
60
|
|
|
46
61
|
```bash
|
|
47
62
|
cd your-supabase-project
|
|
48
63
|
srtd init
|
|
49
64
|
```
|
|
50
65
|
|
|
51
|
-
Create
|
|
66
|
+
### Create Your First Template
|
|
67
|
+
|
|
68
|
+
Create `supabase/migrations-templates/my_function.sql`:
|
|
52
69
|
|
|
53
70
|
```sql
|
|
54
71
|
CREATE OR REPLACE FUNCTION my_function()
|
|
@@ -59,145 +76,153 @@ END;
|
|
|
59
76
|
$$ LANGUAGE plpgsql;
|
|
60
77
|
```
|
|
61
78
|
|
|
62
|
-
|
|
79
|
+
### Development Workflow
|
|
63
80
|
|
|
81
|
+
1. Start watch mode:
|
|
64
82
|
```bash
|
|
65
83
|
srtd watch # Changes auto-apply to local database
|
|
66
84
|
```
|
|
67
85
|
|
|
68
|
-
When ready to deploy:
|
|
69
|
-
|
|
86
|
+
2. When ready to deploy:
|
|
70
87
|
```bash
|
|
71
|
-
srtd build
|
|
72
|
-
supabase
|
|
88
|
+
srtd build # Creates timestamped migration file
|
|
89
|
+
supabase migration up # Apply using Supabase CLI
|
|
73
90
|
```
|
|
74
91
|
|
|
75
92
|
## Commands 🎮
|
|
76
93
|
|
|
77
|
-
|
|
94
|
+
### Interactive Mode
|
|
78
95
|
|
|
79
|
-
|
|
80
|
-
❯ 🏗️ build - Build Supabase migrations from templates
|
|
81
|
-
▶️ apply - Apply migration templates directly to database
|
|
82
|
-
✍️ register - Register templates as already built
|
|
83
|
-
👀 watch - Watch templates for changes, apply directly to database
|
|
84
|
-
```
|
|
96
|
+
Running `srtd` without arguments opens an interactive menu:
|
|
85
97
|
|
|
86
|
-
|
|
98
|
+
### CLI Mode
|
|
87
99
|
|
|
88
|
-
- 🏗️ `build` - Generate
|
|
89
|
-
- ▶️ `apply` - Apply templates directly to local database
|
|
90
|
-
- ✍️ `register [file.sql]` - Mark templates as already built
|
|
91
|
-
- 👀 `watch` - Watch
|
|
100
|
+
- 🏗️ `srtd build [--force]` - Generate migrations from templates
|
|
101
|
+
- ▶️ `srtd apply [--force]` - Apply templates directly to local database
|
|
102
|
+
- ✍️ `srtd register [file.sql]` - Mark templates as already built
|
|
103
|
+
- 👀 `srtd watch` - Watch and auto-apply changes
|
|
104
|
+
- 🧹 `srtd clean` - Remove all logs and reset config
|
|
92
105
|
|
|
93
|
-
|
|
106
|
+
> [!IMPORTANT]
|
|
107
|
+
> `watch` and `apply` commands modify your local database directly and don't clean up after themselves. Use with caution!
|
|
94
108
|
|
|
95
|
-
|
|
109
|
+
## The Power of Templates 💪
|
|
96
110
|
|
|
97
|
-
✅ Functions and stored procedures:
|
|
98
|
-
```sql
|
|
99
|
-
CREATE OR REPLACE FUNCTION search_products(query text, category_id uuid DEFAULT NULL)
|
|
100
|
-
RETURNS SETOF products AS $$
|
|
101
|
-
BEGIN
|
|
102
|
-
RETURN QUERY
|
|
103
|
-
SELECT p.* FROM products p
|
|
104
|
-
LEFT JOIN product_categories pc ON pc.product_id = p.id
|
|
105
|
-
WHERE to_tsvector('english',
|
|
106
|
-
p.name || ' ' ||
|
|
107
|
-
p.description || ' ' ||
|
|
108
|
-
p.tags || ' ' ||
|
|
109
|
-
COALESCE((
|
|
110
|
-
SELECT string_agg(c.name, ' ')
|
|
111
|
-
FROM categories c
|
|
112
|
-
WHERE c.id = ANY(p.category_ids)
|
|
113
|
-
), '')
|
|
114
|
-
) @@ plainto_tsquery('english', query)
|
|
115
|
-
AND (category_id IS NULL OR pc.category_id = category_id);
|
|
116
|
-
END;
|
|
117
|
-
$$ LANGUAGE plpgsql;
|
|
118
|
-
```
|
|
119
111
|
|
|
120
|
-
|
|
121
|
-
```sql
|
|
122
|
-
CREATE POLICY "users can view own data"
|
|
123
|
-
ON profiles FOR SELECT
|
|
124
|
-
USING (auth.uid() = user_id);
|
|
125
|
-
```
|
|
112
|
+
Templates make code reviews meaningful. Consider this PR adding priority to a notification function:
|
|
126
113
|
|
|
127
|
-
|
|
128
|
-
```sql
|
|
129
|
-
CREATE ROLE authenticated;
|
|
130
|
-
GRANT USAGE ON SCHEMA public TO authenticated;
|
|
131
|
-
GRANT SELECT ON ALL TABLES IN SCHEMA public TO authenticated;
|
|
132
|
-
```
|
|
114
|
+
Without templates, this would appear as a complete rewrite in your PR.
|
|
133
115
|
|
|
134
|
-
|
|
116
|
+
### Perfect For 🎯
|
|
135
117
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
118
|
+
✅ Database functions:
|
|
119
|
+
```diff
|
|
120
|
+
-- Event notifications
|
|
121
|
+
CREATE OR REPLACE FUNCTION notify_changes()
|
|
122
|
+
RETURNS trigger AS $$
|
|
123
|
+
BEGIN
|
|
124
|
+
PERFORM pg_notify(
|
|
125
|
+
'changes',
|
|
126
|
+
json_build_object('table', TG_TABLE_NAME, 'id', NEW.id)::text
|
|
127
|
+
);
|
|
128
|
+
+ RAISE NOTICE 'Notified changes for %', TG_TABLE_NAME; -- Debug logging
|
|
129
|
+
RETURN NEW;
|
|
130
|
+
END;
|
|
131
|
+
$$ LANGUAGE plpgsql;
|
|
132
|
+
```
|
|
140
133
|
|
|
141
|
-
|
|
134
|
+
✅ Row-Level Security (RLS):
|
|
135
|
+
```diff
|
|
136
|
+
-- Replace/update policies safely
|
|
137
|
+
DROP POLICY IF EXISTS "workspace_access" ON resources;
|
|
138
|
+
CREATE POLICY "workspace_access" ON resources
|
|
139
|
+
USING (workspace_id IN (
|
|
140
|
+
SELECT id FROM workspaces
|
|
141
|
+
WHERE organization_id = auth.organization_id()
|
|
142
|
+
+ AND auth.user_role() NOT IN ('pending')
|
|
143
|
+
));
|
|
144
|
+
```
|
|
142
145
|
|
|
143
|
-
|
|
146
|
+
✅ Views for data abstraction:
|
|
147
|
+
```diff
|
|
148
|
+
CREATE OR REPLACE VIEW active_subscriptions AS
|
|
149
|
+
SELECT
|
|
150
|
+
s.*,
|
|
151
|
+
p.name as plan_name,
|
|
152
|
+
p.features
|
|
153
|
+
FROM subscriptions s
|
|
154
|
+
JOIN plans p ON p.id = s.plan_id
|
|
155
|
+
- WHERE s.status = 'active';
|
|
156
|
+
+ WHERE s.status = 'active'
|
|
157
|
+
+ AND s.expires_at > CURRENT_TIMESTAMP;
|
|
158
|
+
```
|
|
144
159
|
|
|
145
|
-
|
|
160
|
+
✅ Roles and Permissions:
|
|
161
|
+
```diff
|
|
162
|
+
-- Revoke all first for clean state
|
|
163
|
+
REVOKE ALL ON ALL TABLES IN SCHEMA public FROM public;
|
|
146
164
|
|
|
147
|
-
|
|
165
|
+
-- Grant specific access
|
|
166
|
+
GRANT USAGE ON SCHEMA public TO authenticated;
|
|
167
|
+
GRANT SELECT ON ALL TABLES IN SCHEMA public TO authenticated;
|
|
168
|
+
+ GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO admin;
|
|
169
|
+
```
|
|
148
170
|
|
|
171
|
+
✅ Safe Type Extensions:
|
|
149
172
|
```diff
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
-- Create notification record
|
|
165
|
-
+ -- Include priority based on notification type
|
|
166
|
-
INSERT INTO notifications (
|
|
167
|
-
id,
|
|
168
|
-
user_id,
|
|
169
|
-
type,
|
|
170
|
-
payload,
|
|
171
|
-
+ priority,
|
|
172
|
-
created_at
|
|
173
|
-
) VALUES (
|
|
174
|
-
gen_random_uuid(),
|
|
175
|
-
dispatch_notification.user_id,
|
|
176
|
-
type,
|
|
177
|
-
payload,
|
|
178
|
-
+ COALESCE((SELECT priority FROM notification_types WHERE name = type), 'normal'),
|
|
179
|
-
CURRENT_TIMESTAMP
|
|
180
|
-
)
|
|
181
|
-
RETURNING id INTO notification_id;
|
|
173
|
+
DO $$
|
|
174
|
+
BEGIN
|
|
175
|
+
-- Add new enum values idempotently
|
|
176
|
+
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'notification_type') THEN
|
|
177
|
+
CREATE TYPE notification_type AS ENUM ('email', 'sms');
|
|
178
|
+
END IF;
|
|
179
|
+
|
|
180
|
+
-- Extend existing enum safely
|
|
181
|
+
ALTER TYPE notification_type ADD VALUE IF NOT EXISTS 'push';
|
|
182
|
+
ALTER TYPE notification_type ADD VALUE IF NOT EXISTS 'pusher';
|
|
183
|
+
ALTER TYPE notification_type ADD VALUE IF NOT EXISTS 'webhook';
|
|
184
|
+
+ ALTER TYPE notification_type ADD VALUE IF NOT EXISTS 'email';
|
|
185
|
+
END $$;
|
|
182
186
|
```
|
|
183
187
|
|
|
184
|
-
|
|
188
|
+
### Not Recommended For
|
|
189
|
+
|
|
190
|
+
* ❌ Table structures
|
|
191
|
+
* ❌ Indexes
|
|
192
|
+
* ❌ Data modifications
|
|
193
|
+
* ❌ Non-idempotent operations
|
|
194
|
+
|
|
195
|
+
Use regular [Supabase](https://supabase.com) migrations for these cases.
|
|
185
196
|
|
|
186
197
|
## Configuration 📝
|
|
187
198
|
|
|
188
|
-
|
|
199
|
+
`srtd.config.json` created during initialization:
|
|
189
200
|
|
|
190
|
-
```
|
|
201
|
+
```jsonc
|
|
191
202
|
{
|
|
203
|
+
// Prevents building templates with this extension
|
|
192
204
|
"wipIndicator": ".wip",
|
|
205
|
+
|
|
206
|
+
// Migration file naming: 20211001000000_srtd-my_function.sql
|
|
207
|
+
"migrationPrefix": "srtd",
|
|
208
|
+
|
|
209
|
+
// Template discovery
|
|
193
210
|
"filter": "**/*.sql",
|
|
211
|
+
|
|
212
|
+
// Migration file comments
|
|
194
213
|
"banner": "You very likely **DO NOT** want to manually edit this generated file.",
|
|
195
214
|
"footer": "",
|
|
215
|
+
|
|
216
|
+
// Wrap migrations in transaction
|
|
196
217
|
"wrapInTransaction": true,
|
|
218
|
+
|
|
219
|
+
// File paths
|
|
197
220
|
"templateDir": "supabase/migrations-templates",
|
|
198
221
|
"migrationDir": "supabase/migrations",
|
|
199
222
|
"buildLog": "supabase/migrations-templates/.buildlog.json",
|
|
200
223
|
"localBuildLog": "supabase/migrations-templates/.buildlog.local.json",
|
|
224
|
+
|
|
225
|
+
// Database connection
|
|
201
226
|
"pgConnection": "postgresql://postgres:postgres@localhost:54322/postgres"
|
|
202
227
|
}
|
|
203
228
|
```
|
|
@@ -206,74 +231,73 @@ During initialization, `srtd` creates a `srtd.config.json`:
|
|
|
206
231
|
|
|
207
232
|
### Work in Progress Templates
|
|
208
233
|
|
|
209
|
-
Add `.wip.sql` extension to
|
|
210
|
-
|
|
234
|
+
Add `.wip.sql` extension to prevent migration generation:
|
|
211
235
|
```bash
|
|
212
|
-
my_function.wip.sql #
|
|
236
|
+
my_function.wip.sql # Only applied locally, never built
|
|
213
237
|
```
|
|
214
238
|
|
|
215
239
|
### Template State Management
|
|
216
240
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
- `.buildlog.json` -
|
|
220
|
-
- `.buildlog.local.json` - Tracks local database state (add to .gitignore)
|
|
241
|
+
Two state tracking files:
|
|
242
|
+
- `.buildlog.json` - Migration build state (commit this)
|
|
243
|
+
- `.buildlog.local.json` - Local database state (add to `.gitignore`)
|
|
221
244
|
|
|
222
245
|
### Register Existing Objects
|
|
223
246
|
|
|
224
|
-
Import existing database objects
|
|
225
|
-
|
|
247
|
+
Import existing database objects:
|
|
226
248
|
```bash
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
249
|
+
# Register specific template
|
|
250
|
+
srtd register my_function.sql
|
|
251
|
+
|
|
252
|
+
# Interactive multi-select UI
|
|
253
|
+
srtd register
|
|
230
254
|
```
|
|
231
255
|
|
|
232
256
|
## Development 🛠️
|
|
233
257
|
|
|
234
|
-
|
|
258
|
+
### Local Setup
|
|
235
259
|
|
|
236
|
-
1. Set up the development environment:
|
|
237
260
|
```bash
|
|
261
|
+
# Clone and install
|
|
238
262
|
git clone https://github.com/stokke/srtd.git
|
|
239
263
|
cd srtd
|
|
240
264
|
npm install
|
|
241
|
-
```
|
|
242
265
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
npm
|
|
246
|
-
npm
|
|
247
|
-
npm start # Builds, links, and runs CLI
|
|
248
|
-
```
|
|
266
|
+
# Development
|
|
267
|
+
npm run dev # Watch mode
|
|
268
|
+
npm test # Run tests
|
|
269
|
+
npm start # Build, link, run
|
|
249
270
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
npm run
|
|
253
|
-
npm run
|
|
254
|
-
npm run test:coverage # Test coverage
|
|
271
|
+
# Quality Checks
|
|
272
|
+
npm run typecheck # Type checking
|
|
273
|
+
npm run lint # Lint and fix
|
|
274
|
+
npm run test:coverage # Test coverage
|
|
255
275
|
```
|
|
256
276
|
|
|
257
277
|
## Contributing 🤝
|
|
258
278
|
|
|
259
|
-
|
|
279
|
+
While feature-complete for our needs, we welcome:
|
|
260
280
|
|
|
261
|
-
- Bug fixes and reliability improvements
|
|
262
|
-
- Documentation improvements
|
|
263
|
-
- Test coverage
|
|
264
|
-
- Performance optimizations
|
|
281
|
+
- 🐛 Bug fixes and reliability improvements
|
|
282
|
+
- 📚 Documentation improvements
|
|
283
|
+
- ✅ Test coverage enhancements
|
|
284
|
+
- ⚡️ Performance optimizations
|
|
265
285
|
|
|
266
|
-
### Contribution
|
|
286
|
+
### Contribution Process
|
|
267
287
|
|
|
268
288
|
1. Create a [changeset](https://github.com/changesets/changesets) (`npm run changeset`)
|
|
269
289
|
2. Ensure tests pass (`npm test`)
|
|
270
290
|
3. Follow existing code style
|
|
271
|
-
4. Update documentation
|
|
291
|
+
4. Update documentation
|
|
272
292
|
|
|
273
|
-
Note
|
|
293
|
+
Note: New features are evaluated based on alignment with project scope.
|
|
274
294
|
|
|
275
295
|
## License
|
|
276
296
|
|
|
277
|
-
|
|
297
|
+
MIT License - see [LICENSE](LICENSE) file.
|
|
298
|
+
|
|
299
|
+
---
|
|
278
300
|
|
|
279
301
|
Made with 🪄 by [Timm Stokke](https://timm.stokke.me) & [Claude Sonnet](https://claude.ai)
|
|
302
|
+
|
|
303
|
+
[](https://www.buymeacoffee.com/t1mmen)
|
|
@@ -5,19 +5,35 @@ import { afterAll, beforeAll, vi } from 'vitest';
|
|
|
5
5
|
import { connect, disconnect } from '../utils/databaseConnection.js';
|
|
6
6
|
export const TEST_FN_PREFIX = 'srtd_scoped_test_func_';
|
|
7
7
|
export const TEST_ROOT = join(tmpdir(), `srtd-test-${Date.now()}`);
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
8
|
+
vi.mock('../utils/logger', () => ({
|
|
9
|
+
logger: {
|
|
10
|
+
info: () => {
|
|
11
|
+
/** noop */
|
|
12
|
+
},
|
|
13
|
+
success: () => {
|
|
14
|
+
/** noop */
|
|
15
|
+
},
|
|
16
|
+
warn: () => {
|
|
17
|
+
/** noop */
|
|
18
|
+
},
|
|
19
|
+
error: () => {
|
|
20
|
+
/** noop */
|
|
21
|
+
},
|
|
22
|
+
skip: () => {
|
|
23
|
+
/** noop */
|
|
24
|
+
},
|
|
25
|
+
debug: () => {
|
|
26
|
+
/** noop */
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
}));
|
|
19
30
|
beforeAll(async () => {
|
|
20
|
-
|
|
31
|
+
try {
|
|
32
|
+
await fs.mkdir(TEST_ROOT, { recursive: true });
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
console.error('Error creating test root:', error, ', retrying once.');
|
|
36
|
+
}
|
|
21
37
|
});
|
|
22
38
|
afterAll(async () => {
|
|
23
39
|
await fs.rm(TEST_ROOT, { recursive: true, force: true });
|
|
@@ -26,19 +42,19 @@ afterAll(async () => {
|
|
|
26
42
|
try {
|
|
27
43
|
await client.query('BEGIN');
|
|
28
44
|
await client.query(`
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
45
|
+
DO $$
|
|
46
|
+
DECLARE
|
|
47
|
+
r record;
|
|
48
|
+
BEGIN
|
|
49
|
+
FOR r IN
|
|
50
|
+
SELECT quote_ident(proname) AS func_name
|
|
51
|
+
FROM pg_proc
|
|
52
|
+
WHERE proname LIKE '${TEST_FN_PREFIX}%'
|
|
53
|
+
LOOP
|
|
54
|
+
EXECUTE 'DROP FUNCTION IF EXISTS ' || r.func_name;
|
|
55
|
+
END LOOP;
|
|
56
|
+
END;
|
|
57
|
+
$$;
|
|
42
58
|
`);
|
|
43
59
|
await client.query('COMMIT');
|
|
44
60
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vitest.setup.js","sourceRoot":"","sources":["../../src/__tests__/vitest.setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAErE,MAAM,CAAC,MAAM,cAAc,GAAG,wBAAwB,CAAC;AACvD,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,aAAa,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AAEnE,
|
|
1
|
+
{"version":3,"file":"vitest.setup.js","sourceRoot":"","sources":["../../src/__tests__/vitest.setup.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,7 +18,6 @@ describe('Watch Command', () => {
|
|
|
18
18
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
19
19
|
const output = lastFrame();
|
|
20
20
|
expect(output).toContain('Watch Mode');
|
|
21
|
-
expect(output).toContain('Watching for template changes');
|
|
22
21
|
});
|
|
23
22
|
});
|
|
24
23
|
//# sourceMappingURL=watch.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watch.test.js","sourceRoot":"","sources":["../../src/__tests__/watch.test.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAChE,OAAO,KAAK,MAAM,sBAAsB,CAAC;AAEzC,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAC,cAAc,EAAC,EAAE;IACpC,MAAM,MAAM,GAAG,CAAC,MAAM,cAAc,EAAE,CAAyB,CAAC;IAChE,OAAO;QACL,GAAG,MAAM;QACT,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC;KAClC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,aAAa,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC,oBAAC,KAAK,OAAG,CAAC,CAAC;QACxC,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QAEvD,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;QAC3B,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"watch.test.js","sourceRoot":"","sources":["../../src/__tests__/watch.test.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAChE,OAAO,KAAK,MAAM,sBAAsB,CAAC;AAEzC,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAC,cAAc,EAAC,EAAE;IACpC,MAAM,MAAM,GAAG,CAAC,MAAM,cAAc,EAAE,CAAyB,CAAC;IAChE,OAAO;QACL,GAAG,MAAM;QACT,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC;KAClC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,aAAa,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC,oBAAC,KAAK,OAAG,CAAC,CAAC;QACxC,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QAEvD,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;QAC3B,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env -S node --no-warnings
|
|
2
2
|
import Pastel from 'pastel';
|
|
3
|
+
import updateNotifier from 'update-notifier';
|
|
4
|
+
import packageJson from '../package.json' assert { type: 'json' };
|
|
5
|
+
updateNotifier({ pkg: packageJson }).notify();
|
|
3
6
|
const app = new Pastel({
|
|
4
7
|
importMeta: import.meta,
|
|
5
8
|
});
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.tsx"],"names":[],"mappings":";AACA,OAAO,MAAM,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.tsx"],"names":[],"mappings":";AACA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,cAAc,MAAM,iBAAiB,CAAC;AAC7C,OAAO,WAAW,MAAM,iBAAiB,CAAC,SAAS,IAAI,EAAE,MAAM,EAAE,CAAC;AAElE,cAAc,CAAC,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;AAE9C,MAAM,GAAG,GAAG,IAAI,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC,IAAI;CACxB,CAAC,CAAC;AAEH,MAAM,GAAG,CAAC,GAAG,EAAE,CAAC"}
|
package/dist/commands/_app.js
CHANGED
|
@@ -1,7 +1,35 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Alert, ThemeProvider, defaultTheme, extendTheme } from '@inkjs/ui';
|
|
2
|
+
import { Box, Static, Text } from 'ink';
|
|
2
3
|
import React from 'react';
|
|
4
|
+
import { useDatabaseConnection } from '../hooks/useDatabaseConnection.js';
|
|
5
|
+
const customTheme = extendTheme(defaultTheme, {
|
|
6
|
+
components: {
|
|
7
|
+
Spinner: {
|
|
8
|
+
styles: {
|
|
9
|
+
frame: () => ({
|
|
10
|
+
color: 'magenta',
|
|
11
|
+
}),
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
});
|
|
3
16
|
export default function App({ Component, commandProps }) {
|
|
4
|
-
|
|
5
|
-
|
|
17
|
+
const { error } = useDatabaseConnection();
|
|
18
|
+
return (React.createElement(ThemeProvider, { theme: customTheme },
|
|
19
|
+
React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
20
|
+
!!error && (React.createElement(Static, { items: [error] }, error => (React.createElement(Box, { key: error },
|
|
21
|
+
React.createElement(Alert, { variant: "error" },
|
|
22
|
+
React.createElement(Text, { bold: true, color: "red" },
|
|
23
|
+
"Error:",
|
|
24
|
+
' '),
|
|
25
|
+
error))))),
|
|
26
|
+
React.createElement(Component, { ...commandProps }))));
|
|
6
27
|
}
|
|
28
|
+
// Mimick fullscreen behavior
|
|
29
|
+
const enterAltScreenCommand = '\x1b[?1049h';
|
|
30
|
+
const leaveAltScreenCommand = '\x1b[?1049l';
|
|
31
|
+
process.stdout.write(enterAltScreenCommand);
|
|
32
|
+
process.on('exit', () => {
|
|
33
|
+
process.stdout.write(leaveAltScreenCommand);
|
|
34
|
+
});
|
|
7
35
|
//# sourceMappingURL=_app.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_app.js","sourceRoot":"","sources":["../../src/commands/_app.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"_app.js","sourceRoot":"","sources":["../../src/commands/_app.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC5E,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAkB,MAAM,KAAK,CAAC;AAExD,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAE1E,MAAM,WAAW,GAAG,WAAW,CAAC,YAAY,EAAE;IAC5C,UAAU,EAAE;QACV,OAAO,EAAE;YACP,MAAM,EAAE;gBACN,KAAK,EAAE,GAAc,EAAE,CAAC,CAAC;oBACvB,KAAK,EAAE,SAAS;iBACjB,CAAC;aACH;SACF;KACF;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,OAAO,UAAU,GAAG,CAAC,EAAE,SAAS,EAAE,YAAY,EAAY;IAC/D,MAAM,EAAE,KAAK,EAAE,GAAG,qBAAqB,EAAE,CAAC;IAE1C,OAAO,CACL,oBAAC,aAAa,IAAC,KAAK,EAAE,WAAW;QAC/B,oBAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,OAAO,EAAE,CAAC;YACnC,CAAC,CAAC,KAAK,IAAI,CACV,oBAAC,MAAM,IAAC,KAAK,EAAE,CAAC,KAAK,CAAC,IACnB,KAAK,CAAC,EAAE,CAAC,CACR,oBAAC,GAAG,IAAC,GAAG,EAAE,KAAK;gBACb,oBAAC,KAAK,IAAC,OAAO,EAAC,OAAO;oBACpB,oBAAC,IAAI,IAAC,IAAI,QAAC,KAAK,EAAC,KAAK;;wBACb,GAAG,CACL;oBACN,KAAK,CACA,CACJ,CACP,CACM,CACV;YACD,oBAAC,SAAS,OAAK,YAAY,GAAI,CAC3B,CACQ,CACjB,CAAC;AACJ,CAAC;AAED,6BAA6B;AAC7B,MAAM,qBAAqB,GAAG,aAAa,CAAC;AAC5C,MAAM,qBAAqB,GAAG,aAAa,CAAC;AAC5C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;AAC5C,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;IACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;AAC9C,CAAC,CAAC,CAAC"}
|
package/dist/commands/apply.d.ts
CHANGED
|
@@ -1 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
import zod from 'zod';
|
|
2
|
+
export declare const options: zod.ZodObject<{
|
|
3
|
+
force: zod.ZodBoolean;
|
|
4
|
+
}, "strip", zod.ZodTypeAny, {
|
|
5
|
+
force: boolean;
|
|
6
|
+
}, {
|
|
7
|
+
force: boolean;
|
|
8
|
+
}>;
|
|
9
|
+
type Props = {
|
|
10
|
+
options: zod.infer<typeof options>;
|
|
11
|
+
};
|
|
12
|
+
export default function Apply({ options }: Props): null;
|
|
13
|
+
export {};
|