ts_schema 0.1.12 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8602c4a7ca10962ac35fd7c64a18d0669ed3f7d1ecdfdf7bc9c29a258bff754a
4
- data.tar.gz: 322d779a986f2edf18d53829a6a8669326732be7aa4080567d2f4a1ecb1ebac0
3
+ metadata.gz: cf11b26c1cf7b979dc749c5ed2a7cd5c6f580a1d93d715dc684a3dd11cdf0f1d
4
+ data.tar.gz: 671e245c29ff9511be5db1f83815bfe6553bccea06021eaabe86414e9f034fff
5
5
  SHA512:
6
- metadata.gz: 88fd048bbffe0eb93ac910bdcaf456a35e4ded1bf934dab9330d5ad1dba4d57ad3106c07a549a92555f312fe4d713d1b1b4b8c7d29d3909d85a7062df96e6426
7
- data.tar.gz: 4c778296ba8de708bf9539bdcd163d79370c0477600d2bdbfd98a0e5c0355d3e02872728452be964922032cc880b3ac92ee270f40269e251734fb48ebfb74bcb
6
+ metadata.gz: 39fd032dd6b861491e69439e46ca7d0150455795f6c3c85e192d14720f2b9299471ec9c333f8dddeb6e41f3eeae2759e3b6beed2c989c4f51d805340277e14e5
7
+ data.tar.gz: 938c2fd5b9bc1320e56a5db9444a644473909f876de0c9561d04af0245c2b91e2e9ec5f3feb4d1cd619d490e77317631334c3d458e76ec036080ebd6a736be36
data/README.md CHANGED
@@ -16,9 +16,9 @@ rails generate ts_schema:install
16
16
 
17
17
  ## Usage
18
18
 
19
- All options with their defaults are in the config file.
19
+ All options with their defaults are in the generated initializer file.
20
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.
21
+ By default, every migration will auto generate a new schema file, replacing the existing one. You can disable this behavior in the config file.
22
22
 
23
23
  You can manually generate the schema file by running:
24
24
 
@@ -26,9 +26,51 @@ You can manually generate the schema file by running:
26
26
  rails ts_schema:generate
27
27
  ```
28
28
 
29
+ ### Default type mappings
30
+
31
+ |Ruby Type|Typescript Type|
32
+ |:---|:---|
33
+ |string|string|
34
+ |text|string|
35
+ |integer|number|
36
+ |enum|number|
37
+ |bigint|number|
38
+ |float|number|
39
+ |decimal|number|
40
+ |json|Record<string, any>|
41
+ |jsonb|Record<string, any>|
42
+ |binary|string|
43
+ |boolean|boolean|
44
+ |date|string|
45
+ |datetime|string|
46
+ |timestamp|string|
47
+ |datetime_with_timezone|string|
48
+ |inet|string|
49
+ |cidr|string|
50
+ |macaddr|string|
51
+
52
+ ### Initializer options
53
+
54
+ |Option|Default|Values|Description|
55
+ |---|---|---|---|
56
+ |case |`:camel`|`:camel`<br/>`:snake`<br/>`:pascal`|camelCase<br/>snake_case<br/>PascalCase|
57
+ |output |`Rails.root.join('app', 'assets', 'javascripts', 'schema.d.ts')`|Any path|Path to output generated file|
58
+ |auto_generate |`true`|`boolean`|Whether to automatically (re)generate the defenitions after running migrations|
59
+ |custom_types |`{}`|`{ ruby_type: 'typescriptType' }`|Use to add or override type mappings for any type|
60
+ |default_type |`:string`|Any typescript type|The default output type to use if a ruby type is not included in the type mappings|
61
+ |include_associated|`true`|`boolean`|Whether to include associated models as fields on the generated interfaces|
62
+ |parent_classes |`["ApplicationRecord"]`|Array of string names of top level classes|Any class names included in this array will be querried for subclasses to generate types for|
63
+ |additional_models |`[]`|Array of string names of ActiveRecord models|Add model names which don't inherit from classes included in `parent_classes`, but which should have types generated|
64
+ |field_overrides |`{ encrypted_password: :password, password: :optional, }`|Hash of field names with the following values:<br/> `:optional`: Makes it an optional field by adding '?' to the defintion (example: password?: string)<br/>`:omit`: Omits the field from being output in the schema entirely<br/>`[string]`: Field name override. Will replace any instance of the hash key with the value. The default values replace `password` with `encrypted_password`|Overwrite, omit, or make optional any field name. Applies to all generated classes|
65
+ |namespace |`:schema`|string\|symbol|The typescript namespace to contain generated types|
66
+ |schema_type |`:interface`|`:interface`\|`:type`|Whether to generate typescript definitions as types or interfaces. Interfaces are recommended since they are easier to extend|
67
+ |indent|`:tab`|`:tab`\|`:space`|Indentation using tabs or spaces|
68
+ |spaces|`2`|number|Number of spaces for indentation if indentation is set to spaces|
69
+
70
+
29
71
  ## Gotchas
30
72
 
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"`.
73
+ 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
74
 
33
75
  ## License
34
76
 
@@ -1,26 +1,5 @@
1
- # Default type mappings:
2
- #
3
- # string: string
4
- # text: string
5
- # integer: number
6
- # enum: number
7
- # bigint: number
8
- # float: number
9
- # decimal: number
10
- # json: Record<string, any>
11
- # jsonb: Record<string, any>
12
- # binary: string
13
- # boolean: boolean
14
- # date: string
15
- # datetime: string
16
- # timestamp: string
17
- # datetime_with_timezone: string
18
- # inet: string
19
- # cidr: string
20
- # macaddr: string
21
-
22
1
  TsSchema.setup do |config|
23
- # Case options: camel|snake|pascal
2
+ # Case options for field names: camel|snake|pascal
24
3
  #
25
4
  # config.case = :camel
26
5
 
@@ -35,7 +14,27 @@ TsSchema.setup do |config|
35
14
  # config.auto_generate = true
36
15
 
37
16
 
38
- # Add custom type mappings or overrides
17
+ # Add custom type mappings or overrides (as strings or symbols)
18
+ #
19
+ # Default type mappings:
20
+ # string: string
21
+ # text: string
22
+ # integer: number
23
+ # enum: number
24
+ # bigint: number
25
+ # float: number
26
+ # decimal: number
27
+ # json: Record<string, any>
28
+ # jsonb: Record<string, any>
29
+ # binary: string
30
+ # boolean: boolean
31
+ # date: string
32
+ # datetime: string
33
+ # timestamp: string
34
+ # datetime_with_timezone: string
35
+ # inet: string
36
+ # cidr: string
37
+ # macaddr: string
39
38
  #
40
39
  # config.custom_types = {
41
40
  #
@@ -68,6 +67,28 @@ TsSchema.setup do |config|
68
67
  # ]
69
68
 
70
69
 
70
+ # Ignore certain fields, omitting them from the generated schema: :optional|(string)|false
71
+ # Key is the name of the field to override options for.
72
+ #
73
+ # [:optional] will make this an optional field by adding '?' to the defintion (example: password?: string)
74
+ # [(string)] enter a field name override, for instance rename encrypted_password to password
75
+ # In that scenario, also specifying password as an optional field will append a ? to password
76
+ # [:omit] will omit the field from being output in the schema entirely
77
+ #
78
+ # config.field_overrides: {
79
+ # encrypted_password: :password,
80
+ # password: :optional,
81
+ # }
82
+
83
+ # Override types for fields by field name. This is globally applied.
84
+ # Useful for polymorphic associations which would otherwise be of type string, e.g.:
85
+ # commentable_type: "'Product'|'Review'"
86
+
87
+ # config.field_type_overrides: {
88
+
89
+ # }
90
+
91
+
71
92
  # Namespace for generated types
72
93
  #
73
94
  # config.namespace = :schema
@@ -10,12 +10,17 @@ module TsSchema
10
10
  custom_types: {},
11
11
  default_type: :string,
12
12
  include_associated: true,
13
+ parent_classes: ["ApplicationRecord"],
14
+ additional_models: [],
15
+ field_overrides: {
16
+ "encrypted_password" => :password,
17
+ "password" => :optional,
18
+ },
19
+ field_type_overrides: {},
13
20
  namespace: :schema,
14
- schema_type: :interface,
21
+ schema_type: :interface,
15
22
  indent: :tab,
16
23
  spaces: 2,
17
- parent_classes: ["ApplicationRecord"],
18
- additional_models: []
19
24
  }
20
25
 
21
26
  attr_accessor(*DEFAULTS.keys)
@@ -7,6 +7,8 @@ module TsSchema
7
7
 
8
8
  def initialize(config = nil)
9
9
  @config = config || TsSchema::Configuration.new
10
+ @config.field_overrides = @config.field_overrides.stringify_keys
11
+ @config.field_type_overrides = @config.field_type_overrides.stringify_keys
10
12
  @models = []
11
13
 
12
14
  Rails.application.eager_load!
@@ -18,6 +20,8 @@ module TsSchema
18
20
  m.to_s.constantize
19
21
  end)
20
22
  end
23
+ @models.sort_by! { |c| c.name }
24
+
21
25
  @types = @config.types.stringify_keys.merge(@config.custom_types.stringify_keys || {})
22
26
  end
23
27
 
@@ -33,7 +37,7 @@ module TsSchema
33
37
 
34
38
  def generate
35
39
  type_template = ""
36
-
40
+
37
41
  @models.each do |model|
38
42
  columns = map_column_types(model)
39
43
  columns.concat(map_associations(model)) if @config.include_associated
@@ -65,18 +69,38 @@ module TsSchema
65
69
  end
66
70
 
67
71
  def map_column_types(model)
68
- model.columns.map { |i|
69
- type = @types[i.type.to_s] || @config.default_type
70
-
71
- if(enum = model.defined_enums[i.name])
72
+ model.columns.map { |column|
73
+ column_name = column.name.to_s
74
+ next if @config.field_overrides[column_name] == :omit
75
+
76
+ type_override = config.field_type_overrides[column_name]
77
+
78
+ type = type_override ? type_override : @types[column.type.to_s] || @config.default_type
79
+ name = map_name(column.name)
80
+ null = column.null
81
+ null = true if @config.field_overrides[name]&.to_s == "optional"
82
+
83
+ if(enum = model.defined_enums[name])
72
84
  type = enum.keys.map { |k| "'#{k}'" }.join("|")
73
85
  end
74
-
86
+
75
87
  {
76
- name: "#{i.name}#{"?" if i.null }",
77
- ts_type: "#{type}#{" | null" if i.null}"
88
+ name: "#{name}#{"?" if null }",
89
+ ts_type: "#{type}#{" | null" if null}"
78
90
  }
79
- }
91
+ }.compact
92
+ end
93
+
94
+ def map_name(name)
95
+ final_name = name.to_s
96
+ return final_name unless @config.field_overrides[final_name]
97
+
98
+ if @config.field_overrides[final_name]&.to_s != "optional"
99
+ final_name = @config.field_overrides[final_name]&.to_s
100
+
101
+ final_name = map_name(final_name) if @config.field_overrides[final_name]
102
+ end
103
+ final_name
80
104
  end
81
105
 
82
106
  def map_associations(model)
@@ -1,3 +1,3 @@
1
1
  module TsSchema
2
- VERSION = "0.1.12"
2
+ VERSION = "0.2.1"
3
3
  end
data/lib/ts_schema.rb CHANGED
@@ -34,4 +34,3 @@ module TsSchema
34
34
  end
35
35
 
36
36
  require "generators/install_generator"
37
- require "generators/generate_generator"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ts_schema
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.12
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Avram Walden
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-04-06 00:00:00.000000000 Z
11
+ date: 2022-07-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails