ts_schema 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +160 -0
- data/MIT-LICENSE +20 -0
- data/README.md +35 -0
- data/Rakefile +3 -0
- data/bin/test +5 -0
- data/lib/generators/install_generator.rb +21 -0
- data/lib/generators/templates/ts_schema.rb +30 -0
- data/lib/tasks/ts_schema_tasks.rake +24 -0
- data/lib/ts_schema/configuration.rb +41 -0
- data/lib/ts_schema/conversion_table.yml +18 -0
- data/lib/ts_schema/railtie.rb +4 -0
- data/lib/ts_schema/schema_generator.rb +110 -0
- data/lib/ts_schema/version.rb +3 -0
- data/lib/ts_schema.rb +21 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/images/.keep +0 -0
- data/test/dummy/app/assets/javascripts/schema.d.ts +71 -0
- data/test/dummy/app/assets/stylesheets/application.css +1 -0
- data/test/dummy/app/controllers/application_controller.rb +2 -0
- data/test/dummy/app/controllers/concerns/.keep +0 -0
- data/test/dummy/app/frontend/types/schema.d.ts +71 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/jobs/application_job.rb +7 -0
- data/test/dummy/app/models/application_record.rb +3 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/models/example.rb +15 -0
- data/test/dummy/app/models/five.rb +3 -0
- data/test/dummy/app/models/four.rb +4 -0
- data/test/dummy/app/models/one.rb +4 -0
- data/test/dummy/app/models/three.rb +4 -0
- data/test/dummy/app/models/two.rb +3 -0
- data/test/dummy/app/views/layouts/application.html.erb +15 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +33 -0
- data/test/dummy/config/application.rb +41 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +86 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +63 -0
- data/test/dummy/config/environments/production.rb +76 -0
- data/test/dummy/config/environments/test.rb +53 -0
- data/test/dummy/config/initializers/config/initializers/ts_schema.rb +30 -0
- data/test/dummy/config/initializers/content_security_policy.rb +26 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +8 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/permissions_policy.rb +11 -0
- data/test/dummy/config/locales/en.yml +33 -0
- data/test/dummy/config/puma.rb +43 -0
- data/test/dummy/config/routes.rb +6 -0
- data/test/dummy/config/storage.yml +34 -0
- data/test/dummy/config.ru +6 -0
- data/test/dummy/db/migrate/20220401195333_create_examples.rb +23 -0
- data/test/dummy/db/migrate/20220402131712_create_ones.rb +9 -0
- data/test/dummy/db/migrate/20220402131955_create_twos.rb +9 -0
- data/test/dummy/db/migrate/20220402132415_create_threes.rb +7 -0
- data/test/dummy/db/migrate/20220402132543_create_fours.rb +10 -0
- data/test/dummy/db/migrate/20220402132906_create_fives.rb +12 -0
- data/test/dummy/db/schema.rb +81 -0
- data/test/dummy/lib/assets/.keep +0 -0
- data/test/dummy/log/.keep +0 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/apple-touch-icon-precomposed.png +0 -0
- data/test/dummy/public/apple-touch-icon.png +0 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/install_generator_test.rb +13 -0
- data/test/test_helper.rb +18 -0
- data/test/tmp/config/initializers/ts_schema.rb +30 -0
- data/test/ts_schema_test.rb +26 -0
- data/ts_schema.gemspec +20 -0
- metadata +139 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 96932379344d1d2f349abd58ab8bdae2fb1f13f5d4d8ca4df3493c128c368570
|
|
4
|
+
data.tar.gz: 55df2424b71f2ea51974599412edda16699050eb1c0a59f6e3e2f13b30a8ead3
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 00a7114be00a9aaf267910349fbdff03f2923c4fd318f564e2a950e0c4efe0b00324fe860099f5b2e9d3f87b68d526bc42d69f91108262af0331a27451279d08
|
|
7
|
+
data.tar.gz: 20b24ef08c0fac099b6accc8e722b8878dc47ebf6a55cb848cca54de779b661ec4ed9f0fb29c98c0844fe69a82ec10b72551778c0bcc6df4fad4a60775caa4f1
|
data/.gitignore
ADDED
data/Gemfile
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
source "https://rubygems.org"
|
|
2
|
+
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
|
3
|
+
|
|
4
|
+
# Specify your gem's dependencies in ts_schema.gemspec.
|
|
5
|
+
gemspec
|
|
6
|
+
|
|
7
|
+
gem "pg"
|
|
8
|
+
|
|
9
|
+
# Start debugger with binding.b [https://github.com/ruby/debug]
|
|
10
|
+
# gem "debug", ">= 1.0.0"
|
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
ts_schema (0.1.0)
|
|
5
|
+
rails (>= 7.0.2.3)
|
|
6
|
+
|
|
7
|
+
GEM
|
|
8
|
+
remote: https://rubygems.org/
|
|
9
|
+
specs:
|
|
10
|
+
actioncable (7.0.2.3)
|
|
11
|
+
actionpack (= 7.0.2.3)
|
|
12
|
+
activesupport (= 7.0.2.3)
|
|
13
|
+
nio4r (~> 2.0)
|
|
14
|
+
websocket-driver (>= 0.6.1)
|
|
15
|
+
actionmailbox (7.0.2.3)
|
|
16
|
+
actionpack (= 7.0.2.3)
|
|
17
|
+
activejob (= 7.0.2.3)
|
|
18
|
+
activerecord (= 7.0.2.3)
|
|
19
|
+
activestorage (= 7.0.2.3)
|
|
20
|
+
activesupport (= 7.0.2.3)
|
|
21
|
+
mail (>= 2.7.1)
|
|
22
|
+
net-imap
|
|
23
|
+
net-pop
|
|
24
|
+
net-smtp
|
|
25
|
+
actionmailer (7.0.2.3)
|
|
26
|
+
actionpack (= 7.0.2.3)
|
|
27
|
+
actionview (= 7.0.2.3)
|
|
28
|
+
activejob (= 7.0.2.3)
|
|
29
|
+
activesupport (= 7.0.2.3)
|
|
30
|
+
mail (~> 2.5, >= 2.5.4)
|
|
31
|
+
net-imap
|
|
32
|
+
net-pop
|
|
33
|
+
net-smtp
|
|
34
|
+
rails-dom-testing (~> 2.0)
|
|
35
|
+
actionpack (7.0.2.3)
|
|
36
|
+
actionview (= 7.0.2.3)
|
|
37
|
+
activesupport (= 7.0.2.3)
|
|
38
|
+
rack (~> 2.0, >= 2.2.0)
|
|
39
|
+
rack-test (>= 0.6.3)
|
|
40
|
+
rails-dom-testing (~> 2.0)
|
|
41
|
+
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
|
42
|
+
actiontext (7.0.2.3)
|
|
43
|
+
actionpack (= 7.0.2.3)
|
|
44
|
+
activerecord (= 7.0.2.3)
|
|
45
|
+
activestorage (= 7.0.2.3)
|
|
46
|
+
activesupport (= 7.0.2.3)
|
|
47
|
+
globalid (>= 0.6.0)
|
|
48
|
+
nokogiri (>= 1.8.5)
|
|
49
|
+
actionview (7.0.2.3)
|
|
50
|
+
activesupport (= 7.0.2.3)
|
|
51
|
+
builder (~> 3.1)
|
|
52
|
+
erubi (~> 1.4)
|
|
53
|
+
rails-dom-testing (~> 2.0)
|
|
54
|
+
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
|
55
|
+
activejob (7.0.2.3)
|
|
56
|
+
activesupport (= 7.0.2.3)
|
|
57
|
+
globalid (>= 0.3.6)
|
|
58
|
+
activemodel (7.0.2.3)
|
|
59
|
+
activesupport (= 7.0.2.3)
|
|
60
|
+
activerecord (7.0.2.3)
|
|
61
|
+
activemodel (= 7.0.2.3)
|
|
62
|
+
activesupport (= 7.0.2.3)
|
|
63
|
+
activestorage (7.0.2.3)
|
|
64
|
+
actionpack (= 7.0.2.3)
|
|
65
|
+
activejob (= 7.0.2.3)
|
|
66
|
+
activerecord (= 7.0.2.3)
|
|
67
|
+
activesupport (= 7.0.2.3)
|
|
68
|
+
marcel (~> 1.0)
|
|
69
|
+
mini_mime (>= 1.1.0)
|
|
70
|
+
activesupport (7.0.2.3)
|
|
71
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
72
|
+
i18n (>= 1.6, < 2)
|
|
73
|
+
minitest (>= 5.1)
|
|
74
|
+
tzinfo (~> 2.0)
|
|
75
|
+
builder (3.2.4)
|
|
76
|
+
concurrent-ruby (1.1.10)
|
|
77
|
+
crass (1.0.6)
|
|
78
|
+
digest (3.1.0)
|
|
79
|
+
erubi (1.10.0)
|
|
80
|
+
globalid (1.0.0)
|
|
81
|
+
activesupport (>= 5.0)
|
|
82
|
+
i18n (1.10.0)
|
|
83
|
+
concurrent-ruby (~> 1.0)
|
|
84
|
+
loofah (2.15.0)
|
|
85
|
+
crass (~> 1.0.2)
|
|
86
|
+
nokogiri (>= 1.5.9)
|
|
87
|
+
mail (2.7.1)
|
|
88
|
+
mini_mime (>= 0.1.1)
|
|
89
|
+
marcel (1.0.2)
|
|
90
|
+
method_source (1.0.0)
|
|
91
|
+
mini_mime (1.1.2)
|
|
92
|
+
minitest (5.15.0)
|
|
93
|
+
net-imap (0.2.3)
|
|
94
|
+
digest
|
|
95
|
+
net-protocol
|
|
96
|
+
strscan
|
|
97
|
+
net-pop (0.1.1)
|
|
98
|
+
digest
|
|
99
|
+
net-protocol
|
|
100
|
+
timeout
|
|
101
|
+
net-protocol (0.1.3)
|
|
102
|
+
timeout
|
|
103
|
+
net-smtp (0.3.1)
|
|
104
|
+
digest
|
|
105
|
+
net-protocol
|
|
106
|
+
timeout
|
|
107
|
+
nio4r (2.5.8)
|
|
108
|
+
nokogiri (1.13.3-x86_64-linux)
|
|
109
|
+
racc (~> 1.4)
|
|
110
|
+
pg (1.3.5)
|
|
111
|
+
racc (1.6.0)
|
|
112
|
+
rack (2.2.3)
|
|
113
|
+
rack-test (1.1.0)
|
|
114
|
+
rack (>= 1.0, < 3)
|
|
115
|
+
rails (7.0.2.3)
|
|
116
|
+
actioncable (= 7.0.2.3)
|
|
117
|
+
actionmailbox (= 7.0.2.3)
|
|
118
|
+
actionmailer (= 7.0.2.3)
|
|
119
|
+
actionpack (= 7.0.2.3)
|
|
120
|
+
actiontext (= 7.0.2.3)
|
|
121
|
+
actionview (= 7.0.2.3)
|
|
122
|
+
activejob (= 7.0.2.3)
|
|
123
|
+
activemodel (= 7.0.2.3)
|
|
124
|
+
activerecord (= 7.0.2.3)
|
|
125
|
+
activestorage (= 7.0.2.3)
|
|
126
|
+
activesupport (= 7.0.2.3)
|
|
127
|
+
bundler (>= 1.15.0)
|
|
128
|
+
railties (= 7.0.2.3)
|
|
129
|
+
rails-dom-testing (2.0.3)
|
|
130
|
+
activesupport (>= 4.2.0)
|
|
131
|
+
nokogiri (>= 1.6)
|
|
132
|
+
rails-html-sanitizer (1.4.2)
|
|
133
|
+
loofah (~> 2.3)
|
|
134
|
+
railties (7.0.2.3)
|
|
135
|
+
actionpack (= 7.0.2.3)
|
|
136
|
+
activesupport (= 7.0.2.3)
|
|
137
|
+
method_source
|
|
138
|
+
rake (>= 12.2)
|
|
139
|
+
thor (~> 1.0)
|
|
140
|
+
zeitwerk (~> 2.5)
|
|
141
|
+
rake (13.0.6)
|
|
142
|
+
strscan (3.0.1)
|
|
143
|
+
thor (1.2.1)
|
|
144
|
+
timeout (0.2.0)
|
|
145
|
+
tzinfo (2.0.4)
|
|
146
|
+
concurrent-ruby (~> 1.0)
|
|
147
|
+
websocket-driver (0.7.5)
|
|
148
|
+
websocket-extensions (>= 0.1.0)
|
|
149
|
+
websocket-extensions (0.1.5)
|
|
150
|
+
zeitwerk (2.5.4)
|
|
151
|
+
|
|
152
|
+
PLATFORMS
|
|
153
|
+
x86_64-linux
|
|
154
|
+
|
|
155
|
+
DEPENDENCIES
|
|
156
|
+
pg
|
|
157
|
+
ts_schema!
|
|
158
|
+
|
|
159
|
+
BUNDLED WITH
|
|
160
|
+
2.2.32
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright 2022 Avram Walden
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# TsSchema
|
|
2
|
+
|
|
3
|
+
Uses ActiveRecord to generate a schema.d.ts file for use in typescript frontends.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
bundle add "ts_schema"
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Then generate the initializer file:
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
rails generate ts_schema:install
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
All options with their defaults are in the config file.
|
|
20
|
+
|
|
21
|
+
By default, every migration, rollback, reset or setup task will auto generate a new schema file, replacing the existing one. You can disable this behavior in the config file.
|
|
22
|
+
|
|
23
|
+
You can manually generate the schema file by running:
|
|
24
|
+
|
|
25
|
+
```ruby
|
|
26
|
+
rails ts_schema:generate
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Gotchas
|
|
30
|
+
|
|
31
|
+
Apparantly, sometimes ActiveRecord's inflections will alter the class name. For instance, with a class named `Five`; `"Fives".singularize` returns "Fife", which is not the classname. In the case where Rails alters the classname for an association, you must explicitly define it on the association in the model using `class_name`. Example: `has_many :fives, class_name: "Five"`.
|
|
32
|
+
|
|
33
|
+
## License
|
|
34
|
+
|
|
35
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/test
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails/generators/base'
|
|
4
|
+
|
|
5
|
+
module TsSchema
|
|
6
|
+
module Generators
|
|
7
|
+
class InstallGenerator < Rails::Generators::Base
|
|
8
|
+
source_root File.expand_path("../templates", __FILE__)
|
|
9
|
+
|
|
10
|
+
desc "Creates ts_schmea.rb in config/initializers with default options."
|
|
11
|
+
|
|
12
|
+
def copy_initializer
|
|
13
|
+
template "ts_schema.rb", "config/initializers/ts_schema.rb"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# def show_readme
|
|
17
|
+
# readme "README" if behavior == :invoke
|
|
18
|
+
# end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
TsSchema.setup do |config|
|
|
2
|
+
# Options: camel|snake|pascal
|
|
3
|
+
# config.case = :camel
|
|
4
|
+
|
|
5
|
+
# Customize output path and file name
|
|
6
|
+
# config.output = Rails.root.join('app', 'assets', 'javascripts', 'schema.d.ts')
|
|
7
|
+
|
|
8
|
+
# Whether to generate the schema file on migrations and rollbacks
|
|
9
|
+
# config.auto_generate = true
|
|
10
|
+
|
|
11
|
+
# Add custom type mappings or overrides
|
|
12
|
+
# config.custom_types = {
|
|
13
|
+
#
|
|
14
|
+
# }
|
|
15
|
+
|
|
16
|
+
# Default type for unrecognized types
|
|
17
|
+
# config.default_type = :string
|
|
18
|
+
|
|
19
|
+
# Whether to generate types for associations
|
|
20
|
+
# config.include_associated = true
|
|
21
|
+
|
|
22
|
+
# Namespace
|
|
23
|
+
# config.namespace = :schema
|
|
24
|
+
|
|
25
|
+
# Options: tab|space
|
|
26
|
+
# config.indent = :tab
|
|
27
|
+
|
|
28
|
+
# If indent is spaces, specify how many
|
|
29
|
+
# config.spaces = 2
|
|
30
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
namespace :ts_schema do
|
|
2
|
+
desc "Generates a schema file in the default javascripts location, or the location specified in the ts_config initializer options"
|
|
3
|
+
task :generate do
|
|
4
|
+
TsSchema.generate
|
|
5
|
+
end
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
namespace :db do
|
|
9
|
+
task migrate: :environment do
|
|
10
|
+
TsSchema.generate if TsSchema.configuration.auto_generate
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
task rollback: :environment do
|
|
14
|
+
TsSchema.generate if TsSchema.configuration.auto_generate
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
task reset: :environment do
|
|
18
|
+
TsSchema.generate if TsSchema.configuration.auto_generate
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
task setup: :environment do
|
|
22
|
+
TsSchema.generate if TsSchema.configuration.auto_generate
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require "pathname"
|
|
2
|
+
|
|
3
|
+
module TsSchema
|
|
4
|
+
class Configuration
|
|
5
|
+
DEFAULTS = {
|
|
6
|
+
case: :camel,
|
|
7
|
+
output: -> { Rails.root.join('app', 'assets', 'javascripts', 'schema.d.ts') },
|
|
8
|
+
auto_generate: true,
|
|
9
|
+
types: ->{ YAML.load_file(File.expand_path(__dir__) + '/conversion_table.yml').to_h },
|
|
10
|
+
custom_types: {},
|
|
11
|
+
default_type: :string,
|
|
12
|
+
include_associated: true,
|
|
13
|
+
namespace: :schema,
|
|
14
|
+
indent: :tab,
|
|
15
|
+
spaces: 2,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
attr_accessor(*DEFAULTS.keys)
|
|
19
|
+
|
|
20
|
+
def initialize(attributes = nil)
|
|
21
|
+
assign(DEFAULTS)
|
|
22
|
+
return unless attributes
|
|
23
|
+
assign(attributes)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def assign(attributes = nil, &block)
|
|
27
|
+
if !attributes && !block
|
|
28
|
+
raise "Provide attributes or block"
|
|
29
|
+
end
|
|
30
|
+
tap(&block) if block
|
|
31
|
+
if attributes
|
|
32
|
+
attributes.each do |attribute, value|
|
|
33
|
+
value = value.call if value.is_a?(Proc)
|
|
34
|
+
send(:"#{attribute}=", value)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
self
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
string: string
|
|
2
|
+
text: string
|
|
3
|
+
integer: number
|
|
4
|
+
enum: number
|
|
5
|
+
bigint: number
|
|
6
|
+
float: number
|
|
7
|
+
decimal: number
|
|
8
|
+
json: Record<string, any>
|
|
9
|
+
jsonb: Record<string, any>
|
|
10
|
+
binary: string
|
|
11
|
+
boolean: boolean
|
|
12
|
+
date: string
|
|
13
|
+
datetime: string
|
|
14
|
+
timestamp: string
|
|
15
|
+
datetime_with_timezone: :string
|
|
16
|
+
inet: string
|
|
17
|
+
cidr: string
|
|
18
|
+
macaddr: string
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
|
|
3
|
+
module TsSchema
|
|
4
|
+
class SchemaGenerator
|
|
5
|
+
def initialize
|
|
6
|
+
Rails.application.eager_load!
|
|
7
|
+
@models = ApplicationRecord.send(:subclasses)
|
|
8
|
+
@types = TsSchema.configuration.types.merge(TsSchema.configuration.custom_types || {})
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def generate
|
|
12
|
+
ts = generate_typescript
|
|
13
|
+
output_file(ts)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def generate_typescript
|
|
19
|
+
type_template = ""
|
|
20
|
+
@models.each do |model|
|
|
21
|
+
columns = map_column_types(model)
|
|
22
|
+
columns.concat(map_associations(model)) if TsSchema.configuration.include_associated
|
|
23
|
+
|
|
24
|
+
type_template += <<~TYPESCRIPT
|
|
25
|
+
interface #{model.model_name.name} {
|
|
26
|
+
#{columns.map { |column| "#{indent_as_str}#{column_name_cased(column[:name])}: #{column[:ts_type]};" }.join("\n")}
|
|
27
|
+
}\n
|
|
28
|
+
TYPESCRIPT
|
|
29
|
+
end
|
|
30
|
+
type_template = <<~TPL
|
|
31
|
+
declare namespace #{TsSchema.configuration.namespace} {
|
|
32
|
+
#{indent_wrapper(type_template)}
|
|
33
|
+
}
|
|
34
|
+
TPL
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def map_column_types(model)
|
|
38
|
+
model.columns.map { |i|
|
|
39
|
+
type = @types[i.type.to_s] || TsSchema.configuration.default_type
|
|
40
|
+
|
|
41
|
+
if(enum = model.defined_enums[i.name])
|
|
42
|
+
type = enum.keys.map { |k| "'#{k}'" }.join(" | ")
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
{
|
|
46
|
+
name: "#{i.name}#{"?" if i.null }",
|
|
47
|
+
ts_type: "#{type}#{" | null" if i.null}"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def map_associations(model)
|
|
53
|
+
model.reflect_on_all_associations.reject(&:polymorphic?).map do |association|
|
|
54
|
+
case
|
|
55
|
+
when association.has_one? || association.belongs_to?
|
|
56
|
+
{
|
|
57
|
+
name: "#{association.name}?",
|
|
58
|
+
ts_type: association.class_name
|
|
59
|
+
}
|
|
60
|
+
when association.collection?
|
|
61
|
+
{
|
|
62
|
+
name: "#{association.name}?",
|
|
63
|
+
ts_type: "#{association.class_name}[]"
|
|
64
|
+
}
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def column_name_cased(name)
|
|
70
|
+
case TsSchema.configuration.case.to_sym
|
|
71
|
+
when :camel
|
|
72
|
+
name.camelize(:lower)
|
|
73
|
+
when :pascal
|
|
74
|
+
name.camelize
|
|
75
|
+
else
|
|
76
|
+
name
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def output_file(content)
|
|
81
|
+
path = TsSchema.configuration.output
|
|
82
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
83
|
+
|
|
84
|
+
return if File.exist?(path) && File.read(path) == content
|
|
85
|
+
|
|
86
|
+
File.open(path, 'w') do |f|
|
|
87
|
+
f.write content
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def indent_as_str
|
|
92
|
+
case TsSchema.configuration.indent.to_sym
|
|
93
|
+
when :space || :spaces
|
|
94
|
+
"".rjust(TsSchema.configuration.spaces, " ")
|
|
95
|
+
else
|
|
96
|
+
"\t"
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def indent_wrapper(str)
|
|
101
|
+
case TsSchema.configuration.indent.to_sym
|
|
102
|
+
when :space || :spaces
|
|
103
|
+
str.indent(TsSchema.configuration.spaces)
|
|
104
|
+
else
|
|
105
|
+
str.indent(1, "\t")
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
end
|
|
110
|
+
end
|
data/lib/ts_schema.rb
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require "ts_schema/version"
|
|
2
|
+
require "ts_schema/railtie"
|
|
3
|
+
|
|
4
|
+
require "ts_schema/configuration"
|
|
5
|
+
require "ts_schema/schema_generator"
|
|
6
|
+
|
|
7
|
+
module TsSchema
|
|
8
|
+
class << self
|
|
9
|
+
def setup(&block)
|
|
10
|
+
configuration.assign(&block)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def configuration
|
|
14
|
+
@configuration ||= Configuration.new
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def generate
|
|
18
|
+
SchemaGenerator.new.generate
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
data/test/dummy/Rakefile
ADDED
|
File without changes
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
declare namespace schema {
|
|
2
|
+
interface Example {
|
|
3
|
+
id: number;
|
|
4
|
+
colString: string;
|
|
5
|
+
colText: string;
|
|
6
|
+
colInteger: number;
|
|
7
|
+
colEnum: 'zero' | 'one' | 'two';
|
|
8
|
+
colBigint: number;
|
|
9
|
+
colFloat: number;
|
|
10
|
+
colDecimal: number;
|
|
11
|
+
colJson?: Record<string, any> | null;
|
|
12
|
+
colJsonb?: Record<string, any> | null;
|
|
13
|
+
colBinary?: string | null;
|
|
14
|
+
colBoolean?: boolean | null;
|
|
15
|
+
colDate?: string | null;
|
|
16
|
+
colDatetime?: string | null;
|
|
17
|
+
colTimestamp?: string | null;
|
|
18
|
+
colInet?: string | null;
|
|
19
|
+
colCidr?: string | null;
|
|
20
|
+
colMacaddr?: string | null;
|
|
21
|
+
one?: One;
|
|
22
|
+
two?: Two;
|
|
23
|
+
fours?: Four[];
|
|
24
|
+
threes?: Three[];
|
|
25
|
+
fives?: Five[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface Five {
|
|
29
|
+
id: number;
|
|
30
|
+
createdAt: string;
|
|
31
|
+
updatedAt: string;
|
|
32
|
+
examples?: Example[];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface Four {
|
|
36
|
+
id: number;
|
|
37
|
+
exampleId: number;
|
|
38
|
+
threeId: number;
|
|
39
|
+
createdAt: string;
|
|
40
|
+
updatedAt: string;
|
|
41
|
+
example?: Example;
|
|
42
|
+
three?: Three;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
interface One {
|
|
46
|
+
id: number;
|
|
47
|
+
exampleId: number;
|
|
48
|
+
createdAt: string;
|
|
49
|
+
updatedAt: string;
|
|
50
|
+
example?: Example;
|
|
51
|
+
two?: Two;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
interface Three {
|
|
55
|
+
id: number;
|
|
56
|
+
createdAt: string;
|
|
57
|
+
updatedAt: string;
|
|
58
|
+
fours?: Four[];
|
|
59
|
+
examples?: Example[];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
interface Two {
|
|
63
|
+
id: number;
|
|
64
|
+
exampleId: number;
|
|
65
|
+
createdAt: string;
|
|
66
|
+
updatedAt: string;
|
|
67
|
+
example?: Example;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/* Application styles */
|
|
File without changes
|