mbeditor 0.7.2 → 0.7.4
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.
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dd301d5fbcf6d107417270314be0561ac408505b9fc5d9c3862077ce17c68d10
|
|
4
|
+
data.tar.gz: 60bf4c608bf64ee929bde7c1ba537c4d07b26374e35233fdc2c0563b350eb20d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: eb42152a396ec834bf84207e1e9c6a77a5a21c11d6a3c63be839c19f48856cdd08b95e3921ad6acf843a0f2d0debefc6e769ef14a1813c162d02a5912d3691cb
|
|
7
|
+
data.tar.gz: ffe883ef2af226e85c53978f4165c04bbe62cf83364f4a6b25bdf7cbbdcc7b52d984733b0ed549e2a978b953366153ca944f4df184c0cb69c80c40b6ad3fd1a2
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.7.4] - 2026-06-03
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- **Custom path reverse lookup (frontend)** — the v0.7.3 backend fix was complete, but the frontend's `resourceLabelFromPath` still returned `null` for paths under `app/` that weren't `controllers|models|views|helpers`, so custom paths like `app/assets/javascripts/…` were never recognized. Moved the custom-path check to the top of the function, matching the backend approach.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## [0.7.3] - 2026-06-03
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- **Custom path reverse lookup (backend)** — moved the custom-path check in `extract_resource_names` before the `case` statement so paths under `app/assets/`, `app/javascript/`, etc. are handled. Stripped `_controller`/`_model`/`_helper`/`_service` suffixes from custom-path filenames for consistent label/grouping.
|
|
19
|
+
- **Schema modal `self.table_name` support** — reads `self.table_name` from the model file before falling back to `ActiveSupport::Inflector.tableize`, enabling custom table names.
|
|
20
|
+
- **Structure.sql broader schema-prefix regex** — handles quoted schemas, non-public schemas, and no prefix.
|
|
21
|
+
- **PostgreSQL type coverage** — expanded `sql_type_to_rails` with full PostgreSQL type coverage (timestamptz, double precision, citext, hstore, geometric types, etc.).
|
|
22
|
+
- **Schema read error handling** — broadened rescue in `try_schema_rb`/`try_structure_sql` to catch encoding errors.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
8
26
|
## [0.7.2] - 2026-06-03
|
|
9
27
|
|
|
10
28
|
### Changed
|
|
@@ -1610,6 +1610,26 @@ var MbeditorApp = function MbeditorApp() {
|
|
|
1610
1610
|
|
|
1611
1611
|
var resourceLabelFromPath = function(p) {
|
|
1612
1612
|
if (!p) return null;
|
|
1613
|
+
|
|
1614
|
+
// Custom paths are checked first so they work regardless of top-level prefix.
|
|
1615
|
+
// Paths under app/assets/, app/javascript/, etc. never match standard
|
|
1616
|
+
// app/controllers|models|views|helpers, so the check must happen first.
|
|
1617
|
+
var customPaths = customPathsRef.current;
|
|
1618
|
+
for (var ci = 0; ci < customPaths.length; ci++) {
|
|
1619
|
+
var base = customPaths[ci];
|
|
1620
|
+
if (p.startsWith(base + '/')) {
|
|
1621
|
+
var rest = p.slice(base.length + 1);
|
|
1622
|
+
var resource = rest.split('/')[0].replace(/\.[^.]+$/, '');
|
|
1623
|
+
resource = resource.replace(/_(controller|model|helper|service)$/, '');
|
|
1624
|
+
if (resource) {
|
|
1625
|
+
var seg = resource.replace(/ies$/, 'y')
|
|
1626
|
+
.replace(/([^aeiou])es$/, '$1')
|
|
1627
|
+
.replace(/([^s])s$/, '$1');
|
|
1628
|
+
return seg.replace(/_/g, ' ').replace(/\b\w/g, function(c) { return c.toUpperCase(); });
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1613
1633
|
var parts = p.split('/');
|
|
1614
1634
|
var file = parts[parts.length - 1];
|
|
1615
1635
|
var name;
|
|
@@ -1624,23 +1644,9 @@ var MbeditorApp = function MbeditorApp() {
|
|
|
1624
1644
|
else if (parts[1] === 'models') name = file.replace(/_(test|spec)\.rb$/, '');
|
|
1625
1645
|
else return null;
|
|
1626
1646
|
} else {
|
|
1627
|
-
// Check custom paths
|
|
1628
|
-
var customPaths = customPathsRef.current;
|
|
1629
|
-
for (var ci = 0; ci < customPaths.length; ci++) {
|
|
1630
|
-
var base = customPaths[ci];
|
|
1631
|
-
if (p.startsWith(base + '/')) {
|
|
1632
|
-
var rest = p.slice(base.length + 1);
|
|
1633
|
-
var resource = rest.split('/')[0].replace(/\.[^.]+$/, '');
|
|
1634
|
-
if (resource) {
|
|
1635
|
-
var seg = resource.replace(/_/g, ' ').replace(/\b\w/g, function(c) { return c.toUpperCase(); });
|
|
1636
|
-
return seg;
|
|
1637
|
-
}
|
|
1638
|
-
}
|
|
1639
|
-
}
|
|
1640
1647
|
return null;
|
|
1641
1648
|
}
|
|
1642
1649
|
var seg = (name || '').split('/').pop() || name || '';
|
|
1643
|
-
// Normalize plural→singular so views/users and models/user share one group
|
|
1644
1650
|
seg = seg.replace(/ies$/, 'y')
|
|
1645
1651
|
.replace(/([^aeiou])es$/, '$1')
|
|
1646
1652
|
.replace(/([^s])s$/, '$1');
|
|
@@ -124,6 +124,20 @@ module Mbeditor
|
|
|
124
124
|
parts = relative_path.to_s.split("/")
|
|
125
125
|
return nil unless parts.length >= 2
|
|
126
126
|
|
|
127
|
+
# Custom paths are checked first so they work regardless of top-level prefix.
|
|
128
|
+
# Paths under app/assets/, app/javascript/, etc. never reach the standard
|
|
129
|
+
# "app" branch, so the check must happen before the case statement.
|
|
130
|
+
Array(custom_paths).each do |base|
|
|
131
|
+
base = base.to_s.strip
|
|
132
|
+
next if base.empty?
|
|
133
|
+
next unless relative_path.start_with?("#{base}/")
|
|
134
|
+
rest = relative_path.delete_prefix("#{base}/")
|
|
135
|
+
resource = rest.split('/').first.to_s.sub(/\.[^.]+$/, '') # first segment, no extension
|
|
136
|
+
resource = resource.sub(/_(controller|model|helper|service)$/, '') # strip Rails suffixes
|
|
137
|
+
next if resource.empty?
|
|
138
|
+
return [pluralize(resource), singularize(resource)]
|
|
139
|
+
end
|
|
140
|
+
|
|
127
141
|
case parts[0]
|
|
128
142
|
when "app"
|
|
129
143
|
case parts[1]
|
|
@@ -230,16 +244,6 @@ module Mbeditor
|
|
|
230
244
|
end
|
|
231
245
|
|
|
232
246
|
else
|
|
233
|
-
# Custom path fallback — must be last
|
|
234
|
-
Array(custom_paths).each do |base|
|
|
235
|
-
base = base.to_s.strip
|
|
236
|
-
next if base.empty?
|
|
237
|
-
next unless relative_path.start_with?("#{base}/")
|
|
238
|
-
rest = relative_path.delete_prefix("#{base}/")
|
|
239
|
-
resource = rest.split('/').first.to_s.sub(/\.[^.]+$/, '') # first path segment, no extension
|
|
240
|
-
next if resource.empty?
|
|
241
|
-
return [pluralize(resource), singularize(resource)]
|
|
242
|
-
end
|
|
243
247
|
nil
|
|
244
248
|
end
|
|
245
249
|
end
|
|
@@ -40,8 +40,25 @@ module Mbeditor
|
|
|
40
40
|
private
|
|
41
41
|
|
|
42
42
|
# "User" → "users", "OrderItem" → "order_items", "Order Item" → "order_items"
|
|
43
|
+
# Also checks the model file for an explicit `self.table_name = "..."` declaration.
|
|
43
44
|
def derive_table_name(model_name)
|
|
44
45
|
normalized = model_name.delete(" ")
|
|
46
|
+
|
|
47
|
+
# Check model file for an explicit table_name override
|
|
48
|
+
singular = ActiveSupport::Inflector.underscore(normalized)
|
|
49
|
+
model_file = File.join(@workspace_root, "app", "models", "#{singular}.rb")
|
|
50
|
+
if File.exist?(model_file)
|
|
51
|
+
begin
|
|
52
|
+
source = File.read(model_file, encoding: "utf-8")
|
|
53
|
+
# Matches: self.table_name = "name" or = :name or = 'name'
|
|
54
|
+
if (m = source.match(/self\.table_name\s*=\s*[:"']([^"'\s]+)["']?/))
|
|
55
|
+
return m[1]
|
|
56
|
+
end
|
|
57
|
+
rescue StandardError
|
|
58
|
+
# fall through to default derivation
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
45
62
|
ActiveSupport::Inflector.tableize(normalized)
|
|
46
63
|
end
|
|
47
64
|
|
|
@@ -53,7 +70,7 @@ module Mbeditor
|
|
|
53
70
|
begin
|
|
54
71
|
content = File.read(schema_path, encoding: "utf-8")
|
|
55
72
|
parse_schema_rb(content, table_name)
|
|
56
|
-
rescue
|
|
73
|
+
rescue StandardError => e
|
|
57
74
|
Rails.logger.debug("SchemaService: failed to read #{schema_path}: #{e.message}")
|
|
58
75
|
nil
|
|
59
76
|
end
|
|
@@ -67,7 +84,7 @@ module Mbeditor
|
|
|
67
84
|
begin
|
|
68
85
|
content = File.read(schema_path, encoding: "utf-8")
|
|
69
86
|
parse_structure_sql(content, table_name)
|
|
70
|
-
rescue
|
|
87
|
+
rescue StandardError => e
|
|
71
88
|
Rails.logger.debug("SchemaService: failed to read #{schema_path}: #{e.message}")
|
|
72
89
|
nil
|
|
73
90
|
end
|
|
@@ -145,11 +162,13 @@ module Mbeditor
|
|
|
145
162
|
# Handles: PostgreSQL, MySQL, SQLite with quoted/unquoted names
|
|
146
163
|
# Ends with different delimiters: ); ENGINE...; or just );
|
|
147
164
|
quoted_name = Regexp.escape(table_name)
|
|
165
|
+
# Schema prefix pattern: matches public., "public"., myschema., "myschema". or nothing.
|
|
166
|
+
schema_prefix = /(?:(?:"[^"]+"|`[^`]+`|\w+)\.)?/
|
|
148
167
|
patterns = [
|
|
149
|
-
# PostgreSQL
|
|
150
|
-
/CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)
|
|
151
|
-
# MySQL
|
|
152
|
-
/CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)
|
|
168
|
+
# PostgreSQL: CREATE TABLE [schema.]table ( ... );
|
|
169
|
+
/CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?#{schema_prefix}["`]?#{quoted_name}["`]?\s*\(([\s\S]*?)\)\s*;/mi,
|
|
170
|
+
# MySQL: CREATE TABLE [schema.]`table` ( ... ) ENGINE=...;
|
|
171
|
+
/CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?#{schema_prefix}["`]?#{quoted_name}["`]?\s*\(([\s\S]*?)\)\s*(?:ENGINE|DEFAULT)/mi
|
|
153
172
|
]
|
|
154
173
|
|
|
155
174
|
table_def = nil
|
|
@@ -240,6 +259,9 @@ module Mbeditor
|
|
|
240
259
|
type_map = {
|
|
241
260
|
'integer' => 'integer',
|
|
242
261
|
'int' => 'integer',
|
|
262
|
+
'int4' => 'integer',
|
|
263
|
+
'int2' => 'integer',
|
|
264
|
+
'int8' => 'bigint',
|
|
243
265
|
'bigint' => 'bigint',
|
|
244
266
|
'smallint' => 'integer',
|
|
245
267
|
'bigserial' => 'bigint',
|
|
@@ -247,21 +269,50 @@ module Mbeditor
|
|
|
247
269
|
'varchar' => 'string',
|
|
248
270
|
'character varying' => 'string',
|
|
249
271
|
'character' => 'string',
|
|
272
|
+
'char' => 'string',
|
|
250
273
|
'text' => 'text',
|
|
274
|
+
'citext' => 'string',
|
|
251
275
|
'boolean' => 'boolean',
|
|
252
276
|
'bool' => 'boolean',
|
|
253
277
|
'decimal' => 'decimal',
|
|
254
278
|
'numeric' => 'decimal',
|
|
279
|
+
'real' => 'float',
|
|
255
280
|
'float' => 'float',
|
|
281
|
+
'float4' => 'float',
|
|
282
|
+
'float8' => 'float',
|
|
283
|
+
'double precision' => 'float',
|
|
256
284
|
'double' => 'float',
|
|
285
|
+
'money' => 'decimal',
|
|
257
286
|
'timestamp' => 'datetime',
|
|
287
|
+
'timestamp without time zone' => 'datetime',
|
|
288
|
+
'timestamp with time zone' => 'datetime',
|
|
289
|
+
'timestamptz' => 'datetime',
|
|
258
290
|
'datetime' => 'datetime',
|
|
259
291
|
'date' => 'date',
|
|
260
292
|
'time' => 'time',
|
|
293
|
+
'time without time zone' => 'time',
|
|
294
|
+
'time with time zone' => 'time',
|
|
295
|
+
'interval' => 'string',
|
|
261
296
|
'json' => 'json',
|
|
262
297
|
'jsonb' => 'jsonb',
|
|
263
298
|
'uuid' => 'uuid',
|
|
264
|
-
'bytea' => 'binary'
|
|
299
|
+
'bytea' => 'binary',
|
|
300
|
+
'bit' => 'string',
|
|
301
|
+
'bit varying' => 'string',
|
|
302
|
+
'inet' => 'string',
|
|
303
|
+
'cidr' => 'string',
|
|
304
|
+
'macaddr' => 'string',
|
|
305
|
+
'xml' => 'string',
|
|
306
|
+
'hstore' => 'hstore',
|
|
307
|
+
'tsvector' => 'string',
|
|
308
|
+
'ltree' => 'string',
|
|
309
|
+
'point' => 'string',
|
|
310
|
+
'line' => 'string',
|
|
311
|
+
'lseg' => 'string',
|
|
312
|
+
'box' => 'string',
|
|
313
|
+
'path' => 'string',
|
|
314
|
+
'polygon' => 'string',
|
|
315
|
+
'circle' => 'string'
|
|
265
316
|
}
|
|
266
317
|
|
|
267
318
|
type_map[sql_type.downcase] || sql_type
|
data/lib/mbeditor/version.rb
CHANGED