aurora-data-api 0.1.0 → 0.1.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 344043ce8593c877dc10b721e2b1724ea96265ed5411fbef7828a7c670a3d40e
4
- data.tar.gz: b3b440e30ef5b87abb26d987c8a35951cdb5e4c135181fc20ef9d59142a1f625
3
+ metadata.gz: b1c7df96cdee98eea8565914c4918918c98c1f917d91e32a143330d03b5b9d0c
4
+ data.tar.gz: 63c65eb4a6d6448f5f0ebd5902c6edb71d990ba8e20b01846156eed53fe6af64
5
5
  SHA512:
6
- metadata.gz: dd445671cf4c71684bcc20f24e0eea75d82218dd6959d338cc87e6faafd59a02644fd95fa31e8310645b2796114ea3d541ffd4fa71eb92c81846fd775fcba56e
7
- data.tar.gz: dcdcf6717773ed3bc9921193eddac358496fc19aa90a4e4b7e3ba41c87096ecdc932e69fdd968f37b269e06e6a3ccf0812f755e87e79ee24af167bb65766cbea
6
+ metadata.gz: '08580f3de132c79bec933f95fd8fc384c79f7cdf7cdc68063c128d848809625932a3790e58c6501a68c066f9fa6173759e613e3c16d3870b166c9aa5ed6986b2'
7
+ data.tar.gz: f4597f745ffb462a498d586b582e1360c3bb79c0f6a0276f3e265e3789334b83b7fe7ed868fe7b32a9ef5781b27c3cefd3cb772e6d3f526179767c14de328dca
data/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## 0.1.3 - 2022-06-02
2
+
3
+ - Bundle tzinfo 😅
4
+
5
+ ## 0.1.2 - 2022-06-02
6
+
7
+ - Fix inconsistency of version in Gemfile.lock
8
+
9
+ ## 0.1.1 - 2022-06-02
10
+
11
+ - Fix some issues (experimental)
12
+
1
13
  ## 0.1.0 - 2022-05-31
2
14
 
3
15
  - Initial release (experimental)
data/Gemfile.lock CHANGED
@@ -1,9 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- aurora-data-api (0.1.0)
4
+ aurora-data-api (0.1.3)
5
5
  aws-sdk-rdsdataservice (~> 1.35.0)
6
6
  thor
7
+ tzinfo
7
8
 
8
9
  GEM
9
10
  remote: https://rubygems.org/
@@ -15,7 +16,7 @@ GEM
15
16
  tzinfo (~> 2.0)
16
17
  ast (2.4.2)
17
18
  aws-eventstream (1.2.0)
18
- aws-partitions (1.591.0)
19
+ aws-partitions (1.595.0)
19
20
  aws-sdk-core (3.131.1)
20
21
  aws-eventstream (~> 1, >= 1.0.2)
21
22
  aws-partitions (~> 1, >= 1.525.0)
@@ -46,7 +47,7 @@ GEM
46
47
  rb-inotify (0.10.1)
47
48
  ffi (~> 1.0)
48
49
  rbs (2.5.0)
49
- regexp_parser (2.4.0)
50
+ regexp_parser (2.5.0)
50
51
  rexml (3.2.5)
51
52
  rr (3.0.9)
52
53
  rubocop (1.29.1)
@@ -100,4 +101,4 @@ DEPENDENCIES
100
101
  test-unit-rr
101
102
 
102
103
  BUNDLED WITH
103
- 2.3.14
104
+ 2.3.15
data/README.md CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  A kind of ORM for Amazon Aurora Serverless v1.
4
4
 
5
- Supposing that you are using Ruby (typically on AWS Lambda) as an application, Aurora Serverless v1 (NOT v2) as a database, and Data API as the database adapter.
5
+ Supposing that you are using Ruby (typically on AWS Lambda) as an application, Aurora Serverless v1 (NOT v2) as a database, and Data API as a database adapter.
6
+
7
+ This gem doesn't depend on ActiveRecord and takes advantage of PORO (plain old Ruby object) like Array, Hash, and Struct internally so you can easily hack.
6
8
 
7
9
  PostgreSQL is the only target as of now.
8
10
 
@@ -213,10 +215,15 @@ The following variables should be defined:
213
215
  ENV['PGDATABASE'] # Database name
214
216
  ENV['RDS_RESOURCE_ARN'] # Resource ARN of RDS Aurora Serverless
215
217
  ENV['RDS_SECRET_ARN'] # Secret ARN that is stored in AWS Secrets Manager
218
+ ENV['TZ'] # (Optional) Timezone. Internal default is "UTC"
216
219
  ```
217
220
 
218
221
  RDS_SECRET_ARN has to be attached to an IAM role of the "application".
219
222
 
223
+ ## Example project with Serverless Project
224
+
225
+ See [example](https://github.com/hasumikin/aurora-data-api/tree/master/example)
226
+
220
227
  ## Development
221
228
 
222
229
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/Steepfile CHANGED
@@ -1,5 +1,5 @@
1
1
  target :lib do
2
2
  signature "sig"
3
3
  check "lib"
4
- library "time"
4
+ library "time", "date"
5
5
  end
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.email = ["hasumikin@gmail.com"]
10
10
 
11
11
  spec.summary = "A kind of ORM for Amazon Aurora Serverless v1"
12
- spec.description = "Assuming you are using AWS Lambda as a backend, Aurora Serverless v1 (NOT v2) as a database, and Data API as an adapter"
12
+ spec.description = "Doesn't depend on ActiveRecord and takes advantage of PORO (plain old Ruby object) like Array, Hash, and Struct internally so you can easily hack."
13
13
  spec.homepage = "https://github.com/hasumikin/aurora-data-api"
14
14
  spec.license = "MIT"
15
15
  spec.required_ruby_version = ">= 2.7.0"
@@ -31,4 +31,5 @@ Gem::Specification.new do |spec|
31
31
 
32
32
  spec.add_dependency "aws-sdk-rdsdataservice", "~> 1.35.0"
33
33
  spec.add_dependency "thor"
34
+ spec.add_dependency "tzinfo"
34
35
  end
data/example/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'aurora-data-api', github: 'hasumikin/aurora-data-api'
3
+ gem 'aurora-data-api'
4
4
  gem 'aws-sdk-lambda'
5
5
 
6
6
  group :test, :development do
data/example/Gemfile.lock CHANGED
@@ -1,14 +1,9 @@
1
- GIT
2
- remote: https://github.com/hasumikin/aurora-data-api.git
3
- revision: 70ae5070c8391c6be2ac9b4209425308ed01f2e7
1
+ GEM
2
+ remote: https://rubygems.org/
4
3
  specs:
5
4
  aurora-data-api (0.1.0)
6
5
  aws-sdk-rdsdataservice (~> 1.35.0)
7
6
  thor
8
-
9
- GEM
10
- remote: https://rubygems.org/
11
- specs:
12
7
  aws-eventstream (1.2.0)
13
8
  aws-partitions (1.594.0)
14
9
  aws-sdk-core (3.131.1)
@@ -39,7 +34,7 @@ PLATFORMS
39
34
  x86_64-linux
40
35
 
41
36
  DEPENDENCIES
42
- aurora-data-api!
37
+ aurora-data-api
43
38
  aws-sdk-lambda
44
39
  rake
45
40
  test-unit-rr
data/example/README.md CHANGED
@@ -2,44 +2,119 @@
2
2
 
3
3
  ### Stack
4
4
 
5
+ - Ruby + aurora-data-api gem
5
6
  - Serverless Framework
6
- - Lamdda functions (outside VPC)
7
- - RDS Aurora Serverless v1 (inside VPC) +
7
+ - Lambda functions outside VPC
8
+ - RDS Aurora Serverless v1 inside VPC + Data API (HTTP endpoint)
9
+ - Secrets Manager, IAM, etc.
8
10
 
9
- ### Getting started
11
+ ### Try in your local computer with docker
10
12
 
11
13
  ```sh
12
14
  docker compose build
13
- docker compose run --rm serverless rake db:create_database
14
- docker compose run --rm serverless bundle exec aurora-data-api export
15
- docker compose run --rm serverless rake db:migrate_dry_run
16
- docker compose run --rm serverless rake db:migrate
17
15
  ```
16
+
17
+ #### Create database
18
+
19
+ ```sh
20
+ docker compose run --rm serverless rake db:create
21
+ ```
22
+
23
+ #### Confirm the SQL of migration
24
+
18
25
  ```sh
19
26
  docker compose run --rm serverless rake db:migrate_dry_run
20
- => -- Nothing is modified --
21
27
  ```
28
+
29
+ #### Migrate
30
+
31
+ ```sh
32
+ docker compose run --rm serverless rake db:migrate
33
+ ```
34
+
35
+ #### Start containers
36
+
22
37
  ```sh
23
38
  docker compose up
24
39
  ```
40
+
41
+ ### APIs
42
+
25
43
  ```sh
26
44
  curl http://localhost:4000/offline/hello
27
45
  ```
28
46
 
47
+ #### Create a user
48
+
29
49
  ```sh
30
50
  curl -X POST http://localhost:4000/offline/create_user \
31
51
  -H 'Content-Type: application/json' \
32
52
  -d '{"name":"HASUMI Hitoshi", "internet_account":"hasumikin"}'
53
+ ```
54
+
55
+ #### List users
33
56
 
57
+ ```sh
58
+ curl http://localhost:4000/offline/users
59
+ ```
60
+
61
+ #### Update the user
62
+
63
+ ```sh
34
64
  curl -X PUT http://localhost:4000/offline/update_user \
35
65
  -H 'Content-Type: application/json' \
36
66
  -d '{"id":1, "name":"anonymous", "internet_account":"hasumikin"}'
67
+ ```
37
68
 
69
+ #### Create an entry
70
+
71
+ ```sh
38
72
  curl -X POST http://localhost:4000/offline/create_entry \
39
73
  -H 'Content-Type: application/json' \
40
74
  -d '{"title":"My first atrticle", "user_id":1}'
75
+ ```
76
+
77
+ #### List entries
78
+
79
+ ```sh
80
+ curl http://localhost:4000/offline/entries
81
+ ```
41
82
 
83
+ #### Delete the entry
84
+
85
+ ```sh
42
86
  curl -X POST http://localhost:4000/offline/delete_entry \
43
87
  -H 'Content-Type: application/json' \
44
88
  -d '{"entry_id":1}'
45
89
  ```
90
+
91
+ ### Deploy to AWS
92
+
93
+ Supposing you have an AWS credential in $HOME/.aws/credentials.
94
+ It has to have almost administrative permission in order to provision a Serverless Framework app:
95
+
96
+ ```
97
+ [YourAWSProfileName]
98
+ aws_access_key_id=AKIAxxxxxxxxxxxxxxxxx
99
+ aws_secret_access_key=xxxxxxxxxxxxxxxxxxxxxxxxxx
100
+ ```
101
+
102
+ ```sh
103
+ serverless deploy --stage production --aws-profile [YourAWSProfileName]
104
+ ```
105
+
106
+ About 30 minutes later, all stacks should've been provisioned in AWS.
107
+
108
+ - You can see API endpoints by `sls info --stage production --aws-profile [YourAWSProfileName]`
109
+ - Open the AWS management console
110
+ - Find *RDS_SECRET_ARN* value lools like `arn:aws:secretsmanager:ap-northeast-1:01234567890:secret:aurora-data-api-example-production-AuroraUserSecret-xxxxxx` in "Secrets Manager"
111
+
112
+ <img src="https://raw.githubusercontent.com/hasumikin/aurora-data-api/master/example/doc/query-edidor.png" width="400" />
113
+
114
+ - Go to "RDS" > "Query Editor" of and connect with the secret ARN above, then run the content of `db/schema.sql` to create tables
115
+
116
+ Now that you can call APIs like:
117
+
118
+ ```sh
119
+ curl https://xxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/production/hello
120
+ ```
data/example/Rakefile CHANGED
@@ -1,7 +1,7 @@
1
1
 
2
2
  namespace "db" do
3
3
  desc "Create database"
4
- task :create_database do
4
+ task :create do
5
5
  sql = <<~SQL
6
6
  CREATE DATABASE #{ENV['PGDATABASE']}
7
7
  TEMPLATE template0 ENCODING 'UTF-8' LC_COLLATE 'C' LC_CTYPE 'C';
@@ -10,7 +10,7 @@ namespace "db" do
10
10
  end
11
11
 
12
12
  desc "Drop database"
13
- task :drop_database do
13
+ task :drop do
14
14
  sql = <<~SQL
15
15
  DROP DATABASE #{ENV['PGDATABASE']};
16
16
  SQL
@@ -1,9 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- Dir.glob("/var/runtime/bundler/gems/**").each do |dir|
4
- $LOAD_PATH.unshift("#{dir}/lib/")
5
- end
6
-
7
3
  require "json"
8
4
  require "aurora-data-api"
9
5
  require_relative "../depots/user_depot"
@@ -6,6 +6,7 @@ class Entry < AuroraDataApi::Model
6
6
  col :user, :User, table: :users, null: false
7
7
  col :title, String
8
8
  col :body, String
9
+ col :publish_date, Date
9
10
  timestamp
10
11
  end
11
12
  end
Binary file
@@ -108,7 +108,7 @@ resources:
108
108
  AutoPause: true
109
109
  MaxCapacity: ${self:custom.myEnvironment.DBMaxCapacity.${sls:stage}, 2}
110
110
  MinCapacity: 2
111
- SecondsUntilAutoPause: 900 # 15 min for example
111
+ SecondsUntilAutoPause: 3600 # 60 min for example
112
112
  DBSubnetGroupName:
113
113
  Ref: DBSubnetGroup
114
114
  DBSecret:
data/exe/aurora-data-api CHANGED
@@ -2,9 +2,8 @@
2
2
 
3
3
  require "aurora-data-api/version"
4
4
  require "thor"
5
-
6
- class Date
7
- end
5
+ require "date"
6
+ require "fileutils"
8
7
 
9
8
  module AuroraDataApi
10
9
  class Error < StandardError; end
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "date"
4
+ require "tzinfo"
5
+
3
6
  module AuroraDataApi
4
7
  class Depot
5
8
  def self.[](model, &block)
@@ -13,6 +16,7 @@ module AuroraDataApi
13
16
  @model = model
14
17
  instance_eval { block.call }
15
18
  @data_service = DataService.new
19
+ @observed_utc_offset = TZInfo::Timezone.get(ENV["TZ"] || "UTC").observed_utc_offset
16
20
  end
17
21
 
18
22
  def table_name
@@ -103,7 +107,9 @@ module AuroraDataApi
103
107
  when "text"
104
108
  col.value.gsub("''", "'")
105
109
  when "timestamptz"
106
- Time.parse(col.value) + 9 * 60 * 60 # workaround
110
+ Time.parse(col.value) + @observed_utc_offset
111
+ when "date"
112
+ Date.parse(col.value)
107
113
  else
108
114
  col.value
109
115
  end
@@ -44,7 +44,7 @@ module AuroraDataApi
44
44
  end
45
45
 
46
46
  def self.relationship_by(table_sym)
47
- result = Model::SCHEMA[name&.to_sym].select { |_k, v|
47
+ result = Model::SCHEMA[to_s.to_sym].select { |_k, v|
48
48
  v.is_a? Hash
49
49
  }.select { |_k, v|
50
50
  v.dig(:opt, :table) == table_sym
@@ -94,7 +94,7 @@ module AuroraDataApi
94
94
  if @struct[method_name].nil?
95
95
  col_id = "#{method_name}_#{literal_id}".to_sym
96
96
  if members.include?(col_id) && @struct[col_id]
97
- col_model = SCHEMA[self.class.name&.to_sym][:cols].dig(method_name, :type)
97
+ col_model = SCHEMA[self.class.to_s.to_sym][:cols].dig(method_name, :type)
98
98
  return nil unless col_model
99
99
  @struct[method_name] = AuroraDataApi.const_get("#{col_model}Depot".to_sym).select(
100
100
  %(where "#{literal_id}" = :id), id: @struct[col_id]
@@ -109,7 +109,7 @@ module AuroraDataApi
109
109
  end
110
110
 
111
111
  def table_name
112
- SCHEMA[self.class.name&.to_sym][:table_name]
112
+ SCHEMA[self.class.to_s.to_sym][:table_name]
113
113
  end
114
114
 
115
115
  def literal_id
@@ -120,7 +120,7 @@ module AuroraDataApi
120
120
  {}.tap do |hash|
121
121
  members.each do |member|
122
122
  next if member == literal_id && !include_id
123
- next if SCHEMA[self.class.name&.to_sym][:cols][member][:type].is_a? Symbol
123
+ next if SCHEMA[self.class.to_s.to_sym][:cols][member][:type].is_a? Symbol
124
124
  send(member).then { |v| hash[member] = v }
125
125
  end
126
126
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AuroraDataApi
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.3"
5
5
  end
@@ -9,6 +9,3 @@ module AuroraDataApi
9
9
  class Error < StandardError; end
10
10
  # Your code goes here...
11
11
  end
12
-
13
- class Date
14
- end
@@ -2,9 +2,6 @@ module AuroraDataApi
2
2
  Error: StandardError
3
3
  end
4
4
 
5
- class Date
6
- end
7
-
8
5
  module Aws
9
6
  def self.config: -> Hash[Symbol, untyped]
10
7
 
data/sig/depot.rbs CHANGED
@@ -7,6 +7,7 @@ module AuroraDataApi
7
7
  @data_service: DataService
8
8
  @table_name: String
9
9
  @literal_id: Symbol
10
+ @observed_utc_offset: Integer
10
11
 
11
12
  def self.[]: (singleton(Model) model) -> Depot
12
13
  def initialize: (singleton(Model) model, Proc block) -> void
data/sig/model.rbs CHANGED
@@ -2,20 +2,32 @@
2
2
 
3
3
  # Classes
4
4
  module AuroraDataApi
5
+ type attribute = Symbol | Time | Date | Integer | Symbol | bool | nil
6
+ type attribute_type = singleton(String)
7
+ | singleton(Time)
8
+ | singleton(Date)
9
+ | singleton(Integer)
10
+ | Symbol
11
+
5
12
  class Model
6
- SCHEMA: Hash[untyped, untyped]
7
- STRUCTS: Hash[untyped, untyped]
13
+ SCHEMA: Hash[Symbol, untyped]
14
+ STRUCTS: Hash[Symbol, untyped]
8
15
  @struct: untyped
9
16
 
17
+ type col_opt = Hash[:table, Symbol]
18
+ | Hash[:null, bool]
19
+ | Hash[:unique, bool]
20
+ | Hash[:default, untyped]
21
+
10
22
  def self.model_name: -> Symbol
11
23
  def self.literal_id: (Symbol lit) -> Symbol
12
24
  def self.table: (Symbol name) -> Symbol
13
25
  def self.table_name: -> Symbol
14
26
  def self.schema: () { () -> void } -> void
15
- def self.col: (Symbol name, singleton(String) | singleton(Time) | singleton(Date) | singleton(Integer) | Symbol type, ?Hash[Symbol, Symbol | bool] opt) -> void
27
+ def self.col: (Symbol name, attribute_type type, ?col_opt opt) -> void
16
28
  def self.timestamp: -> void
17
29
  def self.relationship_by: (Symbol table_sym) -> [untyped, untyped]?
18
- def initialize: (**Hash[Symbol, untyped]) -> void
30
+ def initialize: (**Hash[Symbol, attribute]) -> void
19
31
 
20
32
  attr_reader id: Integer?
21
33
  attr_reader timestamp: bool
@@ -25,11 +37,11 @@ module AuroraDataApi
25
37
  def set_timestamp: (at: :update | :create) -> bool
26
38
  def members: -> Array[Symbol]
27
39
  def respond_to_missing?: (untyped symbol, untyped include_private) -> true
28
- def method_missing: (untyped method_name, *untyped args) -> nil
40
+ def method_missing: (Symbol method_name, *untyped args) -> nil
29
41
  def table_name: -> Symbol
30
42
  def literal_id: -> Symbol
31
- def build_params: (?include_id: bool) -> Hash[Symbol, untyped]
32
- def attributes: -> Hash[Symbol, untyped]
43
+ def build_params: (?include_id: bool) -> Hash[Symbol, attribute]
44
+ def attributes: -> Hash[Symbol, attribute]
33
45
  def _set_id: (Integer? id) -> void
34
46
  def _destroy: -> bool
35
47
  end
data/sig/tzinfo.rbs ADDED
@@ -0,0 +1,9 @@
1
+ module TZInfo
2
+ class Timezone
3
+ def self.get: (String) -> DataTimezone
4
+ end
5
+
6
+ class DataTimezone
7
+ def observed_utc_offset: -> Integer
8
+ end
9
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aurora-data-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - HASUMI Hitoshi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-05-31 00:00:00.000000000 Z
11
+ date: 2022-06-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-rdsdataservice
@@ -38,8 +38,22 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
- description: Assuming you are using AWS Lambda as a backend, Aurora Serverless v1
42
- (NOT v2) as a database, and Data API as an adapter
41
+ - !ruby/object:Gem::Dependency
42
+ name: tzinfo
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Doesn't depend on ActiveRecord and takes advantage of PORO (plain old
56
+ Ruby object) like Array, Hash, and Struct internally so you can easily hack.
43
57
  email:
44
58
  - hasumikin@gmail.com
45
59
  executables:
@@ -75,6 +89,7 @@ files:
75
89
  - example/compose.yml
76
90
  - example/db/.gitignore
77
91
  - example/db/.keep
92
+ - example/doc/query-edidor.png
78
93
  - example/package-lock.json
79
94
  - example/package.json
80
95
  - example/serverless.yml
@@ -90,6 +105,7 @@ files:
90
105
  - sig/depot.rbs
91
106
  - sig/environment.rbs
92
107
  - sig/model.rbs
108
+ - sig/tzinfo.rbs
93
109
  - sig/version.rbs
94
110
  homepage: https://github.com/hasumikin/aurora-data-api
95
111
  licenses: