Skip to content

Commit a06012d

Browse files
authored
Merge pull request #23 from ArtieFuzzz/ex-impl
Elixir Implementation
2 parents acc5ac0 + 2d3e43f commit a06012d

File tree

16 files changed

+749
-0
lines changed

16 files changed

+749
-0
lines changed

.github/workflows/pr-ex-test.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: Test Elixir implementation
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- main
7+
paths:
8+
- "impl/ex/**"
9+
- ".github/workflows/pr-ex-test.yml"
10+
11+
jobs:
12+
credo:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v4
16+
- uses: erlef/setup-beam@v1
17+
with:
18+
elixir-version: "1.16.1"
19+
otp-version: "26"
20+
- name: Run credo
21+
run: |
22+
cd impl/ex
23+
24+
mix deps.get && mix deps.compile
25+
26+
mix credo
27+
28+
test:
29+
runs-on: ubuntu-latest
30+
name: OTP ${{matrix.otp}} / Elixir ${{matrix.elixir}}
31+
strategy:
32+
matrix:
33+
otp: ["25"]
34+
elixir: ["1.16.1", "1.15.7", "1.14.0"]
35+
steps:
36+
- uses: actions/checkout@v4
37+
- uses: erlef/setup-beam@v1
38+
with:
39+
otp-version: ${{matrix.otp}}
40+
elixir-version: ${{matrix.elixir}}
41+
- name: Run Tests
42+
run: |
43+
cd impl/ex
44+
45+
mix deps.get && mix deps.compile
46+
47+
mix test
48+

impl/ex/.credo.exs

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
%{
2+
configs: [
3+
%{
4+
name: "default",
5+
files: %{
6+
included: [
7+
"lib/",
8+
"src/",
9+
"test/",
10+
"web/"
11+
],
12+
excluded: [~r"/_build/", ~r"/deps/", ~r"/node_modules/"]
13+
},
14+
plugins: [],
15+
requires: [],
16+
strict: true,
17+
parse_timeout: 5000,
18+
color: false,
19+
checks: %{
20+
enabled: [
21+
#
22+
## Consistency Checks
23+
#
24+
{Credo.Check.Consistency.ExceptionNames, []},
25+
{Credo.Check.Consistency.LineEndings, []},
26+
{Credo.Check.Consistency.ParameterPatternMatching, []},
27+
{Credo.Check.Consistency.SpaceAroundOperators, []},
28+
{Credo.Check.Consistency.SpaceInParentheses, []},
29+
{Credo.Check.Consistency.TabsOrSpaces, []},
30+
31+
#
32+
## Design Checks
33+
#
34+
# You can customize the priority of any check
35+
# Priority values are: `low, normal, high, higher`
36+
#
37+
{Credo.Check.Design.AliasUsage,
38+
[priority: :low, if_nested_deeper_than: 2, if_called_more_often_than: 0]},
39+
{Credo.Check.Design.TagFIXME, []},
40+
# You can also customize the exit_status of each check.
41+
# If you don't want TODO comments to cause `mix credo` to fail, just
42+
# set this value to 0 (zero).
43+
#
44+
{Credo.Check.Design.TagTODO, [exit_status: 2]},
45+
46+
#
47+
## Readability Checks
48+
#
49+
{Credo.Check.Readability.AliasOrder, []},
50+
{Credo.Check.Readability.FunctionNames, []},
51+
{Credo.Check.Readability.LargeNumbers, []},
52+
{Credo.Check.Readability.MaxLineLength, [priority: :low, max_length: 120]},
53+
{Credo.Check.Readability.ModuleAttributeNames, []},
54+
{Credo.Check.Readability.ModuleDoc, []},
55+
{Credo.Check.Readability.ModuleNames, []},
56+
{Credo.Check.Readability.ParenthesesInCondition, []},
57+
{Credo.Check.Readability.ParenthesesOnZeroArityDefs, []},
58+
{Credo.Check.Readability.PipeIntoAnonymousFunctions, []},
59+
{Credo.Check.Readability.PredicateFunctionNames, []},
60+
{Credo.Check.Readability.PreferImplicitTry, []},
61+
{Credo.Check.Readability.RedundantBlankLines, []},
62+
{Credo.Check.Readability.Semicolons, []},
63+
{Credo.Check.Readability.SpaceAfterCommas, []},
64+
{Credo.Check.Readability.StringSigils, []},
65+
{Credo.Check.Readability.TrailingBlankLine, []},
66+
{Credo.Check.Readability.TrailingWhiteSpace, []},
67+
{Credo.Check.Readability.UnnecessaryAliasExpansion, []},
68+
{Credo.Check.Readability.VariableNames, []},
69+
{Credo.Check.Readability.WithSingleClause, []},
70+
71+
#
72+
## Refactoring Opportunities
73+
#
74+
{Credo.Check.Refactor.Apply, []},
75+
{Credo.Check.Refactor.CondStatements, []},
76+
{Credo.Check.Refactor.CyclomaticComplexity, []},
77+
{Credo.Check.Refactor.FilterCount, []},
78+
{Credo.Check.Refactor.FilterFilter, []},
79+
{Credo.Check.Refactor.FunctionArity, []},
80+
{Credo.Check.Refactor.LongQuoteBlocks, []},
81+
{Credo.Check.Refactor.MapJoin, []},
82+
{Credo.Check.Refactor.MatchInCondition, []},
83+
{Credo.Check.Refactor.NegatedConditionsInUnless, []},
84+
{Credo.Check.Refactor.NegatedConditionsWithElse, []},
85+
{Credo.Check.Refactor.Nesting, []},
86+
{Credo.Check.Refactor.RedundantWithClauseResult, []},
87+
{Credo.Check.Refactor.RejectReject, []},
88+
{Credo.Check.Refactor.UnlessWithElse, []},
89+
{Credo.Check.Refactor.WithClauses, []},
90+
91+
#
92+
## Warnings
93+
#
94+
{Credo.Check.Warning.ApplicationConfigInModuleAttribute, []},
95+
{Credo.Check.Warning.BoolOperationOnSameValues, []},
96+
{Credo.Check.Warning.Dbg, []},
97+
{Credo.Check.Warning.ExpensiveEmptyEnumCheck, []},
98+
{Credo.Check.Warning.IExPry, []},
99+
{Credo.Check.Warning.IoInspect, []},
100+
{Credo.Check.Warning.MissedMetadataKeyInLoggerConfig, []},
101+
{Credo.Check.Warning.OperationOnSameValues, []},
102+
{Credo.Check.Warning.OperationWithConstantResult, []},
103+
{Credo.Check.Warning.RaiseInsideRescue, []},
104+
{Credo.Check.Warning.SpecWithStruct, []},
105+
{Credo.Check.Warning.UnsafeExec, []},
106+
{Credo.Check.Warning.UnusedEnumOperation, []},
107+
{Credo.Check.Warning.UnusedFileOperation, []},
108+
{Credo.Check.Warning.UnusedKeywordOperation, []},
109+
{Credo.Check.Warning.UnusedListOperation, []},
110+
{Credo.Check.Warning.UnusedPathOperation, []},
111+
{Credo.Check.Warning.UnusedRegexOperation, []},
112+
{Credo.Check.Warning.UnusedStringOperation, []},
113+
{Credo.Check.Warning.UnusedTupleOperation, []},
114+
{Credo.Check.Warning.WrongTestFileExtension, []}
115+
],
116+
disabled: [
117+
#
118+
# Checks scheduled for next check update (opt-in for now)
119+
{Credo.Check.Refactor.UtcNowTruncate, []},
120+
121+
#
122+
# Controversial and experimental checks (opt-in, just move the check to `:enabled`
123+
# and be sure to use `mix credo --strict` to see low priority checks)
124+
#
125+
{Credo.Check.Consistency.MultiAliasImportRequireUse, []},
126+
{Credo.Check.Consistency.UnusedVariableNames, []},
127+
{Credo.Check.Design.DuplicatedCode, []},
128+
{Credo.Check.Design.SkipTestWithoutComment, []},
129+
{Credo.Check.Readability.AliasAs, []},
130+
{Credo.Check.Readability.BlockPipe, []},
131+
{Credo.Check.Readability.ImplTrue, []},
132+
{Credo.Check.Readability.MultiAlias, []},
133+
{Credo.Check.Readability.NestedFunctionCalls, []},
134+
{Credo.Check.Readability.OneArityFunctionInPipe, []},
135+
{Credo.Check.Readability.OnePipePerLine, []},
136+
{Credo.Check.Readability.SeparateAliasRequire, []},
137+
{Credo.Check.Readability.SingleFunctionToBlockPipe, []},
138+
{Credo.Check.Readability.SinglePipe, []},
139+
{Credo.Check.Readability.Specs, []},
140+
{Credo.Check.Readability.StrictModuleLayout, []},
141+
{Credo.Check.Readability.WithCustomTaggedTuple, []},
142+
{Credo.Check.Refactor.ABCSize, []},
143+
{Credo.Check.Refactor.AppendSingleItem, []},
144+
{Credo.Check.Refactor.DoubleBooleanNegation, []},
145+
{Credo.Check.Refactor.FilterReject, []},
146+
{Credo.Check.Refactor.IoPuts, []},
147+
{Credo.Check.Refactor.MapMap, []},
148+
{Credo.Check.Refactor.ModuleDependencies, []},
149+
{Credo.Check.Refactor.NegatedIsNil, []},
150+
{Credo.Check.Refactor.PassAsyncInTestCases, []},
151+
{Credo.Check.Refactor.PipeChainStart, []},
152+
{Credo.Check.Refactor.RejectFilter, []},
153+
{Credo.Check.Refactor.VariableRebinding, []},
154+
{Credo.Check.Warning.LazyLogging, []},
155+
{Credo.Check.Warning.LeakyEnvironment, []},
156+
{Credo.Check.Warning.MapGetUnsafePass, []},
157+
{Credo.Check.Warning.MixEnv, []},
158+
{Credo.Check.Warning.UnsafeToAtom, []}
159+
160+
# {Credo.Check.Refactor.MapInto, []},
161+
162+
#
163+
# Custom checks can be created using `mix credo.gen.check`.
164+
#
165+
]
166+
}
167+
}
168+
]
169+
}

impl/ex/.formatter.exs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Used by "mix format"
2+
[
3+
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
4+
]

impl/ex/.gitignore

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# The directory Mix will write compiled artifacts to.
2+
/_build/
3+
4+
# If you run "mix test --cover", coverage assets end up here.
5+
/cover/
6+
7+
# The directory Mix downloads your dependencies sources to.
8+
/deps/
9+
10+
# Where third-party dependencies like ExDoc output generated docs.
11+
/doc/
12+
13+
# Ignore .fetch files in case you like to edit your project deps locally.
14+
/.fetch
15+
16+
# If the VM crashes, it generates a dump, let's ignore it too.
17+
erl_crash.dump
18+
19+
# Also ignore archive artifacts (built via "mix archive.build").
20+
*.ez
21+
22+
# Ignore package tarball (built via "mix hex.build").
23+
pika-*.tar
24+
25+
# Temporary files, for example, from tests.
26+
/tmp/

impl/ex/README.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Pika
2+
3+
> Elixir implementation of Pika
4+
5+
Combine Stripe IDs with Snowflakes you get Pika! The last ID system you'll ever need!
6+
Combining pragmatism with functionality
7+
8+
## Features
9+
10+
- Written in pure Elixir
11+
- Zero Dependencies
12+
13+
## Installation
14+
15+
The package can be installed by adding `pika` to your list of dependencies in `mix.exs`:
16+
17+
```elixir
18+
def deps do
19+
[
20+
{:pika, "~> 0.1.0"}
21+
]
22+
end
23+
```
24+
25+
In your `config.exs`:
26+
27+
```elixir
28+
config :pika,
29+
prefixes: [
30+
%{prefix: "user", description: "User IDs"},
31+
%{prefix: "server", description: "Server IDs", secure: true},
32+
# ...
33+
]
34+
```
35+
36+
## Example
37+
38+
`Pika.Snowflake` should be started under a `Supervisor` or `Application` before you start using
39+
`Pika.gen/1` or `Pika.deconstruct/1`
40+
41+
```elixir
42+
defmodule MyApp.Application do
43+
use Application
44+
45+
def start(_type, _args) do
46+
children = [Pika.Snowflake]
47+
48+
Supervisor.start_link(children, strategy: :one_for_one)
49+
end
50+
end
51+
```
52+
53+
Somewhere in your application:
54+
55+
```elixir
56+
# ...
57+
Pika.gen("user") # or Pika.gen!("user")
58+
59+
{:ok, "user_MjgyNDQ2NjY1OTk3MjEzNjk3"}
60+
```

impl/ex/benchmarks/generation.exs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
defmodule Generation do
2+
def id(), do: Pika.gen("user")
3+
def id_secure(), do: Pika.gen("server")
4+
def snowflake(), do: Pika.Snowflake.generate()
5+
end
6+
7+
Pika.Snowflake.start_link()
8+
9+
Benchee.run(
10+
%{
11+
"Generate IDs" => fn -> Generation.id() end,
12+
"Generate Secure IDs" => fn -> Generation.id_secure() end,
13+
"Generate Snowflakes" => fn -> Generation.snowflake() end
14+
},
15+
time: 5
16+
)

impl/ex/config/config.exs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import Config
2+
3+
case config_env() do
4+
:docs ->
5+
:ok
6+
7+
_ ->
8+
import_config "#{Mix.env()}.exs"
9+
end

impl/ex/config/dev.exs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import Config
2+
3+
config :pika,
4+
prefixes: [
5+
%{prefix: "user", description: "User IDs"},
6+
%{prefix: "server", description: "Server IDs", secure: true}
7+
]

impl/ex/config/test.exs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import Config
2+
3+
config :pika,
4+
prefixes: [
5+
%{prefix: "user", description: "User IDs"},
6+
%{prefix: "server", description: "Server IDs", secure: true}
7+
]

0 commit comments

Comments
 (0)