make_id 0.1.1 → 0.1.2

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.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +28 -24
  3. data/lib/make_id/version.rb +1 -1
  4. data/lib/make_id.rb +45 -59
  5. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 30fbadcaf247ed032060da86a3634f1124cc550b6061fd8599dd63f8f07ce473
4
- data.tar.gz: 1fed2e5cd4c0ace07c5457a7b0f3839ea0756d737a842f2876390121cf88374e
3
+ metadata.gz: 2448e655a9a006abb23272b2b54c6b4fc537f702407c931afcf106b82c468b04
4
+ data.tar.gz: 9852758f34e12c2be8aa90149cdded09e011f2ab879320089fc1bfb3f577d849
5
5
  SHA512:
6
- metadata.gz: 234e0c71427fd3ec7f522862c42698afb475702baf6e70bf9e524d98ded74c26f9652b404e4afea82bbb0b0e2cd8daf181c505bb2a44c25ac12d5611418feb43
7
- data.tar.gz: 2f682f097b4d791c956b381c9007c14a4748dc2e3e97c21f5e8a5942f54e1369c5cc361033a41aa88e65f2ce9f1fada51fac98b4f22c1684e36d3fbf6a46bc05
6
+ metadata.gz: 108e40b61bfdcc00ac5e550b4afb14fb8f7298df617d10b7179975b2be8f6f04c6b4693fc6909de26f42e6a9977333d12f7ecc5c5846b1317b3ab728b6e6d04d
7
+ data.tar.gz: 25c7229af03bc353707c2ee832f00c2ad63243318156ffa51bcd197f328a2cae865eaf37fa0949d7c8d98bcf9e583b4ec8f2fb2563317d7584b906b9f3c8cf08
data/README.md CHANGED
@@ -61,8 +61,14 @@ MakeId can return a random (8-byte by default) integer. You can request it retur
61
61
  and with an optional check_digit.
62
62
  Usually, you would use the integer returned, and call `int_to_base` to format for a URL or code.
63
63
 
64
- MakeId.random_id() #=> 15379918763975837985ZZ
65
- MakeId.random_id(base: 62, check_digit: true) #=> "2984biEwRT1"
64
+ MakeId.id() #=> 15379918763975837985ZZ
65
+ MakeId.id(base: 62, check_digit: true) #=> "2984biEwRT1"
66
+
67
+ Nano Id's are shorter unique strings generated from random characters, usually as a friendlier alternative
68
+ to UUID's. These are 8-byte numeric identifiers in extended bases, such as 36 or 62.
69
+
70
+ MakeId.nano_id() #=> "iZnLn96FVcjivEJA" (Base-62 be default)
71
+ MakeId.nano_id(base: 36) #=> "sf8kqb8ekn7k98rq"
66
72
 
67
73
  ### UUID
68
74
 
@@ -76,16 +82,28 @@ can be used to transform a long UUID into a possibly more palettable base repres
76
82
  MakeId.uuid_to_base(u, 62) #=> "fWJtuXEQJnkjxroWjkmei" (21 characters)
77
83
 
78
84
  Note that some databases support a UUID type which makes storing UUID's easier, and since they are stored as a binary
79
- field, consume less space.ZZ
85
+ field, consume less space.
80
86
 
81
- ### Nano Id
87
+ ### Tokens
82
88
 
83
- Nano Id's are shorter unique strings generated from random characters, usually as a friendlier alternative
84
- to UUID's. They also can be of any size, depending on the key range you require. Pay attention to the keyspace,
85
- ensuring you have enough characters to avoid predictable collisions in the future.
89
+ Tokens are randomly-generated strings of the character set of the requested base.
90
+ The default size is 16 characters of the Base-62 character set.
91
+
92
+ MakeId.token() #=> "Na4VX61PBFVZWL6Y"
93
+ MakeId.token(8, base:36) #=> "BK0ZTL9H"
94
+
95
+ ### Codes
86
96
 
87
- MakeId.nano_id(size: 16) #=> "iZnLn96FVcjivEJA"
88
- MakeId.nano_id(size: 16, base: 32) #=> "sf8kqb8ekn7k98rq"
97
+ Codes are string tokens to send to users for input. They have no ambiguous characters to avoid confusion.
98
+ This is useful for verifications such as two-factor authentication codes, or license numbers.
99
+ This returns an 8-character string by default. Specify a group (size) and delimiter (default is a hyphen)
100
+ to make long codes readable.
101
+
102
+ MakeId.code #=> "22E0D18F"
103
+ MakeId.code(20) #=> "Y41Q24AG7DYZYTAZWQZX"
104
+ MakeId.code(20, group: 4, delimiter: "-") #=> "9975-V5VM-KKSR-4PQ6-7F4G"
105
+
106
+ ### Temporal Identifiers
89
107
 
90
108
  A `request_id` is a nano_id that can be used to track requests and jobs. It is a 16-byte string, the same
91
109
  storage as a UUID, but with columnar values. The substring of 3 for 8 is a short (8 character) version that
@@ -96,9 +114,7 @@ can be used as well, is easier to read, sortable within a day, and unique enough
96
114
  id[3,8] #=> "f1272t01"
97
115
  #-------------------------->Hsssuuqq
98
116
 
99
- ### Snowflake Id
100
-
101
- Snowflakes were invented at Twitter to stamp an identifier for a tweet or direct message.
117
+ Snowflake Id's were invented at Twitter to stamp an identifier for a tweet or direct message.
102
118
  It is an 8-byte integer intended to be time-sorted and unique across the fleet of servers saving messages.
103
119
  It is a bit-mapped integer consisting of these parts:
104
120
 
@@ -137,18 +153,6 @@ records or when you need a slowflake ID but have a UUID column to fill.
137
153
  MakeID.snowflake_datetime_uuid #=> "20240904-1418-5332-2000-3a38e61d5582"
138
154
  #------------------------>YYYYMMDD-hhmm-ssuu-uwww-rrrrrrrrrrrr
139
155
 
140
- ## Experimental Id's
141
-
142
- The `event_id` is a string, sortable by creation time, with visible time seperator columns.
143
- It is of the format "YMDhmsuurrrr", using Base62, with an optional check_sum characer.
144
- It also used the application epoch described under `snowflake_id`. "uu" represents the fractional
145
- seconds that can be represented in Base62, and a 4-character random Base64 "nano_id".
146
-
147
- MakeId.epoch = 2020
148
- MakeId.event_id #=> "493KgpQGErTB"
149
- #------------------->YMDhmsuurrrr ()
150
- MakeId.event_id(check_digit: true) #=> "493Kkha6HZa2" (3 random chars + check digit)
151
-
152
156
  ## Development
153
157
 
154
158
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MakeId
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.2"
5
5
  end
data/lib/make_id.rb CHANGED
@@ -73,24 +73,11 @@ module MakeId
73
73
  end
74
74
 
75
75
  ##############################################################################
76
- # Random Strings
77
- ##############################################################################
78
-
79
- # Returns a random alphanumeric string of the given base, default of 62.
80
- # Base 64 uses URL-safe characters. Bases 19-32 and below use a special
81
- # character set that avoids visually ambiguous characters. Other bases
82
- # utilize the full alphanumeric characer set (digits, lower/upper letters).
83
- def self.random(size = 16, base: 62, chars: nil)
84
- _, chars = base_characters(base, chars)
85
- SecureRandom.alphanumeric(size, chars: chars.chars)
86
- end
87
-
88
- ##############################################################################
89
- # Integers
76
+ # Numeric Identifiers (of any suported base)
90
77
  ##############################################################################
91
78
 
92
79
  # Random Integer ID
93
- def self.random_id(bytes: 8, base: 10, absolute: true, check_digit: false)
80
+ def self.id(bytes: 8, base: 10, absolute: true, check_digit: false)
94
81
  id = SecureRandom.random_number(2**(bytes * 8) - 2) + 1 # +1 to avoid zero
95
82
  id = id.abs if absolute
96
83
  id = int_to_base(id, base) unless base == 10
@@ -98,17 +85,26 @@ module MakeId
98
85
  id
99
86
  end
100
87
 
101
- def self.random_id_password(bytes: 8, base: 10, absolute: true, alpha: nil)
102
- id = random_id(bytes: bytes)
103
- pass = random_id(bytes: 16)
88
+ def self.id_password(bytes: 8, base: 10, absolute: true, alpha: nil)
89
+ id = id(bytes: bytes)
90
+ pass = id(bytes: 16)
104
91
  [int_to_base(id, base), encode_alphabet(pass, alpha || BASE94, seed: id)]
105
92
  end
106
93
 
94
+ # Generates a 8-byte "nano id", a string of random characters of the given alphabet,
95
+ # suitable for URL's or where you don't want to show a sequential number.
96
+ # A check digit can be added to the end to help prevent typos.
97
+ def self.nano_id(bytes: 8, base: 62, check_digit: true)
98
+ bytes -= 1 if check_digit
99
+ id = id(bytes: bytes, base: base)
100
+ check_digit ? append_check_digit(id, base) : id
101
+ end
102
+
107
103
  ##############################################################################
108
104
  # UUID - Universally Unique Identifier
109
105
  ##############################################################################
110
106
 
111
- # Returns a (securely) random generated UUID v4
107
+ # Returns a 16-byte securely-random generated UUID v4
112
108
  def self.uuid
113
109
  SecureRandom.uuid
114
110
  end
@@ -121,49 +117,40 @@ module MakeId
121
117
  end
122
118
 
123
119
  ##############################################################################
124
- # Nano Id - Simple, secure URL-friendly unique string ID generator
120
+ # Strings Identifiers
125
121
  ##############################################################################
126
122
 
127
- # Generates a "nano id", a string of random characters of the given alphabet,
128
- # suitable for URL's or where you don't want to show a sequential number.
129
- # A check digit is added to the end to help prevent typos.
130
- def self.nano_id(size: 20, base: 62, check_digit: true)
131
- # alpha = (base <= 32) ? BASE32 : BASE62
132
- size -= 1 if check_digit
133
- id = random(size, base: base)
134
- check_digit ? append_check_digit(id, base) : id
135
- end
136
-
137
- # Given a nano_id, replaces visually ambiguous characters and verifies the
138
- # check digit. Returns the corrected id or nil if the check digit is invalid.
139
- def self.verify_base32_id(nanoid)
140
- nanoid.gsub!(/[oO]/, "0")
141
- nanoid.gsub!(/[lLiI]/, "1")
142
- nanoid.downcase
143
- valid_check_digit?(nanoid, base: 32)
123
+ # Returns a random alphanumeric string of the given base, default of 62.
124
+ # Base 64 uses URL-safe characters. Bases 19-32 and below use a special
125
+ # character set that avoids visually ambiguous characters. Other bases
126
+ # utilize the full alphanumeric characer set (digits, lower/upper letters).
127
+ def self.token(size = 16, base: 62, chars: nil)
128
+ _, chars = base_characters(base, chars)
129
+ SecureRandom.alphanumeric(size, chars: chars.chars)
144
130
  end
145
131
 
146
- # Manual Id is a code and/or identifier that is manually entered by a user.
147
- # Examples of this would be a Two-Factor Authentication challenge, a code
148
- # used for confirmation, redemption, or a short-term record lookup code
149
- # (like an airline ticket/itenerary code)
150
- # It uses a base-32 (non-ambiguous character set) by default,
151
- def self.manual_id(size: 6, base: 32, check_digit: false)
152
- base = 32 if base > 36 # For upcasing
153
- nano_id(size: size, base: base, check_digit: check_digit).upcase
132
+ # Returns a new, ramdonly-generated Base-32 code (no ambiguous characters).
133
+ # Use this for Two-Factor Authorization, and serial number codes to be
134
+ # input by users. Use verify_code() to "fix" user-input of codes.
135
+ def self.code(size = 8, group: 0, delimiter: "-")
136
+ id = token(size, base: 32)
137
+ id = id.chars.each_slice(group).map(&:join).join(delimiter) if group > 0
138
+ id
154
139
  end
155
140
 
156
- def self.fix_manual_id(id, base: 32, check_digit: false)
157
- if base == 32
158
- id = id.gsub(/[oO]/, "0")
159
- id = id.gsub(/[lLiI]/, "1")
160
- end
161
- id = valid_check_digit?(id.downcase, base: 32) if check_digit
162
- id.upcase
141
+ # Given a nano_id, replaces visually ambiguous characters and verifies the
142
+ # check digit. Returns the corrected id or nil if the check digit is invalid.
143
+ def self.verify_code(nanoid, check_digit: false)
144
+ nanoid = nanoid.gsub(/\W/, "")
145
+ nanoid = nanoid.gsub(/[oO]/, "0")
146
+ nanoid = nanoid.gsub(/[lLiI]/, "1")
147
+ nanoid = nanoid.upcase
148
+ return valid_check_digit?(nanoid, base: 32) if check_digit
149
+ nanoid
163
150
  end
164
151
 
165
152
  ##############################################################################
166
- # TEMPORAL ID's
153
+ # TEMPORAL Identifiers
167
154
  ##############################################################################
168
155
 
169
156
  # Event Id - A nano_id, but timestamped event identifier: YMDHMSUUrrrrc
@@ -180,7 +167,7 @@ module MakeId
180
167
  usec.rjust(2, "0") # 2-chars, 0..3843
181
168
  ]
182
169
  nano_size = size - 8 - (check_digit ? 1 : 0)
183
- parts << nano_id(size: nano_size, base: 62) if nano_size > 0
170
+ parts << token(nano_size, base: 62) if nano_size > 0
184
171
  id = check_digit ? append_check_digit(parts.join, 62) : parts.join
185
172
  id[0, size]
186
173
  end
@@ -206,7 +193,7 @@ module MakeId
206
193
  int_to_base((time.subsec.to_f * 32 * 32).to_i, 32), # 2 chars
207
194
  sequence.to_s(32).rjust(2, "0"), # 2 chars "-",
208
195
  (app_worker_id % 1024).to_s(32).rjust(2, "0"), # 2 chars
209
- random(3, base: 32)
196
+ token(3, base: 32)
210
197
  ].join
211
198
  end
212
199
 
@@ -323,7 +310,7 @@ module MakeId
323
310
 
324
311
  # Parses a string as a base n number and returns its decimal integer value
325
312
  def self.base_to_int(string, base = 62, check_digit: false)
326
- # TODO check_digit
313
+ # TODO: check_digit
327
314
  _, chars = base_characters(base, chars)
328
315
  decode_alphabet(string, chars)
329
316
  end
@@ -367,9 +354,7 @@ module MakeId
367
354
  else
368
355
  chars = BASE62[0..(base - 1)]
369
356
  end
370
- if shuffle_seed
371
- chars = chars.chars.shuffle(random: Random.new(shuffle_seed)).join
372
- end
357
+ chars = chars.chars.shuffle(random: Random.new(shuffle_seed)).join if shuffle_seed
373
358
  base = chars.size
374
359
 
375
360
  [base, chars]
@@ -389,6 +374,7 @@ module MakeId
389
374
  # Uses a pre-defined check_proc if configured. See check_proc=().
390
375
  def self.compute_check_digit(id, base = 10)
391
376
  return @@check_proc.call(id, base) if @@check_proc.is_a?(Proc)
377
+
392
378
  int_to_base(Zlib.crc32(id.to_s) % base, base)
393
379
  end
394
380
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: make_id
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Allen Fair
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-11-11 00:00:00.000000000 Z
11
+ date: 2024-11-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64