├── .env.example
├── .gitignore
├── .idea
├── .gitignore
├── dataSources.xml
├── modules.xml
├── prettier.xml
├── stripe_to_postgres.iml
└── vcs.xml
├── .prettierrc
├── Dockerfile
├── Makefile
├── README.md
├── docker-compose.yml
├── migrations
├── 0000_create_schema.sql
└── 0001_add_updated_at.sql
├── package-lock.json
├── package.json
├── src
├── config.ts
├── connection.ts
├── migrate.ts
├── server.ts
├── stripe.ts
├── sync.ts
├── utils.ts
└── webhook.ts
└── tsconfig.json
/.env.example:
--------------------------------------------------------------------------------
1 | NODE_ENV=development
2 | PORT=3000
3 | SKIP_SYNC=false
4 | SKIP_MIGRATIONS=false
5 | DATABASE_URL=postgres://postgres:postgres@host:5432/postgres?sslmode=disable&search_path=stripe
6 | STRIPE_SECRET_KEY=sk_test_
7 | STRIPE_WEBHOOK_SECRET=
8 | WEBHOOK_URL=
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.toptal.com/developers/gitignore/api/node,macos,linux,webstorm,visualstudiocode,sublimetext
2 | # Edit at https://www.toptal.com/developers/gitignore?templates=node,macos,linux,webstorm,visualstudiocode,sublimetext
3 |
4 | ### Linux ###
5 | *~
6 |
7 | # temporary files which can be created if a process still has a handle open of a deleted file
8 | .fuse_hidden*
9 |
10 | # KDE directory preferences
11 | .directory
12 |
13 | # Linux trash folder which might appear on any partition or disk
14 | .Trash-*
15 |
16 | # .nfs files are created when an open file is removed but is still being accessed
17 | .nfs*
18 |
19 | ### macOS ###
20 | # General
21 | .DS_Store
22 | .AppleDouble
23 | .LSOverride
24 |
25 | # Icon must end with two \r
26 | Icon
27 |
28 |
29 | # Thumbnails
30 | ._*
31 |
32 | # Files that might appear in the root of a volume
33 | .DocumentRevisions-V100
34 | .fseventsd
35 | .Spotlight-V100
36 | .TemporaryItems
37 | .Trashes
38 | .VolumeIcon.icns
39 | .com.apple.timemachine.donotpresent
40 |
41 | # Directories potentially created on remote AFP share
42 | .AppleDB
43 | .AppleDesktop
44 | Network Trash Folder
45 | Temporary Items
46 | .apdisk
47 |
48 | ### macOS Patch ###
49 | # iCloud generated files
50 | *.icloud
51 |
52 | ### Node ###
53 | # Logs
54 | logs
55 | *.log
56 | npm-debug.log*
57 | yarn-debug.log*
58 | yarn-error.log*
59 | lerna-debug.log*
60 | .pnpm-debug.log*
61 |
62 | # Diagnostic reports (https://nodejs.org/api/report.html)
63 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
64 |
65 | # Runtime data
66 | pids
67 | *.pid
68 | *.seed
69 | *.pid.lock
70 |
71 | # Directory for instrumented libs generated by jscoverage/JSCover
72 | lib-cov
73 |
74 | # Coverage directory used by tools like istanbul
75 | coverage
76 | *.lcov
77 |
78 | # nyc test coverage
79 | .nyc_output
80 |
81 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
82 | .grunt
83 |
84 | # Bower dependency directory (https://bower.io/)
85 | bower_components
86 |
87 | # node-waf configuration
88 | .lock-wscript
89 |
90 | # Compiled binary addons (https://nodejs.org/api/addons.html)
91 | build/Release
92 |
93 | # Dependency directories
94 | node_modules/
95 | jspm_packages/
96 |
97 | # Snowpack dependency directory (https://snowpack.dev/)
98 | web_modules/
99 |
100 | # TypeScript cache
101 | *.tsbuildinfo
102 |
103 | # Optional npm cache directory
104 | .npm
105 |
106 | # Optional eslint cache
107 | .eslintcache
108 |
109 | # Optional stylelint cache
110 | .stylelintcache
111 |
112 | # Microbundle cache
113 | .rpt2_cache/
114 | .rts2_cache_cjs/
115 | .rts2_cache_es/
116 | .rts2_cache_umd/
117 |
118 | # Optional REPL history
119 | .node_repl_history
120 |
121 | # Output of 'npm pack'
122 | *.tgz
123 |
124 | # Yarn Integrity file
125 | .yarn-integrity
126 |
127 | # dotenv environment variable files
128 | .env
129 | .env.development.local
130 | .env.test.local
131 | .env.production.local
132 | .env.local
133 |
134 | # parcel-bundler cache (https://parceljs.org/)
135 | .cache
136 | .parcel-cache
137 |
138 | # Next.js build output
139 | .next
140 | out
141 |
142 | # Nuxt.js build / generate output
143 | .nuxt
144 | dist
145 |
146 | # Gatsby files
147 | .cache/
148 | # Comment in the public line in if your project uses Gatsby and not Next.js
149 | # https://nextjs.org/blog/next-9-1#public-directory-support
150 | # public
151 |
152 | # vuepress build output
153 | .vuepress/dist
154 |
155 | # vuepress v2.x temp and cache directory
156 | .temp
157 |
158 | # Docusaurus cache and generated files
159 | .docusaurus
160 |
161 | # Serverless directories
162 | .serverless/
163 |
164 | # FuseBox cache
165 | .fusebox/
166 |
167 | # DynamoDB Local files
168 | .dynamodb/
169 |
170 | # TernJS port file
171 | .tern-port
172 |
173 | # Stores VSCode versions used for testing VSCode extensions
174 | .vscode-test
175 |
176 | # yarn v2
177 | .yarn/cache
178 | .yarn/unplugged
179 | .yarn/build-state.yml
180 | .yarn/install-state.gz
181 | .pnp.*
182 |
183 | ### Node Patch ###
184 | # Serverless Webpack directories
185 | .webpack/
186 |
187 | # Optional stylelint cache
188 |
189 | # SvelteKit build / generate output
190 | .svelte-kit
191 |
192 | ### SublimeText ###
193 | # Cache files for Sublime Text
194 | *.tmlanguage.cache
195 | *.tmPreferences.cache
196 | *.stTheme.cache
197 |
198 | # Workspace files are user-specific
199 | *.sublime-workspace
200 |
201 | # Project files should be checked into the repository, unless a significant
202 | # proportion of contributors will probably not be using Sublime Text
203 | # *.sublime-project
204 |
205 | # SFTP configuration file
206 | sftp-config.json
207 | sftp-config-alt*.json
208 |
209 | # Package control specific files
210 | Package Control.last-run
211 | Package Control.ca-list
212 | Package Control.ca-bundle
213 | Package Control.system-ca-bundle
214 | Package Control.cache/
215 | Package Control.ca-certs/
216 | Package Control.merged-ca-bundle
217 | Package Control.user-ca-bundle
218 | oscrypto-ca-bundle.crt
219 | bh_unicode_properties.cache
220 |
221 | # Sublime-github package stores a github token in this file
222 | # https://packagecontrol.io/packages/sublime-github
223 | GitHub.sublime-settings
224 |
225 | ### VisualStudioCode ###
226 | .vscode/*
227 | !.vscode/settings.json
228 | !.vscode/tasks.json
229 | !.vscode/launch.json
230 | !.vscode/extensions.json
231 | !.vscode/*.code-snippets
232 |
233 | # Local History for Visual Studio Code
234 | .history/
235 |
236 | # Built Visual Studio Code Extensions
237 | *.vsix
238 |
239 | ### VisualStudioCode Patch ###
240 | # Ignore all local history of files
241 | .history
242 | .ionide
243 |
244 | # Support for Project snippet scope
245 | .vscode/*.code-snippets
246 |
247 | # Ignore code-workspaces
248 | *.code-workspace
249 |
250 | ### WebStorm ###
251 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
252 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
253 |
254 | # User-specific stuff
255 | .idea/**/workspace.xml
256 | .idea/**/tasks.xml
257 | .idea/**/usage.statistics.xml
258 | .idea/**/dictionaries
259 | .idea/**/shelf
260 |
261 | # AWS User-specific
262 | .idea/**/aws.xml
263 |
264 | # Generated files
265 | .idea/**/contentModel.xml
266 |
267 | # Sensitive or high-churn files
268 | .idea/**/dataSources/
269 | .idea/**/dataSources.ids
270 | .idea/**/dataSources.local.xml
271 | .idea/**/sqlDataSources.xml
272 | .idea/**/dynamic.xml
273 | .idea/**/uiDesigner.xml
274 | .idea/**/dbnavigator.xml
275 |
276 | # Gradle
277 | .idea/**/gradle.xml
278 | .idea/**/libraries
279 |
280 | # Gradle and Maven with auto-import
281 | # When using Gradle or Maven with auto-import, you should exclude module files,
282 | # since they will be recreated, and may cause churn. Uncomment if using
283 | # auto-import.
284 | # .idea/artifacts
285 | # .idea/compiler.xml
286 | # .idea/jarRepositories.xml
287 | # .idea/modules.xml
288 | # .idea/*.iml
289 | # .idea/modules
290 | # *.iml
291 | # *.ipr
292 |
293 | # CMake
294 | cmake-build-*/
295 |
296 | # Mongo Explorer plugin
297 | .idea/**/mongoSettings.xml
298 |
299 | # File-based project format
300 | *.iws
301 |
302 | # IntelliJ
303 | out/
304 |
305 | # mpeltonen/sbt-idea plugin
306 | .idea_modules/
307 |
308 | # JIRA plugin
309 | atlassian-ide-plugin.xml
310 |
311 | # Cursive Clojure plugin
312 | .idea/replstate.xml
313 |
314 | # SonarLint plugin
315 | .idea/sonarlint/
316 |
317 | # Crashlytics plugin (for Android Studio and IntelliJ)
318 | com_crashlytics_export_strings.xml
319 | crashlytics.properties
320 | crashlytics-build.properties
321 | fabric.properties
322 |
323 | # Editor-based Rest Client
324 | .idea/httpRequests
325 |
326 | # Android studio 3.1+ serialized cache file
327 | .idea/caches/build_file_checksums.ser
328 |
329 | ### WebStorm Patch ###
330 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
331 |
332 | # *.iml
333 | # modules.xml
334 | # .idea/misc.xml
335 | # *.ipr
336 |
337 | # Sonarlint plugin
338 | # https://plugins.jetbrains.com/plugin/7973-sonarlint
339 | .idea/**/sonarlint/
340 |
341 | # SonarQube Plugin
342 | # https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
343 | .idea/**/sonarIssues.xml
344 |
345 | # Markdown Navigator plugin
346 | # https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
347 | .idea/**/markdown-navigator.xml
348 | .idea/**/markdown-navigator-enh.xml
349 | .idea/**/markdown-navigator/
350 |
351 | # Cache file creation bug
352 | # See https://youtrack.jetbrains.com/issue/JBR-2257
353 | .idea/$CACHE_FILE$
354 |
355 | # CodeStream plugin
356 | # https://plugins.jetbrains.com/plugin/12206-codestream
357 | .idea/codestream.xml
358 |
359 | # Azure Toolkit for IntelliJ plugin
360 | # https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij
361 | .idea/**/azureSettings.xml
362 |
363 | # End of https://www.toptal.com/developers/gitignore/api/node,macos,linux,webstorm,visualstudiocode,sublimetext
364 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/.idea/dataSources.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | postgresql
6 | true
7 | org.postgresql.Driver
8 | jdbc:postgresql://localhost:5432/postgres
9 | $ProjectFileDir$
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/prettier.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/stripe_to_postgres.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "es5",
3 | "semi": false,
4 | "singleQuote": true
5 | }
6 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:18-alpine AS builder
2 |
3 | WORKDIR /usr/src/app
4 |
5 | COPY package*.json tsconfig.json ./
6 |
7 | RUN npm install --only=dev
8 |
9 | COPY src ./src
10 |
11 | RUN npm run build
12 |
13 | FROM node:18-alpine
14 |
15 | ENV NODE_ENV production
16 |
17 | WORKDIR /usr/src/app
18 |
19 | COPY package*.json ./
20 |
21 | RUN npm install --only=prod
22 |
23 | COPY --from=builder /usr/src/app/dist ./dist
24 |
25 | COPY migrations ./migrations
26 |
27 | CMD npm start
28 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: all buildx
2 |
3 | all: buildx
4 |
5 | buildx:
6 | @docker buildx build --platform linux/amd64,linux/arm64 -t usenoori/stripe_to_postgres:latest -t usenoori/stripe_to_postgres:`npm pkg get version | tr -d '"'` --push .
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # stripe_to_postgres
2 |
3 | ## Why we exist
4 |
5 | We built Noori after working on multiple startups, where we had to rewrite the same code each time. We thought there should be an easier solution. After looking around we realized no one was building it..so we build it!
6 |
7 | ## Usage
8 |
9 | `stripe_to_postgres` is packaged as a Docker image you can run directly.
10 |
11 | The image needs the following environment variables.
12 |
13 | - `DATABASE_URL` is your Postgres instance's connection string.
14 | - `STRIPE_SECRET_KEY` can be obtained from the Stripe dashboard https://dashboard.stripe.com/apikeys.
15 | - `WEBHOOK_URL` is your https enabled endpoint where this image is deployed.
16 |
17 | Example:
18 |
19 | - Put the env vars in a .env file then run `docker run --env-file=.env usenoori/stripe_to_postgres`
20 |
21 | ### Update your Postgres search_path
22 |
23 | By default, most database tools only look up database objects in the `public` schema, you might need to update
24 | the `search_path` in your existing tooling to include the `stripe` schema we created for you.
25 |
26 | ## How does it work?
27 |
28 | 1. `stripe_to_postgres` will first create a `stripe` schema then create all the necessary table structures in your database.
29 | 2. Then it will call Stripe and page through your Stripe data to stores them in your database.
30 | 3. After the data sync is done a Stripe webhook will be created that keep your database up to date.
31 |
32 | These are the Stripe resources that are currently handled by us.
33 |
34 | - events
35 | - products
36 | - prices
37 | - customers
38 | - subscriptions
39 | - invoices
40 | - charges
41 | - coupons
42 | - disputes
43 | - plans
44 |
45 | ## Requirements
46 |
47 | At the moment we support Postgres from version 10, as the features evolve this support target could move towards
48 | Postgres 12.
49 |
50 | ## Development
51 |
52 | 1. Start local Postgres instance: `docker compose up`
53 | 2. Run `stripe listen --forward-to localhost:3000` and add the output secret as `STRIPE_WEBHOOK_SECRET` env var
54 | 3. Start development server `npm run dev`
55 |
56 | ## Contact
57 | Questions? Comments? Email us at hello@usenoori.com
58 |
59 |
60 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.8"
2 |
3 | services:
4 | db:
5 | image: postgres:14
6 | ports:
7 | - "5432:5432"
8 | environment:
9 | POSTGRES_PASSWORD: postgres
10 | volumes:
11 | - db_data:/var/lib/postgresql/data
12 |
13 | volumes:
14 | db_data:
15 |
--------------------------------------------------------------------------------
/migrations/0000_create_schema.sql:
--------------------------------------------------------------------------------
1 | create table if not exists stripe.events
2 | (
3 | id text primary key,
4 | object text,
5 | api_version text,
6 | created integer,
7 | data jsonb,
8 | livemode boolean,
9 | pending_webhooks integer,
10 | request jsonb,
11 | type text
12 | );
13 |
14 | create table if not exists stripe.products
15 | (
16 | id text primary key,
17 | object text,
18 | active boolean,
19 | created integer,
20 | default_price text,
21 | description text,
22 | images jsonb,
23 | livemode boolean,
24 | metadata jsonb,
25 | name text,
26 | package_dimensions jsonb,
27 | shippable boolean,
28 | statement_descriptor text,
29 | tax_code text,
30 | unit_label text,
31 | updated integer,
32 | url text
33 | );
34 |
35 | create type stripe.pricing_type as enum (
36 | 'one_time',
37 | 'recurring'
38 | );
39 |
40 | create type stripe.pricing_tiers as enum (
41 | 'graduated',
42 | 'volume'
43 | );
44 |
45 | create table if not exists stripe.prices
46 | (
47 | id text primary key,
48 | object text,
49 | active boolean,
50 | billing_scheme text,
51 | created integer,
52 | currency text,
53 | custom_unit_amount jsonb,
54 | livemode boolean,
55 | lookup_key text,
56 | metadata jsonb,
57 | nickname text,
58 | product text,
59 | recurring jsonb,
60 | tax_behavior text,
61 | tiers_mode stripe.pricing_tiers,
62 | transform_quantity jsonb,
63 | type stripe.pricing_type,
64 | unit_amount integer,
65 | unit_amount_decimal text
66 | );
67 |
68 | create table if not exists stripe.customers
69 | (
70 | id text primary key,
71 | object text,
72 | address jsonb,
73 | balance integer,
74 | created integer,
75 | currency text,
76 | default_source text,
77 | delinquent boolean,
78 | description text,
79 | discount jsonb,
80 | email text,
81 | invoice_prefix text,
82 | invoice_settings jsonb,
83 | livemode boolean,
84 | metadata jsonb,
85 | name text,
86 | phone text,
87 | preferred_locales jsonb,
88 | shipping jsonb,
89 | tax_exempt text
90 | );
91 |
92 | create type stripe.subscription_status as enum (
93 | 'trialing',
94 | 'active',
95 | 'canceled',
96 | 'incomplete',
97 | 'incomplete_expired',
98 | 'past_due',
99 | 'unpaid'
100 | );
101 |
102 | create table if not exists stripe.subscriptions
103 | (
104 | id text primary key,
105 | object text,
106 | application text,
107 | application_fee_percent double precision,
108 | automatic_tax jsonb,
109 | billing_cycle_anchor integer,
110 | billing_thresholds jsonb,
111 | cancel_at integer,
112 | cancel_at_period_end boolean,
113 | canceled_at integer,
114 | collection_method text,
115 | created integer,
116 | currency text,
117 | current_period_end integer,
118 | current_period_start integer,
119 | customer text,
120 | days_until_due integer,
121 | default_payment_method text,
122 | default_source text,
123 | default_tax_rates jsonb,
124 | description text,
125 | discount jsonb,
126 | ended_at integer,
127 | items jsonb,
128 | latest_invoice text,
129 | livemode boolean,
130 | metadata jsonb,
131 | next_pending_invoice_item_invoice integer,
132 | pause_collection jsonb,
133 | payment_settings jsonb,
134 | pending_invoice_item_interval jsonb,
135 | pending_setup_intent text,
136 | pending_update jsonb,
137 | schedule text,
138 | start_date integer,
139 | status stripe.subscription_status,
140 | test_clock text,
141 | transfer_data jsonb,
142 | trial_end jsonb,
143 | trial_start jsonb
144 | );
145 |
146 | create type stripe.invoice_status as enum (
147 | 'draft',
148 | 'open',
149 | 'paid',
150 | 'uncollectible',
151 | 'void'
152 | );
153 |
154 | create table if not exists stripe.invoices
155 | (
156 | id text primary key,
157 | object text,
158 | account_country text,
159 | account_name text,
160 | account_tax_ids jsonb,
161 | amount_due integer,
162 | amount_paid integer,
163 | amount_remaining integer,
164 | application text,
165 | application_fee_amount integer,
166 | attempt_count integer,
167 | attempted boolean,
168 | auto_advance boolean,
169 | automatic_tax jsonb,
170 | billing_reason text,
171 | charge text,
172 | collection_method text,
173 | created integer,
174 | currency text,
175 | custom_fields jsonb,
176 | customer text,
177 | customer_address jsonb,
178 | customer_email text,
179 | customer_name text,
180 | customer_phone text,
181 | customer_shipping jsonb,
182 | customer_tax_exempt text,
183 | customer_tax_ids jsonb,
184 | default_payment_method text,
185 | default_source text,
186 | default_tax_rates jsonb,
187 | description text,
188 | discount jsonb,
189 | discounts jsonb,
190 | due_date integer,
191 | ending_balance integer,
192 | footer text,
193 | from_invoice jsonb,
194 | hosted_invoice_url text,
195 | invoice_pdf text,
196 | last_finalization_error jsonb,
197 | latest_revision text,
198 | lines jsonb,
199 | livemode boolean,
200 | metadata jsonb,
201 | next_payment_attempt integer,
202 | number text,
203 | on_behalf_of text,
204 | paid boolean,
205 | paid_out_of_band boolean,
206 | payment_intent text,
207 | payment_settings jsonb,
208 | period_end integer,
209 | period_start integer,
210 | post_payment_credit_notes_amount integer,
211 | pre_payment_credit_notes_amount integer,
212 | quote text,
213 | receipt_number text,
214 | rendering_options jsonb,
215 | starting_balance integer,
216 | statement_descriptor text,
217 | status stripe.invoice_status,
218 | status_transitions jsonb,
219 | subscription text,
220 | subtotal integer,
221 | subtotal_excluding_tax integer,
222 | tax integer,
223 | test_clock text,
224 | total integer,
225 | total_discount_amounts jsonb,
226 | total_excluding_tax integer,
227 | total_tax_amounts jsonb,
228 | transfer_data jsonb,
229 | webhooks_delivered_at integer
230 | );
231 |
232 | create type stripe.charges_status as enum (
233 | 'succeeded',
234 | 'pending',
235 | 'failed'
236 | );
237 |
238 | create table if not exists stripe.charges
239 | (
240 | id text primary key,
241 | object text,
242 | amount integer,
243 | amount_captured integer,
244 | amount_refunded integer,
245 | application text,
246 | application_fee text,
247 | application_fee_amount integer,
248 | balance_transaction text,
249 | billing_details jsonb,
250 | calculated_statement_descriptor text,
251 | captured boolean,
252 | created integer,
253 | currency text,
254 | customer text,
255 | description text,
256 | disputed boolean,
257 | failure_balance_transaction text,
258 | failure_code text,
259 | failure_message text,
260 | fraud_details jsonb,
261 | invoice text,
262 | livemode boolean,
263 | metadata jsonb,
264 | on_behalf_of text,
265 | outcome jsonb,
266 | paid boolean,
267 | payment_intent text,
268 | payment_method text,
269 | payment_method_details jsonb,
270 | receipt_email text,
271 | receipt_number text,
272 | receipt_url text,
273 | refunded boolean,
274 | refunds jsonb,
275 | review text,
276 | shipping jsonb,
277 | source_transfer text,
278 | statement_descriptor text,
279 | statement_descriptor_suffix text,
280 | status stripe.charges_status,
281 | transfer_data jsonb,
282 | transfer_group text
283 | );
284 |
285 | create type stripe.coupons_duration as enum (
286 | 'forever',
287 | 'once',
288 | 'repeating'
289 | );
290 |
291 | create table if not exists stripe.coupons
292 | (
293 | id text primary key,
294 | object text,
295 | amount_off integer,
296 | created integer,
297 | currency text,
298 | duration stripe.coupons_duration,
299 | duration_in_months integer,
300 | livemode boolean,
301 | max_redemptions integer,
302 | metadata jsonb,
303 | name text,
304 | percent_off double precision,
305 | redeem_by integer,
306 | times_redeemed integer,
307 | valid boolean
308 | );
309 |
310 | create type stripe.disputes_status as enum (
311 | 'warning_needs_response',
312 | 'warning_under_review',
313 | 'warning_closed',
314 | 'needs_response',
315 | 'under_review',
316 | 'charge_refunded',
317 | 'won',
318 | 'lost'
319 | );
320 |
321 | create table if not exists stripe.disputes
322 | (
323 | id text primary key,
324 | object text,
325 | amount integer,
326 | balance_transactions jsonb,
327 | created integer,
328 | currency text,
329 | evidence jsonb,
330 | status stripe.disputes_status,
331 | transaction text
332 | );
333 |
334 | create type stripe.plans_interval as enum (
335 | 'day',
336 | 'week',
337 | 'month',
338 | 'year'
339 | );
340 |
341 | create table if not exists stripe.plans
342 | (
343 | id text primary key,
344 | object text,
345 | active boolean,
346 | aggregate_usage text,
347 | amount integer,
348 | amount_decimal text,
349 | billing_scheme text,
350 | created integer,
351 | currency text,
352 | interval stripe.plans_interval,
353 | interval_count integer,
354 | livemode boolean,
355 | metadata jsonb,
356 | nickname text,
357 | product text,
358 | tiers jsonb,
359 | tiers_mode text,
360 | transform_usage text,
361 | trial_period_days integer,
362 | usage_type text
363 | );
364 |
--------------------------------------------------------------------------------
/migrations/0001_add_updated_at.sql:
--------------------------------------------------------------------------------
1 | create or replace function stripe.set_updated_at() returns trigger
2 | language plpgsql
3 | as
4 | $$
5 | begin
6 | new.updated_at = now();
7 | return new;
8 | end;
9 | $$;
10 |
11 | alter function stripe.set_updated_at() owner to postgres;
12 |
13 | alter table stripe.subscriptions
14 | add updated_at timestamptz default timezone('utc'::text, now()) not null;
15 |
16 | create trigger handle_updated_at
17 | before update
18 | on stripe.subscriptions
19 | for each row
20 | execute procedure stripe.set_updated_at();
21 |
22 | alter table stripe.products
23 | add updated_at timestamptz default timezone('utc'::text, now()) not null;
24 |
25 | create trigger handle_updated_at
26 | before update
27 | on stripe.products
28 | for each row
29 | execute procedure stripe.set_updated_at();
30 |
31 | alter table stripe.customers
32 | add updated_at timestamptz default timezone('utc'::text, now()) not null;
33 |
34 | create trigger handle_updated_at
35 | before update
36 | on stripe.customers
37 | for each row
38 | execute procedure stripe.set_updated_at();
39 |
40 | alter table stripe.prices
41 | add updated_at timestamptz default timezone('utc'::text, now()) not null;
42 |
43 | create trigger handle_updated_at
44 | before update
45 | on stripe.prices
46 | for each row
47 | execute procedure stripe.set_updated_at();
48 |
49 | alter table stripe.invoices
50 | add updated_at timestamptz default timezone('utc'::text, now()) not null;
51 |
52 | create trigger handle_updated_at
53 | before update
54 | on stripe.invoices
55 | for each row
56 | execute procedure stripe.set_updated_at();
57 |
58 | alter table stripe.charges
59 | add updated_at timestamptz default timezone('utc'::text, now()) not null;
60 |
61 | create trigger handle_updated_at
62 | before update
63 | on stripe.charges
64 | for each row
65 | execute procedure stripe.set_updated_at();
66 |
67 | alter table stripe.coupons
68 | add updated_at timestamptz default timezone('utc'::text, now()) not null;
69 |
70 | create trigger handle_updated_at
71 | before update
72 | on stripe.coupons
73 | for each row
74 | execute procedure stripe.set_updated_at();
75 |
76 | alter table stripe.disputes
77 | add updated_at timestamptz default timezone('utc'::text, now()) not null;
78 |
79 | create trigger handle_updated_at
80 | before update
81 | on stripe.disputes
82 | for each row
83 | execute procedure stripe.set_updated_at();
84 |
85 | alter table stripe.events
86 | add updated_at timestamptz default timezone('utc'::text, now()) not null;
87 |
88 | create trigger handle_updated_at
89 | before update
90 | on stripe.events
91 | for each row
92 | execute procedure stripe.set_updated_at();
93 |
94 | alter table stripe.plans
95 | add updated_at timestamptz default timezone('utc'::text, now()) not null;
96 |
97 | create trigger handle_updated_at
98 | before update
99 | on stripe.plans
100 | for each row
101 | execute procedure stripe.set_updated_at();
102 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "stripe_to_postgres",
3 | "version": "0.2.0",
4 | "lockfileVersion": 2,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "stripe_to_postgres",
9 | "version": "0.2.0",
10 | "dependencies": {
11 | "@whollacsek/pg-node-migrations": "^0.0.8",
12 | "dotenv": "^16.0.3",
13 | "lodash.chunk": "^4.2.0",
14 | "micro": "9.4.0",
15 | "pg": "^8.8.0",
16 | "stripe": "^10.12.0"
17 | },
18 | "devDependencies": {
19 | "@types/lodash.chunk": "^4.2.7",
20 | "@types/node": "^18.8.0",
21 | "@types/pg": "^8.6.5",
22 | "@types/yesql": "^4.1.1",
23 | "prettier": "^2.7.1",
24 | "ts-node-dev": "^2.0.0",
25 | "typescript": "^4.8.4"
26 | }
27 | },
28 | "@whollacsek/pg-node-migrations@0.0.8": {
29 | "extraneous": true
30 | },
31 | "node_modules/@cspotcode/source-map-support": {
32 | "version": "0.8.1",
33 | "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
34 | "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
35 | "dev": true,
36 | "dependencies": {
37 | "@jridgewell/trace-mapping": "0.3.9"
38 | },
39 | "engines": {
40 | "node": ">=12"
41 | }
42 | },
43 | "node_modules/@jridgewell/resolve-uri": {
44 | "version": "3.1.0",
45 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
46 | "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
47 | "dev": true,
48 | "engines": {
49 | "node": ">=6.0.0"
50 | }
51 | },
52 | "node_modules/@jridgewell/sourcemap-codec": {
53 | "version": "1.4.14",
54 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
55 | "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
56 | "dev": true
57 | },
58 | "node_modules/@jridgewell/trace-mapping": {
59 | "version": "0.3.9",
60 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
61 | "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
62 | "dev": true,
63 | "dependencies": {
64 | "@jridgewell/resolve-uri": "^3.0.3",
65 | "@jridgewell/sourcemap-codec": "^1.4.10"
66 | }
67 | },
68 | "node_modules/@tsconfig/node10": {
69 | "version": "1.0.9",
70 | "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
71 | "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==",
72 | "dev": true
73 | },
74 | "node_modules/@tsconfig/node12": {
75 | "version": "1.0.11",
76 | "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
77 | "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
78 | "dev": true
79 | },
80 | "node_modules/@tsconfig/node14": {
81 | "version": "1.0.3",
82 | "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
83 | "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
84 | "dev": true
85 | },
86 | "node_modules/@tsconfig/node16": {
87 | "version": "1.0.3",
88 | "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz",
89 | "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==",
90 | "dev": true
91 | },
92 | "node_modules/@types/lodash": {
93 | "version": "4.14.186",
94 | "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.186.tgz",
95 | "integrity": "sha512-eHcVlLXP0c2FlMPm56ITode2AgLMSa6aJ05JTTbYbI+7EMkCEE5qk2E41d5g2lCVTqRe0GnnRFurmlCsDODrPw==",
96 | "dev": true
97 | },
98 | "node_modules/@types/lodash.chunk": {
99 | "version": "4.2.7",
100 | "resolved": "https://registry.npmjs.org/@types/lodash.chunk/-/lodash.chunk-4.2.7.tgz",
101 | "integrity": "sha512-//tmaWHiANgToom/YYYKKqiCtlNz11fwYtMUUbaemNSbWTI+2zHtYW5nt1PHNCRWHPAJHHhn4UVFD9LKUFvatA==",
102 | "dev": true,
103 | "dependencies": {
104 | "@types/lodash": "*"
105 | }
106 | },
107 | "node_modules/@types/node": {
108 | "version": "18.8.0",
109 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.8.0.tgz",
110 | "integrity": "sha512-u+h43R6U8xXDt2vzUaVP3VwjjLyOJk6uEciZS8OSyziUQGOwmk+l+4drxcsDboHXwyTaqS1INebghmWMRxq3LA=="
111 | },
112 | "node_modules/@types/pg": {
113 | "version": "8.6.5",
114 | "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.5.tgz",
115 | "integrity": "sha512-tOkGtAqRVkHa/PVZicq67zuujI4Oorfglsr2IbKofDwBSysnaqSx7W1mDqFqdkGE6Fbgh+PZAl0r/BWON/mozw==",
116 | "dev": true,
117 | "dependencies": {
118 | "@types/node": "*",
119 | "pg-protocol": "*",
120 | "pg-types": "^2.2.0"
121 | }
122 | },
123 | "node_modules/@types/strip-bom": {
124 | "version": "3.0.0",
125 | "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz",
126 | "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==",
127 | "dev": true
128 | },
129 | "node_modules/@types/strip-json-comments": {
130 | "version": "0.0.30",
131 | "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz",
132 | "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==",
133 | "dev": true
134 | },
135 | "node_modules/@types/yesql": {
136 | "version": "4.1.1",
137 | "resolved": "https://registry.npmjs.org/@types/yesql/-/yesql-4.1.1.tgz",
138 | "integrity": "sha512-aLTGG0R/wNCBAzvMNk7pGLFcamZeJMBiKqrObK8BukmcpDEtyvfpR/Hzpta5L9VEtyWgF5w5VIW8HiOUfwhSKw==",
139 | "dev": true
140 | },
141 | "node_modules/@whollacsek/pg-node-migrations": {
142 | "version": "0.0.8",
143 | "resolved": "https://registry.npmjs.org/@whollacsek/pg-node-migrations/-/pg-node-migrations-0.0.8.tgz",
144 | "integrity": "sha512-1T6a1+N54zWeKJr95/QzNCs35j/d349aW4YCYApd1rcGQirQRfSDlnLQ8Ws6ijba8CRYWkbujP2Yhf+upI6G2A==",
145 | "dependencies": {
146 | "pg": "^8.6.0",
147 | "sql-template-strings": "^2.2.2"
148 | },
149 | "bin": {
150 | "pg-validate-migrations": "dist/bin/validate.js"
151 | },
152 | "engines": {
153 | "node": ">10.17.0"
154 | }
155 | },
156 | "node_modules/acorn": {
157 | "version": "8.8.0",
158 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
159 | "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==",
160 | "dev": true,
161 | "bin": {
162 | "acorn": "bin/acorn"
163 | },
164 | "engines": {
165 | "node": ">=0.4.0"
166 | }
167 | },
168 | "node_modules/acorn-walk": {
169 | "version": "8.2.0",
170 | "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
171 | "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
172 | "dev": true,
173 | "engines": {
174 | "node": ">=0.4.0"
175 | }
176 | },
177 | "node_modules/anymatch": {
178 | "version": "3.1.2",
179 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
180 | "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
181 | "dev": true,
182 | "dependencies": {
183 | "normalize-path": "^3.0.0",
184 | "picomatch": "^2.0.4"
185 | },
186 | "engines": {
187 | "node": ">= 8"
188 | }
189 | },
190 | "node_modules/arg": {
191 | "version": "4.1.3",
192 | "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
193 | "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
194 | "dev": true
195 | },
196 | "node_modules/balanced-match": {
197 | "version": "1.0.2",
198 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
199 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
200 | "dev": true
201 | },
202 | "node_modules/binary-extensions": {
203 | "version": "2.2.0",
204 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
205 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
206 | "dev": true,
207 | "engines": {
208 | "node": ">=8"
209 | }
210 | },
211 | "node_modules/brace-expansion": {
212 | "version": "1.1.11",
213 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
214 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
215 | "dev": true,
216 | "dependencies": {
217 | "balanced-match": "^1.0.0",
218 | "concat-map": "0.0.1"
219 | }
220 | },
221 | "node_modules/braces": {
222 | "version": "3.0.2",
223 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
224 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
225 | "dev": true,
226 | "dependencies": {
227 | "fill-range": "^7.0.1"
228 | },
229 | "engines": {
230 | "node": ">=8"
231 | }
232 | },
233 | "node_modules/buffer-from": {
234 | "version": "1.1.2",
235 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
236 | "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
237 | "dev": true
238 | },
239 | "node_modules/buffer-writer": {
240 | "version": "2.0.0",
241 | "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz",
242 | "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==",
243 | "engines": {
244 | "node": ">=4"
245 | }
246 | },
247 | "node_modules/bytes": {
248 | "version": "3.1.0",
249 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
250 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
251 | "engines": {
252 | "node": ">= 0.8"
253 | }
254 | },
255 | "node_modules/call-bind": {
256 | "version": "1.0.2",
257 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
258 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
259 | "dependencies": {
260 | "function-bind": "^1.1.1",
261 | "get-intrinsic": "^1.0.2"
262 | },
263 | "funding": {
264 | "url": "https://github.com/sponsors/ljharb"
265 | }
266 | },
267 | "node_modules/chokidar": {
268 | "version": "3.5.3",
269 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
270 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
271 | "dev": true,
272 | "funding": [
273 | {
274 | "type": "individual",
275 | "url": "https://paulmillr.com/funding/"
276 | }
277 | ],
278 | "dependencies": {
279 | "anymatch": "~3.1.2",
280 | "braces": "~3.0.2",
281 | "glob-parent": "~5.1.2",
282 | "is-binary-path": "~2.1.0",
283 | "is-glob": "~4.0.1",
284 | "normalize-path": "~3.0.0",
285 | "readdirp": "~3.6.0"
286 | },
287 | "engines": {
288 | "node": ">= 8.10.0"
289 | },
290 | "optionalDependencies": {
291 | "fsevents": "~2.3.2"
292 | }
293 | },
294 | "node_modules/concat-map": {
295 | "version": "0.0.1",
296 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
297 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
298 | "dev": true
299 | },
300 | "node_modules/content-type": {
301 | "version": "1.0.4",
302 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
303 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
304 | "engines": {
305 | "node": ">= 0.6"
306 | }
307 | },
308 | "node_modules/create-require": {
309 | "version": "1.1.1",
310 | "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
311 | "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
312 | "dev": true
313 | },
314 | "node_modules/depd": {
315 | "version": "1.1.2",
316 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
317 | "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
318 | "engines": {
319 | "node": ">= 0.6"
320 | }
321 | },
322 | "node_modules/diff": {
323 | "version": "4.0.2",
324 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
325 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
326 | "dev": true,
327 | "engines": {
328 | "node": ">=0.3.1"
329 | }
330 | },
331 | "node_modules/dotenv": {
332 | "version": "16.0.3",
333 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz",
334 | "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==",
335 | "engines": {
336 | "node": ">=12"
337 | }
338 | },
339 | "node_modules/dynamic-dedupe": {
340 | "version": "0.3.0",
341 | "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz",
342 | "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==",
343 | "dev": true,
344 | "dependencies": {
345 | "xtend": "^4.0.0"
346 | }
347 | },
348 | "node_modules/fill-range": {
349 | "version": "7.0.1",
350 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
351 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
352 | "dev": true,
353 | "dependencies": {
354 | "to-regex-range": "^5.0.1"
355 | },
356 | "engines": {
357 | "node": ">=8"
358 | }
359 | },
360 | "node_modules/fs.realpath": {
361 | "version": "1.0.0",
362 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
363 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
364 | "dev": true
365 | },
366 | "node_modules/fsevents": {
367 | "version": "2.3.2",
368 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
369 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
370 | "dev": true,
371 | "hasInstallScript": true,
372 | "optional": true,
373 | "os": [
374 | "darwin"
375 | ],
376 | "engines": {
377 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
378 | }
379 | },
380 | "node_modules/function-bind": {
381 | "version": "1.1.1",
382 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
383 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
384 | },
385 | "node_modules/get-intrinsic": {
386 | "version": "1.1.3",
387 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
388 | "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==",
389 | "dependencies": {
390 | "function-bind": "^1.1.1",
391 | "has": "^1.0.3",
392 | "has-symbols": "^1.0.3"
393 | },
394 | "funding": {
395 | "url": "https://github.com/sponsors/ljharb"
396 | }
397 | },
398 | "node_modules/glob": {
399 | "version": "7.2.3",
400 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
401 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
402 | "dev": true,
403 | "dependencies": {
404 | "fs.realpath": "^1.0.0",
405 | "inflight": "^1.0.4",
406 | "inherits": "2",
407 | "minimatch": "^3.1.1",
408 | "once": "^1.3.0",
409 | "path-is-absolute": "^1.0.0"
410 | },
411 | "engines": {
412 | "node": "*"
413 | },
414 | "funding": {
415 | "url": "https://github.com/sponsors/isaacs"
416 | }
417 | },
418 | "node_modules/glob-parent": {
419 | "version": "5.1.2",
420 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
421 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
422 | "dev": true,
423 | "dependencies": {
424 | "is-glob": "^4.0.1"
425 | },
426 | "engines": {
427 | "node": ">= 6"
428 | }
429 | },
430 | "node_modules/has": {
431 | "version": "1.0.3",
432 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
433 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
434 | "dependencies": {
435 | "function-bind": "^1.1.1"
436 | },
437 | "engines": {
438 | "node": ">= 0.4.0"
439 | }
440 | },
441 | "node_modules/has-symbols": {
442 | "version": "1.0.3",
443 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
444 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
445 | "engines": {
446 | "node": ">= 0.4"
447 | },
448 | "funding": {
449 | "url": "https://github.com/sponsors/ljharb"
450 | }
451 | },
452 | "node_modules/http-errors": {
453 | "version": "1.7.3",
454 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz",
455 | "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==",
456 | "dependencies": {
457 | "depd": "~1.1.2",
458 | "inherits": "2.0.4",
459 | "setprototypeof": "1.1.1",
460 | "statuses": ">= 1.5.0 < 2",
461 | "toidentifier": "1.0.0"
462 | },
463 | "engines": {
464 | "node": ">= 0.6"
465 | }
466 | },
467 | "node_modules/iconv-lite": {
468 | "version": "0.4.24",
469 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
470 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
471 | "dependencies": {
472 | "safer-buffer": ">= 2.1.2 < 3"
473 | },
474 | "engines": {
475 | "node": ">=0.10.0"
476 | }
477 | },
478 | "node_modules/inflight": {
479 | "version": "1.0.6",
480 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
481 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
482 | "dev": true,
483 | "dependencies": {
484 | "once": "^1.3.0",
485 | "wrappy": "1"
486 | }
487 | },
488 | "node_modules/inherits": {
489 | "version": "2.0.4",
490 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
491 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
492 | },
493 | "node_modules/is-binary-path": {
494 | "version": "2.1.0",
495 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
496 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
497 | "dev": true,
498 | "dependencies": {
499 | "binary-extensions": "^2.0.0"
500 | },
501 | "engines": {
502 | "node": ">=8"
503 | }
504 | },
505 | "node_modules/is-core-module": {
506 | "version": "2.10.0",
507 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz",
508 | "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==",
509 | "dev": true,
510 | "dependencies": {
511 | "has": "^1.0.3"
512 | },
513 | "funding": {
514 | "url": "https://github.com/sponsors/ljharb"
515 | }
516 | },
517 | "node_modules/is-extglob": {
518 | "version": "2.1.1",
519 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
520 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
521 | "dev": true,
522 | "engines": {
523 | "node": ">=0.10.0"
524 | }
525 | },
526 | "node_modules/is-glob": {
527 | "version": "4.0.3",
528 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
529 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
530 | "dev": true,
531 | "dependencies": {
532 | "is-extglob": "^2.1.1"
533 | },
534 | "engines": {
535 | "node": ">=0.10.0"
536 | }
537 | },
538 | "node_modules/is-number": {
539 | "version": "7.0.0",
540 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
541 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
542 | "dev": true,
543 | "engines": {
544 | "node": ">=0.12.0"
545 | }
546 | },
547 | "node_modules/lodash.chunk": {
548 | "version": "4.2.0",
549 | "resolved": "https://registry.npmjs.org/lodash.chunk/-/lodash.chunk-4.2.0.tgz",
550 | "integrity": "sha512-ZzydJKfUHJwHa+hF5X66zLFCBrWn5GeF28OHEr4WVWtNDXlQ/IjWKPBiikqKo2ne0+v6JgCgJ0GzJp8k8bHC7w=="
551 | },
552 | "node_modules/make-error": {
553 | "version": "1.3.6",
554 | "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
555 | "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
556 | "dev": true
557 | },
558 | "node_modules/micro": {
559 | "version": "9.4.0",
560 | "resolved": "https://registry.npmjs.org/micro/-/micro-9.4.0.tgz",
561 | "integrity": "sha512-F3uh5Ob+0896E1skflRvcY6Cpq6/sA0RB7exMl/IhQ2wbwL79aF+mDAyjDcKNhXKkJVEXhKZrPqOEFLXkJW9og==",
562 | "dependencies": {
563 | "arg": "4.1.0",
564 | "content-type": "1.0.4",
565 | "raw-body": "2.4.1"
566 | },
567 | "bin": {
568 | "micro": "bin/micro.js"
569 | },
570 | "engines": {
571 | "node": ">= 8.0.0"
572 | }
573 | },
574 | "node_modules/micro/node_modules/arg": {
575 | "version": "4.1.0",
576 | "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz",
577 | "integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg=="
578 | },
579 | "node_modules/minimatch": {
580 | "version": "3.1.2",
581 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
582 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
583 | "dev": true,
584 | "dependencies": {
585 | "brace-expansion": "^1.1.7"
586 | },
587 | "engines": {
588 | "node": "*"
589 | }
590 | },
591 | "node_modules/minimist": {
592 | "version": "1.2.6",
593 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
594 | "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
595 | "dev": true
596 | },
597 | "node_modules/mkdirp": {
598 | "version": "1.0.4",
599 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
600 | "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
601 | "dev": true,
602 | "bin": {
603 | "mkdirp": "bin/cmd.js"
604 | },
605 | "engines": {
606 | "node": ">=10"
607 | }
608 | },
609 | "node_modules/normalize-path": {
610 | "version": "3.0.0",
611 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
612 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
613 | "dev": true,
614 | "engines": {
615 | "node": ">=0.10.0"
616 | }
617 | },
618 | "node_modules/object-inspect": {
619 | "version": "1.12.2",
620 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
621 | "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==",
622 | "funding": {
623 | "url": "https://github.com/sponsors/ljharb"
624 | }
625 | },
626 | "node_modules/once": {
627 | "version": "1.4.0",
628 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
629 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
630 | "dev": true,
631 | "dependencies": {
632 | "wrappy": "1"
633 | }
634 | },
635 | "node_modules/packet-reader": {
636 | "version": "1.0.0",
637 | "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz",
638 | "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ=="
639 | },
640 | "node_modules/path-is-absolute": {
641 | "version": "1.0.1",
642 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
643 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
644 | "dev": true,
645 | "engines": {
646 | "node": ">=0.10.0"
647 | }
648 | },
649 | "node_modules/path-parse": {
650 | "version": "1.0.7",
651 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
652 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
653 | "dev": true
654 | },
655 | "node_modules/pg": {
656 | "version": "8.8.0",
657 | "resolved": "https://registry.npmjs.org/pg/-/pg-8.8.0.tgz",
658 | "integrity": "sha512-UXYN0ziKj+AeNNP7VDMwrehpACThH7LUl/p8TDFpEUuSejCUIwGSfxpHsPvtM6/WXFy6SU4E5RG4IJV/TZAGjw==",
659 | "dependencies": {
660 | "buffer-writer": "2.0.0",
661 | "packet-reader": "1.0.0",
662 | "pg-connection-string": "^2.5.0",
663 | "pg-pool": "^3.5.2",
664 | "pg-protocol": "^1.5.0",
665 | "pg-types": "^2.1.0",
666 | "pgpass": "1.x"
667 | },
668 | "engines": {
669 | "node": ">= 8.0.0"
670 | },
671 | "peerDependencies": {
672 | "pg-native": ">=3.0.1"
673 | },
674 | "peerDependenciesMeta": {
675 | "pg-native": {
676 | "optional": true
677 | }
678 | }
679 | },
680 | "node_modules/pg-connection-string": {
681 | "version": "2.5.0",
682 | "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz",
683 | "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ=="
684 | },
685 | "node_modules/pg-int8": {
686 | "version": "1.0.1",
687 | "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
688 | "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
689 | "engines": {
690 | "node": ">=4.0.0"
691 | }
692 | },
693 | "node_modules/pg-pool": {
694 | "version": "3.5.2",
695 | "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.5.2.tgz",
696 | "integrity": "sha512-His3Fh17Z4eg7oANLob6ZvH8xIVen3phEZh2QuyrIl4dQSDVEabNducv6ysROKpDNPSD+12tONZVWfSgMvDD9w==",
697 | "peerDependencies": {
698 | "pg": ">=8.0"
699 | }
700 | },
701 | "node_modules/pg-protocol": {
702 | "version": "1.5.0",
703 | "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz",
704 | "integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ=="
705 | },
706 | "node_modules/pg-types": {
707 | "version": "2.2.0",
708 | "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
709 | "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
710 | "dependencies": {
711 | "pg-int8": "1.0.1",
712 | "postgres-array": "~2.0.0",
713 | "postgres-bytea": "~1.0.0",
714 | "postgres-date": "~1.0.4",
715 | "postgres-interval": "^1.1.0"
716 | },
717 | "engines": {
718 | "node": ">=4"
719 | }
720 | },
721 | "node_modules/pgpass": {
722 | "version": "1.0.5",
723 | "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz",
724 | "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==",
725 | "dependencies": {
726 | "split2": "^4.1.0"
727 | }
728 | },
729 | "node_modules/picomatch": {
730 | "version": "2.3.1",
731 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
732 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
733 | "dev": true,
734 | "engines": {
735 | "node": ">=8.6"
736 | },
737 | "funding": {
738 | "url": "https://github.com/sponsors/jonschlinkert"
739 | }
740 | },
741 | "node_modules/postgres-array": {
742 | "version": "2.0.0",
743 | "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
744 | "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
745 | "engines": {
746 | "node": ">=4"
747 | }
748 | },
749 | "node_modules/postgres-bytea": {
750 | "version": "1.0.0",
751 | "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
752 | "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==",
753 | "engines": {
754 | "node": ">=0.10.0"
755 | }
756 | },
757 | "node_modules/postgres-date": {
758 | "version": "1.0.7",
759 | "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
760 | "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
761 | "engines": {
762 | "node": ">=0.10.0"
763 | }
764 | },
765 | "node_modules/postgres-interval": {
766 | "version": "1.2.0",
767 | "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
768 | "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
769 | "dependencies": {
770 | "xtend": "^4.0.0"
771 | },
772 | "engines": {
773 | "node": ">=0.10.0"
774 | }
775 | },
776 | "node_modules/prettier": {
777 | "version": "2.7.1",
778 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
779 | "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
780 | "dev": true,
781 | "bin": {
782 | "prettier": "bin-prettier.js"
783 | },
784 | "engines": {
785 | "node": ">=10.13.0"
786 | },
787 | "funding": {
788 | "url": "https://github.com/prettier/prettier?sponsor=1"
789 | }
790 | },
791 | "node_modules/qs": {
792 | "version": "6.11.0",
793 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
794 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
795 | "dependencies": {
796 | "side-channel": "^1.0.4"
797 | },
798 | "engines": {
799 | "node": ">=0.6"
800 | },
801 | "funding": {
802 | "url": "https://github.com/sponsors/ljharb"
803 | }
804 | },
805 | "node_modules/raw-body": {
806 | "version": "2.4.1",
807 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz",
808 | "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==",
809 | "dependencies": {
810 | "bytes": "3.1.0",
811 | "http-errors": "1.7.3",
812 | "iconv-lite": "0.4.24",
813 | "unpipe": "1.0.0"
814 | },
815 | "engines": {
816 | "node": ">= 0.8"
817 | }
818 | },
819 | "node_modules/readdirp": {
820 | "version": "3.6.0",
821 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
822 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
823 | "dev": true,
824 | "dependencies": {
825 | "picomatch": "^2.2.1"
826 | },
827 | "engines": {
828 | "node": ">=8.10.0"
829 | }
830 | },
831 | "node_modules/resolve": {
832 | "version": "1.22.1",
833 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
834 | "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
835 | "dev": true,
836 | "dependencies": {
837 | "is-core-module": "^2.9.0",
838 | "path-parse": "^1.0.7",
839 | "supports-preserve-symlinks-flag": "^1.0.0"
840 | },
841 | "bin": {
842 | "resolve": "bin/resolve"
843 | },
844 | "funding": {
845 | "url": "https://github.com/sponsors/ljharb"
846 | }
847 | },
848 | "node_modules/rimraf": {
849 | "version": "2.7.1",
850 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
851 | "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
852 | "dev": true,
853 | "dependencies": {
854 | "glob": "^7.1.3"
855 | },
856 | "bin": {
857 | "rimraf": "bin.js"
858 | }
859 | },
860 | "node_modules/safer-buffer": {
861 | "version": "2.1.2",
862 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
863 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
864 | },
865 | "node_modules/setprototypeof": {
866 | "version": "1.1.1",
867 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
868 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
869 | },
870 | "node_modules/side-channel": {
871 | "version": "1.0.4",
872 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
873 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
874 | "dependencies": {
875 | "call-bind": "^1.0.0",
876 | "get-intrinsic": "^1.0.2",
877 | "object-inspect": "^1.9.0"
878 | },
879 | "funding": {
880 | "url": "https://github.com/sponsors/ljharb"
881 | }
882 | },
883 | "node_modules/source-map": {
884 | "version": "0.6.1",
885 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
886 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
887 | "dev": true,
888 | "engines": {
889 | "node": ">=0.10.0"
890 | }
891 | },
892 | "node_modules/source-map-support": {
893 | "version": "0.5.21",
894 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
895 | "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
896 | "dev": true,
897 | "dependencies": {
898 | "buffer-from": "^1.0.0",
899 | "source-map": "^0.6.0"
900 | }
901 | },
902 | "node_modules/split2": {
903 | "version": "4.1.0",
904 | "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz",
905 | "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==",
906 | "engines": {
907 | "node": ">= 10.x"
908 | }
909 | },
910 | "node_modules/sql-template-strings": {
911 | "version": "2.2.2",
912 | "resolved": "https://registry.npmjs.org/sql-template-strings/-/sql-template-strings-2.2.2.tgz",
913 | "integrity": "sha512-UXhXR2869FQaD+GMly8jAMCRZ94nU5KcrFetZfWEMd+LVVG6y0ExgHAhatEcKZ/wk8YcKPdi+hiD2wm75lq3/Q==",
914 | "engines": {
915 | "node": ">=4.0.0"
916 | }
917 | },
918 | "node_modules/statuses": {
919 | "version": "1.5.0",
920 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
921 | "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
922 | "engines": {
923 | "node": ">= 0.6"
924 | }
925 | },
926 | "node_modules/strip-bom": {
927 | "version": "3.0.0",
928 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
929 | "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
930 | "dev": true,
931 | "engines": {
932 | "node": ">=4"
933 | }
934 | },
935 | "node_modules/strip-json-comments": {
936 | "version": "2.0.1",
937 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
938 | "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
939 | "dev": true,
940 | "engines": {
941 | "node": ">=0.10.0"
942 | }
943 | },
944 | "node_modules/stripe": {
945 | "version": "10.12.0",
946 | "resolved": "https://registry.npmjs.org/stripe/-/stripe-10.12.0.tgz",
947 | "integrity": "sha512-4ijMsbTVSy6rzWIkal+/dFGeTXtjqLeZ/oo/jc2jhICbf3Dby0CBTPxAg6ZhBPXQL96TJxI613C/NhhE7LvrWw==",
948 | "dependencies": {
949 | "@types/node": ">=8.1.0",
950 | "qs": "^6.10.3"
951 | },
952 | "engines": {
953 | "node": "^8.1 || >=10.*"
954 | }
955 | },
956 | "node_modules/supports-preserve-symlinks-flag": {
957 | "version": "1.0.0",
958 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
959 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
960 | "dev": true,
961 | "engines": {
962 | "node": ">= 0.4"
963 | },
964 | "funding": {
965 | "url": "https://github.com/sponsors/ljharb"
966 | }
967 | },
968 | "node_modules/to-regex-range": {
969 | "version": "5.0.1",
970 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
971 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
972 | "dev": true,
973 | "dependencies": {
974 | "is-number": "^7.0.0"
975 | },
976 | "engines": {
977 | "node": ">=8.0"
978 | }
979 | },
980 | "node_modules/toidentifier": {
981 | "version": "1.0.0",
982 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
983 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
984 | "engines": {
985 | "node": ">=0.6"
986 | }
987 | },
988 | "node_modules/tree-kill": {
989 | "version": "1.2.2",
990 | "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
991 | "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
992 | "dev": true,
993 | "bin": {
994 | "tree-kill": "cli.js"
995 | }
996 | },
997 | "node_modules/ts-node": {
998 | "version": "10.9.1",
999 | "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
1000 | "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==",
1001 | "dev": true,
1002 | "dependencies": {
1003 | "@cspotcode/source-map-support": "^0.8.0",
1004 | "@tsconfig/node10": "^1.0.7",
1005 | "@tsconfig/node12": "^1.0.7",
1006 | "@tsconfig/node14": "^1.0.0",
1007 | "@tsconfig/node16": "^1.0.2",
1008 | "acorn": "^8.4.1",
1009 | "acorn-walk": "^8.1.1",
1010 | "arg": "^4.1.0",
1011 | "create-require": "^1.1.0",
1012 | "diff": "^4.0.1",
1013 | "make-error": "^1.1.1",
1014 | "v8-compile-cache-lib": "^3.0.1",
1015 | "yn": "3.1.1"
1016 | },
1017 | "bin": {
1018 | "ts-node": "dist/bin.js",
1019 | "ts-node-cwd": "dist/bin-cwd.js",
1020 | "ts-node-esm": "dist/bin-esm.js",
1021 | "ts-node-script": "dist/bin-script.js",
1022 | "ts-node-transpile-only": "dist/bin-transpile.js",
1023 | "ts-script": "dist/bin-script-deprecated.js"
1024 | },
1025 | "peerDependencies": {
1026 | "@swc/core": ">=1.2.50",
1027 | "@swc/wasm": ">=1.2.50",
1028 | "@types/node": "*",
1029 | "typescript": ">=2.7"
1030 | },
1031 | "peerDependenciesMeta": {
1032 | "@swc/core": {
1033 | "optional": true
1034 | },
1035 | "@swc/wasm": {
1036 | "optional": true
1037 | }
1038 | }
1039 | },
1040 | "node_modules/ts-node-dev": {
1041 | "version": "2.0.0",
1042 | "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-2.0.0.tgz",
1043 | "integrity": "sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w==",
1044 | "dev": true,
1045 | "dependencies": {
1046 | "chokidar": "^3.5.1",
1047 | "dynamic-dedupe": "^0.3.0",
1048 | "minimist": "^1.2.6",
1049 | "mkdirp": "^1.0.4",
1050 | "resolve": "^1.0.0",
1051 | "rimraf": "^2.6.1",
1052 | "source-map-support": "^0.5.12",
1053 | "tree-kill": "^1.2.2",
1054 | "ts-node": "^10.4.0",
1055 | "tsconfig": "^7.0.0"
1056 | },
1057 | "bin": {
1058 | "ts-node-dev": "lib/bin.js",
1059 | "tsnd": "lib/bin.js"
1060 | },
1061 | "engines": {
1062 | "node": ">=0.8.0"
1063 | },
1064 | "peerDependencies": {
1065 | "node-notifier": "*",
1066 | "typescript": "*"
1067 | },
1068 | "peerDependenciesMeta": {
1069 | "node-notifier": {
1070 | "optional": true
1071 | }
1072 | }
1073 | },
1074 | "node_modules/tsconfig": {
1075 | "version": "7.0.0",
1076 | "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz",
1077 | "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==",
1078 | "dev": true,
1079 | "dependencies": {
1080 | "@types/strip-bom": "^3.0.0",
1081 | "@types/strip-json-comments": "0.0.30",
1082 | "strip-bom": "^3.0.0",
1083 | "strip-json-comments": "^2.0.0"
1084 | }
1085 | },
1086 | "node_modules/typescript": {
1087 | "version": "4.8.4",
1088 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
1089 | "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
1090 | "dev": true,
1091 | "bin": {
1092 | "tsc": "bin/tsc",
1093 | "tsserver": "bin/tsserver"
1094 | },
1095 | "engines": {
1096 | "node": ">=4.2.0"
1097 | }
1098 | },
1099 | "node_modules/unpipe": {
1100 | "version": "1.0.0",
1101 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
1102 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
1103 | "engines": {
1104 | "node": ">= 0.8"
1105 | }
1106 | },
1107 | "node_modules/v8-compile-cache-lib": {
1108 | "version": "3.0.1",
1109 | "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
1110 | "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
1111 | "dev": true
1112 | },
1113 | "node_modules/wrappy": {
1114 | "version": "1.0.2",
1115 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
1116 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
1117 | "dev": true
1118 | },
1119 | "node_modules/xtend": {
1120 | "version": "4.0.2",
1121 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
1122 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
1123 | "engines": {
1124 | "node": ">=0.4"
1125 | }
1126 | },
1127 | "node_modules/yn": {
1128 | "version": "3.1.1",
1129 | "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
1130 | "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
1131 | "dev": true,
1132 | "engines": {
1133 | "node": ">=6"
1134 | }
1135 | }
1136 | },
1137 | "dependencies": {
1138 | "@cspotcode/source-map-support": {
1139 | "version": "0.8.1",
1140 | "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
1141 | "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
1142 | "dev": true,
1143 | "requires": {
1144 | "@jridgewell/trace-mapping": "0.3.9"
1145 | }
1146 | },
1147 | "@jridgewell/resolve-uri": {
1148 | "version": "3.1.0",
1149 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
1150 | "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
1151 | "dev": true
1152 | },
1153 | "@jridgewell/sourcemap-codec": {
1154 | "version": "1.4.14",
1155 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
1156 | "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
1157 | "dev": true
1158 | },
1159 | "@jridgewell/trace-mapping": {
1160 | "version": "0.3.9",
1161 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
1162 | "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
1163 | "dev": true,
1164 | "requires": {
1165 | "@jridgewell/resolve-uri": "^3.0.3",
1166 | "@jridgewell/sourcemap-codec": "^1.4.10"
1167 | }
1168 | },
1169 | "@tsconfig/node10": {
1170 | "version": "1.0.9",
1171 | "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
1172 | "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==",
1173 | "dev": true
1174 | },
1175 | "@tsconfig/node12": {
1176 | "version": "1.0.11",
1177 | "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
1178 | "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
1179 | "dev": true
1180 | },
1181 | "@tsconfig/node14": {
1182 | "version": "1.0.3",
1183 | "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
1184 | "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
1185 | "dev": true
1186 | },
1187 | "@tsconfig/node16": {
1188 | "version": "1.0.3",
1189 | "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz",
1190 | "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==",
1191 | "dev": true
1192 | },
1193 | "@types/lodash": {
1194 | "version": "4.14.186",
1195 | "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.186.tgz",
1196 | "integrity": "sha512-eHcVlLXP0c2FlMPm56ITode2AgLMSa6aJ05JTTbYbI+7EMkCEE5qk2E41d5g2lCVTqRe0GnnRFurmlCsDODrPw==",
1197 | "dev": true
1198 | },
1199 | "@types/lodash.chunk": {
1200 | "version": "4.2.7",
1201 | "resolved": "https://registry.npmjs.org/@types/lodash.chunk/-/lodash.chunk-4.2.7.tgz",
1202 | "integrity": "sha512-//tmaWHiANgToom/YYYKKqiCtlNz11fwYtMUUbaemNSbWTI+2zHtYW5nt1PHNCRWHPAJHHhn4UVFD9LKUFvatA==",
1203 | "dev": true,
1204 | "requires": {
1205 | "@types/lodash": "*"
1206 | }
1207 | },
1208 | "@types/node": {
1209 | "version": "18.8.0",
1210 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.8.0.tgz",
1211 | "integrity": "sha512-u+h43R6U8xXDt2vzUaVP3VwjjLyOJk6uEciZS8OSyziUQGOwmk+l+4drxcsDboHXwyTaqS1INebghmWMRxq3LA=="
1212 | },
1213 | "@types/pg": {
1214 | "version": "8.6.5",
1215 | "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.5.tgz",
1216 | "integrity": "sha512-tOkGtAqRVkHa/PVZicq67zuujI4Oorfglsr2IbKofDwBSysnaqSx7W1mDqFqdkGE6Fbgh+PZAl0r/BWON/mozw==",
1217 | "dev": true,
1218 | "requires": {
1219 | "@types/node": "*",
1220 | "pg-protocol": "*",
1221 | "pg-types": "^2.2.0"
1222 | }
1223 | },
1224 | "@types/strip-bom": {
1225 | "version": "3.0.0",
1226 | "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz",
1227 | "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==",
1228 | "dev": true
1229 | },
1230 | "@types/strip-json-comments": {
1231 | "version": "0.0.30",
1232 | "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz",
1233 | "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==",
1234 | "dev": true
1235 | },
1236 | "@types/yesql": {
1237 | "version": "4.1.1",
1238 | "resolved": "https://registry.npmjs.org/@types/yesql/-/yesql-4.1.1.tgz",
1239 | "integrity": "sha512-aLTGG0R/wNCBAzvMNk7pGLFcamZeJMBiKqrObK8BukmcpDEtyvfpR/Hzpta5L9VEtyWgF5w5VIW8HiOUfwhSKw==",
1240 | "dev": true
1241 | },
1242 | "@whollacsek/pg-node-migrations": {
1243 | "version": "0.0.8",
1244 | "resolved": "https://registry.npmjs.org/@whollacsek/pg-node-migrations/-/pg-node-migrations-0.0.8.tgz",
1245 | "integrity": "sha512-1T6a1+N54zWeKJr95/QzNCs35j/d349aW4YCYApd1rcGQirQRfSDlnLQ8Ws6ijba8CRYWkbujP2Yhf+upI6G2A==",
1246 | "requires": {
1247 | "pg": "^8.6.0",
1248 | "sql-template-strings": "^2.2.2"
1249 | }
1250 | },
1251 | "acorn": {
1252 | "version": "8.8.0",
1253 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
1254 | "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==",
1255 | "dev": true
1256 | },
1257 | "acorn-walk": {
1258 | "version": "8.2.0",
1259 | "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
1260 | "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
1261 | "dev": true
1262 | },
1263 | "anymatch": {
1264 | "version": "3.1.2",
1265 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
1266 | "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
1267 | "dev": true,
1268 | "requires": {
1269 | "normalize-path": "^3.0.0",
1270 | "picomatch": "^2.0.4"
1271 | }
1272 | },
1273 | "arg": {
1274 | "version": "4.1.3",
1275 | "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
1276 | "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
1277 | "dev": true
1278 | },
1279 | "balanced-match": {
1280 | "version": "1.0.2",
1281 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
1282 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
1283 | "dev": true
1284 | },
1285 | "binary-extensions": {
1286 | "version": "2.2.0",
1287 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
1288 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
1289 | "dev": true
1290 | },
1291 | "brace-expansion": {
1292 | "version": "1.1.11",
1293 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
1294 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
1295 | "dev": true,
1296 | "requires": {
1297 | "balanced-match": "^1.0.0",
1298 | "concat-map": "0.0.1"
1299 | }
1300 | },
1301 | "braces": {
1302 | "version": "3.0.2",
1303 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
1304 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
1305 | "dev": true,
1306 | "requires": {
1307 | "fill-range": "^7.0.1"
1308 | }
1309 | },
1310 | "buffer-from": {
1311 | "version": "1.1.2",
1312 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
1313 | "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
1314 | "dev": true
1315 | },
1316 | "buffer-writer": {
1317 | "version": "2.0.0",
1318 | "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz",
1319 | "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw=="
1320 | },
1321 | "bytes": {
1322 | "version": "3.1.0",
1323 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
1324 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
1325 | },
1326 | "call-bind": {
1327 | "version": "1.0.2",
1328 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
1329 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
1330 | "requires": {
1331 | "function-bind": "^1.1.1",
1332 | "get-intrinsic": "^1.0.2"
1333 | }
1334 | },
1335 | "chokidar": {
1336 | "version": "3.5.3",
1337 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
1338 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
1339 | "dev": true,
1340 | "requires": {
1341 | "anymatch": "~3.1.2",
1342 | "braces": "~3.0.2",
1343 | "fsevents": "~2.3.2",
1344 | "glob-parent": "~5.1.2",
1345 | "is-binary-path": "~2.1.0",
1346 | "is-glob": "~4.0.1",
1347 | "normalize-path": "~3.0.0",
1348 | "readdirp": "~3.6.0"
1349 | }
1350 | },
1351 | "concat-map": {
1352 | "version": "0.0.1",
1353 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
1354 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
1355 | "dev": true
1356 | },
1357 | "content-type": {
1358 | "version": "1.0.4",
1359 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
1360 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
1361 | },
1362 | "create-require": {
1363 | "version": "1.1.1",
1364 | "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
1365 | "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
1366 | "dev": true
1367 | },
1368 | "depd": {
1369 | "version": "1.1.2",
1370 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
1371 | "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ=="
1372 | },
1373 | "diff": {
1374 | "version": "4.0.2",
1375 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
1376 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
1377 | "dev": true
1378 | },
1379 | "dotenv": {
1380 | "version": "16.0.3",
1381 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz",
1382 | "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ=="
1383 | },
1384 | "dynamic-dedupe": {
1385 | "version": "0.3.0",
1386 | "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz",
1387 | "integrity": "sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==",
1388 | "dev": true,
1389 | "requires": {
1390 | "xtend": "^4.0.0"
1391 | }
1392 | },
1393 | "fill-range": {
1394 | "version": "7.0.1",
1395 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
1396 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
1397 | "dev": true,
1398 | "requires": {
1399 | "to-regex-range": "^5.0.1"
1400 | }
1401 | },
1402 | "fs.realpath": {
1403 | "version": "1.0.0",
1404 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
1405 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
1406 | "dev": true
1407 | },
1408 | "fsevents": {
1409 | "version": "2.3.2",
1410 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
1411 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
1412 | "dev": true,
1413 | "optional": true
1414 | },
1415 | "function-bind": {
1416 | "version": "1.1.1",
1417 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
1418 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
1419 | },
1420 | "get-intrinsic": {
1421 | "version": "1.1.3",
1422 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
1423 | "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==",
1424 | "requires": {
1425 | "function-bind": "^1.1.1",
1426 | "has": "^1.0.3",
1427 | "has-symbols": "^1.0.3"
1428 | }
1429 | },
1430 | "glob": {
1431 | "version": "7.2.3",
1432 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
1433 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
1434 | "dev": true,
1435 | "requires": {
1436 | "fs.realpath": "^1.0.0",
1437 | "inflight": "^1.0.4",
1438 | "inherits": "2",
1439 | "minimatch": "^3.1.1",
1440 | "once": "^1.3.0",
1441 | "path-is-absolute": "^1.0.0"
1442 | }
1443 | },
1444 | "glob-parent": {
1445 | "version": "5.1.2",
1446 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
1447 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
1448 | "dev": true,
1449 | "requires": {
1450 | "is-glob": "^4.0.1"
1451 | }
1452 | },
1453 | "has": {
1454 | "version": "1.0.3",
1455 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
1456 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
1457 | "requires": {
1458 | "function-bind": "^1.1.1"
1459 | }
1460 | },
1461 | "has-symbols": {
1462 | "version": "1.0.3",
1463 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
1464 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
1465 | },
1466 | "http-errors": {
1467 | "version": "1.7.3",
1468 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz",
1469 | "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==",
1470 | "requires": {
1471 | "depd": "~1.1.2",
1472 | "inherits": "2.0.4",
1473 | "setprototypeof": "1.1.1",
1474 | "statuses": ">= 1.5.0 < 2",
1475 | "toidentifier": "1.0.0"
1476 | }
1477 | },
1478 | "iconv-lite": {
1479 | "version": "0.4.24",
1480 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
1481 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
1482 | "requires": {
1483 | "safer-buffer": ">= 2.1.2 < 3"
1484 | }
1485 | },
1486 | "inflight": {
1487 | "version": "1.0.6",
1488 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
1489 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
1490 | "dev": true,
1491 | "requires": {
1492 | "once": "^1.3.0",
1493 | "wrappy": "1"
1494 | }
1495 | },
1496 | "inherits": {
1497 | "version": "2.0.4",
1498 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
1499 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
1500 | },
1501 | "is-binary-path": {
1502 | "version": "2.1.0",
1503 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
1504 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
1505 | "dev": true,
1506 | "requires": {
1507 | "binary-extensions": "^2.0.0"
1508 | }
1509 | },
1510 | "is-core-module": {
1511 | "version": "2.10.0",
1512 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz",
1513 | "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==",
1514 | "dev": true,
1515 | "requires": {
1516 | "has": "^1.0.3"
1517 | }
1518 | },
1519 | "is-extglob": {
1520 | "version": "2.1.1",
1521 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
1522 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
1523 | "dev": true
1524 | },
1525 | "is-glob": {
1526 | "version": "4.0.3",
1527 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
1528 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
1529 | "dev": true,
1530 | "requires": {
1531 | "is-extglob": "^2.1.1"
1532 | }
1533 | },
1534 | "is-number": {
1535 | "version": "7.0.0",
1536 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
1537 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
1538 | "dev": true
1539 | },
1540 | "lodash.chunk": {
1541 | "version": "4.2.0",
1542 | "resolved": "https://registry.npmjs.org/lodash.chunk/-/lodash.chunk-4.2.0.tgz",
1543 | "integrity": "sha512-ZzydJKfUHJwHa+hF5X66zLFCBrWn5GeF28OHEr4WVWtNDXlQ/IjWKPBiikqKo2ne0+v6JgCgJ0GzJp8k8bHC7w=="
1544 | },
1545 | "make-error": {
1546 | "version": "1.3.6",
1547 | "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
1548 | "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
1549 | "dev": true
1550 | },
1551 | "micro": {
1552 | "version": "9.4.0",
1553 | "resolved": "https://registry.npmjs.org/micro/-/micro-9.4.0.tgz",
1554 | "integrity": "sha512-F3uh5Ob+0896E1skflRvcY6Cpq6/sA0RB7exMl/IhQ2wbwL79aF+mDAyjDcKNhXKkJVEXhKZrPqOEFLXkJW9og==",
1555 | "requires": {
1556 | "arg": "4.1.0",
1557 | "content-type": "1.0.4",
1558 | "raw-body": "2.4.1"
1559 | },
1560 | "dependencies": {
1561 | "arg": {
1562 | "version": "4.1.0",
1563 | "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz",
1564 | "integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg=="
1565 | }
1566 | }
1567 | },
1568 | "minimatch": {
1569 | "version": "3.1.2",
1570 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
1571 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
1572 | "dev": true,
1573 | "requires": {
1574 | "brace-expansion": "^1.1.7"
1575 | }
1576 | },
1577 | "minimist": {
1578 | "version": "1.2.6",
1579 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
1580 | "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
1581 | "dev": true
1582 | },
1583 | "mkdirp": {
1584 | "version": "1.0.4",
1585 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
1586 | "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
1587 | "dev": true
1588 | },
1589 | "normalize-path": {
1590 | "version": "3.0.0",
1591 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
1592 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
1593 | "dev": true
1594 | },
1595 | "object-inspect": {
1596 | "version": "1.12.2",
1597 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
1598 | "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ=="
1599 | },
1600 | "once": {
1601 | "version": "1.4.0",
1602 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
1603 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
1604 | "dev": true,
1605 | "requires": {
1606 | "wrappy": "1"
1607 | }
1608 | },
1609 | "packet-reader": {
1610 | "version": "1.0.0",
1611 | "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz",
1612 | "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ=="
1613 | },
1614 | "path-is-absolute": {
1615 | "version": "1.0.1",
1616 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
1617 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
1618 | "dev": true
1619 | },
1620 | "path-parse": {
1621 | "version": "1.0.7",
1622 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
1623 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
1624 | "dev": true
1625 | },
1626 | "pg": {
1627 | "version": "8.8.0",
1628 | "resolved": "https://registry.npmjs.org/pg/-/pg-8.8.0.tgz",
1629 | "integrity": "sha512-UXYN0ziKj+AeNNP7VDMwrehpACThH7LUl/p8TDFpEUuSejCUIwGSfxpHsPvtM6/WXFy6SU4E5RG4IJV/TZAGjw==",
1630 | "requires": {
1631 | "buffer-writer": "2.0.0",
1632 | "packet-reader": "1.0.0",
1633 | "pg-connection-string": "^2.5.0",
1634 | "pg-pool": "^3.5.2",
1635 | "pg-protocol": "^1.5.0",
1636 | "pg-types": "^2.1.0",
1637 | "pgpass": "1.x"
1638 | }
1639 | },
1640 | "pg-connection-string": {
1641 | "version": "2.5.0",
1642 | "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz",
1643 | "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ=="
1644 | },
1645 | "pg-int8": {
1646 | "version": "1.0.1",
1647 | "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
1648 | "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="
1649 | },
1650 | "pg-pool": {
1651 | "version": "3.5.2",
1652 | "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.5.2.tgz",
1653 | "integrity": "sha512-His3Fh17Z4eg7oANLob6ZvH8xIVen3phEZh2QuyrIl4dQSDVEabNducv6ysROKpDNPSD+12tONZVWfSgMvDD9w==",
1654 | "requires": {}
1655 | },
1656 | "pg-protocol": {
1657 | "version": "1.5.0",
1658 | "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz",
1659 | "integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ=="
1660 | },
1661 | "pg-types": {
1662 | "version": "2.2.0",
1663 | "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
1664 | "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
1665 | "requires": {
1666 | "pg-int8": "1.0.1",
1667 | "postgres-array": "~2.0.0",
1668 | "postgres-bytea": "~1.0.0",
1669 | "postgres-date": "~1.0.4",
1670 | "postgres-interval": "^1.1.0"
1671 | }
1672 | },
1673 | "pgpass": {
1674 | "version": "1.0.5",
1675 | "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz",
1676 | "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==",
1677 | "requires": {
1678 | "split2": "^4.1.0"
1679 | }
1680 | },
1681 | "picomatch": {
1682 | "version": "2.3.1",
1683 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
1684 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
1685 | "dev": true
1686 | },
1687 | "postgres-array": {
1688 | "version": "2.0.0",
1689 | "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
1690 | "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="
1691 | },
1692 | "postgres-bytea": {
1693 | "version": "1.0.0",
1694 | "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
1695 | "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w=="
1696 | },
1697 | "postgres-date": {
1698 | "version": "1.0.7",
1699 | "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
1700 | "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q=="
1701 | },
1702 | "postgres-interval": {
1703 | "version": "1.2.0",
1704 | "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
1705 | "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
1706 | "requires": {
1707 | "xtend": "^4.0.0"
1708 | }
1709 | },
1710 | "prettier": {
1711 | "version": "2.7.1",
1712 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
1713 | "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
1714 | "dev": true
1715 | },
1716 | "qs": {
1717 | "version": "6.11.0",
1718 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
1719 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
1720 | "requires": {
1721 | "side-channel": "^1.0.4"
1722 | }
1723 | },
1724 | "raw-body": {
1725 | "version": "2.4.1",
1726 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz",
1727 | "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==",
1728 | "requires": {
1729 | "bytes": "3.1.0",
1730 | "http-errors": "1.7.3",
1731 | "iconv-lite": "0.4.24",
1732 | "unpipe": "1.0.0"
1733 | }
1734 | },
1735 | "readdirp": {
1736 | "version": "3.6.0",
1737 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
1738 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
1739 | "dev": true,
1740 | "requires": {
1741 | "picomatch": "^2.2.1"
1742 | }
1743 | },
1744 | "resolve": {
1745 | "version": "1.22.1",
1746 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
1747 | "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
1748 | "dev": true,
1749 | "requires": {
1750 | "is-core-module": "^2.9.0",
1751 | "path-parse": "^1.0.7",
1752 | "supports-preserve-symlinks-flag": "^1.0.0"
1753 | }
1754 | },
1755 | "rimraf": {
1756 | "version": "2.7.1",
1757 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
1758 | "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
1759 | "dev": true,
1760 | "requires": {
1761 | "glob": "^7.1.3"
1762 | }
1763 | },
1764 | "safer-buffer": {
1765 | "version": "2.1.2",
1766 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
1767 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
1768 | },
1769 | "setprototypeof": {
1770 | "version": "1.1.1",
1771 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
1772 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
1773 | },
1774 | "side-channel": {
1775 | "version": "1.0.4",
1776 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
1777 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
1778 | "requires": {
1779 | "call-bind": "^1.0.0",
1780 | "get-intrinsic": "^1.0.2",
1781 | "object-inspect": "^1.9.0"
1782 | }
1783 | },
1784 | "source-map": {
1785 | "version": "0.6.1",
1786 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
1787 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
1788 | "dev": true
1789 | },
1790 | "source-map-support": {
1791 | "version": "0.5.21",
1792 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
1793 | "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
1794 | "dev": true,
1795 | "requires": {
1796 | "buffer-from": "^1.0.0",
1797 | "source-map": "^0.6.0"
1798 | }
1799 | },
1800 | "split2": {
1801 | "version": "4.1.0",
1802 | "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz",
1803 | "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ=="
1804 | },
1805 | "sql-template-strings": {
1806 | "version": "2.2.2",
1807 | "resolved": "https://registry.npmjs.org/sql-template-strings/-/sql-template-strings-2.2.2.tgz",
1808 | "integrity": "sha512-UXhXR2869FQaD+GMly8jAMCRZ94nU5KcrFetZfWEMd+LVVG6y0ExgHAhatEcKZ/wk8YcKPdi+hiD2wm75lq3/Q=="
1809 | },
1810 | "statuses": {
1811 | "version": "1.5.0",
1812 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
1813 | "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA=="
1814 | },
1815 | "strip-bom": {
1816 | "version": "3.0.0",
1817 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
1818 | "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
1819 | "dev": true
1820 | },
1821 | "strip-json-comments": {
1822 | "version": "2.0.1",
1823 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
1824 | "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
1825 | "dev": true
1826 | },
1827 | "stripe": {
1828 | "version": "10.12.0",
1829 | "resolved": "https://registry.npmjs.org/stripe/-/stripe-10.12.0.tgz",
1830 | "integrity": "sha512-4ijMsbTVSy6rzWIkal+/dFGeTXtjqLeZ/oo/jc2jhICbf3Dby0CBTPxAg6ZhBPXQL96TJxI613C/NhhE7LvrWw==",
1831 | "requires": {
1832 | "@types/node": ">=8.1.0",
1833 | "qs": "^6.10.3"
1834 | }
1835 | },
1836 | "supports-preserve-symlinks-flag": {
1837 | "version": "1.0.0",
1838 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
1839 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
1840 | "dev": true
1841 | },
1842 | "to-regex-range": {
1843 | "version": "5.0.1",
1844 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
1845 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
1846 | "dev": true,
1847 | "requires": {
1848 | "is-number": "^7.0.0"
1849 | }
1850 | },
1851 | "toidentifier": {
1852 | "version": "1.0.0",
1853 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
1854 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
1855 | },
1856 | "tree-kill": {
1857 | "version": "1.2.2",
1858 | "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
1859 | "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
1860 | "dev": true
1861 | },
1862 | "ts-node": {
1863 | "version": "10.9.1",
1864 | "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
1865 | "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==",
1866 | "dev": true,
1867 | "requires": {
1868 | "@cspotcode/source-map-support": "^0.8.0",
1869 | "@tsconfig/node10": "^1.0.7",
1870 | "@tsconfig/node12": "^1.0.7",
1871 | "@tsconfig/node14": "^1.0.0",
1872 | "@tsconfig/node16": "^1.0.2",
1873 | "acorn": "^8.4.1",
1874 | "acorn-walk": "^8.1.1",
1875 | "arg": "^4.1.0",
1876 | "create-require": "^1.1.0",
1877 | "diff": "^4.0.1",
1878 | "make-error": "^1.1.1",
1879 | "v8-compile-cache-lib": "^3.0.1",
1880 | "yn": "3.1.1"
1881 | }
1882 | },
1883 | "ts-node-dev": {
1884 | "version": "2.0.0",
1885 | "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-2.0.0.tgz",
1886 | "integrity": "sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w==",
1887 | "dev": true,
1888 | "requires": {
1889 | "chokidar": "^3.5.1",
1890 | "dynamic-dedupe": "^0.3.0",
1891 | "minimist": "^1.2.6",
1892 | "mkdirp": "^1.0.4",
1893 | "resolve": "^1.0.0",
1894 | "rimraf": "^2.6.1",
1895 | "source-map-support": "^0.5.12",
1896 | "tree-kill": "^1.2.2",
1897 | "ts-node": "^10.4.0",
1898 | "tsconfig": "^7.0.0"
1899 | }
1900 | },
1901 | "tsconfig": {
1902 | "version": "7.0.0",
1903 | "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz",
1904 | "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==",
1905 | "dev": true,
1906 | "requires": {
1907 | "@types/strip-bom": "^3.0.0",
1908 | "@types/strip-json-comments": "0.0.30",
1909 | "strip-bom": "^3.0.0",
1910 | "strip-json-comments": "^2.0.0"
1911 | }
1912 | },
1913 | "typescript": {
1914 | "version": "4.8.4",
1915 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
1916 | "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
1917 | "dev": true
1918 | },
1919 | "unpipe": {
1920 | "version": "1.0.0",
1921 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
1922 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="
1923 | },
1924 | "v8-compile-cache-lib": {
1925 | "version": "3.0.1",
1926 | "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
1927 | "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
1928 | "dev": true
1929 | },
1930 | "wrappy": {
1931 | "version": "1.0.2",
1932 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
1933 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
1934 | "dev": true
1935 | },
1936 | "xtend": {
1937 | "version": "4.0.2",
1938 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
1939 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
1940 | },
1941 | "yn": {
1942 | "version": "3.1.1",
1943 | "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
1944 | "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
1945 | "dev": true
1946 | }
1947 | }
1948 | }
1949 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "stripe_to_postgres",
3 | "version": "0.2.0",
4 | "description": "Sync Stripe to Postgres",
5 | "main": "index.js",
6 | "scripts": {
7 | "dev": "ts-node-dev --log-error --files ./src/server.ts",
8 | "build": "tsc -p tsconfig.json",
9 | "start": "node dist/server.js",
10 | "release": "npm version minor && make"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "git+https://github.com/usenoori/stripe_to_postgres.git"
15 | },
16 | "keywords": [
17 | "Stripe",
18 | "Postgres"
19 | ],
20 | "author": "usenoori",
21 | "bugs": {
22 | "url": "https://github.com/usenoori/stripe_to_postgres/issues"
23 | },
24 | "homepage": "https://github.com/usenoori/stripe_to_postgres#readme",
25 | "dependencies": {
26 | "@whollacsek/pg-node-migrations": "^0.0.8",
27 | "dotenv": "^16.0.3",
28 | "lodash.chunk": "^4.2.0",
29 | "micro": "9.4.0",
30 | "pg": "^8.8.0",
31 | "stripe": "^10.12.0"
32 | },
33 | "devDependencies": {
34 | "@types/lodash.chunk": "^4.2.7",
35 | "@types/node": "^18.8.0",
36 | "@types/pg": "^8.6.5",
37 | "@types/yesql": "^4.1.1",
38 | "prettier": "^2.7.1",
39 | "ts-node-dev": "^2.0.0",
40 | "typescript": "^4.8.4"
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/config.ts:
--------------------------------------------------------------------------------
1 | import dotenv from 'dotenv'
2 |
3 | type configType = {
4 | PORT: string
5 | SKIP_SYNC: string
6 | SKIP_MIGRATIONS: string
7 | DATABASE_URL: string
8 | NODE_ENV: string
9 | STRIPE_SECRET_KEY: string
10 | STRIPE_WEBHOOK_SECRET: string | undefined
11 | WEBHOOK_URL: string | undefined
12 | }
13 |
14 | export function getConfig(): configType {
15 | dotenv.config()
16 | return {
17 | PORT: process.env.PORT ?? '3000',
18 | SKIP_SYNC: process.env.SKIP_SYNC ?? 'false',
19 | SKIP_MIGRATIONS: process.env.SKIP_MIGRATIONS ?? 'false',
20 | NODE_ENV: process.env.NODE_ENV ?? 'development',
21 | DATABASE_URL: process.env.DATABASE_URL as string,
22 | STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY as string,
23 | STRIPE_WEBHOOK_SECRET: process.env.STRIPE_WEBHOOK_SECRET,
24 | WEBHOOK_URL: process.env.WEBHOOK_URL,
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/connection.ts:
--------------------------------------------------------------------------------
1 | import { Pool, QueryResult } from 'pg'
2 | import { getConfig } from './config'
3 |
4 | const config = getConfig()
5 | const pool = new Pool({ connectionString: config.DATABASE_URL })
6 |
7 | export const query = (
8 | text: string,
9 | params?: string[]
10 | ): Promise => {
11 | return pool.query(text, params)
12 | }
13 |
14 | export const stringifyArray = (obj: {
15 | [Key: string]: any
16 | }): {
17 | [Key: string]: any
18 | } => {
19 | const cleansed = { ...obj }
20 | Object.keys(cleansed).map((k) => {
21 | const data = cleansed[k]
22 | if (Array.isArray(data)) {
23 | cleansed[k] = JSON.stringify(data)
24 | }
25 | })
26 | return cleansed
27 | }
28 |
29 | export const constructUpsertSql = (
30 | schema: string,
31 | table: string,
32 | columns: string[],
33 | rows: Object[],
34 | options?: {
35 | conflict?: string
36 | }
37 | ): { text: string; values: string[] } => {
38 | const { conflict = 'id' } = options || {}
39 | const values: string[] = []
40 |
41 | // language=txt
42 | const text = `
43 | insert into "${schema}"."${table}" (${columns
44 | .map((x) => `"${x}"`)
45 | .join(',')})
46 | values
47 | ${rows
48 | .map((row, i) => {
49 | const sanitized = stringifyArray(row)
50 | return `(${columns
51 | .map((column, j) => {
52 | values.push(sanitized[column])
53 | return `$${columns.length * (i + 1) - (columns.length - 1 - j)}`
54 | })
55 | .join(',')})`
56 | })
57 | .join(',')}
58 | on conflict (
59 | ${conflict}
60 | )
61 | do update set ${columns
62 | .map((x) => `"${x}" = excluded.${x}`)
63 | .join(',')};`
64 |
65 | return { text, values }
66 | }
67 |
68 | export const upsert = async (
69 | table: string,
70 | columns: string[],
71 | rows: T[]
72 | ): Promise => {
73 | const { text, values } = constructUpsertSql('stripe', table, columns, rows)
74 | const result = await query(text, values)
75 | return result.rows
76 | }
77 |
78 | export async function getColumns(table: string) {
79 | const { rows } = await query(
80 | 'SELECT column_name FROM information_schema.columns where table_name = $1',
81 | [table]
82 | )
83 | const columns: string[] = rows
84 | .map((row) => row.column_name)
85 | .filter((col) => col !== 'updated_at')
86 | return columns
87 | }
88 |
--------------------------------------------------------------------------------
/src/migrate.ts:
--------------------------------------------------------------------------------
1 | import { Client } from 'pg'
2 | import { migrate } from '@whollacsek/pg-node-migrations'
3 | import { getConfig } from './config'
4 |
5 | const config = getConfig()
6 |
7 | async function connectAndMigrate(
8 | databaseUrl: string | undefined,
9 | migrationsDirectory: string,
10 | logOnError = false
11 | ) {
12 | const dbConfig = {
13 | connectionString: databaseUrl,
14 | connectionTimeoutMillis: 1000,
15 | }
16 | const optionalConfig = {
17 | schemaName: 'stripe',
18 | tableName: 'migrations',
19 | }
20 |
21 | const client = new Client(dbConfig)
22 | try {
23 | await client.connect()
24 | await migrate({ client }, migrationsDirectory, optionalConfig)
25 | } catch (error) {
26 | if (logOnError && error instanceof Error) {
27 | console.error('Migration error:', error.message)
28 | } else {
29 | throw error
30 | }
31 | } finally {
32 | await client.end()
33 | }
34 | }
35 |
36 | export async function runMigrations(): Promise {
37 | try {
38 | console.log('Running migrations')
39 | await connectAndMigrate(config.DATABASE_URL, './migrations')
40 | } catch (error) {
41 | throw error
42 | } finally {
43 | console.log('Finished migrations')
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/server.ts:
--------------------------------------------------------------------------------
1 | import { runMigrations } from './migrate'
2 | import { runSync } from './sync'
3 | import { getConfig } from './config'
4 | import { startWebhook } from './webhook'
5 |
6 | const config = getConfig()
7 |
8 | const main = async () => {
9 | if (config.SKIP_MIGRATIONS === 'true') {
10 | console.log('Skipping migrations')
11 | } else {
12 | await runMigrations()
13 | }
14 |
15 | if (config.SKIP_SYNC === 'true') {
16 | console.log('Skipping sync')
17 | } else {
18 | await runSync()
19 | }
20 |
21 | startWebhook()
22 | }
23 |
24 | main()
25 |
--------------------------------------------------------------------------------
/src/stripe.ts:
--------------------------------------------------------------------------------
1 | import Stripe from 'stripe'
2 | import { getConfig } from './config'
3 |
4 | const config = getConfig()
5 |
6 | export const stripe = new Stripe(config.STRIPE_SECRET_KEY, {
7 | apiVersion: '2022-08-01',
8 | })
9 |
--------------------------------------------------------------------------------
/src/sync.ts:
--------------------------------------------------------------------------------
1 | import chunk from 'lodash.chunk'
2 | import { stripe } from './stripe'
3 | import { getColumns, upsert } from './connection'
4 | import { filterRecord, Record } from './utils'
5 |
6 | async function upsertRecords(
7 | table: string,
8 | resource: AsyncIterableIterator
9 | ) {
10 | const columns = await getColumns(table)
11 |
12 | console.log(`Upserting ${table}`)
13 | const rows = []
14 | for await (const record of resource) {
15 | const row = filterRecord(record, columns)
16 | rows.push(row)
17 | }
18 |
19 | // TODO: find optimal chunk size
20 | for (const chunkedRows of chunk(rows, 100)) {
21 | await upsert(table, columns, chunkedRows)
22 | }
23 | console.log(`Upserted ${rows.length} ${table}`)
24 | }
25 |
26 | export async function runSync() {
27 | await upsertRecords('products', stripe.products.list({ limit: 100 }))
28 | await upsertRecords('prices', stripe.prices.list({ limit: 100 }))
29 | await upsertRecords('customers', stripe.customers.list({ limit: 100 }))
30 | await upsertRecords(
31 | 'subscriptions',
32 | stripe.subscriptions.list({ limit: 100, status: 'all' })
33 | )
34 | await upsertRecords('invoices', stripe.invoices.list({ limit: 100 }))
35 | await upsertRecords('charges', stripe.charges.list({ limit: 100 }))
36 | await upsertRecords('coupons', stripe.coupons.list({ limit: 100 }))
37 | await upsertRecords('disputes', stripe.disputes.list({ limit: 100 }))
38 | await upsertRecords('plans', stripe.plans.list({ limit: 100 }))
39 | await upsertRecords('events', stripe.events.list({ limit: 100 }))
40 | }
41 |
--------------------------------------------------------------------------------
/src/utils.ts:
--------------------------------------------------------------------------------
1 | export type Record = { [Key: string]: any }
2 |
3 | export function filterRecord(record: Record, columns: string[]) {
4 | return Object.fromEntries(
5 | columns.reduce((entries, column) => {
6 | entries.push([column, record[column]])
7 | return entries
8 | }, [] as Array<[string, any]>)
9 | )
10 | }
11 |
--------------------------------------------------------------------------------
/src/webhook.ts:
--------------------------------------------------------------------------------
1 | import { getConfig } from './config'
2 | import http from 'http'
3 | import serve, { buffer, send, sendError } from 'micro'
4 | import Stripe from 'stripe'
5 | import { stripe } from './stripe'
6 | import { filterRecord, Record } from './utils'
7 | import { getColumns, upsert } from './connection'
8 |
9 | const WEBHOOK_API_VERSION = '2022-08-01'
10 |
11 | // https://stripe.com/docs/api/webhook_endpoints/create#create_webhook_endpoint-enabled_events
12 | const enabled_events: Array = [
13 | 'charge.failed',
14 | 'charge.refunded',
15 | 'charge.succeeded',
16 | 'customer.created',
17 | 'customer.updated',
18 | 'customer.subscription.created',
19 | 'customer.subscription.deleted',
20 | 'customer.subscription.updated',
21 | 'invoice.created',
22 | 'invoice.finalized',
23 | 'invoice.paid',
24 | 'invoice.payment_failed',
25 | 'invoice.payment_succeeded',
26 | 'invoice.updated',
27 | 'product.created',
28 | 'product.updated',
29 | // 'product.deleted',
30 | 'price.created',
31 | 'price.updated',
32 | // 'price.deleted',
33 | ]
34 |
35 | const config = getConfig()
36 |
37 | async function upsertRecord(table: string, record: Record) {
38 | const columns = await getColumns(table)
39 | const row = filterRecord(record, columns)
40 | await upsert(table, columns, [row])
41 | }
42 |
43 | function makeServer(webhookSecret: string) {
44 | return new http.Server(
45 | serve(async (req, res) => {
46 | const sig = req.headers['stripe-signature'] as string
47 | const body = await buffer(req)
48 |
49 | try {
50 | const event = stripe.webhooks.constructEvent(body, sig, webhookSecret)
51 | await upsertRecord('events', event)
52 | console.log(`Handling event ${event.type} ${event.id}`)
53 | switch (event.type) {
54 | case 'charge.failed':
55 | case 'charge.refunded':
56 | case 'charge.succeeded': {
57 | const charge = event.data.object as Stripe.Charge
58 | await upsertRecord('charges', charge)
59 | break
60 | }
61 | case 'customer.created':
62 | case 'customer.updated': {
63 | const customer = event.data.object as Stripe.Customer
64 | await upsertRecord('customers', customer)
65 | break
66 | }
67 | case 'customer.subscription.created':
68 | case 'customer.subscription.deleted':
69 | case 'customer.subscription.updated': {
70 | const subscription = event.data.object as Stripe.Subscription
71 | await upsertRecord('subscriptions', subscription)
72 | break
73 | }
74 | case 'invoice.created':
75 | case 'invoice.finalized':
76 | case 'invoice.paid':
77 | case 'invoice.payment_failed':
78 | case 'invoice.payment_succeeded':
79 | case 'invoice.updated': {
80 | const invoice = event.data.object as Stripe.Invoice
81 | await upsertRecord('invoices', invoice)
82 | break
83 | }
84 | case 'product.created':
85 | case 'product.updated': {
86 | const product = event.data.object as Stripe.Product
87 | await upsertRecord('products', product)
88 | break
89 | }
90 | case 'price.created':
91 | case 'price.updated': {
92 | const price = event.data.object as Stripe.Price
93 | await upsertRecord('prices', price)
94 | break
95 | }
96 | default:
97 | console.log('Unhandled webhook event')
98 | }
99 |
100 | await send(res, 200)
101 | } catch (err) {
102 | await sendError(req, res, err)
103 | }
104 | })
105 | )
106 | }
107 |
108 | async function getOrCreateWebhook() {
109 | const webhookEndpoints = await stripe.webhookEndpoints
110 | .list()
111 | .autoPagingToArray({ limit: 100 })
112 | const webhookEndpoint = webhookEndpoints.find(
113 | (value) => value.metadata.creator === 'stripe_to_postgres'
114 | )
115 |
116 | // Create webhook if not exists
117 | if (webhookEndpoint == null) {
118 | console.log(`Creating webhook ${config.WEBHOOK_URL}`)
119 | const { id, secret } = await stripe.webhookEndpoints.create({
120 | api_version: WEBHOOK_API_VERSION,
121 | url: config.WEBHOOK_URL as string,
122 | metadata: { creator: 'stripe_to_postgres' },
123 | description: 'stripe_to_postgres webhook',
124 | enabled_events,
125 | })
126 |
127 | return stripe.webhookEndpoints.update(id, {
128 | metadata: { secret: secret as string },
129 | })
130 | }
131 |
132 | console.log(
133 | `Found existing webhook ${webhookEndpoint.api_version} ${webhookEndpoint.url}`
134 | )
135 |
136 | // Update url
137 | if (webhookEndpoint.url !== config.WEBHOOK_URL) {
138 | console.log('Updating webhook url')
139 | return stripe.webhookEndpoints.update(webhookEndpoint.id, {
140 | url: config.WEBHOOK_URL,
141 | })
142 | }
143 |
144 | // Update enabled_events
145 | if (
146 | webhookEndpoint.enabled_events.length !== enabled_events.length ||
147 | enabled_events.some(
148 | (value) => !webhookEndpoint.enabled_events.includes(value)
149 | )
150 | ) {
151 | console.log('Updating webhook enabled_events')
152 | return stripe.webhookEndpoints.update(webhookEndpoint.id, {
153 | enabled_events,
154 | })
155 | }
156 |
157 | return webhookEndpoint
158 | }
159 |
160 | export async function startWebhook() {
161 | let secret: string
162 | if (config.NODE_ENV === 'production') {
163 | const webhookEndpoint = await getOrCreateWebhook()
164 | const { secret: webhookSecret } = webhookEndpoint.metadata
165 | secret = webhookSecret
166 | } else {
167 | secret = config.STRIPE_WEBHOOK_SECRET as string
168 | }
169 | makeServer(secret).listen(config.PORT, () => {
170 | console.log(`Webhook listening on ${config.PORT}`)
171 | })
172 | }
173 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "emitDecoratorMetadata": true,
4 | "experimentalDecorators": true,
5 | "esModuleInterop": true,
6 | "preserveConstEnums": true,
7 | "removeComments": true,
8 | "rootDir": "src",
9 | "outDir": "dist",
10 | "sourceMap": true,
11 | "strict": true,
12 | "lib": ["ES6", "DOM"],
13 | "resolveJsonModule": true,
14 | "useUnknownInCatchVariables": false,
15 | },
16 | "include": [
17 | "./src/**/*"
18 | ],
19 | "exclude": [
20 | "node_modules",
21 | "dist"
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------