make_id 0.1.1 → 0.1.2

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