@rivascva/dt-idl 1.1.166 → 1.1.169

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.
@@ -0,0 +1,24 @@
1
+ name: Deploy DB
2
+
3
+ on:
4
+ push:
5
+ paths: ['supabase/**']
6
+ branches: [main]
7
+ workflow_dispatch:
8
+ # allows manual runs
9
+
10
+ jobs:
11
+ migrate:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: supabase/setup-cli@v1
16
+ with:
17
+ version: latest
18
+ - run: supabase link --project-ref ${{ secrets.SUPABASE_PROJECT_REF }}
19
+ env:
20
+ SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
21
+ - run: supabase db push
22
+ env:
23
+ SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
24
+ SUPABASE_DB_PASSWORD: ${{ secrets.SUPABASE_DB_PASSWORD }}
@@ -1,4 +1,4 @@
1
- name: Publish
1
+ name: Publish NPM
2
2
 
3
3
  on:
4
4
  push:
@@ -1,9 +1,6 @@
1
1
  {
2
2
  "editor.defaultFormatter": "esbenp.prettier-vscode",
3
3
  "editor.formatOnSave": true,
4
- "editor.codeActionsOnSave": {
5
- "source.fixAll": "explicit"
6
- },
7
4
  "editor.detectIndentation": false,
8
5
  "editor.tabSize": 2,
9
6
  "files.insertFinalNewline": true,
package/Makefile CHANGED
@@ -7,3 +7,9 @@ lint:
7
7
 
8
8
  format:
9
9
  golangci-lint run ./... --fix
10
+
11
+ db-start:
12
+ supabase start
13
+
14
+ db-stop:
15
+ supabase stop
package/README.md CHANGED
@@ -4,7 +4,7 @@ The API language for all Dream Trade microservices.
4
4
 
5
5
  [![NPM Version](https://img.shields.io/npm/v/@rivascva/dt-idl.svg?style=flat)](https://www.npmjs.com/package/@rivascva/dt-idl)
6
6
 
7
- ## Setup
7
+ ## Setup Project
8
8
 
9
9
  ### 1. Install `mise`
10
10
 
@@ -60,15 +60,40 @@ go mod tidy
60
60
  npm install
61
61
  ```
62
62
 
63
+ ## Setup Database
64
+
65
+ ### 1. Install Docker Desktop
66
+
67
+ - Follow the official Docker installation [page](https://www.docker.com/products/docker-desktop)
68
+
69
+ ### 2. Configure Supabase
70
+
71
+ - Login to your Supabase account
72
+
73
+ ```bash
74
+ supabase login
75
+ ```
76
+
77
+ - Link the Supabase project
78
+
79
+ ```bash
80
+ supabase link
81
+ ```
82
+
83
+ > Select the "DreamTrade" project when prompted
84
+
63
85
  ### Common Scripts
64
86
 
65
87
  - `npm run lint` - Lints all typescript files
66
88
  - `npm run check` - Checks the syntax of all typescript files
67
89
  - `npm run gen` - Generates typescript service clients
90
+ - `make db-start` - Starts the local Supabase database
91
+ - `make db-stop` - Stops the local Supabase database
68
92
 
69
93
  ### Deployments
70
94
 
71
- Any merge to `main` with changes to the `ts/*` and `go/*` directory will trigger an automatic deployment to `npm`
95
+ - Any merge to `main` with changes to the `ts/*` and `go/*` directory will trigger an automatic deployment to `npm`
96
+ - Any merge to `main` with changes to the `supabase/*` directory will trigger an automatic deployment to the remote database
72
97
 
73
98
  ### Go Package
74
99
 
package/dist/index.d.ts CHANGED
@@ -1150,6 +1150,15 @@ interface operations$2 {
1150
1150
  "application/json": components$2["schemas"]["Order"];
1151
1151
  };
1152
1152
  };
1153
+ /** @description Accepted */
1154
+ 202: {
1155
+ headers: {
1156
+ [name: string]: unknown;
1157
+ };
1158
+ content: {
1159
+ "application/json": Record<string, never>;
1160
+ };
1161
+ };
1153
1162
  400: components$2["responses"]["BadRequest"];
1154
1163
  404: components$2["responses"]["NotFound"];
1155
1164
  500: components$2["responses"]["InternalServerError"];
@@ -13,12 +13,10 @@ import (
13
13
  type RDB interface {
14
14
  // NewRDB creates a new redis database from the parent database.
15
15
  NewRDB(database string) RDB
16
- // Set sets the value for the given key.
17
- Set(ctx context.Context, key string, value any) error
18
- // MSet sets the values for the given entries of key-value pairs.
19
- MSet(ctx context.Context, entries map[string]any) error
20
- // SetWithExpiration sets the value for the given key with an expiration time.
21
- SetWithExpiration(ctx context.Context, key string, value any, expiration time.Duration) error
16
+ // Set sets the value for the given key with the given expiration.
17
+ Set(ctx context.Context, key string, value any, expiration time.Duration) error
18
+ // MSet sets the values for the given entries of key-value pairs with the given expiration.
19
+ MSet(ctx context.Context, entries map[string]any, expiration time.Duration) error
22
20
  // Get gets the value for the given key. It unmarshals the value into the given destination.
23
21
  Get(ctx context.Context, key string, dest any) error
24
22
  // MGet gets the values for the given keys. It unmarshals the values into the given destinations in the same order as the keys.
@@ -54,7 +52,7 @@ func (r *BaseRDB) NewRDB(database string) RDB {
54
52
  }
55
53
  }
56
54
 
57
- func (r *BaseRDB) Set(ctx context.Context, key string, value any) error {
55
+ func (r *BaseRDB) Set(ctx context.Context, key string, value any, expiration time.Duration) error {
58
56
  // marshal the value into a JSON byte array
59
57
  bytes, err := json.Marshal(value)
60
58
  if err != nil {
@@ -62,7 +60,7 @@ func (r *BaseRDB) Set(ctx context.Context, key string, value any) error {
62
60
  }
63
61
 
64
62
  // set the value in the redis client
65
- err = r.client.Set(ctx, FormatKey(r.database, key), bytes, 0).Err()
63
+ err = r.client.Set(ctx, FormatKey(r.database, key), bytes, expiration).Err()
66
64
  if err != nil {
67
65
  return fmt.Errorf("failed to set the value in the redis client: %w", err)
68
66
  }
@@ -70,39 +68,29 @@ func (r *BaseRDB) Set(ctx context.Context, key string, value any) error {
70
68
  return nil
71
69
  }
72
70
 
73
- func (r *BaseRDB) MSet(ctx context.Context, entries map[string]any) error {
74
- // format the entries
75
- args := make([]any, 0, len(entries)*2)
71
+ func (r *BaseRDB) MSet(ctx context.Context, entries map[string]any, expiration time.Duration) error {
72
+ // check that there are entries to set
73
+ if len(entries) == 0 {
74
+ return fmt.Errorf("there are no entries to set")
75
+ }
76
+
77
+ // build a flat list of arguments for the lua script: [k1, v1, k2, v2, ..., expire_sec]
78
+ // the last element is the TTL in seconds. Zero or negative expire means no TTL.
79
+ scriptArgs := make([]any, 0, (len(entries)*2)+1)
76
80
  for key, value := range entries {
77
81
  bytes, err := json.Marshal(value)
78
82
  if err != nil {
79
83
  return fmt.Errorf("failed to marshal the value for key %s: %w", key, err)
80
84
  }
81
- args = append(args, FormatKey(r.database, key), bytes)
85
+ scriptArgs = append(scriptArgs, FormatKey(r.database, key), bytes)
82
86
  }
87
+ scriptArgs = append(scriptArgs, int(expiration.Seconds()))
83
88
 
84
- // set the entries in the redis client
85
- err := r.client.MSet(ctx, args...).Err()
89
+ // run the lua script
90
+ err := MSetWithExpireScript.Run(ctx, r.client, []string{}, scriptArgs...).Err()
86
91
  if err != nil {
87
92
  return fmt.Errorf("failed to set the entries in the redis client: %w", err)
88
93
  }
89
-
90
- return nil
91
- }
92
-
93
- func (r *BaseRDB) SetWithExpiration(ctx context.Context, key string, value any, expiration time.Duration) error {
94
- // marshal the value into a JSON byte array
95
- bytes, err := json.Marshal(value)
96
- if err != nil {
97
- return fmt.Errorf("failed to marshal the value: %w", err)
98
- }
99
-
100
- // set the value in the redis client
101
- err = r.client.Set(ctx, FormatKey(r.database, key), bytes, expiration).Err()
102
- if err != nil {
103
- return fmt.Errorf("failed to set the value in the redis client: %w", err)
104
- }
105
-
106
94
  return nil
107
95
  }
108
96
 
@@ -1,6 +1,25 @@
1
1
  package redis
2
2
 
3
- import "errors"
3
+ import (
4
+ "errors"
5
+
6
+ goredis "github.com/redis/go-redis/v9"
7
+ )
4
8
 
5
9
  // ErrNotFound is returned when a value is not found in the redis database.
6
10
  var ErrNotFound = errors.New("value not found in the redis database")
11
+
12
+ // MSetWithExpireScript is a local lua script that sets the value for the given key with the given expiration.
13
+ var MSetWithExpireScript = goredis.NewScript(`
14
+ local n = #ARGV - 1
15
+ if n < 1 then return 'OK' end
16
+ local expire = tonumber(ARGV[#ARGV])
17
+ for i = 1, n, 2 do
18
+ if expire > 0 then
19
+ redis.call('SET', ARGV[i], ARGV[i+1], 'EX', expire)
20
+ else
21
+ redis.call('SET', ARGV[i], ARGV[i+1])
22
+ end
23
+ end
24
+ return 'OK'
25
+ `)
package/mise.toml CHANGED
@@ -3,3 +3,4 @@ go = "1.23"
3
3
  node = "22"
4
4
  pre-commit = "4.0"
5
5
  golangci-lint = "2.1"
6
+ supabase = "2.78.1"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rivascva/dt-idl",
3
- "version": "1.1.166",
3
+ "version": "1.1.169",
4
4
  "description": "Dream Trade - Interface Definition Language",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.esm.js",
@@ -168,6 +168,12 @@ paths:
168
168
  application/json:
169
169
  schema:
170
170
  $ref: '#/components/schemas/Order'
171
+ 202:
172
+ description: Accepted
173
+ content:
174
+ application/json:
175
+ schema:
176
+ type: object
171
177
  400:
172
178
  $ref: '#/components/responses/BadRequest'
173
179
  404:
@@ -0,0 +1,388 @@
1
+ # For detailed configuration reference documentation, visit:
2
+ # https://supabase.com/docs/guides/local-development/cli/config
3
+ # A string used to distinguish different Supabase projects on the same host. Defaults to the
4
+ # working directory name when running `supabase init`.
5
+ project_id = "dt-idl"
6
+
7
+ [api]
8
+ enabled = true
9
+ # Port to use for the API URL.
10
+ port = 54321
11
+ # Schemas to expose in your API. Tables, views and stored procedures in this schema will get API
12
+ # endpoints. `public` and `graphql_public` schemas are included by default.
13
+ schemas = ["public", "graphql_public"]
14
+ # Extra schemas to add to the search_path of every request.
15
+ extra_search_path = ["public", "extensions"]
16
+ # The maximum number of rows returns from a view, table, or stored procedure. Limits payload size
17
+ # for accidental or malicious requests.
18
+ max_rows = 1000
19
+
20
+ [api.tls]
21
+ # Enable HTTPS endpoints locally using a self-signed certificate.
22
+ enabled = false
23
+ # Paths to self-signed certificate pair.
24
+ # cert_path = "../certs/my-cert.pem"
25
+ # key_path = "../certs/my-key.pem"
26
+
27
+ [db]
28
+ # Port to use for the local database URL.
29
+ port = 54322
30
+ # Port used by db diff command to initialize the shadow database.
31
+ shadow_port = 54320
32
+ # Maximum amount of time to wait for health check when starting the local database.
33
+ health_timeout = "2m"
34
+ # The database major version to use. This has to be the same as your remote database's. Run `SHOW
35
+ # server_version;` on the remote database to check.
36
+ major_version = 17
37
+
38
+ [db.pooler]
39
+ enabled = false
40
+ # Port to use for the local connection pooler.
41
+ port = 54329
42
+ # Specifies when a server connection can be reused by other clients.
43
+ # Configure one of the supported pooler modes: `transaction`, `session`.
44
+ pool_mode = "transaction"
45
+ # How many server connections to allow per user/database pair.
46
+ default_pool_size = 20
47
+ # Maximum number of client connections allowed.
48
+ max_client_conn = 100
49
+
50
+ # [db.vault]
51
+ # secret_key = "env(SECRET_VALUE)"
52
+
53
+ [db.migrations]
54
+ # If disabled, migrations will be skipped during a db push or reset.
55
+ enabled = true
56
+ # Specifies an ordered list of schema files that describe your database.
57
+ # Supports glob patterns relative to supabase directory: "./schemas/*.sql"
58
+ schema_paths = []
59
+
60
+ [db.seed]
61
+ # If enabled, seeds the database after migrations during a db reset.
62
+ enabled = true
63
+ # Specifies an ordered list of seed files to load during db reset.
64
+ # Supports glob patterns relative to supabase directory: "./seeds/*.sql"
65
+ sql_paths = ["./seed.sql"]
66
+
67
+ [db.network_restrictions]
68
+ # Enable management of network restrictions.
69
+ enabled = false
70
+ # List of IPv4 CIDR blocks allowed to connect to the database.
71
+ # Defaults to allow all IPv4 connections. Set empty array to block all IPs.
72
+ allowed_cidrs = ["0.0.0.0/0"]
73
+ # List of IPv6 CIDR blocks allowed to connect to the database.
74
+ # Defaults to allow all IPv6 connections. Set empty array to block all IPs.
75
+ allowed_cidrs_v6 = ["::/0"]
76
+
77
+ # Uncomment to reject non-secure connections to the database.
78
+ # [db.ssl_enforcement]
79
+ # enabled = true
80
+
81
+ [realtime]
82
+ enabled = true
83
+ # Bind realtime via either IPv4 or IPv6. (default: IPv4)
84
+ # ip_version = "IPv6"
85
+ # The maximum length in bytes of HTTP request headers. (default: 4096)
86
+ # max_header_length = 4096
87
+
88
+ [studio]
89
+ enabled = true
90
+ # Port to use for Supabase Studio.
91
+ port = 54323
92
+ # External URL of the API server that frontend connects to.
93
+ api_url = "http://127.0.0.1"
94
+ # OpenAI API Key to use for Supabase AI in the Supabase Studio.
95
+ openai_api_key = "env(OPENAI_API_KEY)"
96
+
97
+ # Email testing server. Emails sent with the local dev setup are not actually sent - rather, they
98
+ # are monitored, and you can view the emails that would have been sent from the web interface.
99
+ [inbucket]
100
+ enabled = true
101
+ # Port to use for the email testing server web interface.
102
+ port = 54324
103
+ # Uncomment to expose additional ports for testing user applications that send emails.
104
+ # smtp_port = 54325
105
+ # pop3_port = 54326
106
+ # admin_email = "admin@email.com"
107
+ # sender_name = "Admin"
108
+
109
+ [storage]
110
+ enabled = true
111
+ # The maximum file size allowed (e.g. "5MB", "500KB").
112
+ file_size_limit = "50MiB"
113
+
114
+ # Uncomment to configure local storage buckets
115
+ # [storage.buckets.images]
116
+ # public = false
117
+ # file_size_limit = "50MiB"
118
+ # allowed_mime_types = ["image/png", "image/jpeg"]
119
+ # objects_path = "./images"
120
+
121
+ # Allow connections via S3 compatible clients
122
+ [storage.s3_protocol]
123
+ enabled = true
124
+
125
+ # Image transformation API is available to Supabase Pro plan.
126
+ # [storage.image_transformation]
127
+ # enabled = true
128
+
129
+ # Store analytical data in S3 for running ETL jobs over Iceberg Catalog
130
+ # This feature is only available on the hosted platform.
131
+ [storage.analytics]
132
+ enabled = false
133
+ max_namespaces = 5
134
+ max_tables = 10
135
+ max_catalogs = 2
136
+
137
+ # Analytics Buckets is available to Supabase Pro plan.
138
+ # [storage.analytics.buckets.my-warehouse]
139
+
140
+ # Store vector embeddings in S3 for large and durable datasets
141
+ # This feature is only available on the hosted platform.
142
+ [storage.vector]
143
+ enabled = false
144
+ max_buckets = 10
145
+ max_indexes = 5
146
+
147
+ # Vector Buckets is available to Supabase Pro plan.
148
+ # [storage.vector.buckets.documents-openai]
149
+
150
+ [auth]
151
+ enabled = true
152
+ # The base URL of your website. Used as an allow-list for redirects and for constructing URLs used
153
+ # in emails.
154
+ site_url = "http://127.0.0.1:3000"
155
+ # A list of *exact* URLs that auth providers are permitted to redirect to post authentication.
156
+ additional_redirect_urls = ["https://127.0.0.1:3000"]
157
+ # How long tokens are valid for, in seconds. Defaults to 3600 (1 hour), maximum 604,800 (1 week).
158
+ jwt_expiry = 3600
159
+ # JWT issuer URL. If not set, defaults to the local API URL (http://127.0.0.1:<port>/auth/v1).
160
+ # jwt_issuer = ""
161
+ # Path to JWT signing key. DO NOT commit your signing keys file to git.
162
+ # signing_keys_path = "./signing_keys.json"
163
+ # If disabled, the refresh token will never expire.
164
+ enable_refresh_token_rotation = true
165
+ # Allows refresh tokens to be reused after expiry, up to the specified interval in seconds.
166
+ # Requires enable_refresh_token_rotation = true.
167
+ refresh_token_reuse_interval = 10
168
+ # Allow/disallow new user signups to your project.
169
+ enable_signup = true
170
+ # Allow/disallow anonymous sign-ins to your project.
171
+ enable_anonymous_sign_ins = false
172
+ # Allow/disallow testing manual linking of accounts
173
+ enable_manual_linking = false
174
+ # Passwords shorter than this value will be rejected as weak. Minimum 6, recommended 8 or more.
175
+ minimum_password_length = 6
176
+ # Passwords that do not meet the following requirements will be rejected as weak. Supported values
177
+ # are: `letters_digits`, `lower_upper_letters_digits`, `lower_upper_letters_digits_symbols`
178
+ password_requirements = ""
179
+
180
+ [auth.rate_limit]
181
+ # Number of emails that can be sent per hour. Requires auth.email.smtp to be enabled.
182
+ email_sent = 2
183
+ # Number of SMS messages that can be sent per hour. Requires auth.sms to be enabled.
184
+ sms_sent = 30
185
+ # Number of anonymous sign-ins that can be made per hour per IP address. Requires enable_anonymous_sign_ins = true.
186
+ anonymous_users = 30
187
+ # Number of sessions that can be refreshed in a 5 minute interval per IP address.
188
+ token_refresh = 150
189
+ # Number of sign up and sign-in requests that can be made in a 5 minute interval per IP address (excludes anonymous users).
190
+ sign_in_sign_ups = 30
191
+ # Number of OTP / Magic link verifications that can be made in a 5 minute interval per IP address.
192
+ token_verifications = 30
193
+ # Number of Web3 logins that can be made in a 5 minute interval per IP address.
194
+ web3 = 30
195
+
196
+ # Configure one of the supported captcha providers: `hcaptcha`, `turnstile`.
197
+ # [auth.captcha]
198
+ # enabled = true
199
+ # provider = "hcaptcha"
200
+ # secret = ""
201
+
202
+ [auth.email]
203
+ # Allow/disallow new user signups via email to your project.
204
+ enable_signup = true
205
+ # If enabled, a user will be required to confirm any email change on both the old, and new email
206
+ # addresses. If disabled, only the new email is required to confirm.
207
+ double_confirm_changes = true
208
+ # If enabled, users need to confirm their email address before signing in.
209
+ enable_confirmations = false
210
+ # If enabled, users will need to reauthenticate or have logged in recently to change their password.
211
+ secure_password_change = false
212
+ # Controls the minimum amount of time that must pass before sending another signup confirmation or password reset email.
213
+ max_frequency = "1s"
214
+ # Number of characters used in the email OTP.
215
+ otp_length = 6
216
+ # Number of seconds before the email OTP expires (defaults to 1 hour).
217
+ otp_expiry = 3600
218
+
219
+ # Use a production-ready SMTP server
220
+ # [auth.email.smtp]
221
+ # enabled = true
222
+ # host = "smtp.sendgrid.net"
223
+ # port = 587
224
+ # user = "apikey"
225
+ # pass = "env(SENDGRID_API_KEY)"
226
+ # admin_email = "admin@email.com"
227
+ # sender_name = "Admin"
228
+
229
+ # Uncomment to customize email template
230
+ # [auth.email.template.invite]
231
+ # subject = "You have been invited"
232
+ # content_path = "./supabase/templates/invite.html"
233
+
234
+ # Uncomment to customize notification email template
235
+ # [auth.email.notification.password_changed]
236
+ # enabled = true
237
+ # subject = "Your password has been changed"
238
+ # content_path = "./templates/password_changed_notification.html"
239
+
240
+ [auth.sms]
241
+ # Allow/disallow new user signups via SMS to your project.
242
+ enable_signup = false
243
+ # If enabled, users need to confirm their phone number before signing in.
244
+ enable_confirmations = false
245
+ # Template for sending OTP to users
246
+ template = "Your code is {{ .Code }}"
247
+ # Controls the minimum amount of time that must pass before sending another sms otp.
248
+ max_frequency = "5s"
249
+
250
+ # Use pre-defined map of phone number to OTP for testing.
251
+ # [auth.sms.test_otp]
252
+ # 4152127777 = "123456"
253
+
254
+ # Configure logged in session timeouts.
255
+ # [auth.sessions]
256
+ # Force log out after the specified duration.
257
+ # timebox = "24h"
258
+ # Force log out if the user has been inactive longer than the specified duration.
259
+ # inactivity_timeout = "8h"
260
+
261
+ # This hook runs before a new user is created and allows developers to reject the request based on the incoming user object.
262
+ # [auth.hook.before_user_created]
263
+ # enabled = true
264
+ # uri = "pg-functions://postgres/auth/before-user-created-hook"
265
+
266
+ # This hook runs before a token is issued and allows you to add additional claims based on the authentication method used.
267
+ # [auth.hook.custom_access_token]
268
+ # enabled = true
269
+ # uri = "pg-functions://<database>/<schema>/<hook_name>"
270
+
271
+ # Configure one of the supported SMS providers: `twilio`, `twilio_verify`, `messagebird`, `textlocal`, `vonage`.
272
+ [auth.sms.twilio]
273
+ enabled = false
274
+ account_sid = ""
275
+ message_service_sid = ""
276
+ # DO NOT commit your Twilio auth token to git. Use environment variable substitution instead:
277
+ auth_token = "env(SUPABASE_AUTH_SMS_TWILIO_AUTH_TOKEN)"
278
+
279
+ # Multi-factor-authentication is available to Supabase Pro plan.
280
+ [auth.mfa]
281
+ # Control how many MFA factors can be enrolled at once per user.
282
+ max_enrolled_factors = 10
283
+
284
+ # Control MFA via App Authenticator (TOTP)
285
+ [auth.mfa.totp]
286
+ enroll_enabled = false
287
+ verify_enabled = false
288
+
289
+ # Configure MFA via Phone Messaging
290
+ [auth.mfa.phone]
291
+ enroll_enabled = false
292
+ verify_enabled = false
293
+ otp_length = 6
294
+ template = "Your code is {{ .Code }}"
295
+ max_frequency = "5s"
296
+
297
+ # Configure MFA via WebAuthn
298
+ # [auth.mfa.web_authn]
299
+ # enroll_enabled = true
300
+ # verify_enabled = true
301
+
302
+ # Use an external OAuth provider. The full list of providers are: `apple`, `azure`, `bitbucket`,
303
+ # `discord`, `facebook`, `github`, `gitlab`, `google`, `keycloak`, `linkedin_oidc`, `notion`, `twitch`,
304
+ # `twitter`, `x`, `slack`, `spotify`, `workos`, `zoom`.
305
+ [auth.external.apple]
306
+ enabled = false
307
+ client_id = ""
308
+ # DO NOT commit your OAuth provider secret to git. Use environment variable substitution instead:
309
+ secret = "env(SUPABASE_AUTH_EXTERNAL_APPLE_SECRET)"
310
+ # Overrides the default auth redirectUrl.
311
+ redirect_uri = ""
312
+ # Overrides the default auth provider URL. Used to support self-hosted gitlab, single-tenant Azure,
313
+ # or any other third-party OIDC providers.
314
+ url = ""
315
+ # If enabled, the nonce check will be skipped. Required for local sign in with Google auth.
316
+ skip_nonce_check = false
317
+ # If enabled, it will allow the user to successfully authenticate when the provider does not return an email address.
318
+ email_optional = false
319
+
320
+ # Allow Solana wallet holders to sign in to your project via the Sign in with Solana (SIWS, EIP-4361) standard.
321
+ # You can configure "web3" rate limit in the [auth.rate_limit] section and set up [auth.captcha] if self-hosting.
322
+ [auth.web3.solana]
323
+ enabled = false
324
+
325
+ # Use Firebase Auth as a third-party provider alongside Supabase Auth.
326
+ [auth.third_party.firebase]
327
+ enabled = false
328
+ # project_id = "my-firebase-project"
329
+
330
+ # Use Auth0 as a third-party provider alongside Supabase Auth.
331
+ [auth.third_party.auth0]
332
+ enabled = false
333
+ # tenant = "my-auth0-tenant"
334
+ # tenant_region = "us"
335
+
336
+ # Use AWS Cognito (Amplify) as a third-party provider alongside Supabase Auth.
337
+ [auth.third_party.aws_cognito]
338
+ enabled = false
339
+ # user_pool_id = "my-user-pool-id"
340
+ # user_pool_region = "us-east-1"
341
+
342
+ # Use Clerk as a third-party provider alongside Supabase Auth.
343
+ [auth.third_party.clerk]
344
+ enabled = false
345
+ # Obtain from https://clerk.com/setup/supabase
346
+ # domain = "example.clerk.accounts.dev"
347
+
348
+ # OAuth server configuration
349
+ [auth.oauth_server]
350
+ # Enable OAuth server functionality
351
+ enabled = false
352
+ # Path for OAuth consent flow UI
353
+ authorization_url_path = "/oauth/consent"
354
+ # Allow dynamic client registration
355
+ allow_dynamic_registration = false
356
+
357
+ [edge_runtime]
358
+ enabled = true
359
+ # Supported request policies: `oneshot`, `per_worker`.
360
+ # `per_worker` (default) — enables hot reload during local development.
361
+ # `oneshot` — fallback mode if hot reload causes issues (e.g. in large repos or with symlinks).
362
+ policy = "per_worker"
363
+ # Port to attach the Chrome inspector for debugging edge functions.
364
+ inspector_port = 8083
365
+ # The Deno major version to use.
366
+ deno_version = 2
367
+
368
+ # [edge_runtime.secrets]
369
+ # secret_key = "env(SECRET_VALUE)"
370
+
371
+ [analytics]
372
+ enabled = true
373
+ port = 54327
374
+ # Configure one of the supported backends: `postgres`, `bigquery`.
375
+ backend = "postgres"
376
+
377
+ # Experimental features may be deprecated any time
378
+ [experimental]
379
+ # Configures Postgres storage engine to use OrioleDB (S3)
380
+ orioledb_version = ""
381
+ # Configures S3 bucket URL, eg. <bucket_name>.s3-<region>.amazonaws.com
382
+ s3_host = "env(S3_HOST)"
383
+ # Configures S3 bucket region, eg. us-east-1
384
+ s3_region = "env(S3_REGION)"
385
+ # Configures AWS_ACCESS_KEY_ID for S3 bucket
386
+ s3_access_key = "env(S3_ACCESS_KEY)"
387
+ # Configures AWS_SECRET_ACCESS_KEY for S3 bucket
388
+ s3_secret_key = "env(S3_SECRET_KEY)"
@@ -0,0 +1,39 @@
1
+ -- Custom Functions
2
+
3
+ CREATE OR REPLACE FUNCTION trigger_date_updated()
4
+ RETURNS TRIGGER AS $$
5
+ BEGIN
6
+ NEW.date_updated = now();
7
+ RETURN NEW;
8
+ END;
9
+ $$ LANGUAGE plpgsql;
10
+
11
+ -- Users Table
12
+
13
+ CREATE TABLE users (
14
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
15
+ email TEXT NOT NULL UNIQUE,
16
+ name TEXT NOT NULL,
17
+ country TEXT NOT NULL,
18
+ image_url TEXT NULL,
19
+ platform TEXT NULL,
20
+ app_version TEXT NULL,
21
+ fcm_token TEXT NULL,
22
+ date_created TIMESTAMPTZ DEFAULT now() NOT NULL,
23
+ date_updated TIMESTAMPTZ DEFAULT now() NOT NULL
24
+ );
25
+
26
+ CREATE TRIGGER update_date_updated BEFORE UPDATE ON users FOR EACH ROW EXECUTE PROCEDURE trigger_date_updated();
27
+
28
+ -- Refresh Tokens Table
29
+
30
+ CREATE TABLE refresh_tokens (
31
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
32
+ user_id UUID REFERENCES users(id) NOT NULL,
33
+ token TEXT NOT NULL,
34
+ date_created TIMESTAMPTZ DEFAULT now() NOT NULL,
35
+ date_updated TIMESTAMPTZ DEFAULT now() NOT NULL,
36
+ date_expired TIMESTAMPTZ NOT NULL
37
+ );
38
+
39
+ CREATE TRIGGER update_date_updated BEFORE UPDATE ON refresh_tokens FOR EACH ROW EXECUTE PROCEDURE trigger_date_updated();
@@ -0,0 +1,57 @@
1
+ -- Portfolios Table
2
+
3
+ CREATE TABLE portfolios (
4
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
5
+ user_id UUID NOT NULL,
6
+ type TEXT NOT NULL,
7
+ cash FLOAT NOT NULL,
8
+ favorite_symbols TEXT[] NOT NULL,
9
+ date_created TIMESTAMPTZ DEFAULT now() NOT NULL,
10
+ date_updated TIMESTAMPTZ DEFAULT now() NOT NULL
11
+ );
12
+
13
+ CREATE TRIGGER update_date_updated BEFORE UPDATE ON portfolios FOR EACH ROW EXECUTE PROCEDURE trigger_date_updated();
14
+
15
+ -- Orders Table
16
+
17
+ CREATE TABLE orders (
18
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
19
+ portfolio_id UUID REFERENCES portfolios(id) NOT NULL,
20
+ type TEXT NOT NULL,
21
+ symbol TEXT NOT NULL,
22
+ shares INTEGER NOT NULL,
23
+ target_price FLOAT NOT NULL,
24
+ final_price FLOAT NULL,
25
+ date_executed TIMESTAMPTZ NULL,
26
+ date_created TIMESTAMPTZ DEFAULT now() NOT NULL,
27
+ date_updated TIMESTAMPTZ DEFAULT now() NOT NULL
28
+ );
29
+
30
+ CREATE TRIGGER update_date_updated BEFORE UPDATE ON orders FOR EACH ROW EXECUTE PROCEDURE trigger_date_updated();
31
+
32
+ -- Holdings Table
33
+
34
+ CREATE TABLE holdings (
35
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
36
+ portfolio_id UUID REFERENCES portfolios(id) NOT NULL,
37
+ symbol TEXT NOT NULL,
38
+ shares INTEGER NOT NULL,
39
+ average_price FLOAT NOT NULL,
40
+ date_created TIMESTAMPTZ DEFAULT now() NOT NULL,
41
+ date_updated TIMESTAMPTZ DEFAULT now() NOT NULL
42
+ );
43
+
44
+ CREATE TRIGGER update_date_updated BEFORE UPDATE ON holdings FOR EACH ROW EXECUTE PROCEDURE trigger_date_updated();
45
+
46
+ -- Portfolio History Values Table
47
+
48
+ CREATE TABLE portfolio_history_values (
49
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
50
+ portfolio_id UUID REFERENCES portfolios(id) NOT NULL,
51
+ cash FLOAT NOT NULL,
52
+ total_value FLOAT NOT NULL,
53
+ date_created TIMESTAMPTZ DEFAULT now() NOT NULL,
54
+ date_updated TIMESTAMPTZ DEFAULT now() NOT NULL
55
+ );
56
+
57
+ CREATE TRIGGER update_date_updated BEFORE UPDATE ON portfolio_history_values FOR EACH ROW EXECUTE PROCEDURE trigger_date_updated();
@@ -0,0 +1,34 @@
1
+ INSERT INTO users (id, email, name, country) VALUES
2
+ ('99999999-9999-9999-9999-999999999999', 'sam.smith@example.com', 'Sam Smith', 'USA'),
3
+ ('88888888-8888-8888-8888-888888888888', 'jane.doe@example.com', 'Jane Doe', 'MEX');
4
+
5
+ INSERT INTO portfolios (id, user_id, type, cash, favorite_symbols) VALUES
6
+ ('99999999-9999-9999-9999-999999999999', '99999999-9999-9999-9999-999999999999', 'PERSONAL', 50000, ARRAY['AAPL', 'MSFT']),
7
+ ('88888888-8888-8888-8888-888888888888', '88888888-8888-8888-8888-888888888888', 'PERSONAL', 50000, ARRAY['GOOGL', 'AMZN']);
8
+
9
+ INSERT INTO orders (portfolio_id, type, symbol, shares, target_price, final_price, date_executed) VALUES
10
+ ('99999999-9999-9999-9999-999999999999', 'BUY_MARKET', 'AAPL', 10, 95.10, 95.15, now()),
11
+ ('99999999-9999-9999-9999-999999999999', 'BUY_MARKET', 'MSFT', 35, 115.20, NULL, NULL),
12
+ ('88888888-8888-8888-8888-888888888888', 'BUY_MARKET', 'MSFT', 35, 115.20, 115.25, now()),
13
+ ('88888888-8888-8888-8888-888888888888', 'BUY_MARKET', 'AAPL', 10, 95.10, NULL, NULL);
14
+
15
+ INSERT INTO holdings (portfolio_id, symbol, shares, average_price) VALUES
16
+ ('99999999-9999-9999-9999-999999999999', 'AAPL', 10, 95.15),
17
+ ('88888888-8888-8888-8888-888888888888', 'MSFT', 35, 115.25);
18
+
19
+ INSERT INTO portfolio_history_values (portfolio_id, cash, total_value, date_created, date_updated) VALUES
20
+ ('99999999-9999-9999-9999-999999999999', 1200, 35000, now() - interval '150 minutes', now() - interval '150 minutes'),
21
+ ('99999999-9999-9999-9999-999999999999', 2400, 40000, now() - interval '135 minutes', now() - interval '135 minutes'),
22
+ ('99999999-9999-9999-9999-999999999999', 3600, 45000, now() - interval '120 minutes', now() - interval '120 minutes'),
23
+ ('99999999-9999-9999-9999-999999999999', 3600, 42500, now() - interval '105 minutes', now() - interval '105 minutes'),
24
+ ('99999999-9999-9999-9999-999999999999', 3600, 39000, now() - interval '90 minutes', now() - interval '90 minutes'),
25
+ ('99999999-9999-9999-9999-999999999999', 3000, 43000, now() - interval '75 minutes', now() - interval '75 minutes'),
26
+ ('99999999-9999-9999-9999-999999999999', 3200, 48000, now() - interval '60 minutes', now() - interval '60 minutes'),
27
+ ('99999999-9999-9999-9999-999999999999', 3200, 47000, now() - interval '45 minutes', now() - interval '45 minutes'),
28
+ ('99999999-9999-9999-9999-999999999999', 2700, 52000, now() - interval '30 minutes', now() - interval '30 minutes'),
29
+ ('99999999-9999-9999-9999-999999999999', 2700, 52500, now() - interval '15 minutes', now() - interval '15 minutes'),
30
+ ('88888888-8888-8888-8888-888888888888', 2500, 32000, now() - interval '75 minutes', now() - interval '75 minutes'),
31
+ ('88888888-8888-8888-8888-888888888888', 1500, 28000, now() - interval '60 minutes', now() - interval '60 minutes'),
32
+ ('88888888-8888-8888-8888-888888888888', 1400, 25000, now() - interval '45 minutes', now() - interval '45 minutes'),
33
+ ('88888888-8888-8888-8888-888888888888', 1200, 22000, now() - interval '30 minutes', now() - interval '30 minutes'),
34
+ ('88888888-8888-8888-8888-888888888888', 1000, 20000, now() - interval '15 minutes', now() - interval '15 minutes');
@@ -467,6 +467,15 @@ export interface operations {
467
467
  "application/json": components["schemas"]["Order"];
468
468
  };
469
469
  };
470
+ /** @description Accepted */
471
+ 202: {
472
+ headers: {
473
+ [name: string]: unknown;
474
+ };
475
+ content: {
476
+ "application/json": Record<string, never>;
477
+ };
478
+ };
470
479
  400: components["responses"]["BadRequest"];
471
480
  404: components["responses"]["NotFound"];
472
481
  500: components["responses"]["InternalServerError"];