turbine-orm 0.27.0 → 0.27.1
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/dist/cjs/cli/destructive.js +47 -31
- package/dist/cli/destructive.js +47 -31
- package/package.json +1 -1
|
@@ -75,6 +75,45 @@ function stripCommentsAndStrings(sql) {
|
|
|
75
75
|
/** Unquote a "quoted" identifier for display. */
|
|
76
76
|
const ident = (raw) => (raw ?? '?').replace(/^"|"$/g, '');
|
|
77
77
|
const IDENT = String.raw `("[^"]+"|[a-zA-Z_][\w$]*)(\.("[^"]+"|[a-zA-Z_][\w$]*))?`;
|
|
78
|
+
/** Ordered rules — first match per statement wins. */
|
|
79
|
+
const RULES = [
|
|
80
|
+
{
|
|
81
|
+
kind: 'drop-table',
|
|
82
|
+
regex: new RegExp(String.raw `^DROP\s+TABLE\s+(IF\s+EXISTS\s+)?${IDENT}`, 'i'),
|
|
83
|
+
target: (m) => (m[4] ? `${ident(m[2])}.${ident(m[4])}` : ident(m[2])),
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
kind: 'drop-schema',
|
|
87
|
+
regex: new RegExp(String.raw `^DROP\s+SCHEMA\s+(IF\s+EXISTS\s+)?${IDENT}`, 'i'),
|
|
88
|
+
target: (m) => ident(m[2]),
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
kind: 'truncate',
|
|
92
|
+
regex: new RegExp(String.raw `^TRUNCATE\s+(TABLE\s+)?(ONLY\s+)?${IDENT}`, 'i'),
|
|
93
|
+
target: (m) => (m[5] ? `${ident(m[3])}.${ident(m[5])}` : ident(m[3])),
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
kind: 'drop-column',
|
|
97
|
+
regex: new RegExp(String.raw `^ALTER\s+TABLE\s+(IF\s+EXISTS\s+)?(ONLY\s+)?${IDENT}[\s\S]*?\bDROP\s+COLUMN\s+(IF\s+EXISTS\s+)?${IDENT}`, 'i'),
|
|
98
|
+
target: (m) => `${ident(m[3])}.${ident(m[7])}`,
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
kind: 'alter-column-type',
|
|
102
|
+
regex: new RegExp(String.raw `^ALTER\s+TABLE\s+(IF\s+EXISTS\s+)?(ONLY\s+)?${IDENT}[\s\S]*?\bALTER\s+(COLUMN\s+)?${IDENT}\s+(SET\s+DATA\s+)?TYPE\b`, 'i'),
|
|
103
|
+
target: (m) => `${ident(m[3])}.${ident(m[7])}`,
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
kind: 'delete',
|
|
107
|
+
regex: new RegExp(String.raw `^DELETE\s+FROM\s+(ONLY\s+)?${IDENT}`, 'i'),
|
|
108
|
+
target: (m) => ident(m[2]),
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
kind: 'update-without-where',
|
|
112
|
+
regex: new RegExp(String.raw `^UPDATE\s+(ONLY\s+)?${IDENT}\b`, 'i'),
|
|
113
|
+
target: (m) => ident(m[2]),
|
|
114
|
+
also: (stmt) => !/\bWHERE\b/i.test(stmt),
|
|
115
|
+
},
|
|
116
|
+
];
|
|
78
117
|
/**
|
|
79
118
|
* Scan SQL (one file's worth; may contain many `;`-separated statements) and
|
|
80
119
|
* return every statement that can destroy data.
|
|
@@ -86,37 +125,14 @@ function scanDestructiveSql(sql) {
|
|
|
86
125
|
const stmt = rawStmt.trim();
|
|
87
126
|
if (!stmt)
|
|
88
127
|
continue;
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
else if ((m = stmt.match(new RegExp(String.raw `^DROP\s+SCHEMA\s+(IF\s+EXISTS\s+)?${IDENT}`, 'i')))) {
|
|
99
|
-
found.push({ statement: display, kind: 'drop-schema', target: ident(m[2]) });
|
|
100
|
-
}
|
|
101
|
-
else if ((m = stmt.match(new RegExp(String.raw `^TRUNCATE\s+(TABLE\s+)?(ONLY\s+)?${IDENT}`, 'i')))) {
|
|
102
|
-
found.push({
|
|
103
|
-
statement: display,
|
|
104
|
-
kind: 'truncate',
|
|
105
|
-
target: ident(m[5] ? `${ident(m[3])}.${ident(m[5])}` : m[3]),
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
else if ((m = stmt.match(new RegExp(String.raw `^ALTER\s+TABLE\s+(IF\s+EXISTS\s+)?(ONLY\s+)?${IDENT}[\s\S]*?\bDROP\s+COLUMN\s+(IF\s+EXISTS\s+)?${IDENT}`, 'i')))) {
|
|
109
|
-
found.push({ statement: display, kind: 'drop-column', target: `${ident(m[3])}.${ident(m[7])}` });
|
|
110
|
-
}
|
|
111
|
-
else if ((m = stmt.match(new RegExp(String.raw `^ALTER\s+TABLE\s+(IF\s+EXISTS\s+)?(ONLY\s+)?${IDENT}[\s\S]*?\bALTER\s+(COLUMN\s+)?${IDENT}\s+(SET\s+DATA\s+)?TYPE\b`, 'i')))) {
|
|
112
|
-
found.push({ statement: display, kind: 'alter-column-type', target: `${ident(m[3])}.${ident(m[7])}` });
|
|
113
|
-
}
|
|
114
|
-
else if ((m = stmt.match(new RegExp(String.raw `^DELETE\s+FROM\s+(ONLY\s+)?${IDENT}`, 'i')))) {
|
|
115
|
-
found.push({ statement: display, kind: 'delete', target: ident(m[2]) });
|
|
116
|
-
}
|
|
117
|
-
else if ((m = stmt.match(new RegExp(String.raw `^UPDATE\s+(ONLY\s+)?${IDENT}\b`, 'i'))) &&
|
|
118
|
-
!/\bWHERE\b/i.test(stmt)) {
|
|
119
|
-
found.push({ statement: display, kind: 'update-without-where', target: ident(m[2]) });
|
|
128
|
+
for (const rule of RULES) {
|
|
129
|
+
const m = stmt.match(rule.regex);
|
|
130
|
+
if (!m)
|
|
131
|
+
continue;
|
|
132
|
+
if (rule.also && !rule.also(stmt))
|
|
133
|
+
continue;
|
|
134
|
+
found.push({ statement: stmt.replace(/\s+/g, ' '), kind: rule.kind, target: rule.target(m) });
|
|
135
|
+
break;
|
|
120
136
|
}
|
|
121
137
|
}
|
|
122
138
|
return found;
|
package/dist/cli/destructive.js
CHANGED
|
@@ -71,6 +71,45 @@ function stripCommentsAndStrings(sql) {
|
|
|
71
71
|
/** Unquote a "quoted" identifier for display. */
|
|
72
72
|
const ident = (raw) => (raw ?? '?').replace(/^"|"$/g, '');
|
|
73
73
|
const IDENT = String.raw `("[^"]+"|[a-zA-Z_][\w$]*)(\.("[^"]+"|[a-zA-Z_][\w$]*))?`;
|
|
74
|
+
/** Ordered rules — first match per statement wins. */
|
|
75
|
+
const RULES = [
|
|
76
|
+
{
|
|
77
|
+
kind: 'drop-table',
|
|
78
|
+
regex: new RegExp(String.raw `^DROP\s+TABLE\s+(IF\s+EXISTS\s+)?${IDENT}`, 'i'),
|
|
79
|
+
target: (m) => (m[4] ? `${ident(m[2])}.${ident(m[4])}` : ident(m[2])),
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
kind: 'drop-schema',
|
|
83
|
+
regex: new RegExp(String.raw `^DROP\s+SCHEMA\s+(IF\s+EXISTS\s+)?${IDENT}`, 'i'),
|
|
84
|
+
target: (m) => ident(m[2]),
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
kind: 'truncate',
|
|
88
|
+
regex: new RegExp(String.raw `^TRUNCATE\s+(TABLE\s+)?(ONLY\s+)?${IDENT}`, 'i'),
|
|
89
|
+
target: (m) => (m[5] ? `${ident(m[3])}.${ident(m[5])}` : ident(m[3])),
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
kind: 'drop-column',
|
|
93
|
+
regex: new RegExp(String.raw `^ALTER\s+TABLE\s+(IF\s+EXISTS\s+)?(ONLY\s+)?${IDENT}[\s\S]*?\bDROP\s+COLUMN\s+(IF\s+EXISTS\s+)?${IDENT}`, 'i'),
|
|
94
|
+
target: (m) => `${ident(m[3])}.${ident(m[7])}`,
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
kind: 'alter-column-type',
|
|
98
|
+
regex: new RegExp(String.raw `^ALTER\s+TABLE\s+(IF\s+EXISTS\s+)?(ONLY\s+)?${IDENT}[\s\S]*?\bALTER\s+(COLUMN\s+)?${IDENT}\s+(SET\s+DATA\s+)?TYPE\b`, 'i'),
|
|
99
|
+
target: (m) => `${ident(m[3])}.${ident(m[7])}`,
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
kind: 'delete',
|
|
103
|
+
regex: new RegExp(String.raw `^DELETE\s+FROM\s+(ONLY\s+)?${IDENT}`, 'i'),
|
|
104
|
+
target: (m) => ident(m[2]),
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
kind: 'update-without-where',
|
|
108
|
+
regex: new RegExp(String.raw `^UPDATE\s+(ONLY\s+)?${IDENT}\b`, 'i'),
|
|
109
|
+
target: (m) => ident(m[2]),
|
|
110
|
+
also: (stmt) => !/\bWHERE\b/i.test(stmt),
|
|
111
|
+
},
|
|
112
|
+
];
|
|
74
113
|
/**
|
|
75
114
|
* Scan SQL (one file's worth; may contain many `;`-separated statements) and
|
|
76
115
|
* return every statement that can destroy data.
|
|
@@ -82,37 +121,14 @@ export function scanDestructiveSql(sql) {
|
|
|
82
121
|
const stmt = rawStmt.trim();
|
|
83
122
|
if (!stmt)
|
|
84
123
|
continue;
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
else if ((m = stmt.match(new RegExp(String.raw `^DROP\s+SCHEMA\s+(IF\s+EXISTS\s+)?${IDENT}`, 'i')))) {
|
|
95
|
-
found.push({ statement: display, kind: 'drop-schema', target: ident(m[2]) });
|
|
96
|
-
}
|
|
97
|
-
else if ((m = stmt.match(new RegExp(String.raw `^TRUNCATE\s+(TABLE\s+)?(ONLY\s+)?${IDENT}`, 'i')))) {
|
|
98
|
-
found.push({
|
|
99
|
-
statement: display,
|
|
100
|
-
kind: 'truncate',
|
|
101
|
-
target: ident(m[5] ? `${ident(m[3])}.${ident(m[5])}` : m[3]),
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
else if ((m = stmt.match(new RegExp(String.raw `^ALTER\s+TABLE\s+(IF\s+EXISTS\s+)?(ONLY\s+)?${IDENT}[\s\S]*?\bDROP\s+COLUMN\s+(IF\s+EXISTS\s+)?${IDENT}`, 'i')))) {
|
|
105
|
-
found.push({ statement: display, kind: 'drop-column', target: `${ident(m[3])}.${ident(m[7])}` });
|
|
106
|
-
}
|
|
107
|
-
else if ((m = stmt.match(new RegExp(String.raw `^ALTER\s+TABLE\s+(IF\s+EXISTS\s+)?(ONLY\s+)?${IDENT}[\s\S]*?\bALTER\s+(COLUMN\s+)?${IDENT}\s+(SET\s+DATA\s+)?TYPE\b`, 'i')))) {
|
|
108
|
-
found.push({ statement: display, kind: 'alter-column-type', target: `${ident(m[3])}.${ident(m[7])}` });
|
|
109
|
-
}
|
|
110
|
-
else if ((m = stmt.match(new RegExp(String.raw `^DELETE\s+FROM\s+(ONLY\s+)?${IDENT}`, 'i')))) {
|
|
111
|
-
found.push({ statement: display, kind: 'delete', target: ident(m[2]) });
|
|
112
|
-
}
|
|
113
|
-
else if ((m = stmt.match(new RegExp(String.raw `^UPDATE\s+(ONLY\s+)?${IDENT}\b`, 'i'))) &&
|
|
114
|
-
!/\bWHERE\b/i.test(stmt)) {
|
|
115
|
-
found.push({ statement: display, kind: 'update-without-where', target: ident(m[2]) });
|
|
124
|
+
for (const rule of RULES) {
|
|
125
|
+
const m = stmt.match(rule.regex);
|
|
126
|
+
if (!m)
|
|
127
|
+
continue;
|
|
128
|
+
if (rule.also && !rule.also(stmt))
|
|
129
|
+
continue;
|
|
130
|
+
found.push({ statement: stmt.replace(/\s+/g, ' '), kind: rule.kind, target: rule.target(m) });
|
|
131
|
+
break;
|
|
116
132
|
}
|
|
117
133
|
}
|
|
118
134
|
return found;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "turbine-orm",
|
|
3
|
-
"version": "0.27.
|
|
3
|
+
"version": "0.27.1",
|
|
4
4
|
"description": "Postgres-native TypeScript ORM — runs on Neon, Vercel Postgres, Cloudflare, Supabase. Streaming cursors, typed errors, single-query nested relations. One dependency, no WASM engine",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|