encoded_id 1.0.0.rc4 → 1.0.0.rc6
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 +4 -4
- data/CHANGELOG.md +84 -1
- data/LICENSE.txt +1 -1
- data/README.md +79 -286
- data/context/encoded_id.md +283 -0
- data/lib/encoded_id/alphabet.rb +36 -3
- data/lib/encoded_id/blocklist.rb +90 -0
- data/lib/encoded_id/encoders/base.rb +71 -0
- data/lib/encoded_id/encoders/hash_id.rb +531 -0
- data/lib/encoded_id/encoders/hash_id_consistent_shuffle.rb +110 -0
- data/lib/encoded_id/encoders/hash_id_ordinal_alphabet_separator_guards.rb +270 -0
- data/lib/encoded_id/encoders/hash_id_salt.rb +51 -0
- data/lib/encoded_id/encoders/my_sqids.rb +465 -0
- data/lib/encoded_id/encoders/sqids.rb +42 -0
- data/lib/encoded_id/hex_representation.rb +23 -5
- data/lib/encoded_id/reversible_id.rb +110 -26
- data/lib/encoded_id/version.rb +4 -1
- data/lib/encoded_id.rb +41 -0
- metadata +17 -31
- data/Gemfile +0 -24
- data/Rakefile +0 -14
- data/Steepfile +0 -5
- data/rbs_collection.yaml +0 -24
- data/sig/encoded_id.rbs +0 -117
- data/sig/hash_ids.rbs +0 -70
|
@@ -1,14 +1,33 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# rbs_inline: enabled
|
|
4
4
|
|
|
5
5
|
# Hashid with a reduced character set Crockford alphabet and split groups
|
|
6
6
|
# See: https://www.crockford.com/wrmg/base32.html
|
|
7
|
-
# Build with https://hashids.org
|
|
8
|
-
# Note hashIds already has a built in profanity limitation algorithm
|
|
7
|
+
# Build with support for https://hashids.org and https://sqids.org
|
|
9
8
|
module EncodedId
|
|
9
|
+
# @rbs!
|
|
10
|
+
# type encodeableValue = Array[String | Integer] | String | Integer
|
|
11
|
+
|
|
10
12
|
class ReversibleId
|
|
11
|
-
|
|
13
|
+
# @rbs VALID_ENCODERS: Array[Symbol]
|
|
14
|
+
VALID_ENCODERS = [:hashids, :sqids].freeze
|
|
15
|
+
# @rbs DEFAULT_ENCODER: Symbol
|
|
16
|
+
DEFAULT_ENCODER = :hashids
|
|
17
|
+
|
|
18
|
+
# @rbs @alphabet: Alphabet
|
|
19
|
+
# @rbs @salt: String
|
|
20
|
+
# @rbs @length: Integer
|
|
21
|
+
# @rbs @split_at: Integer?
|
|
22
|
+
# @rbs @split_with: String?
|
|
23
|
+
# @rbs @hex_represention_encoder: HexRepresentation
|
|
24
|
+
# @rbs @max_length: Integer?
|
|
25
|
+
# @rbs @max_inputs_per_id: Integer
|
|
26
|
+
# @rbs @blocklist: Blocklist
|
|
27
|
+
# @rbs @encoder: Encoders::Base
|
|
28
|
+
|
|
29
|
+
# @rbs (salt: String, ?length: Integer, ?split_at: Integer?, ?split_with: String?, ?alphabet: Alphabet, ?hex_digit_encoding_group_size: Integer, ?max_length: Integer?, ?max_inputs_per_id: Integer, ?encoder: Symbol | Encoders::Base, ?blocklist: Blocklist | Array[String] | Set[String] | nil) -> void
|
|
30
|
+
def initialize(salt:, length: 8, split_at: 4, split_with: "-", alphabet: Alphabet.modified_crockford, hex_digit_encoding_group_size: 4, max_length: 128, max_inputs_per_id: 32, encoder: DEFAULT_ENCODER, blocklist: Blocklist.empty)
|
|
12
31
|
@alphabet = validate_alphabet(alphabet)
|
|
13
32
|
@salt = validate_salt(salt)
|
|
14
33
|
@length = validate_length(length)
|
|
@@ -17,13 +36,27 @@ module EncodedId
|
|
|
17
36
|
@hex_represention_encoder = HexRepresentation.new(hex_digit_encoding_group_size)
|
|
18
37
|
@max_length = validate_max_length(max_length)
|
|
19
38
|
@max_inputs_per_id = validate_max_input(max_inputs_per_id)
|
|
39
|
+
@blocklist = validate_blocklist(blocklist)
|
|
40
|
+
@encoder = create_encoder(validate_encoder(encoder))
|
|
20
41
|
end
|
|
21
42
|
|
|
43
|
+
# Accessors for introspection
|
|
44
|
+
attr_reader :salt #: String
|
|
45
|
+
attr_reader :length #: Integer
|
|
46
|
+
attr_reader :alphabet #: Alphabet
|
|
47
|
+
attr_reader :split_at #: Integer?
|
|
48
|
+
attr_reader :split_with #: String?
|
|
49
|
+
attr_reader :hex_represention_encoder #: HexRepresentation
|
|
50
|
+
attr_reader :max_length #: Integer?
|
|
51
|
+
attr_reader :blocklist #: Blocklist
|
|
52
|
+
attr_reader :encoder #: Encoders::Base
|
|
53
|
+
|
|
22
54
|
# Encode the input values into a hash
|
|
55
|
+
# @rbs (encodeableValue values) -> String
|
|
23
56
|
def encode(values)
|
|
24
57
|
inputs = prepare_input(values)
|
|
25
|
-
encoded_id =
|
|
26
|
-
encoded_id = humanize_length(encoded_id)
|
|
58
|
+
encoded_id = encoder.encode(inputs)
|
|
59
|
+
encoded_id = humanize_length(encoded_id) if split_with && split_at
|
|
27
60
|
|
|
28
61
|
raise EncodedIdLengthError if max_length_exceeded?(encoded_id)
|
|
29
62
|
|
|
@@ -31,78 +64,83 @@ module EncodedId
|
|
|
31
64
|
end
|
|
32
65
|
|
|
33
66
|
# Encode hex strings into a hash
|
|
67
|
+
# @rbs (encodeableHexValue hexs) -> String
|
|
34
68
|
def encode_hex(hexs)
|
|
35
69
|
encode(hex_represention_encoder.hex_as_integers(hexs))
|
|
36
70
|
end
|
|
37
71
|
|
|
38
72
|
# Decode the hash to original array
|
|
73
|
+
# @rbs (String str, ?downcase: bool) -> Array[Integer]
|
|
39
74
|
def decode(str, downcase: true)
|
|
40
|
-
raise
|
|
75
|
+
raise EncodedIdFormatError, "Max length of input exceeded" if max_length_exceeded?(str)
|
|
41
76
|
|
|
42
|
-
|
|
43
|
-
rescue
|
|
77
|
+
encoder.decode(convert_to_hash(str, downcase))
|
|
78
|
+
rescue InvalidInputError => e
|
|
44
79
|
raise EncodedIdFormatError, e.message
|
|
45
80
|
end
|
|
46
81
|
|
|
47
82
|
# Decode hex strings from a hash
|
|
83
|
+
# @rbs (String str, ?downcase: bool) -> Array[String]
|
|
48
84
|
def decode_hex(str, downcase: true)
|
|
49
|
-
integers =
|
|
85
|
+
integers = encoder.decode(convert_to_hash(str, downcase))
|
|
50
86
|
hex_represention_encoder.integers_as_hex(integers)
|
|
51
87
|
end
|
|
52
88
|
|
|
53
89
|
private
|
|
54
90
|
|
|
55
|
-
|
|
56
|
-
:length,
|
|
57
|
-
:alphabet,
|
|
58
|
-
:split_at,
|
|
59
|
-
:split_with,
|
|
60
|
-
:hex_represention_encoder,
|
|
61
|
-
:max_length
|
|
62
|
-
|
|
91
|
+
# @rbs (Alphabet alphabet) -> Alphabet
|
|
63
92
|
def validate_alphabet(alphabet)
|
|
64
93
|
return alphabet if alphabet.is_a?(Alphabet)
|
|
65
94
|
raise InvalidAlphabetError, "alphabet must be an instance of Alphabet"
|
|
66
95
|
end
|
|
67
96
|
|
|
97
|
+
# @rbs (String salt) -> String
|
|
68
98
|
def validate_salt(salt)
|
|
69
99
|
return salt if salt.is_a?(String) && salt.size > 3
|
|
70
100
|
raise InvalidConfigurationError, "Salt must be a string and longer than 3 characters"
|
|
71
101
|
end
|
|
72
102
|
|
|
73
103
|
# Target length of the encoded string (the minimum but not maximum length)
|
|
104
|
+
# @rbs (Integer length) -> Integer
|
|
74
105
|
def validate_length(length)
|
|
75
106
|
return length if valid_integer_option?(length)
|
|
76
107
|
raise InvalidConfigurationError, "Length must be an integer greater than 0"
|
|
77
108
|
end
|
|
78
109
|
|
|
110
|
+
# @rbs (Integer? max_length) -> Integer?
|
|
79
111
|
def validate_max_length(max_length)
|
|
80
112
|
return max_length if valid_integer_option?(max_length) || max_length.nil?
|
|
81
113
|
raise InvalidConfigurationError, "Max length must be an integer greater than 0"
|
|
82
114
|
end
|
|
83
115
|
|
|
116
|
+
# @rbs (Integer max_inputs_per_id) -> Integer
|
|
84
117
|
def validate_max_input(max_inputs_per_id)
|
|
85
118
|
return max_inputs_per_id if valid_integer_option?(max_inputs_per_id)
|
|
86
119
|
raise InvalidConfigurationError, "Max inputs per ID must be an integer greater than 0"
|
|
87
120
|
end
|
|
88
121
|
|
|
89
122
|
# Split the encoded string into groups of this size
|
|
123
|
+
# @rbs (Integer? split_at) -> Integer?
|
|
90
124
|
def validate_split_at(split_at)
|
|
91
125
|
return split_at if valid_integer_option?(split_at) || split_at.nil?
|
|
92
126
|
raise InvalidConfigurationError, "Split at must be an integer greater than 0 or nil"
|
|
93
127
|
end
|
|
94
128
|
|
|
129
|
+
# @rbs (String? split_with, Alphabet alphabet) -> String?
|
|
95
130
|
def validate_split_with(split_with, alphabet)
|
|
96
131
|
return split_with if split_with.nil? || (split_with.is_a?(String) && !alphabet.characters.include?(split_with))
|
|
97
132
|
raise InvalidConfigurationError, "Split with must be a string and not part of the alphabet or nil"
|
|
98
133
|
end
|
|
99
134
|
|
|
135
|
+
# @rbs (Integer? value) -> bool
|
|
100
136
|
def valid_integer_option?(value)
|
|
101
137
|
value.is_a?(Integer) && value > 0
|
|
102
138
|
end
|
|
103
139
|
|
|
140
|
+
# @rbs (encodeableValue value) -> Array[Integer]
|
|
104
141
|
def prepare_input(value)
|
|
105
142
|
inputs = value.is_a?(Array) ? value.map(&:to_i) : [value.to_i]
|
|
143
|
+
raise ::EncodedId::InvalidInputError, "Cannot encode an empty array" if inputs.empty?
|
|
106
144
|
raise ::EncodedId::InvalidInputError, "Integer IDs to be encoded can only be positive" if inputs.any?(&:negative?)
|
|
107
145
|
|
|
108
146
|
raise ::EncodedId::InvalidInputError, "%d integer IDs provided, maximum amount of IDs is %d" % [inputs.length, @max_inputs_per_id] if inputs.length > @max_inputs_per_id
|
|
@@ -110,24 +148,69 @@ module EncodedId
|
|
|
110
148
|
inputs
|
|
111
149
|
end
|
|
112
150
|
|
|
113
|
-
|
|
114
|
-
|
|
151
|
+
# @rbs (Symbol | Encoders::Base encoder) -> Encoders::Base
|
|
152
|
+
def create_encoder(encoder)
|
|
153
|
+
# If an encoder instance was provided, return it directly
|
|
154
|
+
return @encoder if defined?(@encoder) && @encoder.is_a?(Encoders::Base)
|
|
155
|
+
return encoder if encoder.is_a?(Encoders::Base)
|
|
156
|
+
|
|
157
|
+
case encoder
|
|
158
|
+
when :sqids
|
|
159
|
+
if defined?(Encoders::Sqids)
|
|
160
|
+
Encoders::Sqids.new(salt, length, alphabet, @blocklist)
|
|
161
|
+
else
|
|
162
|
+
raise InvalidConfigurationError, "Sqids encoder requested but the sqids gem is not available. Please add 'gem \"sqids\"' to your Gemfile."
|
|
163
|
+
end
|
|
164
|
+
when :hashids
|
|
165
|
+
Encoders::HashId.new(salt, length, alphabet, @blocklist)
|
|
166
|
+
else
|
|
167
|
+
raise InvalidConfigurationError, "The encoder name is not supported '#{encoder}'"
|
|
168
|
+
end
|
|
115
169
|
end
|
|
116
170
|
|
|
117
|
-
|
|
118
|
-
|
|
171
|
+
# @rbs (Symbol | Encoders::Base encoder) -> (Symbol | Encoders::Base)
|
|
172
|
+
def validate_encoder(encoder)
|
|
173
|
+
# Accept either a valid symbol or an Encoders::Base instance
|
|
174
|
+
return encoder if VALID_ENCODERS.include?(encoder) || encoder.is_a?(Encoders::Base)
|
|
175
|
+
raise InvalidConfigurationError, "Encoder must be one of: #{VALID_ENCODERS.join(", ")} or an instance of EncodedId::Encoders::Base"
|
|
119
176
|
end
|
|
120
177
|
|
|
178
|
+
# @rbs (Blocklist | Array[String] | Set[String] | nil blocklist) -> Blocklist
|
|
179
|
+
def validate_blocklist(blocklist)
|
|
180
|
+
return blocklist if blocklist.is_a?(Blocklist)
|
|
181
|
+
return Blocklist.empty if blocklist.nil?
|
|
182
|
+
|
|
183
|
+
return Blocklist.new(blocklist) if blocklist.is_a?(Array) || blocklist.is_a?(Set)
|
|
184
|
+
|
|
185
|
+
raise InvalidConfigurationError, "Blocklist must be an instance of Blocklist, a Set, or an Array of strings"
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# @rbs (String hash) -> String
|
|
121
189
|
def humanize_length(hash)
|
|
122
|
-
hash.
|
|
190
|
+
len = hash.length
|
|
191
|
+
at = split_at #: Integer
|
|
192
|
+
with = split_with #: String
|
|
193
|
+
return hash if len <= at
|
|
194
|
+
|
|
195
|
+
separator_count = (len - 1) / at
|
|
196
|
+
result = hash.dup
|
|
197
|
+
insert_offset = 0
|
|
198
|
+
(1..separator_count).each do |i|
|
|
199
|
+
insert_pos = i * at + insert_offset
|
|
200
|
+
result.insert(insert_pos, with)
|
|
201
|
+
insert_offset += with.length
|
|
202
|
+
end
|
|
203
|
+
result
|
|
123
204
|
end
|
|
124
205
|
|
|
206
|
+
# @rbs (String str, bool downcase) -> String
|
|
125
207
|
def convert_to_hash(str, downcase)
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
map_equivalent_characters(
|
|
208
|
+
str = str.gsub(split_with, "") if split_with
|
|
209
|
+
str = str.downcase if downcase
|
|
210
|
+
map_equivalent_characters(str)
|
|
129
211
|
end
|
|
130
212
|
|
|
213
|
+
# @rbs (String str) -> String
|
|
131
214
|
def map_equivalent_characters(str)
|
|
132
215
|
return str unless alphabet.equivalences
|
|
133
216
|
|
|
@@ -137,6 +220,7 @@ module EncodedId
|
|
|
137
220
|
end
|
|
138
221
|
end
|
|
139
222
|
|
|
223
|
+
# @rbs (String str) -> bool
|
|
140
224
|
def max_length_exceeded?(str)
|
|
141
225
|
return false if max_length.nil?
|
|
142
226
|
|
data/lib/encoded_id/version.rb
CHANGED
data/lib/encoded_id.rb
CHANGED
|
@@ -1,18 +1,59 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
# rbs_inline: enabled
|
|
4
|
+
|
|
3
5
|
require_relative "encoded_id/version"
|
|
4
6
|
require_relative "encoded_id/alphabet"
|
|
5
7
|
require_relative "encoded_id/hex_representation"
|
|
8
|
+
require_relative "encoded_id/blocklist"
|
|
9
|
+
|
|
10
|
+
# Load the encoder framework
|
|
11
|
+
require_relative "encoded_id/encoders/base"
|
|
12
|
+
require_relative "encoded_id/encoders/hash_id_salt"
|
|
13
|
+
require_relative "encoded_id/encoders/hash_id_consistent_shuffle"
|
|
14
|
+
require_relative "encoded_id/encoders/hash_id_ordinal_alphabet_separator_guards"
|
|
15
|
+
require_relative "encoded_id/encoders/hash_id"
|
|
16
|
+
|
|
17
|
+
# Only load Sqids encoder if the gem is available
|
|
18
|
+
begin
|
|
19
|
+
require "sqids"
|
|
20
|
+
require_relative "encoded_id/encoders/my_sqids"
|
|
21
|
+
require_relative "encoded_id/encoders/sqids"
|
|
22
|
+
rescue LoadError
|
|
23
|
+
# Sqids gem not available, encoder will not be loaded
|
|
24
|
+
end
|
|
25
|
+
|
|
6
26
|
require_relative "encoded_id/reversible_id"
|
|
7
27
|
|
|
28
|
+
# @rbs!
|
|
29
|
+
# class Integer
|
|
30
|
+
# MAX: Integer
|
|
31
|
+
# end
|
|
32
|
+
#
|
|
33
|
+
# # Optional Sqids gem support
|
|
34
|
+
# module Sqids
|
|
35
|
+
# DEFAULT_BLOCKLIST: Array[String]
|
|
36
|
+
# end
|
|
37
|
+
|
|
8
38
|
module EncodedId
|
|
39
|
+
# @rbs InvalidConfigurationError: singleton(StandardError)
|
|
9
40
|
class InvalidConfigurationError < StandardError; end
|
|
10
41
|
|
|
42
|
+
# @rbs InvalidAlphabetError: singleton(ArgumentError)
|
|
11
43
|
class InvalidAlphabetError < ArgumentError; end
|
|
12
44
|
|
|
45
|
+
# @rbs EncodedIdFormatError: singleton(ArgumentError)
|
|
13
46
|
class EncodedIdFormatError < ArgumentError; end
|
|
14
47
|
|
|
48
|
+
# @rbs EncodedIdLengthError: singleton(ArgumentError)
|
|
15
49
|
class EncodedIdLengthError < ArgumentError; end
|
|
16
50
|
|
|
51
|
+
# @rbs InvalidInputError: singleton(ArgumentError)
|
|
17
52
|
class InvalidInputError < ArgumentError; end
|
|
53
|
+
|
|
54
|
+
# @rbs BlocklistError: singleton(StandardError)
|
|
55
|
+
class BlocklistError < StandardError; end
|
|
56
|
+
|
|
57
|
+
# @rbs SaltError: singleton(ArgumentError)
|
|
58
|
+
class SaltError < ArgumentError; end
|
|
18
59
|
end
|
metadata
CHANGED
|
@@ -1,34 +1,19 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: encoded_id
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.0.
|
|
4
|
+
version: 1.0.0.rc6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stephen Ierodiaconou
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
12
|
-
dependencies:
|
|
13
|
-
- !ruby/object:Gem::Dependency
|
|
14
|
-
name: hashids
|
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
|
16
|
-
requirements:
|
|
17
|
-
- - "~>"
|
|
18
|
-
- !ruby/object:Gem::Version
|
|
19
|
-
version: '1.0'
|
|
20
|
-
type: :runtime
|
|
21
|
-
prerelease: false
|
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
-
requirements:
|
|
24
|
-
- - "~>"
|
|
25
|
-
- !ruby/object:Gem::Version
|
|
26
|
-
version: '1.0'
|
|
10
|
+
date: 2025-11-17 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
27
12
|
description: Encode your numerical IDs (eg record primary keys) into obfuscated strings
|
|
28
13
|
that can be used in URLs. The obfuscated strings are reversible, so you can decode
|
|
29
14
|
them back into the original numerical IDs. Supports encoding multiple IDs at once,
|
|
30
15
|
and generating IDs with custom alphabets and separators to make the IDs easier to
|
|
31
|
-
read or share.
|
|
16
|
+
read or share. Dependency free.
|
|
32
17
|
email:
|
|
33
18
|
- stevegeek@gmail.com
|
|
34
19
|
executables: []
|
|
@@ -36,27 +21,29 @@ extensions: []
|
|
|
36
21
|
extra_rdoc_files: []
|
|
37
22
|
files:
|
|
38
23
|
- CHANGELOG.md
|
|
39
|
-
- Gemfile
|
|
40
24
|
- LICENSE.txt
|
|
41
25
|
- README.md
|
|
42
|
-
-
|
|
43
|
-
- Steepfile
|
|
26
|
+
- context/encoded_id.md
|
|
44
27
|
- lib/encoded_id.rb
|
|
45
28
|
- lib/encoded_id/alphabet.rb
|
|
29
|
+
- lib/encoded_id/blocklist.rb
|
|
30
|
+
- lib/encoded_id/encoders/base.rb
|
|
31
|
+
- lib/encoded_id/encoders/hash_id.rb
|
|
32
|
+
- lib/encoded_id/encoders/hash_id_consistent_shuffle.rb
|
|
33
|
+
- lib/encoded_id/encoders/hash_id_ordinal_alphabet_separator_guards.rb
|
|
34
|
+
- lib/encoded_id/encoders/hash_id_salt.rb
|
|
35
|
+
- lib/encoded_id/encoders/my_sqids.rb
|
|
36
|
+
- lib/encoded_id/encoders/sqids.rb
|
|
46
37
|
- lib/encoded_id/hex_representation.rb
|
|
47
38
|
- lib/encoded_id/reversible_id.rb
|
|
48
39
|
- lib/encoded_id/version.rb
|
|
49
|
-
- rbs_collection.yaml
|
|
50
|
-
- sig/encoded_id.rbs
|
|
51
|
-
- sig/hash_ids.rbs
|
|
52
40
|
homepage: https://github.com/stevegeek/encoded_id
|
|
53
41
|
licenses:
|
|
54
42
|
- MIT
|
|
55
43
|
metadata:
|
|
56
44
|
homepage_uri: https://github.com/stevegeek/encoded_id
|
|
57
45
|
source_code_uri: https://github.com/stevegeek/encoded_id
|
|
58
|
-
changelog_uri: https://github.com/stevegeek/encoded_id/blob/
|
|
59
|
-
post_install_message:
|
|
46
|
+
changelog_uri: https://github.com/stevegeek/encoded_id/blob/main/CHANGELOG.md
|
|
60
47
|
rdoc_options: []
|
|
61
48
|
require_paths:
|
|
62
49
|
- lib
|
|
@@ -64,16 +51,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
64
51
|
requirements:
|
|
65
52
|
- - ">="
|
|
66
53
|
- !ruby/object:Gem::Version
|
|
67
|
-
version: 2.
|
|
54
|
+
version: 3.2.0
|
|
68
55
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
69
56
|
requirements:
|
|
70
57
|
- - ">="
|
|
71
58
|
- !ruby/object:Gem::Version
|
|
72
59
|
version: '0'
|
|
73
60
|
requirements: []
|
|
74
|
-
rubygems_version: 3.
|
|
75
|
-
signing_key:
|
|
61
|
+
rubygems_version: 3.6.2
|
|
76
62
|
specification_version: 4
|
|
77
63
|
summary: EncodedId is a gem for creating reversible obfuscated IDs from numerical
|
|
78
|
-
IDs. It uses Hash IDs under the hood.
|
|
64
|
+
IDs. It uses an implementation of Hash IDs under the hood.
|
|
79
65
|
test_files: []
|
data/Gemfile
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
source "https://rubygems.org"
|
|
4
|
-
|
|
5
|
-
# Specify your gem's dependencies in encoded_id.gemspec
|
|
6
|
-
gemspec
|
|
7
|
-
|
|
8
|
-
gem "rake", "~> 13.0"
|
|
9
|
-
|
|
10
|
-
gem "minitest"
|
|
11
|
-
|
|
12
|
-
gem "standard", "~> 1.30"
|
|
13
|
-
|
|
14
|
-
gem "rbs"
|
|
15
|
-
|
|
16
|
-
gem "steep"
|
|
17
|
-
|
|
18
|
-
gem "simplecov"
|
|
19
|
-
|
|
20
|
-
gem "benchmark-ips"
|
|
21
|
-
|
|
22
|
-
gem "benchmark-memory"
|
|
23
|
-
|
|
24
|
-
gem "fuzzbert"
|
data/Rakefile
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "bundler/gem_tasks"
|
|
4
|
-
require "rake/testtask"
|
|
5
|
-
|
|
6
|
-
Rake::TestTask.new(:test) do |t|
|
|
7
|
-
t.libs << "test"
|
|
8
|
-
t.libs << "lib"
|
|
9
|
-
t.test_files = FileList["test/**/test_*.rb"]
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
require "standard/rake"
|
|
13
|
-
|
|
14
|
-
task default: %i[test standard]
|
data/Steepfile
DELETED
data/rbs_collection.yaml
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# Download sources
|
|
2
|
-
sources:
|
|
3
|
-
- name: ruby/gem_rbs_collection
|
|
4
|
-
remote: https://github.com/ruby/gem_rbs_collection.git
|
|
5
|
-
revision: main
|
|
6
|
-
repo_dir: gems
|
|
7
|
-
|
|
8
|
-
# A directory to install the downloaded RBSs
|
|
9
|
-
path: .gem_rbs_collection
|
|
10
|
-
|
|
11
|
-
gems:
|
|
12
|
-
# Skip loading rbs gem's RBS.
|
|
13
|
-
# It's unnecessary if you don't use rbs as a library.
|
|
14
|
-
- name: rbs
|
|
15
|
-
ignore: true
|
|
16
|
-
- name: rake
|
|
17
|
-
ignore: true
|
|
18
|
-
- name: minitest
|
|
19
|
-
ignore: true
|
|
20
|
-
- name: standard
|
|
21
|
-
ignore: true
|
|
22
|
-
- name: steep
|
|
23
|
-
ignore: true
|
|
24
|
-
|
data/sig/encoded_id.rbs
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
module EncodedId
|
|
2
|
-
VERSION: ::String
|
|
3
|
-
|
|
4
|
-
InvalidConfigurationError: ::StandardError
|
|
5
|
-
EncodedIdFormatError: ::ArgumentError
|
|
6
|
-
EncodedIdLengthError: ::ArgumentError
|
|
7
|
-
InvalidAlphabetError: ::ArgumentError
|
|
8
|
-
InvalidInputError: ::ArgumentError
|
|
9
|
-
|
|
10
|
-
class Alphabet
|
|
11
|
-
MIN_UNIQUE_CHARACTERS: ::Integer
|
|
12
|
-
|
|
13
|
-
def initialize: (String | ::Array[::String] characters, ::Hash[::String, ::String] ?equivalences) -> void
|
|
14
|
-
|
|
15
|
-
attr_reader unique_characters: ::Array[::String]
|
|
16
|
-
attr_reader characters: String
|
|
17
|
-
attr_reader equivalences: ::Hash[::String, ::String] | nil
|
|
18
|
-
|
|
19
|
-
def include?: (::String character) -> bool
|
|
20
|
-
|
|
21
|
-
def self.modified_crockford: () -> Alphabet
|
|
22
|
-
|
|
23
|
-
private
|
|
24
|
-
|
|
25
|
-
def valid_input_characters?: ((::Array[::String] | ::String) characters) -> bool
|
|
26
|
-
|
|
27
|
-
def valid_characters?: -> bool
|
|
28
|
-
|
|
29
|
-
def sufficient_characters?: -> bool
|
|
30
|
-
|
|
31
|
-
def unique_character_alphabet: ((::Array[::String] | ::String) characters) -> ::Array[::String]
|
|
32
|
-
|
|
33
|
-
def valid_equivalences?: (::Hash[::String, ::String] ?equivalences) -> bool
|
|
34
|
-
|
|
35
|
-
def raise_character_set_too_small!: -> untyped
|
|
36
|
-
|
|
37
|
-
def raise_invalid_alphabet!: -> void
|
|
38
|
-
|
|
39
|
-
def raise_invalid_equivalences!: -> void
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
type encodeableValue = ::Array[::String | ::Integer] | ::String | ::Integer
|
|
43
|
-
type encodeableHexValue = ::Array[::String] | ::String
|
|
44
|
-
|
|
45
|
-
class HexRepresentation
|
|
46
|
-
def initialize: (::Integer) -> void
|
|
47
|
-
def hex_as_integers: (encodeableHexValue) -> ::Array[::Integer]
|
|
48
|
-
def integers_as_hex: (::Array[::Integer]) -> ::Array[::String]
|
|
49
|
-
|
|
50
|
-
private
|
|
51
|
-
|
|
52
|
-
def validate_hex_digit_encoding_group_size: (::Integer) -> ::Integer
|
|
53
|
-
def integer_representation: (encodeableHexValue) -> ::Array[::Integer]
|
|
54
|
-
def integers_to_hex_strings: (::Array[::Integer]) -> ::Array[::String]
|
|
55
|
-
def hex_string_as_integer_representation: (::String) -> ::Array[::Integer]
|
|
56
|
-
def hex_string_separator: -> ::Integer
|
|
57
|
-
def remove_non_hex_characters: (::String) -> ::String
|
|
58
|
-
def convert_to_integer_groups: (::String) -> ::Array[::Integer]
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
class ReversibleId
|
|
62
|
-
def initialize: (salt: ::String, ?length: ::Integer, ?split_at: ::Integer, ?split_with: ::String, ?alphabet: Alphabet, ?hex_digit_encoding_group_size: ::Integer, ?max_length: ::Integer, ?max_inputs_per_id: ::Integer) -> void
|
|
63
|
-
|
|
64
|
-
# Encode the input values into a hash
|
|
65
|
-
def encode: (encodeableValue values) -> ::String
|
|
66
|
-
|
|
67
|
-
# Encode hex strings into a hash
|
|
68
|
-
def encode_hex: (encodeableHexValue hexs) -> ::String
|
|
69
|
-
|
|
70
|
-
# Decode the hash to original array
|
|
71
|
-
def decode: (::String str) -> ::Array[::Integer]
|
|
72
|
-
|
|
73
|
-
# Decode hex strings from a hash
|
|
74
|
-
def decode_hex: (::String str) -> ::Array[::String]
|
|
75
|
-
|
|
76
|
-
private
|
|
77
|
-
|
|
78
|
-
@encoded_id_generator: ::Hashids
|
|
79
|
-
@split_regex: ::Regexp
|
|
80
|
-
@hex_string_separator: ::Integer
|
|
81
|
-
|
|
82
|
-
attr_reader salt: ::String
|
|
83
|
-
|
|
84
|
-
attr_reader length: ::Integer
|
|
85
|
-
attr_reader max_length: ::Integer | nil
|
|
86
|
-
|
|
87
|
-
attr_reader alphabet: Alphabet
|
|
88
|
-
|
|
89
|
-
attr_reader split_at: ::Integer | nil
|
|
90
|
-
attr_reader split_with: ::String
|
|
91
|
-
|
|
92
|
-
attr_reader hex_represention_encoder: HexRepresentation
|
|
93
|
-
|
|
94
|
-
def validate_alphabet: (Alphabet) -> Alphabet
|
|
95
|
-
def validate_salt: (::String) -> ::String
|
|
96
|
-
def validate_length: (::Integer) -> ::Integer
|
|
97
|
-
def validate_max_length: (::Integer | nil) -> (::Integer | nil)
|
|
98
|
-
def validate_max_input: (::Integer) -> ::Integer
|
|
99
|
-
def validate_split_at: (::Integer | nil) -> (::Integer | nil)
|
|
100
|
-
def validate_split_with: (::String, Alphabet) -> ::String
|
|
101
|
-
def validate_hex_digit_encoding_group_size: (::Integer) -> ::Integer
|
|
102
|
-
def valid_integer_option?: (::Integer | nil) -> bool
|
|
103
|
-
|
|
104
|
-
def prepare_input: (untyped value) -> ::Array[::Integer]
|
|
105
|
-
|
|
106
|
-
def encoded_id_generator: () -> ::Hashids
|
|
107
|
-
|
|
108
|
-
def split_regex: () -> ::Regexp
|
|
109
|
-
|
|
110
|
-
def humanize_length: (::String hash) -> ::String
|
|
111
|
-
|
|
112
|
-
def convert_to_hash: (::String str, bool) -> ::String
|
|
113
|
-
|
|
114
|
-
def map_equivalent_characters: (::String str) -> ::String
|
|
115
|
-
def max_length_exceeded?: (::String str) -> bool
|
|
116
|
-
end
|
|
117
|
-
end
|
data/sig/hash_ids.rbs
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
class Hashids
|
|
2
|
-
MIN_ALPHABET_LENGTH: ::Integer
|
|
3
|
-
|
|
4
|
-
SEP_DIV: ::Float
|
|
5
|
-
|
|
6
|
-
GUARD_DIV: ::Float
|
|
7
|
-
|
|
8
|
-
DEFAULT_SEPS: ::String
|
|
9
|
-
|
|
10
|
-
DEFAULT_ALPHABET: ::String
|
|
11
|
-
|
|
12
|
-
attr_reader salt: ::String
|
|
13
|
-
|
|
14
|
-
attr_reader min_hash_length: ::Integer
|
|
15
|
-
|
|
16
|
-
attr_reader alphabet: ::String
|
|
17
|
-
|
|
18
|
-
attr_reader seps: ::String
|
|
19
|
-
|
|
20
|
-
attr_reader guards: untyped
|
|
21
|
-
|
|
22
|
-
def initialize: (?::String salt, ?::Integer min_hash_length, ?untyped alphabet) -> void
|
|
23
|
-
|
|
24
|
-
def encode: (*(Array[::Integer] | ::Integer) numbers) -> ::String
|
|
25
|
-
|
|
26
|
-
def encode_hex: (::String str) -> ::String
|
|
27
|
-
|
|
28
|
-
def decode: (::String hash) -> ::Array[::Integer]
|
|
29
|
-
|
|
30
|
-
def decode_hex: (::String hash) -> ::Array[::Integer]
|
|
31
|
-
|
|
32
|
-
# protected
|
|
33
|
-
|
|
34
|
-
def internal_encode: (untyped numbers) -> untyped
|
|
35
|
-
|
|
36
|
-
def internal_decode: (untyped hash, untyped alphabet) -> untyped
|
|
37
|
-
|
|
38
|
-
def consistent_shuffle: (untyped alphabet, untyped salt) -> untyped
|
|
39
|
-
|
|
40
|
-
def hash: (untyped input, untyped alphabet) -> untyped
|
|
41
|
-
|
|
42
|
-
def unhash: (untyped input, untyped alphabet) -> untyped
|
|
43
|
-
|
|
44
|
-
private
|
|
45
|
-
|
|
46
|
-
def setup_alphabet: () -> untyped
|
|
47
|
-
|
|
48
|
-
def setup_seps: () -> untyped
|
|
49
|
-
|
|
50
|
-
def setup_guards: () -> untyped
|
|
51
|
-
|
|
52
|
-
SaltError: ArgumentError
|
|
53
|
-
|
|
54
|
-
MinLengthError: ArgumentError
|
|
55
|
-
|
|
56
|
-
AlphabetError: ArgumentError
|
|
57
|
-
|
|
58
|
-
InputError: ArgumentError
|
|
59
|
-
|
|
60
|
-
def validate_attributes: () -> untyped
|
|
61
|
-
|
|
62
|
-
def validate_alphabet: () -> (untyped | nil)
|
|
63
|
-
|
|
64
|
-
def hex_string?: (untyped string) -> untyped
|
|
65
|
-
|
|
66
|
-
def pick_characters: (untyped array, untyped index) -> untyped
|
|
67
|
-
|
|
68
|
-
def uniq_characters: (untyped string) -> untyped
|
|
69
|
-
end
|
|
70
|
-
|