@getjack/jack 0.1.25 → 0.1.26

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getjack/jack",
3
- "version": "0.1.25",
3
+ "version": "0.1.26",
4
4
  "description": "Ship before you forget why you started. The vibecoder's deployment CLI.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -52,7 +52,6 @@ export default async function update(): Promise<void> {
52
52
 
53
53
  if (result.success) {
54
54
  success(`Updated to v${result.version ?? latestVersion}`);
55
- info("Restart your terminal to use the new version.");
56
55
  } else {
57
56
  error("Update failed");
58
57
  if (result.error) {
@@ -146,6 +146,24 @@ describe("sql-classifier", () => {
146
146
  expect(result.risk).toBe("write");
147
147
  expect(result.operation).toBe("PRAGMA");
148
148
  });
149
+
150
+ it("classifies ALTER TABLE as write", () => {
151
+ const result = classifyStatement("ALTER TABLE users ADD COLUMN email TEXT");
152
+ expect(result.risk).toBe("write");
153
+ expect(result.operation).toBe("ALTER");
154
+ });
155
+
156
+ it("classifies ALTER TABLE RENAME as write", () => {
157
+ const result = classifyStatement("ALTER TABLE users RENAME TO customers");
158
+ expect(result.risk).toBe("write");
159
+ expect(result.operation).toBe("ALTER");
160
+ });
161
+
162
+ it("classifies ALTER TABLE DROP COLUMN as write", () => {
163
+ const result = classifyStatement("ALTER TABLE users DROP COLUMN email");
164
+ expect(result.risk).toBe("write");
165
+ expect(result.operation).toBe("ALTER");
166
+ });
149
167
  });
150
168
 
151
169
  describe("destructive operations", () => {
@@ -184,24 +202,6 @@ describe("sql-classifier", () => {
184
202
  expect(result.risk).toBe("destructive");
185
203
  expect(result.operation).toBe("DELETE");
186
204
  });
187
-
188
- it("classifies ALTER TABLE as destructive", () => {
189
- const result = classifyStatement("ALTER TABLE users ADD COLUMN email TEXT");
190
- expect(result.risk).toBe("destructive");
191
- expect(result.operation).toBe("ALTER");
192
- });
193
-
194
- it("classifies ALTER TABLE RENAME as destructive", () => {
195
- const result = classifyStatement("ALTER TABLE users RENAME TO customers");
196
- expect(result.risk).toBe("destructive");
197
- expect(result.operation).toBe("ALTER");
198
- });
199
-
200
- it("classifies ALTER TABLE DROP COLUMN as destructive", () => {
201
- const result = classifyStatement("ALTER TABLE users DROP COLUMN email");
202
- expect(result.risk).toBe("destructive");
203
- expect(result.operation).toBe("ALTER");
204
- });
205
205
  });
206
206
 
207
207
  describe("edge cases", () => {
@@ -3,8 +3,8 @@
3
3
  *
4
4
  * Classifies SQL statements by risk level to enable security guardrails:
5
5
  * - read: SELECT, EXPLAIN, PRAGMA (read-only) - safe to run
6
- * - write: INSERT, UPDATE, DELETE (with WHERE) - requires --write flag
7
- * - destructive: DROP, TRUNCATE, DELETE (no WHERE), ALTER - requires --write + confirmation
6
+ * - write: INSERT, UPDATE, DELETE (with WHERE), ALTER - requires --write flag
7
+ * - destructive: DROP, TRUNCATE, DELETE (no WHERE) - requires --write + confirmation
8
8
  *
9
9
  * Uses simple regex-based classification since D1 uses SQLite with a limited SQL surface.
10
10
  */
@@ -31,9 +31,9 @@ const SQL_PATTERNS = {
31
31
  // Destructive operations (dangerous - require confirmation)
32
32
  drop: /^\s*DROP\b/i,
33
33
  truncate: /^\s*TRUNCATE\b/i,
34
- alter: /^\s*ALTER\b/i,
35
34
 
36
35
  // Write operations (require --write flag)
36
+ alter: /^\s*ALTER\b/i,
37
37
  insert: /^\s*INSERT\b/i,
38
38
  update: /^\s*UPDATE\b/i,
39
39
  delete: /^\s*DELETE\b/i,
@@ -157,16 +157,16 @@ export function classifyStatement(sql: string): ClassifiedStatement {
157
157
  return { sql: trimmed, risk: "destructive", operation: "TRUNCATE" };
158
158
  }
159
159
 
160
- if (SQL_PATTERNS.alter.test(cleaned)) {
161
- return { sql: trimmed, risk: "destructive", operation: "ALTER" };
162
- }
163
-
164
160
  // DELETE without WHERE is destructive
165
161
  if (isDeleteWithoutWhere(cleaned)) {
166
162
  return { sql: trimmed, risk: "destructive", operation: "DELETE" };
167
163
  }
168
164
 
169
165
  // Check write operations
166
+ if (SQL_PATTERNS.alter.test(cleaned)) {
167
+ return { sql: trimmed, risk: "write", operation: "ALTER" };
168
+ }
169
+
170
170
  if (SQL_PATTERNS.insert.test(cleaned)) {
171
171
  return { sql: trimmed, risk: "write", operation: "INSERT" };
172
172
  }