add openapi-ts + client
This commit is contained in:
parent
1cc7d01c27
commit
e9938d349c
192
.gitignore
vendored
Normal file
192
.gitignore
vendored
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
# Created by https://www.toptal.com/developers/gitignore/api/django,vue,vuejs
|
||||||
|
# Edit at https://www.toptal.com/developers/gitignore?templates=django,vue,vuejs
|
||||||
|
|
||||||
|
### Django ###
|
||||||
|
*.log
|
||||||
|
*.pot
|
||||||
|
*.pyc
|
||||||
|
__pycache__/
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
media
|
||||||
|
|
||||||
|
# If your build process includes running collectstatic, then you probably don't need or want to include staticfiles/
|
||||||
|
# in your Git repository. Update and uncomment the following line accordingly.
|
||||||
|
# <django-project-name>/staticfiles/
|
||||||
|
|
||||||
|
### Django.Python Stack ###
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
# .python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# poetry
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||||
|
#poetry.lock
|
||||||
|
|
||||||
|
# pdm
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||||
|
#pdm.lock
|
||||||
|
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||||
|
# in version control.
|
||||||
|
# https://pdm.fming.dev/#use-with-ide
|
||||||
|
.pdm.toml
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# pytype static type analyzer
|
||||||
|
.pytype/
|
||||||
|
|
||||||
|
# Cython debug symbols
|
||||||
|
cython_debug/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||||
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
|
#.idea/
|
||||||
|
|
||||||
|
### Vue ###
|
||||||
|
# gitignore template for Vue.js projects
|
||||||
|
#
|
||||||
|
# Recommended template: Node.gitignore
|
||||||
|
|
||||||
|
# TODO: where does this rule come from?
|
||||||
|
docs/_book
|
||||||
|
|
||||||
|
# TODO: where does this rule come from?
|
||||||
|
test/
|
||||||
|
|
||||||
|
### Vuejs ###
|
||||||
|
# Recommended template: Node.gitignore
|
||||||
|
|
||||||
|
node_modules/
|
||||||
|
npm-debug.log
|
||||||
|
yarn-error.log
|
||||||
|
|
||||||
|
# End of https://www.toptal.com/developers/gitignore/api/django,vue,vuejs
|
||||||
750
package-lock.json
generated
Normal file
750
package-lock.json
generated
Normal file
@ -0,0 +1,750 @@
|
|||||||
|
{
|
||||||
|
"name": "polyticket-api",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"devDependencies": {
|
||||||
|
"@hey-api/openapi-ts": "^0.78.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@hey-api/json-schema-ref-parser": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@hey-api/json-schema-ref-parser/-/json-schema-ref-parser-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-yktiFZoWPtEW8QKS65eqKwA5MTKp88CyiL8q72WynrBs/73SAaxlSWlA2zW/DZlywZ5hX1OYzrCC0wFdvO9c2w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@jsdevtools/ono": "^7.1.3",
|
||||||
|
"@types/json-schema": "^7.0.15",
|
||||||
|
"js-yaml": "^4.1.0",
|
||||||
|
"lodash": "^4.17.21"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/hey-api"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@hey-api/openapi-ts": {
|
||||||
|
"version": "0.78.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@hey-api/openapi-ts/-/openapi-ts-0.78.3.tgz",
|
||||||
|
"integrity": "sha512-uTP/EGA/mM4MsFN0xGcQ4fkFxeaAUGT2T1VKnNBv6WUwRY7J59Wg8kVuRXn3dLeI/IWUDwNNdHU0SfnEbXEmYw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@hey-api/json-schema-ref-parser": "1.0.6",
|
||||||
|
"ansi-colors": "4.1.3",
|
||||||
|
"c12": "2.0.1",
|
||||||
|
"color-support": "1.1.3",
|
||||||
|
"commander": "13.0.0",
|
||||||
|
"handlebars": "4.7.8",
|
||||||
|
"open": "10.1.2"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"openapi-ts": "bin/index.cjs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.18.0 || ^20.9.0 || >=22.10.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/hey-api"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": "^5.5.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@jsdevtools/ono": {
|
||||||
|
"version": "7.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz",
|
||||||
|
"integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@types/json-schema": {
|
||||||
|
"version": "7.0.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||||
|
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/acorn": {
|
||||||
|
"version": "8.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||||
|
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"acorn": "bin/acorn"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ansi-colors": {
|
||||||
|
"version": "4.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
|
||||||
|
"integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/argparse": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "Python-2.0"
|
||||||
|
},
|
||||||
|
"node_modules/bundle-name": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"run-applescript": "^7.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/c12": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/c12/-/c12-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-Z4JgsKXHG37C6PYUtIxCfLJZvo6FyhHJoClwwb9ftUkLpPSkuYqn6Tr+vnaN8hymm0kIbcg6Ey3kv/Q71k5w/A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"chokidar": "^4.0.1",
|
||||||
|
"confbox": "^0.1.7",
|
||||||
|
"defu": "^6.1.4",
|
||||||
|
"dotenv": "^16.4.5",
|
||||||
|
"giget": "^1.2.3",
|
||||||
|
"jiti": "^2.3.0",
|
||||||
|
"mlly": "^1.7.1",
|
||||||
|
"ohash": "^1.1.4",
|
||||||
|
"pathe": "^1.1.2",
|
||||||
|
"perfect-debounce": "^1.0.0",
|
||||||
|
"pkg-types": "^1.2.0",
|
||||||
|
"rc9": "^2.1.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"magicast": "^0.3.5"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"magicast": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/chokidar": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"readdirp": "^4.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14.16.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/chownr": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/citty": {
|
||||||
|
"version": "0.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz",
|
||||||
|
"integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"consola": "^3.2.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/color-support": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
|
||||||
|
"integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"bin": {
|
||||||
|
"color-support": "bin.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/commander": {
|
||||||
|
"version": "13.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-13.0.0.tgz",
|
||||||
|
"integrity": "sha512-oPYleIY8wmTVzkvQq10AEok6YcTC4sRUBl8F9gVuwchGVUCTbl/vhLTaQqutuuySYOsu8YTgV+OxKc/8Yvx+mQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/confbox": {
|
||||||
|
"version": "0.1.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz",
|
||||||
|
"integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/consola": {
|
||||||
|
"version": "3.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz",
|
||||||
|
"integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": "^14.18.0 || >=16.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/default-browser": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"bundle-name": "^4.1.0",
|
||||||
|
"default-browser-id": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/default-browser-id": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/define-lazy-prop": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/defu": {
|
||||||
|
"version": "6.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz",
|
||||||
|
"integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/destr": {
|
||||||
|
"version": "2.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz",
|
||||||
|
"integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/dotenv": {
|
||||||
|
"version": "16.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
|
||||||
|
"integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://dotenvx.com"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fs-minipass": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"minipass": "^3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fs-minipass/node_modules/minipass": {
|
||||||
|
"version": "3.3.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
|
||||||
|
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"yallist": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/giget": {
|
||||||
|
"version": "1.2.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/giget/-/giget-1.2.5.tgz",
|
||||||
|
"integrity": "sha512-r1ekGw/Bgpi3HLV3h1MRBIlSAdHoIMklpaQ3OQLFcRw9PwAj2rqigvIbg+dBUI51OxVI2jsEtDywDBjSiuf7Ug==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"citty": "^0.1.6",
|
||||||
|
"consola": "^3.4.0",
|
||||||
|
"defu": "^6.1.4",
|
||||||
|
"node-fetch-native": "^1.6.6",
|
||||||
|
"nypm": "^0.5.4",
|
||||||
|
"pathe": "^2.0.3",
|
||||||
|
"tar": "^6.2.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"giget": "dist/cli.mjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/giget/node_modules/pathe": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/handlebars": {
|
||||||
|
"version": "4.7.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
|
||||||
|
"integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"minimist": "^1.2.5",
|
||||||
|
"neo-async": "^2.6.2",
|
||||||
|
"source-map": "^0.6.1",
|
||||||
|
"wordwrap": "^1.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"handlebars": "bin/handlebars"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.7"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"uglify-js": "^3.1.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-docker": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"is-docker": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-inside-container": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"is-docker": "^3.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"is-inside-container": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-wsl": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"is-inside-container": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/jiti": {
|
||||||
|
"version": "2.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz",
|
||||||
|
"integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"jiti": "lib/jiti-cli.mjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/js-yaml": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"argparse": "^2.0.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"js-yaml": "bin/js-yaml.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/lodash": {
|
||||||
|
"version": "4.17.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||||
|
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/minimist": {
|
||||||
|
"version": "1.2.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||||
|
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/minipass": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/minizlib": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"minipass": "^3.0.0",
|
||||||
|
"yallist": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/minizlib/node_modules/minipass": {
|
||||||
|
"version": "3.3.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
|
||||||
|
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"yallist": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mkdirp": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"mkdirp": "bin/cmd.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mlly": {
|
||||||
|
"version": "1.7.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz",
|
||||||
|
"integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"acorn": "^8.14.0",
|
||||||
|
"pathe": "^2.0.1",
|
||||||
|
"pkg-types": "^1.3.0",
|
||||||
|
"ufo": "^1.5.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mlly/node_modules/pathe": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/neo-async": {
|
||||||
|
"version": "2.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
|
||||||
|
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/node-fetch-native": {
|
||||||
|
"version": "1.6.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.6.tgz",
|
||||||
|
"integrity": "sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/nypm": {
|
||||||
|
"version": "0.5.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/nypm/-/nypm-0.5.4.tgz",
|
||||||
|
"integrity": "sha512-X0SNNrZiGU8/e/zAB7sCTtdxWTMSIO73q+xuKgglm2Yvzwlo8UoC5FNySQFCvl84uPaeADkqHUZUkWy4aH4xOA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"citty": "^0.1.6",
|
||||||
|
"consola": "^3.4.0",
|
||||||
|
"pathe": "^2.0.3",
|
||||||
|
"pkg-types": "^1.3.1",
|
||||||
|
"tinyexec": "^0.3.2",
|
||||||
|
"ufo": "^1.5.4"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"nypm": "dist/cli.mjs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^14.16.0 || >=16.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/nypm/node_modules/pathe": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/ohash": {
|
||||||
|
"version": "1.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/ohash/-/ohash-1.1.6.tgz",
|
||||||
|
"integrity": "sha512-TBu7PtV8YkAZn0tSxobKY2n2aAQva936lhRrj6957aDaCf9IEtqsKbgMzXE/F/sjqYOwmrukeORHNLe5glk7Cg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/open": {
|
||||||
|
"version": "10.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/open/-/open-10.1.2.tgz",
|
||||||
|
"integrity": "sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"default-browser": "^5.2.1",
|
||||||
|
"define-lazy-prop": "^3.0.0",
|
||||||
|
"is-inside-container": "^1.0.0",
|
||||||
|
"is-wsl": "^3.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pathe": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/perfect-debounce": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/pkg-types": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"confbox": "^0.1.8",
|
||||||
|
"mlly": "^1.7.4",
|
||||||
|
"pathe": "^2.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pkg-types/node_modules/pathe": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/rc9": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"defu": "^6.1.4",
|
||||||
|
"destr": "^2.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/readdirp": {
|
||||||
|
"version": "4.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
|
||||||
|
"integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14.18.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://paulmillr.com/funding/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/run-applescript": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/source-map": {
|
||||||
|
"version": "0.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
|
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/tar": {
|
||||||
|
"version": "6.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
|
||||||
|
"integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"chownr": "^2.0.0",
|
||||||
|
"fs-minipass": "^2.0.0",
|
||||||
|
"minipass": "^5.0.0",
|
||||||
|
"minizlib": "^2.1.1",
|
||||||
|
"mkdirp": "^1.0.3",
|
||||||
|
"yallist": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/tinyexec": {
|
||||||
|
"version": "0.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz",
|
||||||
|
"integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/typescript": {
|
||||||
|
"version": "5.8.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
|
||||||
|
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"peer": true,
|
||||||
|
"bin": {
|
||||||
|
"tsc": "bin/tsc",
|
||||||
|
"tsserver": "bin/tsserver"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.17"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ufo": {
|
||||||
|
"version": "1.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz",
|
||||||
|
"integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/uglify-js": {
|
||||||
|
"version": "3.19.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz",
|
||||||
|
"integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"optional": true,
|
||||||
|
"bin": {
|
||||||
|
"uglifyjs": "bin/uglifyjs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/wordwrap": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/yallist": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
5
package.json
Normal file
5
package.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"devDependencies": {
|
||||||
|
"@hey-api/openapi-ts": "^0.78.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/api/client.gen.ts
Normal file
18
src/api/client.gen.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// This file is auto-generated by @hey-api/openapi-ts
|
||||||
|
|
||||||
|
import type { ClientOptions } from './types.gen';
|
||||||
|
import { type Config, type ClientOptions as DefaultClientOptions, createClient, createConfig } from './client';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `createClientConfig()` function will be called on client initialization
|
||||||
|
* and the returned object will become the client's initial configuration.
|
||||||
|
*
|
||||||
|
* You may want to initialize your client this way instead of calling
|
||||||
|
* `setConfig()`. This is useful for example if you're using Next.js
|
||||||
|
* to ensure your client always has the correct values.
|
||||||
|
*/
|
||||||
|
export type CreateClientConfig<T extends DefaultClientOptions = ClientOptions> = (override?: Config<DefaultClientOptions & T>) => Config<Required<DefaultClientOptions> & T>;
|
||||||
|
|
||||||
|
export const client = createClient(createConfig<ClientOptions>({
|
||||||
|
baseUrl: 'https://api.dev.v2.polyticket.ch'
|
||||||
|
}));
|
||||||
195
src/api/client/client.ts
Normal file
195
src/api/client/client.ts
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
import type { Client, Config, RequestOptions } from './types';
|
||||||
|
import {
|
||||||
|
buildUrl,
|
||||||
|
createConfig,
|
||||||
|
createInterceptors,
|
||||||
|
getParseAs,
|
||||||
|
mergeConfigs,
|
||||||
|
mergeHeaders,
|
||||||
|
setAuthParams,
|
||||||
|
} from './utils';
|
||||||
|
|
||||||
|
type ReqInit = Omit<RequestInit, 'body' | 'headers'> & {
|
||||||
|
body?: any;
|
||||||
|
headers: ReturnType<typeof mergeHeaders>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createClient = (config: Config = {}): Client => {
|
||||||
|
let _config = mergeConfigs(createConfig(), config);
|
||||||
|
|
||||||
|
const getConfig = (): Config => ({ ..._config });
|
||||||
|
|
||||||
|
const setConfig = (config: Config): Config => {
|
||||||
|
_config = mergeConfigs(_config, config);
|
||||||
|
return getConfig();
|
||||||
|
};
|
||||||
|
|
||||||
|
const interceptors = createInterceptors<
|
||||||
|
Request,
|
||||||
|
Response,
|
||||||
|
unknown,
|
||||||
|
RequestOptions
|
||||||
|
>();
|
||||||
|
|
||||||
|
const request: Client['request'] = async (options) => {
|
||||||
|
const opts = {
|
||||||
|
..._config,
|
||||||
|
...options,
|
||||||
|
fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
|
||||||
|
headers: mergeHeaders(_config.headers, options.headers),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (opts.security) {
|
||||||
|
await setAuthParams({
|
||||||
|
...opts,
|
||||||
|
security: opts.security,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.requestValidator) {
|
||||||
|
await opts.requestValidator(opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.body && opts.bodySerializer) {
|
||||||
|
opts.body = opts.bodySerializer(opts.body);
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove Content-Type header if body is empty to avoid sending invalid requests
|
||||||
|
if (opts.body === undefined || opts.body === '') {
|
||||||
|
opts.headers.delete('Content-Type');
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = buildUrl(opts);
|
||||||
|
const requestInit: ReqInit = {
|
||||||
|
redirect: 'follow',
|
||||||
|
...opts,
|
||||||
|
};
|
||||||
|
|
||||||
|
let request = new Request(url, requestInit);
|
||||||
|
|
||||||
|
for (const fn of interceptors.request._fns) {
|
||||||
|
if (fn) {
|
||||||
|
request = await fn(request, opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetch must be assigned here, otherwise it would throw the error:
|
||||||
|
// TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
|
||||||
|
const _fetch = opts.fetch!;
|
||||||
|
let response = await _fetch(request);
|
||||||
|
|
||||||
|
for (const fn of interceptors.response._fns) {
|
||||||
|
if (fn) {
|
||||||
|
response = await fn(response, request, opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = {
|
||||||
|
request,
|
||||||
|
response,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
if (
|
||||||
|
response.status === 204 ||
|
||||||
|
response.headers.get('Content-Length') === '0'
|
||||||
|
) {
|
||||||
|
return opts.responseStyle === 'data'
|
||||||
|
? {}
|
||||||
|
: {
|
||||||
|
data: {},
|
||||||
|
...result,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const parseAs =
|
||||||
|
(opts.parseAs === 'auto'
|
||||||
|
? getParseAs(response.headers.get('Content-Type'))
|
||||||
|
: opts.parseAs) ?? 'json';
|
||||||
|
|
||||||
|
let data: any;
|
||||||
|
switch (parseAs) {
|
||||||
|
case 'arrayBuffer':
|
||||||
|
case 'blob':
|
||||||
|
case 'formData':
|
||||||
|
case 'json':
|
||||||
|
case 'text':
|
||||||
|
data = await response[parseAs]();
|
||||||
|
break;
|
||||||
|
case 'stream':
|
||||||
|
return opts.responseStyle === 'data'
|
||||||
|
? response.body
|
||||||
|
: {
|
||||||
|
data: response.body,
|
||||||
|
...result,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parseAs === 'json') {
|
||||||
|
if (opts.responseValidator) {
|
||||||
|
await opts.responseValidator(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.responseTransformer) {
|
||||||
|
data = await opts.responseTransformer(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return opts.responseStyle === 'data'
|
||||||
|
? data
|
||||||
|
: {
|
||||||
|
data,
|
||||||
|
...result,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const textError = await response.text();
|
||||||
|
let jsonError: unknown;
|
||||||
|
|
||||||
|
try {
|
||||||
|
jsonError = JSON.parse(textError);
|
||||||
|
} catch {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
|
const error = jsonError ?? textError;
|
||||||
|
let finalError = error;
|
||||||
|
|
||||||
|
for (const fn of interceptors.error._fns) {
|
||||||
|
if (fn) {
|
||||||
|
finalError = (await fn(error, response, request, opts)) as string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
finalError = finalError || ({} as string);
|
||||||
|
|
||||||
|
if (opts.throwOnError) {
|
||||||
|
throw finalError;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: we probably want to return error and improve types
|
||||||
|
return opts.responseStyle === 'data'
|
||||||
|
? undefined
|
||||||
|
: {
|
||||||
|
error: finalError,
|
||||||
|
...result,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
buildUrl,
|
||||||
|
connect: (options) => request({ ...options, method: 'CONNECT' }),
|
||||||
|
delete: (options) => request({ ...options, method: 'DELETE' }),
|
||||||
|
get: (options) => request({ ...options, method: 'GET' }),
|
||||||
|
getConfig,
|
||||||
|
head: (options) => request({ ...options, method: 'HEAD' }),
|
||||||
|
interceptors,
|
||||||
|
options: (options) => request({ ...options, method: 'OPTIONS' }),
|
||||||
|
patch: (options) => request({ ...options, method: 'PATCH' }),
|
||||||
|
post: (options) => request({ ...options, method: 'POST' }),
|
||||||
|
put: (options) => request({ ...options, method: 'PUT' }),
|
||||||
|
request,
|
||||||
|
setConfig,
|
||||||
|
trace: (options) => request({ ...options, method: 'TRACE' }),
|
||||||
|
};
|
||||||
|
};
|
||||||
22
src/api/client/index.ts
Normal file
22
src/api/client/index.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
export type { Auth } from '../core/auth';
|
||||||
|
export type { QuerySerializerOptions } from '../core/bodySerializer';
|
||||||
|
export {
|
||||||
|
formDataBodySerializer,
|
||||||
|
jsonBodySerializer,
|
||||||
|
urlSearchParamsBodySerializer,
|
||||||
|
} from '../core/bodySerializer';
|
||||||
|
export { buildClientParams } from '../core/params';
|
||||||
|
export { createClient } from './client';
|
||||||
|
export type {
|
||||||
|
Client,
|
||||||
|
ClientOptions,
|
||||||
|
Config,
|
||||||
|
CreateClientConfig,
|
||||||
|
Options,
|
||||||
|
OptionsLegacyParser,
|
||||||
|
RequestOptions,
|
||||||
|
RequestResult,
|
||||||
|
ResponseStyle,
|
||||||
|
TDataShape,
|
||||||
|
} from './types';
|
||||||
|
export { createConfig, mergeHeaders } from './utils';
|
||||||
222
src/api/client/types.ts
Normal file
222
src/api/client/types.ts
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
import type { Auth } from '../core/auth';
|
||||||
|
import type {
|
||||||
|
Client as CoreClient,
|
||||||
|
Config as CoreConfig,
|
||||||
|
} from '../core/types';
|
||||||
|
import type { Middleware } from './utils';
|
||||||
|
|
||||||
|
export type ResponseStyle = 'data' | 'fields';
|
||||||
|
|
||||||
|
export interface Config<T extends ClientOptions = ClientOptions>
|
||||||
|
extends Omit<RequestInit, 'body' | 'headers' | 'method'>,
|
||||||
|
CoreConfig {
|
||||||
|
/**
|
||||||
|
* Base URL for all requests made by this client.
|
||||||
|
*/
|
||||||
|
baseUrl?: T['baseUrl'];
|
||||||
|
/**
|
||||||
|
* Fetch API implementation. You can use this option to provide a custom
|
||||||
|
* fetch instance.
|
||||||
|
*
|
||||||
|
* @default globalThis.fetch
|
||||||
|
*/
|
||||||
|
fetch?: (request: Request) => ReturnType<typeof fetch>;
|
||||||
|
/**
|
||||||
|
* Please don't use the Fetch client for Next.js applications. The `next`
|
||||||
|
* options won't have any effect.
|
||||||
|
*
|
||||||
|
* Install {@link https://www.npmjs.com/package/@hey-api/client-next `@hey-api/client-next`} instead.
|
||||||
|
*/
|
||||||
|
next?: never;
|
||||||
|
/**
|
||||||
|
* Return the response data parsed in a specified format. By default, `auto`
|
||||||
|
* will infer the appropriate method from the `Content-Type` response header.
|
||||||
|
* You can override this behavior with any of the {@link Body} methods.
|
||||||
|
* Select `stream` if you don't want to parse response data at all.
|
||||||
|
*
|
||||||
|
* @default 'auto'
|
||||||
|
*/
|
||||||
|
parseAs?:
|
||||||
|
| 'arrayBuffer'
|
||||||
|
| 'auto'
|
||||||
|
| 'blob'
|
||||||
|
| 'formData'
|
||||||
|
| 'json'
|
||||||
|
| 'stream'
|
||||||
|
| 'text';
|
||||||
|
/**
|
||||||
|
* Should we return only data or multiple fields (data, error, response, etc.)?
|
||||||
|
*
|
||||||
|
* @default 'fields'
|
||||||
|
*/
|
||||||
|
responseStyle?: ResponseStyle;
|
||||||
|
/**
|
||||||
|
* Throw an error instead of returning it in the response?
|
||||||
|
*
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
throwOnError?: T['throwOnError'];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RequestOptions<
|
||||||
|
TResponseStyle extends ResponseStyle = 'fields',
|
||||||
|
ThrowOnError extends boolean = boolean,
|
||||||
|
Url extends string = string,
|
||||||
|
> extends Config<{
|
||||||
|
responseStyle: TResponseStyle;
|
||||||
|
throwOnError: ThrowOnError;
|
||||||
|
}> {
|
||||||
|
/**
|
||||||
|
* Any body that you want to add to your request.
|
||||||
|
*
|
||||||
|
* {@link https://developer.mozilla.org/docs/Web/API/fetch#body}
|
||||||
|
*/
|
||||||
|
body?: unknown;
|
||||||
|
path?: Record<string, unknown>;
|
||||||
|
query?: Record<string, unknown>;
|
||||||
|
/**
|
||||||
|
* Security mechanism(s) to use for the request.
|
||||||
|
*/
|
||||||
|
security?: ReadonlyArray<Auth>;
|
||||||
|
url: Url;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type RequestResult<
|
||||||
|
TData = unknown,
|
||||||
|
TError = unknown,
|
||||||
|
ThrowOnError extends boolean = boolean,
|
||||||
|
TResponseStyle extends ResponseStyle = 'fields',
|
||||||
|
> = ThrowOnError extends true
|
||||||
|
? Promise<
|
||||||
|
TResponseStyle extends 'data'
|
||||||
|
? TData extends Record<string, unknown>
|
||||||
|
? TData[keyof TData]
|
||||||
|
: TData
|
||||||
|
: {
|
||||||
|
data: TData extends Record<string, unknown>
|
||||||
|
? TData[keyof TData]
|
||||||
|
: TData;
|
||||||
|
request: Request;
|
||||||
|
response: Response;
|
||||||
|
}
|
||||||
|
>
|
||||||
|
: Promise<
|
||||||
|
TResponseStyle extends 'data'
|
||||||
|
?
|
||||||
|
| (TData extends Record<string, unknown>
|
||||||
|
? TData[keyof TData]
|
||||||
|
: TData)
|
||||||
|
| undefined
|
||||||
|
: (
|
||||||
|
| {
|
||||||
|
data: TData extends Record<string, unknown>
|
||||||
|
? TData[keyof TData]
|
||||||
|
: TData;
|
||||||
|
error: undefined;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
data: undefined;
|
||||||
|
error: TError extends Record<string, unknown>
|
||||||
|
? TError[keyof TError]
|
||||||
|
: TError;
|
||||||
|
}
|
||||||
|
) & {
|
||||||
|
request: Request;
|
||||||
|
response: Response;
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
|
||||||
|
export interface ClientOptions {
|
||||||
|
baseUrl?: string;
|
||||||
|
responseStyle?: ResponseStyle;
|
||||||
|
throwOnError?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
type MethodFn = <
|
||||||
|
TData = unknown,
|
||||||
|
TError = unknown,
|
||||||
|
ThrowOnError extends boolean = false,
|
||||||
|
TResponseStyle extends ResponseStyle = 'fields',
|
||||||
|
>(
|
||||||
|
options: Omit<RequestOptions<TResponseStyle, ThrowOnError>, 'method'>,
|
||||||
|
) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>;
|
||||||
|
|
||||||
|
type RequestFn = <
|
||||||
|
TData = unknown,
|
||||||
|
TError = unknown,
|
||||||
|
ThrowOnError extends boolean = false,
|
||||||
|
TResponseStyle extends ResponseStyle = 'fields',
|
||||||
|
>(
|
||||||
|
options: Omit<RequestOptions<TResponseStyle, ThrowOnError>, 'method'> &
|
||||||
|
Pick<Required<RequestOptions<TResponseStyle, ThrowOnError>>, 'method'>,
|
||||||
|
) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>;
|
||||||
|
|
||||||
|
type BuildUrlFn = <
|
||||||
|
TData extends {
|
||||||
|
body?: unknown;
|
||||||
|
path?: Record<string, unknown>;
|
||||||
|
query?: Record<string, unknown>;
|
||||||
|
url: string;
|
||||||
|
},
|
||||||
|
>(
|
||||||
|
options: Pick<TData, 'url'> & Options<TData>,
|
||||||
|
) => string;
|
||||||
|
|
||||||
|
export type Client = CoreClient<RequestFn, Config, MethodFn, BuildUrlFn> & {
|
||||||
|
interceptors: Middleware<Request, Response, unknown, RequestOptions>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `createClientConfig()` function will be called on client initialization
|
||||||
|
* and the returned object will become the client's initial configuration.
|
||||||
|
*
|
||||||
|
* You may want to initialize your client this way instead of calling
|
||||||
|
* `setConfig()`. This is useful for example if you're using Next.js
|
||||||
|
* to ensure your client always has the correct values.
|
||||||
|
*/
|
||||||
|
export type CreateClientConfig<T extends ClientOptions = ClientOptions> = (
|
||||||
|
override?: Config<ClientOptions & T>,
|
||||||
|
) => Config<Required<ClientOptions> & T>;
|
||||||
|
|
||||||
|
export interface TDataShape {
|
||||||
|
body?: unknown;
|
||||||
|
headers?: unknown;
|
||||||
|
path?: unknown;
|
||||||
|
query?: unknown;
|
||||||
|
url: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
type OmitKeys<T, K> = Pick<T, Exclude<keyof T, K>>;
|
||||||
|
|
||||||
|
export type Options<
|
||||||
|
TData extends TDataShape = TDataShape,
|
||||||
|
ThrowOnError extends boolean = boolean,
|
||||||
|
TResponseStyle extends ResponseStyle = 'fields',
|
||||||
|
> = OmitKeys<
|
||||||
|
RequestOptions<TResponseStyle, ThrowOnError>,
|
||||||
|
'body' | 'path' | 'query' | 'url'
|
||||||
|
> &
|
||||||
|
Omit<TData, 'url'>;
|
||||||
|
|
||||||
|
export type OptionsLegacyParser<
|
||||||
|
TData = unknown,
|
||||||
|
ThrowOnError extends boolean = boolean,
|
||||||
|
TResponseStyle extends ResponseStyle = 'fields',
|
||||||
|
> = TData extends { body?: any }
|
||||||
|
? TData extends { headers?: any }
|
||||||
|
? OmitKeys<
|
||||||
|
RequestOptions<TResponseStyle, ThrowOnError>,
|
||||||
|
'body' | 'headers' | 'url'
|
||||||
|
> &
|
||||||
|
TData
|
||||||
|
: OmitKeys<RequestOptions<TResponseStyle, ThrowOnError>, 'body' | 'url'> &
|
||||||
|
TData &
|
||||||
|
Pick<RequestOptions<TResponseStyle, ThrowOnError>, 'headers'>
|
||||||
|
: TData extends { headers?: any }
|
||||||
|
? OmitKeys<
|
||||||
|
RequestOptions<TResponseStyle, ThrowOnError>,
|
||||||
|
'headers' | 'url'
|
||||||
|
> &
|
||||||
|
TData &
|
||||||
|
Pick<RequestOptions<TResponseStyle, ThrowOnError>, 'body'>
|
||||||
|
: OmitKeys<RequestOptions<TResponseStyle, ThrowOnError>, 'url'> & TData;
|
||||||
417
src/api/client/utils.ts
Normal file
417
src/api/client/utils.ts
Normal file
@ -0,0 +1,417 @@
|
|||||||
|
import { getAuthToken } from '../core/auth';
|
||||||
|
import type {
|
||||||
|
QuerySerializer,
|
||||||
|
QuerySerializerOptions,
|
||||||
|
} from '../core/bodySerializer';
|
||||||
|
import { jsonBodySerializer } from '../core/bodySerializer';
|
||||||
|
import {
|
||||||
|
serializeArrayParam,
|
||||||
|
serializeObjectParam,
|
||||||
|
serializePrimitiveParam,
|
||||||
|
} from '../core/pathSerializer';
|
||||||
|
import type { Client, ClientOptions, Config, RequestOptions } from './types';
|
||||||
|
|
||||||
|
interface PathSerializer {
|
||||||
|
path: Record<string, unknown>;
|
||||||
|
url: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PATH_PARAM_RE = /\{[^{}]+\}/g;
|
||||||
|
|
||||||
|
type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited';
|
||||||
|
type MatrixStyle = 'label' | 'matrix' | 'simple';
|
||||||
|
type ArraySeparatorStyle = ArrayStyle | MatrixStyle;
|
||||||
|
|
||||||
|
const defaultPathSerializer = ({ path, url: _url }: PathSerializer) => {
|
||||||
|
let url = _url;
|
||||||
|
const matches = _url.match(PATH_PARAM_RE);
|
||||||
|
if (matches) {
|
||||||
|
for (const match of matches) {
|
||||||
|
let explode = false;
|
||||||
|
let name = match.substring(1, match.length - 1);
|
||||||
|
let style: ArraySeparatorStyle = 'simple';
|
||||||
|
|
||||||
|
if (name.endsWith('*')) {
|
||||||
|
explode = true;
|
||||||
|
name = name.substring(0, name.length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name.startsWith('.')) {
|
||||||
|
name = name.substring(1);
|
||||||
|
style = 'label';
|
||||||
|
} else if (name.startsWith(';')) {
|
||||||
|
name = name.substring(1);
|
||||||
|
style = 'matrix';
|
||||||
|
}
|
||||||
|
|
||||||
|
const value = path[name];
|
||||||
|
|
||||||
|
if (value === undefined || value === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
url = url.replace(
|
||||||
|
match,
|
||||||
|
serializeArrayParam({ explode, name, style, value }),
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof value === 'object') {
|
||||||
|
url = url.replace(
|
||||||
|
match,
|
||||||
|
serializeObjectParam({
|
||||||
|
explode,
|
||||||
|
name,
|
||||||
|
style,
|
||||||
|
value: value as Record<string, unknown>,
|
||||||
|
valueOnly: true,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (style === 'matrix') {
|
||||||
|
url = url.replace(
|
||||||
|
match,
|
||||||
|
`;${serializePrimitiveParam({
|
||||||
|
name,
|
||||||
|
value: value as string,
|
||||||
|
})}`,
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const replaceValue = encodeURIComponent(
|
||||||
|
style === 'label' ? `.${value as string}` : (value as string),
|
||||||
|
);
|
||||||
|
url = url.replace(match, replaceValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createQuerySerializer = <T = unknown>({
|
||||||
|
allowReserved,
|
||||||
|
array,
|
||||||
|
object,
|
||||||
|
}: QuerySerializerOptions = {}) => {
|
||||||
|
const querySerializer = (queryParams: T) => {
|
||||||
|
const search: string[] = [];
|
||||||
|
if (queryParams && typeof queryParams === 'object') {
|
||||||
|
for (const name in queryParams) {
|
||||||
|
const value = queryParams[name];
|
||||||
|
|
||||||
|
if (value === undefined || value === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
const serializedArray = serializeArrayParam({
|
||||||
|
allowReserved,
|
||||||
|
explode: true,
|
||||||
|
name,
|
||||||
|
style: 'form',
|
||||||
|
value,
|
||||||
|
...array,
|
||||||
|
});
|
||||||
|
if (serializedArray) search.push(serializedArray);
|
||||||
|
} else if (typeof value === 'object') {
|
||||||
|
const serializedObject = serializeObjectParam({
|
||||||
|
allowReserved,
|
||||||
|
explode: true,
|
||||||
|
name,
|
||||||
|
style: 'deepObject',
|
||||||
|
value: value as Record<string, unknown>,
|
||||||
|
...object,
|
||||||
|
});
|
||||||
|
if (serializedObject) search.push(serializedObject);
|
||||||
|
} else {
|
||||||
|
const serializedPrimitive = serializePrimitiveParam({
|
||||||
|
allowReserved,
|
||||||
|
name,
|
||||||
|
value: value as string,
|
||||||
|
});
|
||||||
|
if (serializedPrimitive) search.push(serializedPrimitive);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return search.join('&');
|
||||||
|
};
|
||||||
|
return querySerializer;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Infers parseAs value from provided Content-Type header.
|
||||||
|
*/
|
||||||
|
export const getParseAs = (
|
||||||
|
contentType: string | null,
|
||||||
|
): Exclude<Config['parseAs'], 'auto'> => {
|
||||||
|
if (!contentType) {
|
||||||
|
// If no Content-Type header is provided, the best we can do is return the raw response body,
|
||||||
|
// which is effectively the same as the 'stream' option.
|
||||||
|
return 'stream';
|
||||||
|
}
|
||||||
|
|
||||||
|
const cleanContent = contentType.split(';')[0]?.trim();
|
||||||
|
|
||||||
|
if (!cleanContent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
cleanContent.startsWith('application/json') ||
|
||||||
|
cleanContent.endsWith('+json')
|
||||||
|
) {
|
||||||
|
return 'json';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cleanContent === 'multipart/form-data') {
|
||||||
|
return 'formData';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
['application/', 'audio/', 'image/', 'video/'].some((type) =>
|
||||||
|
cleanContent.startsWith(type),
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return 'blob';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cleanContent.startsWith('text/')) {
|
||||||
|
return 'text';
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const setAuthParams = async ({
|
||||||
|
security,
|
||||||
|
...options
|
||||||
|
}: Pick<Required<RequestOptions>, 'security'> &
|
||||||
|
Pick<RequestOptions, 'auth' | 'query'> & {
|
||||||
|
headers: Headers;
|
||||||
|
}) => {
|
||||||
|
for (const auth of security) {
|
||||||
|
const token = await getAuthToken(auth, options.auth);
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const name = auth.name ?? 'Authorization';
|
||||||
|
|
||||||
|
switch (auth.in) {
|
||||||
|
case 'query':
|
||||||
|
if (!options.query) {
|
||||||
|
options.query = {};
|
||||||
|
}
|
||||||
|
options.query[name] = token;
|
||||||
|
break;
|
||||||
|
case 'cookie':
|
||||||
|
options.headers.append('Cookie', `${name}=${token}`);
|
||||||
|
break;
|
||||||
|
case 'header':
|
||||||
|
default:
|
||||||
|
options.headers.set(name, token);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const buildUrl: Client['buildUrl'] = (options) => {
|
||||||
|
const url = getUrl({
|
||||||
|
baseUrl: options.baseUrl as string,
|
||||||
|
path: options.path,
|
||||||
|
query: options.query,
|
||||||
|
querySerializer:
|
||||||
|
typeof options.querySerializer === 'function'
|
||||||
|
? options.querySerializer
|
||||||
|
: createQuerySerializer(options.querySerializer),
|
||||||
|
url: options.url,
|
||||||
|
});
|
||||||
|
return url;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getUrl = ({
|
||||||
|
baseUrl,
|
||||||
|
path,
|
||||||
|
query,
|
||||||
|
querySerializer,
|
||||||
|
url: _url,
|
||||||
|
}: {
|
||||||
|
baseUrl?: string;
|
||||||
|
path?: Record<string, unknown>;
|
||||||
|
query?: Record<string, unknown>;
|
||||||
|
querySerializer: QuerySerializer;
|
||||||
|
url: string;
|
||||||
|
}) => {
|
||||||
|
const pathUrl = _url.startsWith('/') ? _url : `/${_url}`;
|
||||||
|
let url = (baseUrl ?? '') + pathUrl;
|
||||||
|
if (path) {
|
||||||
|
url = defaultPathSerializer({ path, url });
|
||||||
|
}
|
||||||
|
let search = query ? querySerializer(query) : '';
|
||||||
|
if (search.startsWith('?')) {
|
||||||
|
search = search.substring(1);
|
||||||
|
}
|
||||||
|
if (search) {
|
||||||
|
url += `?${search}`;
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const mergeConfigs = (a: Config, b: Config): Config => {
|
||||||
|
const config = { ...a, ...b };
|
||||||
|
if (config.baseUrl?.endsWith('/')) {
|
||||||
|
config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);
|
||||||
|
}
|
||||||
|
config.headers = mergeHeaders(a.headers, b.headers);
|
||||||
|
return config;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const mergeHeaders = (
|
||||||
|
...headers: Array<Required<Config>['headers'] | undefined>
|
||||||
|
): Headers => {
|
||||||
|
const mergedHeaders = new Headers();
|
||||||
|
for (const header of headers) {
|
||||||
|
if (!header || typeof header !== 'object') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const iterator =
|
||||||
|
header instanceof Headers ? header.entries() : Object.entries(header);
|
||||||
|
|
||||||
|
for (const [key, value] of iterator) {
|
||||||
|
if (value === null) {
|
||||||
|
mergedHeaders.delete(key);
|
||||||
|
} else if (Array.isArray(value)) {
|
||||||
|
for (const v of value) {
|
||||||
|
mergedHeaders.append(key, v as string);
|
||||||
|
}
|
||||||
|
} else if (value !== undefined) {
|
||||||
|
// assume object headers are meant to be JSON stringified, i.e. their
|
||||||
|
// content value in OpenAPI specification is 'application/json'
|
||||||
|
mergedHeaders.set(
|
||||||
|
key,
|
||||||
|
typeof value === 'object' ? JSON.stringify(value) : (value as string),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mergedHeaders;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ErrInterceptor<Err, Res, Req, Options> = (
|
||||||
|
error: Err,
|
||||||
|
response: Res,
|
||||||
|
request: Req,
|
||||||
|
options: Options,
|
||||||
|
) => Err | Promise<Err>;
|
||||||
|
|
||||||
|
type ReqInterceptor<Req, Options> = (
|
||||||
|
request: Req,
|
||||||
|
options: Options,
|
||||||
|
) => Req | Promise<Req>;
|
||||||
|
|
||||||
|
type ResInterceptor<Res, Req, Options> = (
|
||||||
|
response: Res,
|
||||||
|
request: Req,
|
||||||
|
options: Options,
|
||||||
|
) => Res | Promise<Res>;
|
||||||
|
|
||||||
|
class Interceptors<Interceptor> {
|
||||||
|
_fns: (Interceptor | null)[];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._fns = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this._fns = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
getInterceptorIndex(id: number | Interceptor): number {
|
||||||
|
if (typeof id === 'number') {
|
||||||
|
return this._fns[id] ? id : -1;
|
||||||
|
} else {
|
||||||
|
return this._fns.indexOf(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exists(id: number | Interceptor) {
|
||||||
|
const index = this.getInterceptorIndex(id);
|
||||||
|
return !!this._fns[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
eject(id: number | Interceptor) {
|
||||||
|
const index = this.getInterceptorIndex(id);
|
||||||
|
if (this._fns[index]) {
|
||||||
|
this._fns[index] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update(id: number | Interceptor, fn: Interceptor) {
|
||||||
|
const index = this.getInterceptorIndex(id);
|
||||||
|
if (this._fns[index]) {
|
||||||
|
this._fns[index] = fn;
|
||||||
|
return id;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
use(fn: Interceptor) {
|
||||||
|
this._fns = [...this._fns, fn];
|
||||||
|
return this._fns.length - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// `createInterceptors()` response, meant for external use as it does not
|
||||||
|
// expose internals
|
||||||
|
export interface Middleware<Req, Res, Err, Options> {
|
||||||
|
error: Pick<
|
||||||
|
Interceptors<ErrInterceptor<Err, Res, Req, Options>>,
|
||||||
|
'eject' | 'use'
|
||||||
|
>;
|
||||||
|
request: Pick<Interceptors<ReqInterceptor<Req, Options>>, 'eject' | 'use'>;
|
||||||
|
response: Pick<
|
||||||
|
Interceptors<ResInterceptor<Res, Req, Options>>,
|
||||||
|
'eject' | 'use'
|
||||||
|
>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// do not add `Middleware` as return type so we can use _fns internally
|
||||||
|
export const createInterceptors = <Req, Res, Err, Options>() => ({
|
||||||
|
error: new Interceptors<ErrInterceptor<Err, Res, Req, Options>>(),
|
||||||
|
request: new Interceptors<ReqInterceptor<Req, Options>>(),
|
||||||
|
response: new Interceptors<ResInterceptor<Res, Req, Options>>(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const defaultQuerySerializer = createQuerySerializer({
|
||||||
|
allowReserved: false,
|
||||||
|
array: {
|
||||||
|
explode: true,
|
||||||
|
style: 'form',
|
||||||
|
},
|
||||||
|
object: {
|
||||||
|
explode: true,
|
||||||
|
style: 'deepObject',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const defaultHeaders = {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createConfig = <T extends ClientOptions = ClientOptions>(
|
||||||
|
override: Config<Omit<ClientOptions, keyof T> & T> = {},
|
||||||
|
): Config<Omit<ClientOptions, keyof T> & T> => ({
|
||||||
|
...jsonBodySerializer,
|
||||||
|
headers: defaultHeaders,
|
||||||
|
parseAs: 'auto',
|
||||||
|
querySerializer: defaultQuerySerializer,
|
||||||
|
...override,
|
||||||
|
});
|
||||||
40
src/api/core/auth.ts
Normal file
40
src/api/core/auth.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
export type AuthToken = string | undefined;
|
||||||
|
|
||||||
|
export interface Auth {
|
||||||
|
/**
|
||||||
|
* Which part of the request do we use to send the auth?
|
||||||
|
*
|
||||||
|
* @default 'header'
|
||||||
|
*/
|
||||||
|
in?: 'header' | 'query' | 'cookie';
|
||||||
|
/**
|
||||||
|
* Header or query parameter name.
|
||||||
|
*
|
||||||
|
* @default 'Authorization'
|
||||||
|
*/
|
||||||
|
name?: string;
|
||||||
|
scheme?: 'basic' | 'bearer';
|
||||||
|
type: 'apiKey' | 'http';
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getAuthToken = async (
|
||||||
|
auth: Auth,
|
||||||
|
callback: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken,
|
||||||
|
): Promise<string | undefined> => {
|
||||||
|
const token =
|
||||||
|
typeof callback === 'function' ? await callback(auth) : callback;
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auth.scheme === 'bearer') {
|
||||||
|
return `Bearer ${token}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auth.scheme === 'basic') {
|
||||||
|
return `Basic ${btoa(token)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return token;
|
||||||
|
};
|
||||||
88
src/api/core/bodySerializer.ts
Normal file
88
src/api/core/bodySerializer.ts
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import type {
|
||||||
|
ArrayStyle,
|
||||||
|
ObjectStyle,
|
||||||
|
SerializerOptions,
|
||||||
|
} from './pathSerializer';
|
||||||
|
|
||||||
|
export type QuerySerializer = (query: Record<string, unknown>) => string;
|
||||||
|
|
||||||
|
export type BodySerializer = (body: any) => any;
|
||||||
|
|
||||||
|
export interface QuerySerializerOptions {
|
||||||
|
allowReserved?: boolean;
|
||||||
|
array?: SerializerOptions<ArrayStyle>;
|
||||||
|
object?: SerializerOptions<ObjectStyle>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const serializeFormDataPair = (
|
||||||
|
data: FormData,
|
||||||
|
key: string,
|
||||||
|
value: unknown,
|
||||||
|
): void => {
|
||||||
|
if (typeof value === 'string' || value instanceof Blob) {
|
||||||
|
data.append(key, value);
|
||||||
|
} else {
|
||||||
|
data.append(key, JSON.stringify(value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const serializeUrlSearchParamsPair = (
|
||||||
|
data: URLSearchParams,
|
||||||
|
key: string,
|
||||||
|
value: unknown,
|
||||||
|
): void => {
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
data.append(key, value);
|
||||||
|
} else {
|
||||||
|
data.append(key, JSON.stringify(value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const formDataBodySerializer = {
|
||||||
|
bodySerializer: <T extends Record<string, any> | Array<Record<string, any>>>(
|
||||||
|
body: T,
|
||||||
|
): FormData => {
|
||||||
|
const data = new FormData();
|
||||||
|
|
||||||
|
Object.entries(body).forEach(([key, value]) => {
|
||||||
|
if (value === undefined || value === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
value.forEach((v) => serializeFormDataPair(data, key, v));
|
||||||
|
} else {
|
||||||
|
serializeFormDataPair(data, key, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const jsonBodySerializer = {
|
||||||
|
bodySerializer: <T>(body: T): string =>
|
||||||
|
JSON.stringify(body, (_key, value) =>
|
||||||
|
typeof value === 'bigint' ? value.toString() : value,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
export const urlSearchParamsBodySerializer = {
|
||||||
|
bodySerializer: <T extends Record<string, any> | Array<Record<string, any>>>(
|
||||||
|
body: T,
|
||||||
|
): string => {
|
||||||
|
const data = new URLSearchParams();
|
||||||
|
|
||||||
|
Object.entries(body).forEach(([key, value]) => {
|
||||||
|
if (value === undefined || value === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
value.forEach((v) => serializeUrlSearchParamsPair(data, key, v));
|
||||||
|
} else {
|
||||||
|
serializeUrlSearchParamsPair(data, key, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return data.toString();
|
||||||
|
},
|
||||||
|
};
|
||||||
141
src/api/core/params.ts
Normal file
141
src/api/core/params.ts
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
type Slot = 'body' | 'headers' | 'path' | 'query';
|
||||||
|
|
||||||
|
export type Field =
|
||||||
|
| {
|
||||||
|
in: Exclude<Slot, 'body'>;
|
||||||
|
key: string;
|
||||||
|
map?: string;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
in: Extract<Slot, 'body'>;
|
||||||
|
key?: string;
|
||||||
|
map?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface Fields {
|
||||||
|
allowExtra?: Partial<Record<Slot, boolean>>;
|
||||||
|
args?: ReadonlyArray<Field>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type FieldsConfig = ReadonlyArray<Field | Fields>;
|
||||||
|
|
||||||
|
const extraPrefixesMap: Record<string, Slot> = {
|
||||||
|
$body_: 'body',
|
||||||
|
$headers_: 'headers',
|
||||||
|
$path_: 'path',
|
||||||
|
$query_: 'query',
|
||||||
|
};
|
||||||
|
const extraPrefixes = Object.entries(extraPrefixesMap);
|
||||||
|
|
||||||
|
type KeyMap = Map<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
in: Slot;
|
||||||
|
map?: string;
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
|
||||||
|
const buildKeyMap = (fields: FieldsConfig, map?: KeyMap): KeyMap => {
|
||||||
|
if (!map) {
|
||||||
|
map = new Map();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const config of fields) {
|
||||||
|
if ('in' in config) {
|
||||||
|
if (config.key) {
|
||||||
|
map.set(config.key, {
|
||||||
|
in: config.in,
|
||||||
|
map: config.map,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (config.args) {
|
||||||
|
buildKeyMap(config.args, map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return map;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface Params {
|
||||||
|
body: unknown;
|
||||||
|
headers: Record<string, unknown>;
|
||||||
|
path: Record<string, unknown>;
|
||||||
|
query: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const stripEmptySlots = (params: Params) => {
|
||||||
|
for (const [slot, value] of Object.entries(params)) {
|
||||||
|
if (value && typeof value === 'object' && !Object.keys(value).length) {
|
||||||
|
delete params[slot as Slot];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const buildClientParams = (
|
||||||
|
args: ReadonlyArray<unknown>,
|
||||||
|
fields: FieldsConfig,
|
||||||
|
) => {
|
||||||
|
const params: Params = {
|
||||||
|
body: {},
|
||||||
|
headers: {},
|
||||||
|
path: {},
|
||||||
|
query: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
const map = buildKeyMap(fields);
|
||||||
|
|
||||||
|
let config: FieldsConfig[number] | undefined;
|
||||||
|
|
||||||
|
for (const [index, arg] of args.entries()) {
|
||||||
|
if (fields[index]) {
|
||||||
|
config = fields[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('in' in config) {
|
||||||
|
if (config.key) {
|
||||||
|
const field = map.get(config.key)!;
|
||||||
|
const name = field.map || config.key;
|
||||||
|
(params[field.in] as Record<string, unknown>)[name] = arg;
|
||||||
|
} else {
|
||||||
|
params.body = arg;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (const [key, value] of Object.entries(arg ?? {})) {
|
||||||
|
const field = map.get(key);
|
||||||
|
|
||||||
|
if (field) {
|
||||||
|
const name = field.map || key;
|
||||||
|
(params[field.in] as Record<string, unknown>)[name] = value;
|
||||||
|
} else {
|
||||||
|
const extra = extraPrefixes.find(([prefix]) =>
|
||||||
|
key.startsWith(prefix),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (extra) {
|
||||||
|
const [prefix, slot] = extra;
|
||||||
|
(params[slot] as Record<string, unknown>)[
|
||||||
|
key.slice(prefix.length)
|
||||||
|
] = value;
|
||||||
|
} else {
|
||||||
|
for (const [slot, allowed] of Object.entries(
|
||||||
|
config.allowExtra ?? {},
|
||||||
|
)) {
|
||||||
|
if (allowed) {
|
||||||
|
(params[slot as Slot] as Record<string, unknown>)[key] = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stripEmptySlots(params);
|
||||||
|
|
||||||
|
return params;
|
||||||
|
};
|
||||||
179
src/api/core/pathSerializer.ts
Normal file
179
src/api/core/pathSerializer.ts
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
interface SerializeOptions<T>
|
||||||
|
extends SerializePrimitiveOptions,
|
||||||
|
SerializerOptions<T> {}
|
||||||
|
|
||||||
|
interface SerializePrimitiveOptions {
|
||||||
|
allowReserved?: boolean;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SerializerOptions<T> {
|
||||||
|
/**
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
explode: boolean;
|
||||||
|
style: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited';
|
||||||
|
export type ArraySeparatorStyle = ArrayStyle | MatrixStyle;
|
||||||
|
type MatrixStyle = 'label' | 'matrix' | 'simple';
|
||||||
|
export type ObjectStyle = 'form' | 'deepObject';
|
||||||
|
type ObjectSeparatorStyle = ObjectStyle | MatrixStyle;
|
||||||
|
|
||||||
|
interface SerializePrimitiveParam extends SerializePrimitiveOptions {
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const separatorArrayExplode = (style: ArraySeparatorStyle) => {
|
||||||
|
switch (style) {
|
||||||
|
case 'label':
|
||||||
|
return '.';
|
||||||
|
case 'matrix':
|
||||||
|
return ';';
|
||||||
|
case 'simple':
|
||||||
|
return ',';
|
||||||
|
default:
|
||||||
|
return '&';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const separatorArrayNoExplode = (style: ArraySeparatorStyle) => {
|
||||||
|
switch (style) {
|
||||||
|
case 'form':
|
||||||
|
return ',';
|
||||||
|
case 'pipeDelimited':
|
||||||
|
return '|';
|
||||||
|
case 'spaceDelimited':
|
||||||
|
return '%20';
|
||||||
|
default:
|
||||||
|
return ',';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const separatorObjectExplode = (style: ObjectSeparatorStyle) => {
|
||||||
|
switch (style) {
|
||||||
|
case 'label':
|
||||||
|
return '.';
|
||||||
|
case 'matrix':
|
||||||
|
return ';';
|
||||||
|
case 'simple':
|
||||||
|
return ',';
|
||||||
|
default:
|
||||||
|
return '&';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const serializeArrayParam = ({
|
||||||
|
allowReserved,
|
||||||
|
explode,
|
||||||
|
name,
|
||||||
|
style,
|
||||||
|
value,
|
||||||
|
}: SerializeOptions<ArraySeparatorStyle> & {
|
||||||
|
value: unknown[];
|
||||||
|
}) => {
|
||||||
|
if (!explode) {
|
||||||
|
const joinedValues = (
|
||||||
|
allowReserved ? value : value.map((v) => encodeURIComponent(v as string))
|
||||||
|
).join(separatorArrayNoExplode(style));
|
||||||
|
switch (style) {
|
||||||
|
case 'label':
|
||||||
|
return `.${joinedValues}`;
|
||||||
|
case 'matrix':
|
||||||
|
return `;${name}=${joinedValues}`;
|
||||||
|
case 'simple':
|
||||||
|
return joinedValues;
|
||||||
|
default:
|
||||||
|
return `${name}=${joinedValues}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const separator = separatorArrayExplode(style);
|
||||||
|
const joinedValues = value
|
||||||
|
.map((v) => {
|
||||||
|
if (style === 'label' || style === 'simple') {
|
||||||
|
return allowReserved ? v : encodeURIComponent(v as string);
|
||||||
|
}
|
||||||
|
|
||||||
|
return serializePrimitiveParam({
|
||||||
|
allowReserved,
|
||||||
|
name,
|
||||||
|
value: v as string,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.join(separator);
|
||||||
|
return style === 'label' || style === 'matrix'
|
||||||
|
? separator + joinedValues
|
||||||
|
: joinedValues;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const serializePrimitiveParam = ({
|
||||||
|
allowReserved,
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
}: SerializePrimitiveParam) => {
|
||||||
|
if (value === undefined || value === null) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof value === 'object') {
|
||||||
|
throw new Error(
|
||||||
|
'Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const serializeObjectParam = ({
|
||||||
|
allowReserved,
|
||||||
|
explode,
|
||||||
|
name,
|
||||||
|
style,
|
||||||
|
value,
|
||||||
|
valueOnly,
|
||||||
|
}: SerializeOptions<ObjectSeparatorStyle> & {
|
||||||
|
value: Record<string, unknown> | Date;
|
||||||
|
valueOnly?: boolean;
|
||||||
|
}) => {
|
||||||
|
if (value instanceof Date) {
|
||||||
|
return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (style !== 'deepObject' && !explode) {
|
||||||
|
let values: string[] = [];
|
||||||
|
Object.entries(value).forEach(([key, v]) => {
|
||||||
|
values = [
|
||||||
|
...values,
|
||||||
|
key,
|
||||||
|
allowReserved ? (v as string) : encodeURIComponent(v as string),
|
||||||
|
];
|
||||||
|
});
|
||||||
|
const joinedValues = values.join(',');
|
||||||
|
switch (style) {
|
||||||
|
case 'form':
|
||||||
|
return `${name}=${joinedValues}`;
|
||||||
|
case 'label':
|
||||||
|
return `.${joinedValues}`;
|
||||||
|
case 'matrix':
|
||||||
|
return `;${name}=${joinedValues}`;
|
||||||
|
default:
|
||||||
|
return joinedValues;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const separator = separatorObjectExplode(style);
|
||||||
|
const joinedValues = Object.entries(value)
|
||||||
|
.map(([key, v]) =>
|
||||||
|
serializePrimitiveParam({
|
||||||
|
allowReserved,
|
||||||
|
name: style === 'deepObject' ? `${name}[${key}]` : key,
|
||||||
|
value: v as string,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.join(separator);
|
||||||
|
return style === 'label' || style === 'matrix'
|
||||||
|
? separator + joinedValues
|
||||||
|
: joinedValues;
|
||||||
|
};
|
||||||
104
src/api/core/types.ts
Normal file
104
src/api/core/types.ts
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
import type { Auth, AuthToken } from './auth';
|
||||||
|
import type {
|
||||||
|
BodySerializer,
|
||||||
|
QuerySerializer,
|
||||||
|
QuerySerializerOptions,
|
||||||
|
} from './bodySerializer';
|
||||||
|
|
||||||
|
export interface Client<
|
||||||
|
RequestFn = never,
|
||||||
|
Config = unknown,
|
||||||
|
MethodFn = never,
|
||||||
|
BuildUrlFn = never,
|
||||||
|
> {
|
||||||
|
/**
|
||||||
|
* Returns the final request URL.
|
||||||
|
*/
|
||||||
|
buildUrl: BuildUrlFn;
|
||||||
|
connect: MethodFn;
|
||||||
|
delete: MethodFn;
|
||||||
|
get: MethodFn;
|
||||||
|
getConfig: () => Config;
|
||||||
|
head: MethodFn;
|
||||||
|
options: MethodFn;
|
||||||
|
patch: MethodFn;
|
||||||
|
post: MethodFn;
|
||||||
|
put: MethodFn;
|
||||||
|
request: RequestFn;
|
||||||
|
setConfig: (config: Config) => Config;
|
||||||
|
trace: MethodFn;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Config {
|
||||||
|
/**
|
||||||
|
* Auth token or a function returning auth token. The resolved value will be
|
||||||
|
* added to the request payload as defined by its `security` array.
|
||||||
|
*/
|
||||||
|
auth?: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken;
|
||||||
|
/**
|
||||||
|
* A function for serializing request body parameter. By default,
|
||||||
|
* {@link JSON.stringify()} will be used.
|
||||||
|
*/
|
||||||
|
bodySerializer?: BodySerializer | null;
|
||||||
|
/**
|
||||||
|
* An object containing any HTTP headers that you want to pre-populate your
|
||||||
|
* `Headers` object with.
|
||||||
|
*
|
||||||
|
* {@link https://developer.mozilla.org/docs/Web/API/Headers/Headers#init See more}
|
||||||
|
*/
|
||||||
|
headers?:
|
||||||
|
| RequestInit['headers']
|
||||||
|
| Record<
|
||||||
|
string,
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| (string | number | boolean)[]
|
||||||
|
| null
|
||||||
|
| undefined
|
||||||
|
| unknown
|
||||||
|
>;
|
||||||
|
/**
|
||||||
|
* The request method.
|
||||||
|
*
|
||||||
|
* {@link https://developer.mozilla.org/docs/Web/API/fetch#method See more}
|
||||||
|
*/
|
||||||
|
method?:
|
||||||
|
| 'CONNECT'
|
||||||
|
| 'DELETE'
|
||||||
|
| 'GET'
|
||||||
|
| 'HEAD'
|
||||||
|
| 'OPTIONS'
|
||||||
|
| 'PATCH'
|
||||||
|
| 'POST'
|
||||||
|
| 'PUT'
|
||||||
|
| 'TRACE';
|
||||||
|
/**
|
||||||
|
* A function for serializing request query parameters. By default, arrays
|
||||||
|
* will be exploded in form style, objects will be exploded in deepObject
|
||||||
|
* style, and reserved characters are percent-encoded.
|
||||||
|
*
|
||||||
|
* This method will have no effect if the native `paramsSerializer()` Axios
|
||||||
|
* API function is used.
|
||||||
|
*
|
||||||
|
* {@link https://swagger.io/docs/specification/serialization/#query View examples}
|
||||||
|
*/
|
||||||
|
querySerializer?: QuerySerializer | QuerySerializerOptions;
|
||||||
|
/**
|
||||||
|
* A function validating request data. This is useful if you want to ensure
|
||||||
|
* the request conforms to the desired shape, so it can be safely sent to
|
||||||
|
* the server.
|
||||||
|
*/
|
||||||
|
requestValidator?: (data: unknown) => Promise<unknown>;
|
||||||
|
/**
|
||||||
|
* A function transforming response data before it's returned. This is useful
|
||||||
|
* for post-processing data, e.g. converting ISO strings into Date objects.
|
||||||
|
*/
|
||||||
|
responseTransformer?: (data: unknown) => Promise<unknown>;
|
||||||
|
/**
|
||||||
|
* A function validating response data. This is useful if you want to ensure
|
||||||
|
* the response conforms to the desired shape, so it can be safely passed to
|
||||||
|
* the transformers and returned to the user.
|
||||||
|
*/
|
||||||
|
responseValidator?: (data: unknown) => Promise<unknown>;
|
||||||
|
}
|
||||||
3
src/api/index.ts
Normal file
3
src/api/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// This file is auto-generated by @hey-api/openapi-ts
|
||||||
|
export * from './types.gen';
|
||||||
|
export * from './sdk.gen';
|
||||||
4242
src/api/sdk.gen.ts
Normal file
4242
src/api/sdk.gen.ts
Normal file
File diff suppressed because one or more lines are too long
8620
src/api/types.gen.ts
Normal file
8620
src/api/types.gen.ts
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user