lite-uxid 1.3.0 → 1.5.0

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: e12d0fcd0ea1e1653d22eea382fb4d770aa50dda8d9cfebc3a0633e50e01c64d
4
- data.tar.gz: 4eb22adb047d392dc1ee1645b9465c98940137f2b562635f8678d08398dc06af
3
+ metadata.gz: 750f76e67f536272728bf9234c0ad126f902dbd429a5b8d518af72f955b607dc
4
+ data.tar.gz: 5ac2699b92b9a12944d4cb83fa22b49ef63689567796fae7a563f943535ec86e
5
5
  SHA512:
6
- metadata.gz: 831968f72b1e450f5caaa4b330f236b2c0b1c6780dfe4153d68265f7a53752e12090b589c7235e92c16fd2e1ce2e58da8df7ef6321b47d13c02d514c4bb9f7f1
7
- data.tar.gz: d8491cec5de3a930c968992b2b159691b041549c890ed77a9369b5edaffda1bb6592cba992ad4f7284cd297cc7646c9b5dcefe6f64156fba08e959be57280c68
6
+ metadata.gz: 6b6bd1f1eae662b9a9c275f6acea8b7ca1e39d3e21614bdfdb46a648301f9da6f424655895a288eef683607ff94fd18bdcae88c346a2930f60f7748e778755fc
7
+ data.tar.gz: 6b9f3c95b1c8bbd801a50bdf8791fdb608702e3c65116af06a2be6a1f9112ceb77f8f9450ae612eb198e2c5645e4b9eaf6f38b88e45b64de431a0087bb637dfd
data/.rubocop.yml CHANGED
@@ -6,6 +6,8 @@ AllCops:
6
6
  NewCops: enable
7
7
  DisplayCopNames: true
8
8
  DisplayStyleGuide: true
9
+ Gemspec/DevelopmentDependencies:
10
+ EnforcedStyle: gemspec
9
11
  Gemspec/RequiredRubyVersion:
10
12
  Enabled: false
11
13
  Layout/EmptyLinesAroundAttributeAccessor:
@@ -33,6 +35,8 @@ Metrics/MethodLength:
33
35
  Enabled: false
34
36
  RSpec/MultipleExpectations:
35
37
  Enabled: false
38
+ RSpec/MultipleMemoizedHelpers:
39
+ Enabled: false
36
40
  Style/ArgumentsForwarding:
37
41
  Enabled: false
38
42
  Style/Documentation:
data/CHANGELOG.md CHANGED
@@ -6,13 +6,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [1.5.0] - 2024-09-20
10
+ ### Added
11
+ - Added uuid version option
12
+ - Added prefix option to hashid and nanoid
13
+ ### Changed
14
+ - Move reversible and irreversible files to base namespace
15
+ - Ruby send perf improvements
16
+
17
+ ## [1.4.0] - 2022-11-20
18
+ ### Changed
19
+ - Improved global config flexibility
20
+ - Update config generator to generate dynamic salt
21
+
9
22
  ## [1.3.0] - 2022-11-20
10
23
  ### Added
11
24
  - Added uuid option
12
25
 
13
26
  ## [1.2.0] - 2022-11-19
14
27
  ### Added
15
- - Added individual character and length options
28
+ - Added individual character and size options
16
29
  ### Changed
17
30
  - Improved docs
18
31
  - Improved internal setup
data/Gemfile.lock CHANGED
@@ -1,131 +1,169 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- lite-uxid (1.3.0)
4
+ lite-uxid (1.5.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
- actionpack (7.0.4)
10
- actionview (= 7.0.4)
11
- activesupport (= 7.0.4)
12
- rack (~> 2.0, >= 2.2.0)
9
+ actionpack (7.2.1)
10
+ actionview (= 7.2.1)
11
+ activesupport (= 7.2.1)
12
+ nokogiri (>= 1.8.5)
13
+ racc
14
+ rack (>= 2.2.4, < 3.2)
15
+ rack-session (>= 1.0.1)
13
16
  rack-test (>= 0.6.3)
14
- rails-dom-testing (~> 2.0)
15
- rails-html-sanitizer (~> 1.0, >= 1.2.0)
16
- actionview (7.0.4)
17
- activesupport (= 7.0.4)
17
+ rails-dom-testing (~> 2.2)
18
+ rails-html-sanitizer (~> 1.6)
19
+ useragent (~> 0.16)
20
+ actionview (7.2.1)
21
+ activesupport (= 7.2.1)
18
22
  builder (~> 3.1)
19
- erubi (~> 1.4)
20
- rails-dom-testing (~> 2.0)
21
- rails-html-sanitizer (~> 1.1, >= 1.2.0)
22
- activemodel (7.0.4)
23
- activesupport (= 7.0.4)
24
- activerecord (7.0.4)
25
- activemodel (= 7.0.4)
26
- activesupport (= 7.0.4)
27
- activesupport (7.0.4)
28
- concurrent-ruby (~> 1.0, >= 1.0.2)
23
+ erubi (~> 1.11)
24
+ rails-dom-testing (~> 2.2)
25
+ rails-html-sanitizer (~> 1.6)
26
+ activemodel (7.2.1)
27
+ activesupport (= 7.2.1)
28
+ activerecord (7.2.1)
29
+ activemodel (= 7.2.1)
30
+ activesupport (= 7.2.1)
31
+ timeout (>= 0.4.0)
32
+ activesupport (7.2.1)
33
+ base64
34
+ bigdecimal
35
+ concurrent-ruby (~> 1.0, >= 1.3.1)
36
+ connection_pool (>= 2.2.5)
37
+ drb
29
38
  i18n (>= 1.6, < 2)
39
+ logger (>= 1.4.2)
30
40
  minitest (>= 5.1)
31
- tzinfo (~> 2.0)
41
+ securerandom (>= 0.3)
42
+ tzinfo (~> 2.0, >= 2.0.5)
32
43
  ast (2.4.2)
33
- builder (3.2.4)
34
- colorize (0.8.1)
35
- concurrent-ruby (1.1.10)
44
+ base64 (0.2.0)
45
+ bigdecimal (3.1.8)
46
+ builder (3.3.0)
47
+ concurrent-ruby (1.3.4)
48
+ connection_pool (2.4.1)
36
49
  crass (1.0.6)
37
- database_cleaner (2.0.1)
38
- database_cleaner-active_record (~> 2.0.0)
39
- database_cleaner-active_record (2.0.1)
50
+ database_cleaner (2.0.2)
51
+ database_cleaner-active_record (>= 2, < 3)
52
+ database_cleaner-active_record (2.2.0)
40
53
  activerecord (>= 5.a)
41
54
  database_cleaner-core (~> 2.0.0)
42
55
  database_cleaner-core (2.0.1)
43
- diff-lcs (1.5.0)
44
- erubi (1.11.0)
45
- fasterer (0.10.0)
46
- colorize (~> 0.7)
56
+ diff-lcs (1.5.1)
57
+ drb (2.2.1)
58
+ erubi (1.13.0)
59
+ fasterer (0.11.0)
47
60
  ruby_parser (>= 3.19.1)
48
- generator_spec (0.9.4)
61
+ generator_spec (0.10.0)
49
62
  activesupport (>= 3.0.0)
50
63
  railties (>= 3.0.0)
51
- i18n (1.12.0)
64
+ i18n (1.14.6)
52
65
  concurrent-ruby (~> 1.0)
53
- json (2.6.2)
54
- loofah (2.19.0)
66
+ io-console (0.7.2)
67
+ irb (1.14.0)
68
+ rdoc (>= 4.0.0)
69
+ reline (>= 0.4.2)
70
+ json (2.7.2)
71
+ language_server-protocol (3.17.0.3)
72
+ logger (1.6.1)
73
+ loofah (2.22.0)
55
74
  crass (~> 1.0.2)
56
- nokogiri (>= 1.5.9)
57
- method_source (1.0.0)
58
- mini_portile2 (2.8.0)
59
- minitest (5.16.3)
60
- nokogiri (1.13.9)
61
- mini_portile2 (~> 2.8.0)
75
+ nokogiri (>= 1.12.0)
76
+ mini_portile2 (2.8.7)
77
+ minitest (5.25.1)
78
+ nokogiri (1.16.7)
79
+ mini_portile2 (~> 2.8.2)
62
80
  racc (~> 1.4)
63
- parallel (1.22.1)
64
- parser (3.1.2.1)
81
+ parallel (1.26.3)
82
+ parser (3.3.5.0)
65
83
  ast (~> 2.4.1)
66
- racc (1.6.0)
67
- rack (2.2.4)
68
- rack-test (2.0.2)
84
+ racc
85
+ psych (5.1.2)
86
+ stringio
87
+ racc (1.8.1)
88
+ rack (3.1.7)
89
+ rack-session (2.0.0)
90
+ rack (>= 3.0.0)
91
+ rack-test (2.1.0)
69
92
  rack (>= 1.3)
70
- rails-dom-testing (2.0.3)
71
- activesupport (>= 4.2.0)
93
+ rackup (2.1.0)
94
+ rack (>= 3)
95
+ webrick (~> 1.8)
96
+ rails-dom-testing (2.2.0)
97
+ activesupport (>= 5.0.0)
98
+ minitest
72
99
  nokogiri (>= 1.6)
73
- rails-html-sanitizer (1.4.3)
74
- loofah (~> 2.3)
75
- railties (7.0.4)
76
- actionpack (= 7.0.4)
77
- activesupport (= 7.0.4)
78
- method_source
100
+ rails-html-sanitizer (1.6.0)
101
+ loofah (~> 2.21)
102
+ nokogiri (~> 1.14)
103
+ railties (7.2.1)
104
+ actionpack (= 7.2.1)
105
+ activesupport (= 7.2.1)
106
+ irb (~> 1.13)
107
+ rackup (>= 1.0.0)
79
108
  rake (>= 12.2)
80
- thor (~> 1.0)
81
- zeitwerk (~> 2.5)
109
+ thor (~> 1.0, >= 1.2.2)
110
+ zeitwerk (~> 2.6)
82
111
  rainbow (3.1.1)
83
- rake (13.0.6)
84
- regexp_parser (2.6.1)
85
- rexml (3.2.5)
86
- rspec (3.12.0)
87
- rspec-core (~> 3.12.0)
88
- rspec-expectations (~> 3.12.0)
89
- rspec-mocks (~> 3.12.0)
90
- rspec-core (3.12.0)
91
- rspec-support (~> 3.12.0)
92
- rspec-expectations (3.12.0)
112
+ rake (13.2.1)
113
+ rdoc (6.7.0)
114
+ psych (>= 4.0.0)
115
+ regexp_parser (2.9.2)
116
+ reline (0.5.10)
117
+ io-console (~> 0.5)
118
+ rspec (3.13.0)
119
+ rspec-core (~> 3.13.0)
120
+ rspec-expectations (~> 3.13.0)
121
+ rspec-mocks (~> 3.13.0)
122
+ rspec-core (3.13.1)
123
+ rspec-support (~> 3.13.0)
124
+ rspec-expectations (3.13.3)
93
125
  diff-lcs (>= 1.2.0, < 2.0)
94
- rspec-support (~> 3.12.0)
95
- rspec-mocks (3.12.0)
126
+ rspec-support (~> 3.13.0)
127
+ rspec-mocks (3.13.1)
96
128
  diff-lcs (>= 1.2.0, < 2.0)
97
- rspec-support (~> 3.12.0)
98
- rspec-support (3.12.0)
99
- rubocop (1.39.0)
129
+ rspec-support (~> 3.13.0)
130
+ rspec-support (3.13.1)
131
+ rubocop (1.66.1)
100
132
  json (~> 2.3)
133
+ language_server-protocol (>= 3.17.0)
101
134
  parallel (~> 1.10)
102
- parser (>= 3.1.2.1)
135
+ parser (>= 3.3.0.2)
103
136
  rainbow (>= 2.2.2, < 4.0)
104
- regexp_parser (>= 1.8, < 3.0)
105
- rexml (>= 3.2.5, < 4.0)
106
- rubocop-ast (>= 1.23.0, < 2.0)
137
+ regexp_parser (>= 2.4, < 3.0)
138
+ rubocop-ast (>= 1.32.2, < 2.0)
107
139
  ruby-progressbar (~> 1.7)
108
- unicode-display_width (>= 1.4.0, < 3.0)
109
- rubocop-ast (1.23.0)
110
- parser (>= 3.1.1.0)
111
- rubocop-performance (1.15.1)
112
- rubocop (>= 1.7.0, < 2.0)
113
- rubocop-ast (>= 0.4.0)
140
+ unicode-display_width (>= 2.4.0, < 3.0)
141
+ rubocop-ast (1.32.3)
142
+ parser (>= 3.3.1.0)
143
+ rubocop-performance (1.22.1)
144
+ rubocop (>= 1.48.1, < 2.0)
145
+ rubocop-ast (>= 1.31.1, < 2.0)
114
146
  rubocop-rake (0.6.0)
115
147
  rubocop (~> 1.0)
116
- rubocop-rspec (2.15.0)
117
- rubocop (~> 1.33)
118
- ruby-progressbar (1.11.0)
119
- ruby_parser (3.19.1)
148
+ rubocop-rspec (3.0.5)
149
+ rubocop (~> 1.61)
150
+ ruby-progressbar (1.13.0)
151
+ ruby_parser (3.21.1)
152
+ racc (~> 1.5)
120
153
  sexp_processor (~> 4.16)
121
- sexp_processor (4.16.1)
122
- sqlite3 (1.5.4)
154
+ securerandom (0.3.1)
155
+ sexp_processor (4.17.2)
156
+ sqlite3 (2.0.4)
123
157
  mini_portile2 (~> 2.8.0)
124
- thor (1.2.1)
125
- tzinfo (2.0.5)
158
+ stringio (3.1.1)
159
+ thor (1.3.2)
160
+ timeout (0.4.1)
161
+ tzinfo (2.0.6)
126
162
  concurrent-ruby (~> 1.0)
127
- unicode-display_width (2.3.0)
128
- zeitwerk (2.6.6)
163
+ unicode-display_width (2.6.0)
164
+ useragent (0.16.10)
165
+ webrick (1.8.1)
166
+ zeitwerk (2.6.18)
129
167
 
130
168
  PLATFORMS
131
169
  ruby
@@ -147,4 +185,4 @@ DEPENDENCIES
147
185
  sqlite3
148
186
 
149
187
  BUNDLED WITH
150
- 2.3.26
188
+ 2.5.19
data/README.md CHANGED
@@ -5,6 +5,7 @@
5
5
 
6
6
  Lite::Uxid is a library for generating or obfuscating ID's based on different patterns.
7
7
  It's very useful to hide the number of resources in your database and protect against enumeration attacks.
8
+ By default, it implements websafe variants of each type.
8
9
 
9
10
  ## Installation
10
11
 
@@ -25,6 +26,7 @@ Or install it yourself as:
25
26
  ## Table of Contents
26
27
 
27
28
  * [Configuration](#configuration)
29
+ * [Usage](#usage)
28
30
  * [Hashid](#hashid)
29
31
  * [NanoID](#nanoid)
30
32
  * [ULID](#ulid)
@@ -40,21 +42,37 @@ Or install it yourself as:
40
42
 
41
43
  ```ruby
42
44
  Lite::Uxid.configure do |config|
43
- config.encoding_chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
44
- config.encoding_salt = 1_369_136
45
- config.hashid_length = 12
46
- config.nanoid_length = 21
47
- config.ulid_length = 26
45
+ config.hashid_charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
46
+ config.hashid_salt = 1_369_136
47
+ config.hashid_size = 16
48
+ config.nanoid_charset = "_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
49
+ config.nanoid_size = 21
50
+ config.ulid_charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
51
+ config.ulid_size = 26
52
+ config.uuid_version = 4
48
53
  end
49
54
  ```
50
55
 
56
+ ## Usage
57
+
58
+ #### Instance
59
+ ```ruby
60
+ coder = Lite::Uxid::Hashid.new(10, size: 12)
61
+ coder.encode #=> '67wGI0'
62
+ ```
63
+
64
+ #### Class
65
+ ```ruby
66
+ Lite::Uxid::Hashid.decode('67wGI0', size: 12) #=> 10
67
+ ```
68
+
51
69
  ## Hashid
52
70
 
53
71
  [More information](https://hashids.org)
54
72
 
55
73
  ```ruby
56
- Lite::Uxid::Hashid.encode(10) #=> '67wGI0'
57
- Lite::Uxid::Hashid.decode('67wGI0') #=> 10
74
+ Lite::Uxid::Hashid.encode(10) #=> '1zWr1m0'
75
+ Lite::Uxid::Hashid.decode('1zWr1m0') #=> 10
58
76
  ```
59
77
 
60
78
  ## NanoID
@@ -70,12 +88,12 @@ Lite::Uxid::Nanoid.encode #=> 'sMuNUa3Cegn6r5GRQ4Ij2'
70
88
  [More information](https://github.com/ulid/spec)
71
89
 
72
90
  ```ruby
73
- Lite::Uxid::Ulid.encode #=> '01gial8st6qrroptaks2tj4smq'
91
+ Lite::Uxid::Ulid.encode #=> '01GJAY9KGR539EZF4QWYEJGSN7'
74
92
  ```
75
93
 
76
94
  ## UUID
77
95
 
78
- [More information](https://en.wikipedia.org/wiki/Universally_unique_identifier)
96
+ Implements `v4` and `v7` of the specification. [More information](https://en.wikipedia.org/wiki/Universally_unique_identifier)
79
97
 
80
98
  ```ruby
81
99
  Lite::Uxid::Uuid.encode #=> '4376a67e-1189-44b3-a599-7f7566bf105b'
@@ -86,7 +104,19 @@ Lite::Uxid::Uuid.encode #=> '4376a67e-1189-44b3-a599-7f7566bf105b'
86
104
  Local options can be passed to override global options.
87
105
 
88
106
  ```ruby
89
- Lite::Uxid::Ulid.encode(chars: 'abc123', length: 12) #=> 'a3b12c12c3ca'
107
+ Lite::Uxid::Ulid.encode(charset: 'abc123', size: 12) #=> 'a3b12c12c3ca'
108
+ ```
109
+
110
+ Passable options are:
111
+
112
+ ```ruby
113
+ {
114
+ charset: 'string', # Available for: hashid, nanoid, ulid
115
+ salt: 'string', # Available for: hashid
116
+ size: 'integer', # Available for: hashid, nanoid, ulid
117
+ version: 'integer', # Available for: uuid
118
+ prefix: 'string' # Available for: hashid, nanoid
119
+ }
90
120
  ```
91
121
 
92
122
  ## ActiveRecord
@@ -131,6 +161,18 @@ class User < ActiveRecord::Base
131
161
  end
132
162
  ```
133
163
 
164
+ Add a prefix to `hashid` and `nanoid` record types by adding a `uxid_prefix` method.
165
+
166
+ ```ruby
167
+ class User < ActiveRecord::Base
168
+ include Lite::Uxid::Record::Hashid
169
+
170
+ def uxid_prefix
171
+ "sub_"
172
+ end
173
+ end
174
+ ```
175
+
134
176
  **Usage**
135
177
 
136
178
  Using one of the mixins above provides a handy method to find records by uxid.
@@ -1,9 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  Lite::Uxid.configure do |config|
4
- config.encoding_chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
5
- config.encoding_salt = 1_369_136
6
- config.hashid_length = 12
7
- config.nanoid_length = 21
8
- config.ulid_length = 26
4
+ config.hashid_charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
5
+ config.hashid_salt = 1_369_136
6
+ config.hashid_size = 16
7
+ config.nanoid_charset = "_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
8
+ config.nanoid_size = 21
9
+ config.ulid_charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
10
+ config.ulid_size = 26
9
11
  end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "securerandom" unless defined?(SecureRandom)
4
+
5
+ module Lite
6
+ module Uxid
7
+ module Base
8
+ class Irreversible
9
+
10
+ attr_reader :opts
11
+
12
+ def initialize(opts = {})
13
+ @opts = opts
14
+ end
15
+
16
+ class << self
17
+
18
+ def encode(opts = {})
19
+ klass = new(opts)
20
+ klass.encode
21
+ end
22
+
23
+ def decode(opts = {})
24
+ klass = new(opts)
25
+ klass.decode
26
+ end
27
+
28
+ end
29
+
30
+ def encode
31
+ raise NotImplementedError, "override method in #{coder_class}"
32
+ end
33
+
34
+ def decode
35
+ raise NotImplementedError, "coder does not support decoding"
36
+ end
37
+
38
+ private
39
+
40
+ def coder_value_for(key)
41
+ sym_key = :"#{coder_class.downcase}_#{key}"
42
+ return unless Lite::Uxid.configuration.respond_to?(sym_key)
43
+
44
+ opts.delete(key) || Lite::Uxid.configuration.send(sym_key)
45
+ end
46
+
47
+ def coder_bytes
48
+ @coder_bytes ||= SecureRandom.random_bytes(coder_size).bytes
49
+ end
50
+
51
+ def coder_charset
52
+ @coder_charset ||= coder_value_for(:charset)
53
+ end
54
+
55
+ def coder_class
56
+ @coder_class ||= self.class.name.split("::").last
57
+ end
58
+
59
+ def coder_length
60
+ @coder_length ||= coder_charset.size
61
+ end
62
+
63
+ def coder_prefix
64
+ @coder_prefix ||= opts.delete(:prefix)
65
+ end
66
+
67
+ def coder_salt
68
+ @coder_salt ||= coder_value_for(:salt)
69
+ end
70
+
71
+ def coder_size
72
+ @coder_size ||= coder_value_for(:size)
73
+ end
74
+
75
+ def coder_version
76
+ @coder_version ||= coder_value_for(:version)
77
+ end
78
+
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lite
4
+ module Uxid
5
+ module Base
6
+ class Reversible < Irreversible
7
+
8
+ attr_reader :id
9
+
10
+ def initialize(id, opts = {})
11
+ @id = id
12
+ super(opts)
13
+ end
14
+
15
+ class << self
16
+
17
+ def encode(id, opts = {})
18
+ klass = new(id, opts)
19
+ klass.encode
20
+ end
21
+
22
+ def decode(id, opts = {})
23
+ klass = new(id, opts)
24
+ klass.decode
25
+ end
26
+
27
+ end
28
+
29
+ def decode
30
+ raise NotImplementedError, "override method in #{coder_class}"
31
+ end
32
+
33
+ end
34
+ end
35
+ end
36
+ end
@@ -5,14 +5,20 @@ module Lite
5
5
 
6
6
  class Configuration
7
7
 
8
- attr_accessor :encoding_chars, :encoding_salt, :hashid_length, :nanoid_length, :ulid_length
8
+ attr_accessor :hashid_charset, :hashid_size, :hashid_salt,
9
+ :nanoid_charset, :nanoid_size,
10
+ :ulid_charset, :ulid_size,
11
+ :uuid_version
9
12
 
10
13
  def initialize
11
- @encoding_chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
12
- @encoding_salt = 1_369_136
13
- @hashid_length = 12
14
- @nanoid_length = 21
15
- @ulid_length = 26
14
+ @hashid_charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
15
+ @hashid_salt = 1_369_136
16
+ @hashid_size = 16
17
+ @nanoid_charset = "_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
18
+ @nanoid_size = 21
19
+ @ulid_charset = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
20
+ @ulid_size = 26
21
+ @uuid_version = 4
16
22
  end
17
23
 
18
24
  end
@@ -2,14 +2,16 @@
2
2
 
3
3
  module Lite
4
4
  module Uxid
5
- class Hashid < Reversible
5
+ class Hashid < Base::Reversible
6
6
 
7
7
  def encode
8
- encode_chars((id + coder_salt) << coder_length)
8
+ uxid = encode_chars((id + coder_salt) << coder_size)
9
+ "#{coder_prefix}#{uxid}"
9
10
  end
10
11
 
11
12
  def decode
12
- (decode_chars(id) >> coder_length) - coder_salt
13
+ uxid = id.delete_prefix(coder_prefix.to_s)
14
+ (decode_chars(uxid) >> coder_size) - coder_salt
13
15
  end
14
16
 
15
17
  private
@@ -21,8 +23,8 @@ module Lite
21
23
  str = ""
22
24
 
23
25
  while decoded_id.positive?
24
- str = "#{coder_chars[decoded_id % coder_base]}#{str}"
25
- decoded_id /= coder_base
26
+ str = "#{coder_charset[decoded_id % coder_length]}#{str}"
27
+ decoded_id /= coder_length
26
28
  end
27
29
 
28
30
  str
@@ -31,12 +33,12 @@ module Lite
31
33
  def decode_chars(encoded_id)
32
34
  pos = 0
33
35
  num = 0
34
- len = encoded_id.length
36
+ len = encoded_id.size
35
37
  max = len - 1
36
38
 
37
39
  while pos < len
38
- pow = coder_base**(max - pos)
39
- num += coder_chars.index(encoded_id[pos]) * pow
40
+ pow = coder_length**(max - pos)
41
+ num += coder_charset.index(encoded_id[pos]) * pow
40
42
  pos += 1
41
43
  end
42
44
 
@@ -2,10 +2,14 @@
2
2
 
3
3
  module Lite
4
4
  module Uxid
5
- class Nanoid < Irreversible
5
+ class Nanoid < Base::Irreversible
6
6
 
7
7
  def encode
8
- coder_chars.chars.sample(coder_length).join
8
+ uxid = (0...coder_size).each_with_object(+"") do |i, str|
9
+ str << coder_charset[coder_bytes[i] & 63]
10
+ end
11
+
12
+ "#{coder_prefix}#{uxid}"
9
13
  end
10
14
 
11
15
  end
@@ -15,7 +15,7 @@ module Lite
15
15
 
16
16
  class_methods do
17
17
  def find_by_uxid(uxid)
18
- decoded_id = Lite::Uxid::Hashid.decode(uxid)
18
+ decoded_id = Lite::Uxid::Hashid.decode(uxid, prefix: new.uxid_prefix)
19
19
  find_by(id: decoded_id)
20
20
  end
21
21
 
@@ -30,13 +30,17 @@ module Lite
30
30
  def id_to_uxid
31
31
  return unless respond_to?(:uxid)
32
32
 
33
- Lite::Uxid::Hashid.encode(id)
33
+ Lite::Uxid::Hashid.encode(id, prefix: uxid_prefix)
34
34
  end
35
35
 
36
36
  def uxid_to_id
37
37
  return unless respond_to?(:uxid)
38
38
 
39
- Lite::Uxid::Hashid.decode(uxid)
39
+ Lite::Uxid::Hashid.decode(uxid, prefix: uxid_prefix)
40
+ end
41
+
42
+ def uxid_prefix
43
+ nil
40
44
  end
41
45
 
42
46
  private
@@ -13,13 +13,17 @@ module Lite
13
13
  before_create :callback_generate_uxid!, if: proc { respond_to?(:uxid) && !uxid? }
14
14
  end
15
15
 
16
+ def uxid_prefix
17
+ nil
18
+ end
19
+
16
20
  private
17
21
 
18
22
  def callback_generate_uxid!
19
23
  random_nanoid = nil
20
24
 
21
25
  loop do
22
- random_nanoid = Lite::Uxid::Nanoid.encode
26
+ random_nanoid = Lite::Uxid::Nanoid.encode(prefix: uxid_prefix)
23
27
  break unless self.class.exists?(uxid: random_nanoid)
24
28
  end
25
29
 
@@ -1,20 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "securerandom" unless defined?(SecureRandom)
4
-
5
3
  module Lite
6
4
  module Uxid
7
- class Ulid < Irreversible
5
+ class Ulid < Base::Irreversible
8
6
 
9
7
  MASK = 0x1f
10
8
 
11
9
  def encode
12
10
  oct = octect
13
- ele = "0" * coder_length
14
- pos = coder_length - 1
11
+ ele = "0" * coder_size
12
+ pos = coder_size - 1
15
13
 
16
14
  while oct.positive?
17
- ele[pos] = coder_chars[oct & MASK]
15
+ ele[pos] = coder_charset[oct & MASK]
18
16
  oct >>= 5
19
17
  pos -= 1
20
18
  end
@@ -35,7 +33,7 @@ module Lite
35
33
 
36
34
  def unixtime_ms
37
35
  time = Time.respond_to?(:current) ? Time.current : Time.now
38
- (time.to_f * 1_000).to_i
36
+ time.to_i * 1_000
39
37
  end
40
38
 
41
39
  def unixtime_48bit
@@ -1,13 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "securerandom" unless defined?(SecureRandom)
4
-
5
3
  module Lite
6
4
  module Uxid
7
- class Uuid < Irreversible
5
+ class Uuid < Base::Irreversible
8
6
 
9
7
  def encode
10
- SecureRandom.uuid
8
+ case coder_version
9
+ when 7
10
+ SecureRandom.uuid_v7
11
+ else
12
+ SecureRandom.uuid
13
+ end
11
14
  end
12
15
 
13
16
  end
@@ -3,7 +3,7 @@
3
3
  module Lite
4
4
  module Uxid
5
5
 
6
- VERSION = "1.3.0"
6
+ VERSION = "1.5.0"
7
7
 
8
8
  end
9
9
  end
data/lib/lite/uxid.rb CHANGED
@@ -4,8 +4,8 @@ require "generators/lite/uxid/install_generator" if defined?(Rails::Generators)
4
4
 
5
5
  require "lite/uxid/version"
6
6
  require "lite/uxid/configuration"
7
- require "lite/uxid/irreversible"
8
- require "lite/uxid/reversible"
7
+ require "lite/uxid/base/irreversible"
8
+ require "lite/uxid/base/reversible"
9
9
  require "lite/uxid/record/hashid"
10
10
  require "lite/uxid/record/nanoid"
11
11
  require "lite/uxid/record/ulid"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lite-uxid
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juan Gomez
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-11-20 00:00:00.000000000 Z
11
+ date: 2024-09-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -217,15 +217,15 @@ files:
217
217
  - lib/generators/lite/uxid/install_generator.rb
218
218
  - lib/generators/lite/uxid/templates/install.rb
219
219
  - lib/lite/uxid.rb
220
+ - lib/lite/uxid/base/irreversible.rb
221
+ - lib/lite/uxid/base/reversible.rb
220
222
  - lib/lite/uxid/configuration.rb
221
223
  - lib/lite/uxid/hashid.rb
222
- - lib/lite/uxid/irreversible.rb
223
224
  - lib/lite/uxid/nanoid.rb
224
225
  - lib/lite/uxid/record/hashid.rb
225
226
  - lib/lite/uxid/record/nanoid.rb
226
227
  - lib/lite/uxid/record/ulid.rb
227
228
  - lib/lite/uxid/record/uuid.rb
228
- - lib/lite/uxid/reversible.rb
229
229
  - lib/lite/uxid/ulid.rb
230
230
  - lib/lite/uxid/uuid.rb
231
231
  - lib/lite/uxid/version.rb
@@ -254,7 +254,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
254
254
  - !ruby/object:Gem::Version
255
255
  version: '0'
256
256
  requirements: []
257
- rubygems_version: 3.3.26
257
+ rubygems_version: 3.5.19
258
258
  signing_key:
259
259
  specification_version: 4
260
260
  summary: Generate or obfuscate Id's using different patterns
@@ -1,65 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Lite
4
- module Uxid
5
- class Irreversible
6
-
7
- attr_reader :opts
8
-
9
- def initialize(opts = {})
10
- @opts = opts
11
- end
12
-
13
- class << self
14
-
15
- def encode(opts = {})
16
- klass = new(opts)
17
- klass.encode
18
- end
19
-
20
- def decode(opts = {})
21
- klass = new(opts)
22
- klass.decode
23
- end
24
-
25
- end
26
-
27
- def encode
28
- raise NotImplementedError, "override method in #{coder_class}"
29
- end
30
-
31
- def decode
32
- raise NotImplementedError, "coder does not support decoding"
33
- end
34
-
35
- private
36
-
37
- def coder_base
38
- @coder_base ||= coder_chars.length
39
- end
40
-
41
- def coder_chars
42
- @coder_chars ||=
43
- opts.delete(:chars) ||
44
- Lite::Uxid.configuration.encoding_chars
45
- end
46
-
47
- def coder_class
48
- @coder_class ||= self.class.name.split("::").last
49
- end
50
-
51
- def coder_length
52
- @coder_length ||=
53
- opts.delete(:length) ||
54
- Lite::Uxid.configuration.send("#{coder_class.downcase}_length")
55
- end
56
-
57
- def coder_salt
58
- @coder_salt ||=
59
- opts.delete(:salt) ||
60
- Lite::Uxid.configuration.encoding_salt
61
- end
62
-
63
- end
64
- end
65
- end
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Lite
4
- module Uxid
5
- class Reversible < Irreversible
6
-
7
- attr_reader :id
8
-
9
- def initialize(id, opts = {})
10
- @id = id
11
- super(opts)
12
- end
13
-
14
- class << self
15
-
16
- def encode(id, opts = {})
17
- klass = new(id, opts)
18
- klass.encode
19
- end
20
-
21
- def decode(id, opts = {})
22
- klass = new(id, opts)
23
- klass.decode
24
- end
25
-
26
- end
27
-
28
- def decode
29
- raise NotImplementedError, "override method in #{coder_class}"
30
- end
31
-
32
- end
33
- end
34
- end