lite-uxid 1.3.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
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