dynamic_links 0.1.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 +7 -0
- data/README.md +66 -0
- data/Rakefile +8 -0
- data/app/assets/config/dynamic_links_manifest.js +1 -0
- data/app/assets/stylesheets/dynamic_links/application.css +15 -0
- data/app/controllers/dynamic_links/application_controller.rb +4 -0
- data/app/controllers/dynamic_links/v1/short_links_controller.rb +14 -0
- data/app/helpers/dynamic_links/application_helper.rb +4 -0
- data/app/jobs/dynamic_links/application_job.rb +4 -0
- data/app/jobs/dynamic_links/generate_short_links_job.rb +31 -0
- data/app/mailers/dynamic_links/application_mailer.rb +6 -0
- data/app/models/dynamic_links/application_record.rb +5 -0
- data/app/models/dynamic_links/client.rb +21 -0
- data/app/models/dynamic_links/shortened_url.rb +25 -0
- data/app/views/layouts/dynamic_links/application.html.erb +15 -0
- data/config/routes.rb +8 -0
- data/db/migrate/20231228165744_create_dynamic_links_clients.rb +13 -0
- data/db/migrate/20231228175142_create_dynamic_links_shortened_urls.rb +21 -0
- data/lib/dynamic_links/configuration.rb +10 -0
- data/lib/dynamic_links/engine.rb +5 -0
- data/lib/dynamic_links/shortening_strategies/base_strategy.rb +28 -0
- data/lib/dynamic_links/shortening_strategies/crc32_strategy.rb +19 -0
- data/lib/dynamic_links/shortening_strategies/md5_strategy.rb +20 -0
- data/lib/dynamic_links/shortening_strategies/mock_strategy.rb +10 -0
- data/lib/dynamic_links/shortening_strategies/nano_id_strategy.rb +21 -0
- data/lib/dynamic_links/shortening_strategies/redis_counter_strategy.rb +31 -0
- data/lib/dynamic_links/shortening_strategies/sha256_strategy.rb +20 -0
- data/lib/dynamic_links/strategy_factory.rb +23 -0
- data/lib/dynamic_links/version.rb +3 -0
- data/lib/dynamic_links.rb +53 -0
- data/lib/generators/dynamic_links/add_kgs_migration_generator.rb +16 -0
- data/lib/generators/dynamic_links/templates/migration_template.rb +6 -0
- data/lib/tasks/dynamic_links_tasks.rake +4 -0
- metadata +147 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f8be4269ba92cfbec08c29ec6a6a871383b8470736057204fa24234ebfc70a98
|
4
|
+
data.tar.gz: 90a2df3615def525638fc53eeb23eef0a367d0137993b6303630d7d868ac3443
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3ca6e9c92116542c9df6895e861843c03e951cb7e87bf567bc189b4811f8fb6cf95e097123b4569843ea18f8780289e1bec70b2de2a8bd92532f929277e0578e
|
7
|
+
data.tar.gz: 50e65b566b1b36f9b169f0a7c35610720027f030c31d4fd7fe861ee077ea1b5c043391a51caf4f34c612f13456fdcf16cbb95d39a019c69f65bb2676bc2d7fd7
|
data/README.md
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# DynamicLinks
|
2
|
+
|
3
|
+
DynamicLinks is a flexible URL shortening Ruby gem, designed to provide various strategies for URL shortening, similar to Firebase Dynamic Links.
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
|
7
|
+
To use DynamicLinks, you need to configure the shortening strategy in an initializer or before you start shortening URLs.
|
8
|
+
|
9
|
+
### Configuration
|
10
|
+
|
11
|
+
In your Rails initializer or similar setup code, configure DynamicLinks like this:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
DynamicLinks.configure do |config|
|
15
|
+
config.shortening_strategy = :MD5
|
16
|
+
end
|
17
|
+
```
|
18
|
+
|
19
|
+
### Shortening a URL
|
20
|
+
|
21
|
+
To shorten a URL, simply call:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
shortened_url = DynamicLinks.shorten_url("https://example.com")
|
25
|
+
```
|
26
|
+
|
27
|
+
## Available Shortening Strategies
|
28
|
+
|
29
|
+
DynamicLinks supports various shortening strategies. The default strategy is `MD5`, but you can choose among several others, including `NanoIdStrategy`, `RedisCounterStrategy`, `Sha256Strategy`, and more.
|
30
|
+
|
31
|
+
Depending on the strategy you choose, you may need to install additional dependencies.
|
32
|
+
|
33
|
+
### Optional Dependencies
|
34
|
+
|
35
|
+
- For `NanoIdStrategy`, add `gem 'nanoid', '~> 2.0'` to your Gemfile.
|
36
|
+
- For `RedisCounterStrategy`, add `gem 'redis', '>= 4'` to your Gemfile.
|
37
|
+
|
38
|
+
Ensure you bundle these dependencies along with the DynamicLinks gem if you plan to use these strategies.
|
39
|
+
|
40
|
+
## Installation
|
41
|
+
|
42
|
+
Add this line to your application's Gemfile:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
gem "dynamic_links"
|
46
|
+
```
|
47
|
+
|
48
|
+
And then execute:
|
49
|
+
|
50
|
+
```bash
|
51
|
+
$ bundle
|
52
|
+
```
|
53
|
+
|
54
|
+
Or install it yourself as:
|
55
|
+
|
56
|
+
```bash
|
57
|
+
$ gem install dynamic_links
|
58
|
+
```
|
59
|
+
|
60
|
+
## Contributing
|
61
|
+
|
62
|
+
We welcome contributions to DynamicLinks! Please read the contributing guidelines to get started.
|
63
|
+
|
64
|
+
## License
|
65
|
+
|
66
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
//= link_directory ../stylesheets/dynamic_links .css
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class DynamicLinks::V1::ShortLinksController < ApplicationController
|
2
|
+
def create
|
3
|
+
url = params.require(:url)
|
4
|
+
# validate url
|
5
|
+
# if !url_shortener.valid_url?(url)
|
6
|
+
# render json: { error: 'invalid url' }, status: :bad_request
|
7
|
+
# return
|
8
|
+
# end
|
9
|
+
|
10
|
+
# shorten url
|
11
|
+
# save to db (not implemented yet)
|
12
|
+
render json: DynamicLinks.generate_short_url(url), status: :created
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module DynamicLinks
|
2
|
+
# This job generates short links in the background
|
3
|
+
# It is intended to be run periodically
|
4
|
+
# We can find available short links by querying the database with query:
|
5
|
+
# ShortenedUrl.where(available: true)
|
6
|
+
#
|
7
|
+
# To use this strategy, invoke this cli command first:
|
8
|
+
# `rails generate dynamic_links:add_kgs_migration`
|
9
|
+
class GenerateShortLinksJob < ApplicationJob
|
10
|
+
queue_as :default
|
11
|
+
|
12
|
+
# @param num_links [Integer] Number of short links to generate
|
13
|
+
def perform(num_links = 100)
|
14
|
+
num_links.times do
|
15
|
+
# TODO
|
16
|
+
# Generate a unique short code
|
17
|
+
# Store the short code in the database
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def generate_unique_short_code
|
24
|
+
loop do
|
25
|
+
# code = # TODO generate a short code using specified strategy
|
26
|
+
# break code unless ShortenedUrl.exists?(short_url: code)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# == Schema Information
|
2
|
+
#
|
3
|
+
# Table name: dynamic_links_clients
|
4
|
+
#
|
5
|
+
# id :bigint not null, primary key
|
6
|
+
# name :string not null
|
7
|
+
# api_key :string not null
|
8
|
+
# created_at :datetime not null
|
9
|
+
# updated_at :datetime not null
|
10
|
+
#
|
11
|
+
# Indexes
|
12
|
+
#
|
13
|
+
# index_dynamic_links_clients_on_api_key (api_key) UNIQUE
|
14
|
+
# index_dynamic_links_clients_on_name (name) UNIQUE
|
15
|
+
#
|
16
|
+
module DynamicLinks
|
17
|
+
class Client < ApplicationRecord
|
18
|
+
validates :name, presence: true, uniqueness: true
|
19
|
+
validates :api_key, presence: true, uniqueness: true
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# == Schema Information
|
2
|
+
#
|
3
|
+
# Table name: dynamic_links_shortened_urls
|
4
|
+
#
|
5
|
+
# id :bigint not null, primary key
|
6
|
+
# client_id :bigint
|
7
|
+
# url :string(2083) not null
|
8
|
+
# short_url :string(10) not null
|
9
|
+
# expires_at :datetime
|
10
|
+
# created_at :datetime not null
|
11
|
+
# updated_at :datetime not null
|
12
|
+
#
|
13
|
+
# Indexes
|
14
|
+
#
|
15
|
+
# index_dynamic_links_shortened_urls_on_client_id (client_id)
|
16
|
+
# index_dynamic_links_shortened_urls_on_short_url (short_url) UNIQUE
|
17
|
+
#
|
18
|
+
module DynamicLinks
|
19
|
+
class ShortenedUrl < ApplicationRecord
|
20
|
+
belongs_to :client, optional: true
|
21
|
+
|
22
|
+
validates :url, presence: true
|
23
|
+
validates :short_url, presence: true, uniqueness: true
|
24
|
+
end
|
25
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
class CreateDynamicLinksClients < ActiveRecord::Migration[7.1]
|
2
|
+
def change
|
3
|
+
create_table :dynamic_links_clients do |t|
|
4
|
+
t.string :name, null: false
|
5
|
+
t.string :api_key, null: false
|
6
|
+
|
7
|
+
t.timestamps
|
8
|
+
end
|
9
|
+
|
10
|
+
add_index :dynamic_links_clients, :name, unique: true
|
11
|
+
add_index :dynamic_links_clients, :api_key, unique: true
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class CreateDynamicLinksShortenedUrls < ActiveRecord::Migration[7.1]
|
2
|
+
def change
|
3
|
+
create_table :dynamic_links_shortened_urls, id: false do |t|
|
4
|
+
if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
|
5
|
+
t.bigserial :id, primary_key: true
|
6
|
+
else
|
7
|
+
t.bigint :id, primary_key: true
|
8
|
+
end
|
9
|
+
|
10
|
+
t.references :client, null: true, foreign_key: { to_table: :dynamic_links_clients }, type: :bigint
|
11
|
+
# 2083 is the maximum length of a URL according to the RFC 2616
|
12
|
+
t.string :url, null: false, limit: 2083
|
13
|
+
# 12 is the maximum length of a short URL if we use the RedisCounterStrategy
|
14
|
+
t.string :short_url, null: false, limit: DynamicLinks::ShorteningStrategies::RedisCounterStrategy::MAX_LENGTH
|
15
|
+
t.datetime :expires_at
|
16
|
+
t.timestamps
|
17
|
+
end
|
18
|
+
|
19
|
+
add_index :dynamic_links_shortened_urls, :short_url, unique: true
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module DynamicLinks
|
2
|
+
module ShorteningStrategies
|
3
|
+
class BaseStrategy
|
4
|
+
MIN_LENGTH = 5
|
5
|
+
|
6
|
+
BASE62_CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".freeze
|
7
|
+
|
8
|
+
def shorten(url)
|
9
|
+
raise NotImplementedError, "You must implement the shorten method"
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
# Convert an integer into a Base62 string
|
15
|
+
def base62_encode(integer)
|
16
|
+
return '0' if integer == 0
|
17
|
+
|
18
|
+
result = ''
|
19
|
+
while integer > 0
|
20
|
+
result.prepend(BASE62_CHARS[integer % 62])
|
21
|
+
integer /= 62
|
22
|
+
end
|
23
|
+
result
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module DynamicLinks
|
2
|
+
module ShorteningStrategies
|
3
|
+
class CRC32Strategy < BaseStrategy
|
4
|
+
# @param url [String] The URL to shorten
|
5
|
+
# @param min_length [Integer] The minimum length of the short URL
|
6
|
+
def shorten(url, min_length: MIN_LENGTH)
|
7
|
+
# Create a CRC32 hash of the URL
|
8
|
+
hashed_url = Zlib.crc32(url).to_s(16)
|
9
|
+
|
10
|
+
# Convert the CRC32 hash into a Base62 string
|
11
|
+
short_url = base62_encode(hashed_url.to_i(16))
|
12
|
+
|
13
|
+
# Ensure the short URL is at least #{min_length} characters long
|
14
|
+
short_url.ljust(min_length, '0')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module DynamicLinks
|
2
|
+
module ShorteningStrategies
|
3
|
+
class MD5Strategy < BaseStrategy
|
4
|
+
# Shortens the given URL using an MD5 hash
|
5
|
+
# @param url [String] The URL to shorten
|
6
|
+
# @param min_length [Integer] The minimum length of the short URL
|
7
|
+
def shorten(url, min_length: MIN_LENGTH)
|
8
|
+
# Create an MD5 hash of the URL
|
9
|
+
hashed_url = Digest::MD5.hexdigest(url)
|
10
|
+
|
11
|
+
# Convert a portion of the MD5 hash into a Base62 string
|
12
|
+
short_url = base62_encode(hashed_url[0...10].to_i(16))
|
13
|
+
|
14
|
+
# Ensure the short URL is at least #{min_length} characters long
|
15
|
+
short_url.ljust(min_length, '0')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module DynamicLinks
|
2
|
+
module ShorteningStrategies
|
3
|
+
# Shortens the given URL using Nano ID
|
4
|
+
# This strategy will generate a different short URL for the same given URL
|
5
|
+
class NanoIDStrategy < BaseStrategy
|
6
|
+
begin
|
7
|
+
require 'nanoid'
|
8
|
+
rescue LoadError
|
9
|
+
raise 'Missing dependency: Please add "nanoid" to your Gemfile to use NanoIdStrategy.'
|
10
|
+
end
|
11
|
+
|
12
|
+
# Shortens the given URL using Nano ID
|
13
|
+
# @param url [String] The URL to shorten (not directly used in Nano ID strategy)
|
14
|
+
# @param size [Integer] The size (length) of the generated Nano ID
|
15
|
+
def shorten(url, size: MIN_LENGTH)
|
16
|
+
::Nanoid.generate(size: size)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
module DynamicLinks
|
3
|
+
module ShorteningStrategies
|
4
|
+
class RedisCounterStrategy < BaseStrategy
|
5
|
+
begin
|
6
|
+
require 'redis'
|
7
|
+
rescue LoadError
|
8
|
+
raise 'Missing dependency: Please add "redis" to your Gemfile to use RedisCounterStrategy.'
|
9
|
+
end
|
10
|
+
|
11
|
+
MIN_LENGTH = 12
|
12
|
+
REDIS_COUNTER_KEY = "dynamic_links:counter".freeze
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
# TODO: use pool of connections
|
16
|
+
@redis = Redis.new
|
17
|
+
end
|
18
|
+
|
19
|
+
# Shortens the given URL using a Redis counter
|
20
|
+
# @param url [String] The URL to shorten
|
21
|
+
# @return [String] The shortened URL, 12 characters long
|
22
|
+
def shorten(url, min_length: MIN_LENGTH)
|
23
|
+
counter = @redis.incr(REDIS_COUNTER_KEY)
|
24
|
+
|
25
|
+
short_url = base62_encode("#{counter}#{url.hash.abs}".to_i)
|
26
|
+
short_url.ljust(min_length, '0')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module DynamicLinks
|
2
|
+
module ShorteningStrategies
|
3
|
+
class SHA256Strategy < BaseStrategy
|
4
|
+
# @param url [String] The URL to shorten
|
5
|
+
# @param min_length [Integer] The minimum length of the short URL
|
6
|
+
# we use this parameter to increase the length of the short URL
|
7
|
+
# in order to avoid collisions
|
8
|
+
def shorten(url, min_length: MIN_LENGTH)
|
9
|
+
# Create a hash of the URL
|
10
|
+
hashed_url = Digest::SHA256.hexdigest(url)
|
11
|
+
|
12
|
+
# Convert the first few characters of the hash into a Base62 string
|
13
|
+
short_url = base62_encode(hashed_url[0...10].to_i(16))
|
14
|
+
|
15
|
+
# Ensure the short URL is at least #{min_length} characters
|
16
|
+
short_url.ljust(min_length, '0')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module DynamicLinks
|
2
|
+
class StrategyFactory
|
3
|
+
def self.get_strategy(strategy_name)
|
4
|
+
case strategy_name
|
5
|
+
when :md5
|
6
|
+
ShorteningStrategies::MD5Strategy.new
|
7
|
+
when :sha256
|
8
|
+
ShorteningStrategies::SHA256Strategy.new
|
9
|
+
when :crc32
|
10
|
+
ShorteningStrategies::CRC32Strategy.new
|
11
|
+
when :nano_id
|
12
|
+
ShorteningStrategies::NanoIdStrategy.new
|
13
|
+
when :redis_counter
|
14
|
+
ShorteningStrategies::RedisCounterStrategy.new
|
15
|
+
when :mock
|
16
|
+
ShorteningStrategies::MockStrategy.new
|
17
|
+
else
|
18
|
+
raise "Unknown strategy: #{strategy_name}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require "dynamic_links/version"
|
2
|
+
require "dynamic_links/engine"
|
3
|
+
require "dynamic_links/strategy_factory"
|
4
|
+
require "dynamic_links/shortening_strategies/base_strategy"
|
5
|
+
require "dynamic_links/shortening_strategies/sha256_strategy"
|
6
|
+
require "dynamic_links/shortening_strategies/md5_strategy"
|
7
|
+
require "dynamic_links/shortening_strategies/crc32_strategy"
|
8
|
+
require "dynamic_links/shortening_strategies/nano_id_strategy"
|
9
|
+
require "dynamic_links/shortening_strategies/redis_counter_strategy"
|
10
|
+
require "dynamic_links/shortening_strategies/mock_strategy"
|
11
|
+
require "dynamic_links/configuration"
|
12
|
+
|
13
|
+
module DynamicLinks
|
14
|
+
class << self
|
15
|
+
attr_writer :configuration
|
16
|
+
|
17
|
+
def configuration
|
18
|
+
@configuration ||= Configuration.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def configure
|
22
|
+
yield(configuration)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.shorten_url(url)
|
27
|
+
strategy_key = configuration.shortening_strategy
|
28
|
+
|
29
|
+
begin
|
30
|
+
strategy = StrategyFactory.get_strategy(strategy_key)
|
31
|
+
rescue RuntimeError => e
|
32
|
+
# This will catch the 'Unknown strategy' error from the factory
|
33
|
+
raise "Invalid shortening strategy: #{strategy_key}. Error: #{e.message}"
|
34
|
+
rescue ArgumentError
|
35
|
+
raise "#{strategy_key} strategy needs to be initialized with arguments"
|
36
|
+
rescue => e
|
37
|
+
raise "Unexpected error while initializing the strategy: #{e.message}"
|
38
|
+
end
|
39
|
+
|
40
|
+
strategy.shorten(url)
|
41
|
+
end
|
42
|
+
|
43
|
+
# mimic Firebase Dynamic Links API
|
44
|
+
def self.generate_short_url(original_url)
|
45
|
+
short_link = shorten_url(original_url)
|
46
|
+
|
47
|
+
{
|
48
|
+
shortLink: short_link,
|
49
|
+
previewLink: "#{short_link}?preview=true",
|
50
|
+
warning: []
|
51
|
+
}
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module DynamicLinks
|
2
|
+
module Generators
|
3
|
+
class AddKgsMigrationGenerator < Rails::Generators::Base
|
4
|
+
source_root File.expand_path('templates', __dir__)
|
5
|
+
|
6
|
+
def create_migration_file
|
7
|
+
timestamp = Time.now.utc.strftime("%Y%m%d%H%M%S")
|
8
|
+
migration_filename = "#{timestamp}_add_available_to_shortened_urls.rb"
|
9
|
+
migration_template = File.read(File.join(self.class.source_root, "migration_template.rb"))
|
10
|
+
|
11
|
+
create_file "db/migrate/#{migration_filename}", migration_template
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
metadata
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dynamic_links
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Saiqul Haq
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-01-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: nanoid
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: redis
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '4'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '4'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: annotate
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: dotenv-rails
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: Rails engine to shorten any URL with custom domain.
|
84
|
+
email:
|
85
|
+
- saiqulhaq@gmail.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- README.md
|
91
|
+
- Rakefile
|
92
|
+
- app/assets/config/dynamic_links_manifest.js
|
93
|
+
- app/assets/stylesheets/dynamic_links/application.css
|
94
|
+
- app/controllers/dynamic_links/application_controller.rb
|
95
|
+
- app/controllers/dynamic_links/v1/short_links_controller.rb
|
96
|
+
- app/helpers/dynamic_links/application_helper.rb
|
97
|
+
- app/jobs/dynamic_links/application_job.rb
|
98
|
+
- app/jobs/dynamic_links/generate_short_links_job.rb
|
99
|
+
- app/mailers/dynamic_links/application_mailer.rb
|
100
|
+
- app/models/dynamic_links/application_record.rb
|
101
|
+
- app/models/dynamic_links/client.rb
|
102
|
+
- app/models/dynamic_links/shortened_url.rb
|
103
|
+
- app/views/layouts/dynamic_links/application.html.erb
|
104
|
+
- config/routes.rb
|
105
|
+
- db/migrate/20231228165744_create_dynamic_links_clients.rb
|
106
|
+
- db/migrate/20231228175142_create_dynamic_links_shortened_urls.rb
|
107
|
+
- lib/dynamic_links.rb
|
108
|
+
- lib/dynamic_links/configuration.rb
|
109
|
+
- lib/dynamic_links/engine.rb
|
110
|
+
- lib/dynamic_links/shortening_strategies/base_strategy.rb
|
111
|
+
- lib/dynamic_links/shortening_strategies/crc32_strategy.rb
|
112
|
+
- lib/dynamic_links/shortening_strategies/md5_strategy.rb
|
113
|
+
- lib/dynamic_links/shortening_strategies/mock_strategy.rb
|
114
|
+
- lib/dynamic_links/shortening_strategies/nano_id_strategy.rb
|
115
|
+
- lib/dynamic_links/shortening_strategies/redis_counter_strategy.rb
|
116
|
+
- lib/dynamic_links/shortening_strategies/sha256_strategy.rb
|
117
|
+
- lib/dynamic_links/strategy_factory.rb
|
118
|
+
- lib/dynamic_links/version.rb
|
119
|
+
- lib/generators/dynamic_links/add_kgs_migration_generator.rb
|
120
|
+
- lib/generators/dynamic_links/templates/migration_template.rb
|
121
|
+
- lib/tasks/dynamic_links_tasks.rake
|
122
|
+
homepage: https://saiqulhaq.id/dynamic_links
|
123
|
+
licenses: []
|
124
|
+
metadata:
|
125
|
+
homepage_uri: https://saiqulhaq.id/dynamic_links
|
126
|
+
source_code_uri: https://github.com/saiqulhaq/dynamic_links
|
127
|
+
changelog_uri: https://github.com/saiqulhaq/dynamic_links/blob/master/CHANGELOG.md
|
128
|
+
post_install_message:
|
129
|
+
rdoc_options: []
|
130
|
+
require_paths:
|
131
|
+
- lib
|
132
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - ">="
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
137
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
138
|
+
requirements:
|
139
|
+
- - ">="
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
requirements: []
|
143
|
+
rubygems_version: 3.1.2
|
144
|
+
signing_key:
|
145
|
+
specification_version: 4
|
146
|
+
summary: Alternative to Firebase Dynamic Links feature
|
147
|
+
test_files: []
|