├── .devcontainer └── devcontainer.json ├── .eslintignore ├── .eslintrc.json ├── .github ├── CODEOWNERS ├── CODE_OF_CONDUCT.md └── workflows │ ├── ESLint.yaml │ └── Publish.yaml ├── .gitignore ├── .prettierrc.json ├── .yarn ├── plugins │ └── @yarnpkg │ │ └── plugin-typescript.cjs └── releases │ └── yarn-3.8.3.cjs ├── .yarnrc.yml ├── LICENSE ├── README.md ├── package.json ├── playground ├── nitro │ ├── nitro.config.ts │ ├── package.json │ ├── public │ │ └── wuff.json │ ├── routes │ │ └── index.ts │ ├── server.js │ ├── tsconfig.json │ └── yarn.lock └── nuxt │ ├── .gitignore │ ├── .npmrc │ ├── README.md │ ├── app.vue │ ├── nuxt.config.ts │ ├── package.json │ ├── public │ └── favicon.ico │ ├── tsconfig.json │ └── yarn.lock ├── renovate.json ├── scripts ├── eslint.ts └── tsconfig.json ├── src ├── index.ts └── runtime │ └── fastify.mjs ├── tsconfig.json ├── tsup.config.ts └── yarn.lock /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "noel-nitro-preset", 3 | "remoteUser": "noel", 4 | "containerUser": "noel", 5 | "image": "ghcr.io/auguwu/coder-images/node:latest", 6 | "features": { 7 | // JetBrains Gateway requires an SSH connection to be available, so, 8 | // this is here for that. :) 9 | "ghcr.io/devcontainers/features/sshd:1": { 10 | "version": "latest" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # User-specific stuff 2 | .idea/**/workspace.xml 3 | .idea/**/tasks.xml 4 | .idea/**/usage.statistics.xml 5 | .idea/**/dictionaries 6 | .idea/**/shelf 7 | 8 | # AWS User-specific 9 | .idea/**/aws.xml 10 | 11 | # Generated files 12 | .idea/**/contentModel.xml 13 | 14 | # Sensitive or high-churn files 15 | .idea/**/dataSources/ 16 | .idea/**/dataSources.ids 17 | .idea/**/dataSources.local.xml 18 | .idea/**/sqlDataSources.xml 19 | .idea/**/dynamic.xml 20 | .idea/**/uiDesigner.xml 21 | .idea/**/dbnavigator.xml 22 | 23 | # Gradle 24 | .idea/**/gradle.xml 25 | .idea/**/libraries 26 | 27 | # Gradle and Maven with auto-import 28 | # When using Gradle or Maven with auto-import, you should exclude module files, 29 | # since they will be recreated, and may cause churn. Uncomment if using 30 | # auto-import. 31 | # .idea/artifacts 32 | # .idea/compiler.xml 33 | # .idea/jarRepositories.xml 34 | # .idea/modules.xml 35 | # .idea/*.iml 36 | # .idea/modules 37 | # *.iml 38 | # *.ipr 39 | 40 | # CMake 41 | cmake-build-*/ 42 | 43 | # Mongo Explorer plugin 44 | .idea/**/mongoSettings.xml 45 | 46 | # File-based project format 47 | *.iws 48 | 49 | # IntelliJ 50 | out/ 51 | 52 | # mpeltonen/sbt-idea plugin 53 | .idea_modules/ 54 | 55 | # JIRA plugin 56 | atlassian-ide-plugin.xml 57 | 58 | # Cursive Clojure plugin 59 | .idea/replstate.xml 60 | 61 | # SonarLint plugin 62 | .idea/sonarlint/ 63 | 64 | # Crashlytics plugin (for Android Studio and IntelliJ) 65 | com_crashlytics_export_strings.xml 66 | crashlytics.properties 67 | crashlytics-build.properties 68 | fabric.properties 69 | 70 | # Editor-based Rest Client 71 | .idea/httpRequests 72 | 73 | # Android studio 3.1+ serialized cache file 74 | .idea/caches/build_file_checksums.ser 75 | 76 | ### JetBrains+all Patch ### 77 | # Ignore everything but code style settings and run configurations 78 | # that are supposed to be shared within teams. 79 | 80 | .idea/* 81 | 82 | !.idea/codeStyles 83 | !.idea/runConfigurations 84 | 85 | ### Node ### 86 | # Logs 87 | logs 88 | *.log 89 | npm-debug.log* 90 | yarn-debug.log* 91 | yarn-error.log* 92 | lerna-debug.log* 93 | .pnpm-debug.log* 94 | 95 | # Diagnostic reports (https://nodejs.org/api/report.html) 96 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 97 | 98 | # Runtime data 99 | pids 100 | *.pid 101 | *.seed 102 | *.pid.lock 103 | 104 | # Directory for instrumented libs generated by jscoverage/JSCover 105 | lib-cov 106 | 107 | # Coverage directory used by tools like istanbul 108 | coverage 109 | *.lcov 110 | 111 | # nyc test coverage 112 | .nyc_output 113 | 114 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 115 | .grunt 116 | 117 | # Bower dependency directory (https://bower.io/) 118 | bower_components 119 | 120 | # node-waf configuration 121 | .lock-wscript 122 | 123 | # Compiled binary addons (https://nodejs.org/api/addons.html) 124 | build/Release 125 | 126 | # Dependency directories 127 | node_modules/ 128 | jspm_packages/ 129 | 130 | # Snowpack dependency directory (https://snowpack.dev/) 131 | web_modules/ 132 | 133 | # TypeScript cache 134 | *.tsbuildinfo 135 | 136 | # Optional npm cache directory 137 | .npm 138 | 139 | # Optional eslint cache 140 | .eslintcache 141 | 142 | # Optional stylelint cache 143 | .stylelintcache 144 | 145 | # Microbundle cache 146 | .rpt2_cache/ 147 | .rts2_cache_cjs/ 148 | .rts2_cache_es/ 149 | .rts2_cache_umd/ 150 | 151 | # Optional REPL history 152 | .node_repl_history 153 | 154 | # Output of 'npm pack' 155 | *.tgz 156 | 157 | # Yarn Integrity file 158 | .yarn-integrity 159 | 160 | # dotenv environment variable files 161 | .env 162 | .env.development.local 163 | .env.test.local 164 | .env.production.local 165 | .env.local 166 | 167 | # parcel-bundler cache (https://parceljs.org/) 168 | .cache 169 | .parcel-cache 170 | 171 | # Next.js build output 172 | .next 173 | out 174 | 175 | # Nuxt.js build / generate output 176 | .nuxt 177 | dist 178 | 179 | # Gatsby files 180 | .cache/ 181 | # Comment in the public line in if your project uses Gatsby and not Next.js 182 | # https://nextjs.org/blog/next-9-1#public-directory-support 183 | # public 184 | 185 | # vuepress build output 186 | .vuepress/dist 187 | 188 | # vuepress v2.x temp and cache directory 189 | .temp 190 | 191 | # Docusaurus cache and generated files 192 | .docusaurus 193 | 194 | # Serverless directories 195 | .serverless/ 196 | 197 | # FuseBox cache 198 | .fusebox/ 199 | 200 | # DynamoDB Local files 201 | .dynamodb/ 202 | 203 | # TernJS port file 204 | .tern-port 205 | 206 | # Stores VSCode versions used for testing VSCode extensions 207 | .vscode-test 208 | 209 | # yarn v2 210 | .yarn/cache 211 | .yarn/unplugged 212 | .yarn/build-state.yml 213 | .yarn/install-state.gz 214 | .pnp.* 215 | 216 | ### Node Patch ### 217 | # Serverless Webpack directories 218 | .webpack/ 219 | 220 | # Optional stylelint cache 221 | 222 | # SvelteKit build / generate output 223 | .svelte-kit 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 | ### yarn ### 245 | # https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored 246 | 247 | .yarn/* 248 | !.yarn/releases 249 | !.yarn/patches 250 | !.yarn/plugins 251 | !.yarn/sdks 252 | !.yarn/versions 253 | 254 | # if you are NOT using Zero-installs, then: 255 | # comment the following lines 256 | !.yarn/cache 257 | 258 | # and uncomment the following lines 259 | # .pnp.* 260 | 261 | ### VisualStudio ### 262 | ## Ignore Visual Studio temporary files, build results, and 263 | ## files generated by popular Visual Studio add-ons. 264 | ## 265 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore 266 | 267 | # User-specific files 268 | *.rsuser 269 | *.suo 270 | *.user 271 | *.userosscache 272 | *.sln.docstates 273 | 274 | # User-specific files (MonoDevelop/Xamarin Studio) 275 | *.userprefs 276 | 277 | # Mono auto generated files 278 | mono_crash.* 279 | 280 | # Build results 281 | [Dd]ebug/ 282 | [Dd]ebugPublic/ 283 | [Rr]elease/ 284 | [Rr]eleases/ 285 | x64/ 286 | x86/ 287 | [Ww][Ii][Nn]32/ 288 | [Aa][Rr][Mm]/ 289 | [Aa][Rr][Mm]64/ 290 | bld/ 291 | [Bb]in/ 292 | [Oo]bj/ 293 | [Ll]og/ 294 | [Ll]ogs/ 295 | 296 | # Visual Studio 2015/2017 cache/options directory 297 | .vs/ 298 | # Uncomment if you have tasks that create the project's static files in wwwroot 299 | #wwwroot/ 300 | 301 | # Visual Studio 2017 auto generated files 302 | Generated\ Files/ 303 | 304 | # MSTest test Results 305 | [Tt]est[Rr]esult*/ 306 | [Bb]uild[Ll]og.* 307 | 308 | # NUnit 309 | *.VisualState.xml 310 | TestResult.xml 311 | nunit-*.xml 312 | 313 | # Build Results of an ATL Project 314 | [Dd]ebugPS/ 315 | [Rr]eleasePS/ 316 | dlldata.c 317 | 318 | # Benchmark Results 319 | BenchmarkDotNet.Artifacts/ 320 | 321 | # .NET Core 322 | project.lock.json 323 | project.fragment.lock.json 324 | artifacts/ 325 | 326 | # ASP.NET Scaffolding 327 | ScaffoldingReadMe.txt 328 | 329 | # StyleCop 330 | StyleCopReport.xml 331 | 332 | # Files built by Visual Studio 333 | *_i.c 334 | *_p.c 335 | *_h.h 336 | *.ilk 337 | *.meta 338 | *.obj 339 | *.iobj 340 | *.pch 341 | *.pdb 342 | *.ipdb 343 | *.pgc 344 | *.pgd 345 | *.rsp 346 | *.sbr 347 | *.tlb 348 | *.tli 349 | *.tlh 350 | *.tmp 351 | *.tmp_proj 352 | *_wpftmp.csproj 353 | *.tlog 354 | *.vspscc 355 | *.vssscc 356 | .builds 357 | *.pidb 358 | *.svclog 359 | *.scc 360 | 361 | # Chutzpah Test files 362 | _Chutzpah* 363 | 364 | # Visual C++ cache files 365 | ipch/ 366 | *.aps 367 | *.ncb 368 | *.opendb 369 | *.opensdf 370 | *.sdf 371 | *.cachefile 372 | *.VC.db 373 | *.VC.VC.opendb 374 | 375 | # Visual Studio profiler 376 | *.psess 377 | *.vsp 378 | *.vspx 379 | *.sap 380 | 381 | # Visual Studio Trace Files 382 | *.e2e 383 | 384 | # TFS 2012 Local Workspace 385 | $tf/ 386 | 387 | # Guidance Automation Toolkit 388 | *.gpState 389 | 390 | # ReSharper is a .NET coding add-in 391 | _ReSharper*/ 392 | *.[Rr]e[Ss]harper 393 | *.DotSettings.user 394 | 395 | # TeamCity is a build add-in 396 | _TeamCity* 397 | 398 | # DotCover is a Code Coverage Tool 399 | *.dotCover 400 | 401 | # AxoCover is a Code Coverage Tool 402 | .axoCover/* 403 | !.axoCover/settings.json 404 | 405 | # Coverlet is a free, cross platform Code Coverage Tool 406 | coverage*.json 407 | coverage*.xml 408 | coverage*.info 409 | 410 | # Visual Studio code coverage results 411 | *.coverage 412 | *.coveragexml 413 | 414 | # NCrunch 415 | _NCrunch_* 416 | .*crunch*.local.xml 417 | nCrunchTemp_* 418 | 419 | # MightyMoose 420 | *.mm.* 421 | AutoTest.Net/ 422 | 423 | # Web workbench (sass) 424 | .sass-cache/ 425 | 426 | # Installshield output folder 427 | [Ee]xpress/ 428 | 429 | # DocProject is a documentation generator add-in 430 | DocProject/buildhelp/ 431 | DocProject/Help/*.HxT 432 | DocProject/Help/*.HxC 433 | DocProject/Help/*.hhc 434 | DocProject/Help/*.hhk 435 | DocProject/Help/*.hhp 436 | DocProject/Help/Html2 437 | DocProject/Help/html 438 | 439 | # Click-Once directory 440 | publish/ 441 | 442 | # Publish Web Output 443 | *.[Pp]ublish.xml 444 | *.azurePubxml 445 | # Note: Comment the next line if you want to checkin your web deploy settings, 446 | # but database connection strings (with potential passwords) will be unencrypted 447 | *.pubxml 448 | *.publishproj 449 | 450 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 451 | # checkin your Azure Web App publish settings, but sensitive information contained 452 | # in these scripts will be unencrypted 453 | PublishScripts/ 454 | 455 | # NuGet Packages 456 | *.nupkg 457 | # NuGet Symbol Packages 458 | *.snupkg 459 | # The packages folder can be ignored because of Package Restore 460 | **/[Pp]ackages/* 461 | # except build/, which is used as an MSBuild target. 462 | !**/[Pp]ackages/build/ 463 | # Uncomment if necessary however generally it will be regenerated when needed 464 | #!**/[Pp]ackages/repositories.config 465 | # NuGet v3's project.json files produces more ignorable files 466 | *.nuget.props 467 | *.nuget.targets 468 | 469 | # Microsoft Azure Build Output 470 | csx/ 471 | *.build.csdef 472 | 473 | # Microsoft Azure Emulator 474 | ecf/ 475 | rcf/ 476 | 477 | # Windows Store app package directories and files 478 | AppPackages/ 479 | BundleArtifacts/ 480 | Package.StoreAssociation.xml 481 | _pkginfo.txt 482 | *.appx 483 | *.appxbundle 484 | *.appxupload 485 | 486 | # Visual Studio cache files 487 | # files ending in .cache can be ignored 488 | *.[Cc]ache 489 | # but keep track of directories ending in .cache 490 | !?*.[Cc]ache/ 491 | 492 | # Others 493 | ClientBin/ 494 | ~$* 495 | *~ 496 | *.dbmdl 497 | *.dbproj.schemaview 498 | *.jfm 499 | *.pfx 500 | *.publishsettings 501 | orleans.codegen.cs 502 | 503 | # Including strong name files can present a security risk 504 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 505 | #*.snk 506 | 507 | # Since there are multiple workflows, uncomment next line to ignore bower_components 508 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 509 | #bower_components/ 510 | 511 | # RIA/Silverlight projects 512 | Generated_Code/ 513 | 514 | # Backup & report files from converting an old project file 515 | # to a newer Visual Studio version. Backup files are not needed, 516 | # because we have git ;-) 517 | _UpgradeReport_Files/ 518 | Backup*/ 519 | UpgradeLog*.XML 520 | UpgradeLog*.htm 521 | ServiceFabricBackup/ 522 | *.rptproj.bak 523 | 524 | # SQL Server files 525 | *.mdf 526 | *.ldf 527 | *.ndf 528 | 529 | # Business Intelligence projects 530 | *.rdl.data 531 | *.bim.layout 532 | *.bim_*.settings 533 | *.rptproj.rsuser 534 | *- [Bb]ackup.rdl 535 | *- [Bb]ackup ([0-9]).rdl 536 | *- [Bb]ackup ([0-9][0-9]).rdl 537 | 538 | # Microsoft Fakes 539 | FakesAssemblies/ 540 | 541 | # GhostDoc plugin setting file 542 | *.GhostDoc.xml 543 | 544 | # Node.js Tools for Visual Studio 545 | .ntvs_analysis.dat 546 | 547 | # Visual Studio 6 build log 548 | *.plg 549 | 550 | # Visual Studio 6 workspace options file 551 | *.opt 552 | 553 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 554 | *.vbw 555 | 556 | # Visual Studio 6 auto-generated project file (contains which files were open etc.) 557 | *.vbp 558 | 559 | # Visual Studio 6 workspace and project file (working project files containing files to include in project) 560 | *.dsw 561 | *.dsp 562 | 563 | # Visual Studio 6 technical files 564 | 565 | # Visual Studio LightSwitch build output 566 | **/*.HTMLClient/GeneratedArtifacts 567 | **/*.DesktopClient/GeneratedArtifacts 568 | **/*.DesktopClient/ModelManifest.xml 569 | **/*.Server/GeneratedArtifacts 570 | **/*.Server/ModelManifest.xml 571 | _Pvt_Extensions 572 | 573 | # Paket dependency manager 574 | .paket/paket.exe 575 | paket-files/ 576 | 577 | # FAKE - F# Make 578 | .fake/ 579 | 580 | # CodeRush personal settings 581 | .cr/personal 582 | 583 | # Python Tools for Visual Studio (PTVS) 584 | __pycache__/ 585 | *.pyc 586 | 587 | # Cake - Uncomment if you are using it 588 | # tools/** 589 | # !tools/packages.config 590 | 591 | # Tabs Studio 592 | *.tss 593 | 594 | # Telerik's JustMock configuration file 595 | *.jmconfig 596 | 597 | # BizTalk build output 598 | *.btp.cs 599 | *.btm.cs 600 | *.odx.cs 601 | *.xsd.cs 602 | 603 | # OpenCover UI analysis results 604 | OpenCover/ 605 | 606 | # Azure Stream Analytics local run output 607 | ASALocalRun/ 608 | 609 | # MSBuild Binary and Structured Log 610 | *.binlog 611 | 612 | # NVidia Nsight GPU debugger configuration file 613 | *.nvuser 614 | 615 | # MFractors (Xamarin productivity tool) working folder 616 | .mfractor/ 617 | 618 | # Local History for Visual Studio 619 | .localhistory/ 620 | 621 | # Visual Studio History (VSHistory) files 622 | .vshistory/ 623 | 624 | # BeatPulse healthcheck temp database 625 | healthchecksdb 626 | 627 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 628 | MigrationBackup/ 629 | 630 | # Ionide (cross platform F# VS Code tools) working folder 631 | .ionide/ 632 | 633 | # Fody - auto-generated XML schema 634 | FodyWeavers.xsd 635 | 636 | # VS Code files for those working on multiple tools 637 | *.code-workspace 638 | 639 | # Local History for Visual Studio Code 640 | 641 | # Windows Installer files from build outputs 642 | *.cab 643 | *.msi 644 | *.msix 645 | *.msm 646 | *.msp 647 | 648 | # JetBrains Rider 649 | *.sln.iml 650 | 651 | ### VisualStudio Patch ### 652 | # Additional files built by Visual Studio 653 | 654 | # End of https://www.toptal.com/developers/gitignore/api/Node,Yarn,VisualStudio,VisualStudioCode,JetBrains+All 655 | 656 | .yarn/cache 657 | !.yarn/releases 658 | /**/.nitro 659 | /**/.output 660 | playground/**/ 661 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["prettier", "@augu/eslint-config/ts.js"], 3 | "ignorePatterns": ["**/*.md", "LICENSE"], 4 | "parserOptions": { 5 | "project": "./tsconfig.json" 6 | }, 7 | "overrides": [ 8 | { 9 | "files": ["scripts/**/*.ts"], 10 | "parserOptions": { 11 | "project": "./scripts/tsconfig.json" 12 | } 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @auguwu 2 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustArchive/fastify-nitro/4b51de3bf676e5f40f7128e2b1dd271772840e4f/.github/CODE_OF_CONDUCT.md -------------------------------------------------------------------------------- /.github/workflows/ESLint.yaml: -------------------------------------------------------------------------------- 1 | # 🐻‍❄️⚗️ @augu/fastify-nitro: Experimental Nitro preset to export a Nitro server as middleware for fastify 2 | # Copyright (c) 2023 Noel Towa 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in all 12 | # copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | name: ESLint 23 | on: 24 | workflow_dispatch: 25 | push: 26 | branches: 27 | - master 28 | paths-ignore: 29 | - '.vscode/**' 30 | - '.husky/**' 31 | - '.eslintignore' 32 | - '.gitignore' 33 | - '**.md' 34 | - 'LICENSE' 35 | - 'renovate.json' 36 | 37 | pull_request: 38 | types: [opened, synchronize] 39 | branches: 40 | - master 41 | paths-ignore: 42 | - '.vscode/**' 43 | - '.husky/**' 44 | - '.eslintignore' 45 | - '.gitignore' 46 | - '**.md' 47 | - 'LICENSE' 48 | - 'renovate.json' 49 | jobs: 50 | lint: 51 | runs-on: ubuntu-latest 52 | steps: 53 | - name: Checkout the repository 54 | uses: actions/checkout@v4 55 | 56 | - name: Uses Node.js 20.x 57 | uses: actions/setup-node@v4 58 | with: 59 | node-version: 20.x 60 | 61 | - name: Setup Yarn and node-modules cache 62 | id: yarn-cache 63 | uses: auguwu/node-pm-action@master 64 | 65 | - name: Install dependencies 66 | if: steps.yarn-cache.outputs.cache-hit != 'true' || steps.yarn-cache.outputs.node-modules-cache-hit != 'true' 67 | run: yarn install --immutable 68 | 69 | - name: Lint project with ESLint 70 | run: yarn lint 71 | -------------------------------------------------------------------------------- /.github/workflows/Publish.yaml: -------------------------------------------------------------------------------- 1 | # 🐻‍❄️⚗️ @augu/fastify-nitro: Experimental Nitro preset to export a Nitro server as middleware for fastify 2 | # Copyright (c) 2023 Noel Towa 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in all 12 | # copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | name: Release a new version 23 | on: 24 | release: 25 | types: 26 | - published 27 | jobs: 28 | release: 29 | name: Release a new version 30 | runs-on: ubuntu-latest 31 | steps: 32 | - name: Checkout repository 33 | uses: actions/checkout@v4 34 | 35 | - name: Setup Node.js 19 36 | uses: actions/setup-node@v4 37 | with: 38 | node-version: 19.x 39 | 40 | - name: Setup Yarn and node-modules cache 41 | id: yarn-cache 42 | uses: auguwu/node-pm-action@master 43 | 44 | - name: Install dependencies 45 | if: steps.yarn-cache.outputs.cache-hit != 'true' || steps.yarn-cache.outputs.node-modules-cache-hit != 'true' 46 | run: yarn install --immutable 47 | 48 | - name: Build distribution 49 | run: yarn build 50 | 51 | - name: Add src/runtime/ in dist/ 52 | run: cp -R ./src/runtime ./dist 53 | 54 | - name: Publish! 55 | uses: JS-DevTools/npm-publish@v3 56 | with: 57 | token: ${{ secrets.NPM_TOKEN }} 58 | access: public 59 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # User-specific stuff 2 | .idea/**/workspace.xml 3 | .idea/**/tasks.xml 4 | .idea/**/usage.statistics.xml 5 | .idea/**/dictionaries 6 | .idea/**/shelf 7 | 8 | # AWS User-specific 9 | .idea/**/aws.xml 10 | 11 | # Generated files 12 | .idea/**/contentModel.xml 13 | 14 | # Sensitive or high-churn files 15 | .idea/**/dataSources/ 16 | .idea/**/dataSources.ids 17 | .idea/**/dataSources.local.xml 18 | .idea/**/sqlDataSources.xml 19 | .idea/**/dynamic.xml 20 | .idea/**/uiDesigner.xml 21 | .idea/**/dbnavigator.xml 22 | 23 | # Gradle 24 | .idea/**/gradle.xml 25 | .idea/**/libraries 26 | 27 | # Gradle and Maven with auto-import 28 | # When using Gradle or Maven with auto-import, you should exclude module files, 29 | # since they will be recreated, and may cause churn. Uncomment if using 30 | # auto-import. 31 | # .idea/artifacts 32 | # .idea/compiler.xml 33 | # .idea/jarRepositories.xml 34 | # .idea/modules.xml 35 | # .idea/*.iml 36 | # .idea/modules 37 | # *.iml 38 | # *.ipr 39 | 40 | # CMake 41 | cmake-build-*/ 42 | 43 | # Mongo Explorer plugin 44 | .idea/**/mongoSettings.xml 45 | 46 | # File-based project format 47 | *.iws 48 | 49 | # IntelliJ 50 | out/ 51 | 52 | # mpeltonen/sbt-idea plugin 53 | .idea_modules/ 54 | 55 | # JIRA plugin 56 | atlassian-ide-plugin.xml 57 | 58 | # Cursive Clojure plugin 59 | .idea/replstate.xml 60 | 61 | # SonarLint plugin 62 | .idea/sonarlint/ 63 | 64 | # Crashlytics plugin (for Android Studio and IntelliJ) 65 | com_crashlytics_export_strings.xml 66 | crashlytics.properties 67 | crashlytics-build.properties 68 | fabric.properties 69 | 70 | # Editor-based Rest Client 71 | .idea/httpRequests 72 | 73 | # Android studio 3.1+ serialized cache file 74 | .idea/caches/build_file_checksums.ser 75 | 76 | ### JetBrains+all Patch ### 77 | # Ignore everything but code style settings and run configurations 78 | # that are supposed to be shared within teams. 79 | 80 | .idea/* 81 | 82 | !.idea/codeStyles 83 | !.idea/runConfigurations 84 | 85 | ### Node ### 86 | # Logs 87 | logs 88 | *.log 89 | npm-debug.log* 90 | yarn-debug.log* 91 | yarn-error.log* 92 | lerna-debug.log* 93 | .pnpm-debug.log* 94 | 95 | # Diagnostic reports (https://nodejs.org/api/report.html) 96 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 97 | 98 | # Runtime data 99 | pids 100 | *.pid 101 | *.seed 102 | *.pid.lock 103 | 104 | # Directory for instrumented libs generated by jscoverage/JSCover 105 | lib-cov 106 | 107 | # Coverage directory used by tools like istanbul 108 | coverage 109 | *.lcov 110 | 111 | # nyc test coverage 112 | .nyc_output 113 | 114 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 115 | .grunt 116 | 117 | # Bower dependency directory (https://bower.io/) 118 | bower_components 119 | 120 | # node-waf configuration 121 | .lock-wscript 122 | 123 | # Compiled binary addons (https://nodejs.org/api/addons.html) 124 | build/Release 125 | 126 | # Dependency directories 127 | node_modules/ 128 | jspm_packages/ 129 | 130 | # Snowpack dependency directory (https://snowpack.dev/) 131 | web_modules/ 132 | 133 | # TypeScript cache 134 | *.tsbuildinfo 135 | 136 | # Optional npm cache directory 137 | .npm 138 | 139 | # Optional eslint cache 140 | .eslintcache 141 | 142 | # Optional stylelint cache 143 | .stylelintcache 144 | 145 | # Microbundle cache 146 | .rpt2_cache/ 147 | .rts2_cache_cjs/ 148 | .rts2_cache_es/ 149 | .rts2_cache_umd/ 150 | 151 | # Optional REPL history 152 | .node_repl_history 153 | 154 | # Output of 'npm pack' 155 | *.tgz 156 | 157 | # Yarn Integrity file 158 | .yarn-integrity 159 | 160 | # dotenv environment variable files 161 | .env 162 | .env.development.local 163 | .env.test.local 164 | .env.production.local 165 | .env.local 166 | 167 | # parcel-bundler cache (https://parceljs.org/) 168 | .cache 169 | .parcel-cache 170 | 171 | # Next.js build output 172 | .next 173 | out 174 | 175 | # Nuxt.js build / generate output 176 | .nuxt 177 | dist 178 | 179 | # Gatsby files 180 | .cache/ 181 | # Comment in the public line in if your project uses Gatsby and not Next.js 182 | # https://nextjs.org/blog/next-9-1#public-directory-support 183 | # public 184 | 185 | # vuepress build output 186 | .vuepress/dist 187 | 188 | # vuepress v2.x temp and cache directory 189 | .temp 190 | 191 | # Docusaurus cache and generated files 192 | .docusaurus 193 | 194 | # Serverless directories 195 | .serverless/ 196 | 197 | # FuseBox cache 198 | .fusebox/ 199 | 200 | # DynamoDB Local files 201 | .dynamodb/ 202 | 203 | # TernJS port file 204 | .tern-port 205 | 206 | # Stores VSCode versions used for testing VSCode extensions 207 | .vscode-test 208 | 209 | # yarn v2 210 | .yarn/cache 211 | .yarn/unplugged 212 | .yarn/build-state.yml 213 | .yarn/install-state.gz 214 | .pnp.* 215 | 216 | ### Node Patch ### 217 | # Serverless Webpack directories 218 | .webpack/ 219 | 220 | # Optional stylelint cache 221 | 222 | # SvelteKit build / generate output 223 | .svelte-kit 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 | ### yarn ### 245 | # https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored 246 | 247 | .yarn/* 248 | !.yarn/releases 249 | !.yarn/patches 250 | !.yarn/plugins 251 | !.yarn/sdks 252 | !.yarn/versions 253 | 254 | # if you are NOT using Zero-installs, then: 255 | # comment the following lines 256 | !.yarn/cache 257 | 258 | # and uncomment the following lines 259 | # .pnp.* 260 | 261 | ### VisualStudio ### 262 | ## Ignore Visual Studio temporary files, build results, and 263 | ## files generated by popular Visual Studio add-ons. 264 | ## 265 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore 266 | 267 | # User-specific files 268 | *.rsuser 269 | *.suo 270 | *.user 271 | *.userosscache 272 | *.sln.docstates 273 | 274 | # User-specific files (MonoDevelop/Xamarin Studio) 275 | *.userprefs 276 | 277 | # Mono auto generated files 278 | mono_crash.* 279 | 280 | # Build results 281 | [Dd]ebug/ 282 | [Dd]ebugPublic/ 283 | [Rr]elease/ 284 | [Rr]eleases/ 285 | x64/ 286 | x86/ 287 | [Ww][Ii][Nn]32/ 288 | [Aa][Rr][Mm]/ 289 | [Aa][Rr][Mm]64/ 290 | bld/ 291 | [Bb]in/ 292 | [Oo]bj/ 293 | [Ll]og/ 294 | [Ll]ogs/ 295 | 296 | # Visual Studio 2015/2017 cache/options directory 297 | .vs/ 298 | # Uncomment if you have tasks that create the project's static files in wwwroot 299 | #wwwroot/ 300 | 301 | # Visual Studio 2017 auto generated files 302 | Generated\ Files/ 303 | 304 | # MSTest test Results 305 | [Tt]est[Rr]esult*/ 306 | [Bb]uild[Ll]og.* 307 | 308 | # NUnit 309 | *.VisualState.xml 310 | TestResult.xml 311 | nunit-*.xml 312 | 313 | # Build Results of an ATL Project 314 | [Dd]ebugPS/ 315 | [Rr]eleasePS/ 316 | dlldata.c 317 | 318 | # Benchmark Results 319 | BenchmarkDotNet.Artifacts/ 320 | 321 | # .NET Core 322 | project.lock.json 323 | project.fragment.lock.json 324 | artifacts/ 325 | 326 | # ASP.NET Scaffolding 327 | ScaffoldingReadMe.txt 328 | 329 | # StyleCop 330 | StyleCopReport.xml 331 | 332 | # Files built by Visual Studio 333 | *_i.c 334 | *_p.c 335 | *_h.h 336 | *.ilk 337 | *.meta 338 | *.obj 339 | *.iobj 340 | *.pch 341 | *.pdb 342 | *.ipdb 343 | *.pgc 344 | *.pgd 345 | *.rsp 346 | *.sbr 347 | *.tlb 348 | *.tli 349 | *.tlh 350 | *.tmp 351 | *.tmp_proj 352 | *_wpftmp.csproj 353 | *.tlog 354 | *.vspscc 355 | *.vssscc 356 | .builds 357 | *.pidb 358 | *.svclog 359 | *.scc 360 | 361 | # Chutzpah Test files 362 | _Chutzpah* 363 | 364 | # Visual C++ cache files 365 | ipch/ 366 | *.aps 367 | *.ncb 368 | *.opendb 369 | *.opensdf 370 | *.sdf 371 | *.cachefile 372 | *.VC.db 373 | *.VC.VC.opendb 374 | 375 | # Visual Studio profiler 376 | *.psess 377 | *.vsp 378 | *.vspx 379 | *.sap 380 | 381 | # Visual Studio Trace Files 382 | *.e2e 383 | 384 | # TFS 2012 Local Workspace 385 | $tf/ 386 | 387 | # Guidance Automation Toolkit 388 | *.gpState 389 | 390 | # ReSharper is a .NET coding add-in 391 | _ReSharper*/ 392 | *.[Rr]e[Ss]harper 393 | *.DotSettings.user 394 | 395 | # TeamCity is a build add-in 396 | _TeamCity* 397 | 398 | # DotCover is a Code Coverage Tool 399 | *.dotCover 400 | 401 | # AxoCover is a Code Coverage Tool 402 | .axoCover/* 403 | !.axoCover/settings.json 404 | 405 | # Coverlet is a free, cross platform Code Coverage Tool 406 | coverage*.json 407 | coverage*.xml 408 | coverage*.info 409 | 410 | # Visual Studio code coverage results 411 | *.coverage 412 | *.coveragexml 413 | 414 | # NCrunch 415 | _NCrunch_* 416 | .*crunch*.local.xml 417 | nCrunchTemp_* 418 | 419 | # MightyMoose 420 | *.mm.* 421 | AutoTest.Net/ 422 | 423 | # Web workbench (sass) 424 | .sass-cache/ 425 | 426 | # Installshield output folder 427 | [Ee]xpress/ 428 | 429 | # DocProject is a documentation generator add-in 430 | DocProject/buildhelp/ 431 | DocProject/Help/*.HxT 432 | DocProject/Help/*.HxC 433 | DocProject/Help/*.hhc 434 | DocProject/Help/*.hhk 435 | DocProject/Help/*.hhp 436 | DocProject/Help/Html2 437 | DocProject/Help/html 438 | 439 | # Click-Once directory 440 | publish/ 441 | 442 | # Publish Web Output 443 | *.[Pp]ublish.xml 444 | *.azurePubxml 445 | # Note: Comment the next line if you want to checkin your web deploy settings, 446 | # but database connection strings (with potential passwords) will be unencrypted 447 | *.pubxml 448 | *.publishproj 449 | 450 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 451 | # checkin your Azure Web App publish settings, but sensitive information contained 452 | # in these scripts will be unencrypted 453 | PublishScripts/ 454 | 455 | # NuGet Packages 456 | *.nupkg 457 | # NuGet Symbol Packages 458 | *.snupkg 459 | # The packages folder can be ignored because of Package Restore 460 | **/[Pp]ackages/* 461 | # except build/, which is used as an MSBuild target. 462 | !**/[Pp]ackages/build/ 463 | # Uncomment if necessary however generally it will be regenerated when needed 464 | #!**/[Pp]ackages/repositories.config 465 | # NuGet v3's project.json files produces more ignorable files 466 | *.nuget.props 467 | *.nuget.targets 468 | 469 | # Microsoft Azure Build Output 470 | csx/ 471 | *.build.csdef 472 | 473 | # Microsoft Azure Emulator 474 | ecf/ 475 | rcf/ 476 | 477 | # Windows Store app package directories and files 478 | AppPackages/ 479 | BundleArtifacts/ 480 | Package.StoreAssociation.xml 481 | _pkginfo.txt 482 | *.appx 483 | *.appxbundle 484 | *.appxupload 485 | 486 | # Visual Studio cache files 487 | # files ending in .cache can be ignored 488 | *.[Cc]ache 489 | # but keep track of directories ending in .cache 490 | !?*.[Cc]ache/ 491 | 492 | # Others 493 | ClientBin/ 494 | ~$* 495 | *~ 496 | *.dbmdl 497 | *.dbproj.schemaview 498 | *.jfm 499 | *.pfx 500 | *.publishsettings 501 | orleans.codegen.cs 502 | 503 | # Including strong name files can present a security risk 504 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 505 | #*.snk 506 | 507 | # Since there are multiple workflows, uncomment next line to ignore bower_components 508 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 509 | #bower_components/ 510 | 511 | # RIA/Silverlight projects 512 | Generated_Code/ 513 | 514 | # Backup & report files from converting an old project file 515 | # to a newer Visual Studio version. Backup files are not needed, 516 | # because we have git ;-) 517 | _UpgradeReport_Files/ 518 | Backup*/ 519 | UpgradeLog*.XML 520 | UpgradeLog*.htm 521 | ServiceFabricBackup/ 522 | *.rptproj.bak 523 | 524 | # SQL Server files 525 | *.mdf 526 | *.ldf 527 | *.ndf 528 | 529 | # Business Intelligence projects 530 | *.rdl.data 531 | *.bim.layout 532 | *.bim_*.settings 533 | *.rptproj.rsuser 534 | *- [Bb]ackup.rdl 535 | *- [Bb]ackup ([0-9]).rdl 536 | *- [Bb]ackup ([0-9][0-9]).rdl 537 | 538 | # Microsoft Fakes 539 | FakesAssemblies/ 540 | 541 | # GhostDoc plugin setting file 542 | *.GhostDoc.xml 543 | 544 | # Node.js Tools for Visual Studio 545 | .ntvs_analysis.dat 546 | 547 | # Visual Studio 6 build log 548 | *.plg 549 | 550 | # Visual Studio 6 workspace options file 551 | *.opt 552 | 553 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 554 | *.vbw 555 | 556 | # Visual Studio 6 auto-generated project file (contains which files were open etc.) 557 | *.vbp 558 | 559 | # Visual Studio 6 workspace and project file (working project files containing files to include in project) 560 | *.dsw 561 | *.dsp 562 | 563 | # Visual Studio 6 technical files 564 | 565 | # Visual Studio LightSwitch build output 566 | **/*.HTMLClient/GeneratedArtifacts 567 | **/*.DesktopClient/GeneratedArtifacts 568 | **/*.DesktopClient/ModelManifest.xml 569 | **/*.Server/GeneratedArtifacts 570 | **/*.Server/ModelManifest.xml 571 | _Pvt_Extensions 572 | 573 | # Paket dependency manager 574 | .paket/paket.exe 575 | paket-files/ 576 | 577 | # FAKE - F# Make 578 | .fake/ 579 | 580 | # CodeRush personal settings 581 | .cr/personal 582 | 583 | # Python Tools for Visual Studio (PTVS) 584 | __pycache__/ 585 | *.pyc 586 | 587 | # Cake - Uncomment if you are using it 588 | # tools/** 589 | # !tools/packages.config 590 | 591 | # Tabs Studio 592 | *.tss 593 | 594 | # Telerik's JustMock configuration file 595 | *.jmconfig 596 | 597 | # BizTalk build output 598 | *.btp.cs 599 | *.btm.cs 600 | *.odx.cs 601 | *.xsd.cs 602 | 603 | # OpenCover UI analysis results 604 | OpenCover/ 605 | 606 | # Azure Stream Analytics local run output 607 | ASALocalRun/ 608 | 609 | # MSBuild Binary and Structured Log 610 | *.binlog 611 | 612 | # NVidia Nsight GPU debugger configuration file 613 | *.nvuser 614 | 615 | # MFractors (Xamarin productivity tool) working folder 616 | .mfractor/ 617 | 618 | # Local History for Visual Studio 619 | .localhistory/ 620 | 621 | # Visual Studio History (VSHistory) files 622 | .vshistory/ 623 | 624 | # BeatPulse healthcheck temp database 625 | healthchecksdb 626 | 627 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 628 | MigrationBackup/ 629 | 630 | # Ionide (cross platform F# VS Code tools) working folder 631 | .ionide/ 632 | 633 | # Fody - auto-generated XML schema 634 | FodyWeavers.xsd 635 | 636 | # VS Code files for those working on multiple tools 637 | *.code-workspace 638 | 639 | # Local History for Visual Studio Code 640 | 641 | # Windows Installer files from build outputs 642 | *.cab 643 | *.msi 644 | *.msix 645 | *.msm 646 | *.msp 647 | 648 | # JetBrains Rider 649 | *.sln.iml 650 | 651 | ### VisualStudio Patch ### 652 | # Additional files built by Visual Studio 653 | 654 | # End of https://www.toptal.com/developers/gitignore/api/Node,Yarn,VisualStudio,VisualStudioCode,JetBrains+All 655 | 656 | .yarn/cache 657 | !.yarn/releases 658 | /**/.nitro 659 | /**/.output 660 | playground/**/.yarn 661 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "tabWidth": 4, 4 | "singleQuote": true, 5 | "endOfLine": "lf", 6 | "printWidth": 120, 7 | "trailingComma": "none", 8 | "bracketSpacing": true 9 | } 10 | -------------------------------------------------------------------------------- /.yarn/plugins/@yarnpkg/plugin-typescript.cjs: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | //prettier-ignore 3 | module.exports = { 4 | name: "@yarnpkg/plugin-typescript", 5 | factory: function (require) { 6 | var plugin=(()=>{var Ft=Object.create,H=Object.defineProperty,Bt=Object.defineProperties,Kt=Object.getOwnPropertyDescriptor,zt=Object.getOwnPropertyDescriptors,Gt=Object.getOwnPropertyNames,Q=Object.getOwnPropertySymbols,$t=Object.getPrototypeOf,ne=Object.prototype.hasOwnProperty,De=Object.prototype.propertyIsEnumerable;var Re=(e,t,r)=>t in e?H(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,u=(e,t)=>{for(var r in t||(t={}))ne.call(t,r)&&Re(e,r,t[r]);if(Q)for(var r of Q(t))De.call(t,r)&&Re(e,r,t[r]);return e},g=(e,t)=>Bt(e,zt(t)),Lt=e=>H(e,"__esModule",{value:!0});var R=(e,t)=>{var r={};for(var s in e)ne.call(e,s)&&t.indexOf(s)<0&&(r[s]=e[s]);if(e!=null&&Q)for(var s of Q(e))t.indexOf(s)<0&&De.call(e,s)&&(r[s]=e[s]);return r};var I=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),Vt=(e,t)=>{for(var r in t)H(e,r,{get:t[r],enumerable:!0})},Qt=(e,t,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of Gt(t))!ne.call(e,s)&&s!=="default"&&H(e,s,{get:()=>t[s],enumerable:!(r=Kt(t,s))||r.enumerable});return e},C=e=>Qt(Lt(H(e!=null?Ft($t(e)):{},"default",e&&e.__esModule&&"default"in e?{get:()=>e.default,enumerable:!0}:{value:e,enumerable:!0})),e);var xe=I(J=>{"use strict";Object.defineProperty(J,"__esModule",{value:!0});function _(e){let t=[...e.caches],r=t.shift();return r===void 0?ve():{get(s,n,a={miss:()=>Promise.resolve()}){return r.get(s,n,a).catch(()=>_({caches:t}).get(s,n,a))},set(s,n){return r.set(s,n).catch(()=>_({caches:t}).set(s,n))},delete(s){return r.delete(s).catch(()=>_({caches:t}).delete(s))},clear(){return r.clear().catch(()=>_({caches:t}).clear())}}}function ve(){return{get(e,t,r={miss:()=>Promise.resolve()}){return t().then(n=>Promise.all([n,r.miss(n)])).then(([n])=>n)},set(e,t){return Promise.resolve(t)},delete(e){return Promise.resolve()},clear(){return Promise.resolve()}}}J.createFallbackableCache=_;J.createNullCache=ve});var Ee=I(($s,qe)=>{qe.exports=xe()});var Te=I(ae=>{"use strict";Object.defineProperty(ae,"__esModule",{value:!0});function Jt(e={serializable:!0}){let t={};return{get(r,s,n={miss:()=>Promise.resolve()}){let a=JSON.stringify(r);if(a in t)return Promise.resolve(e.serializable?JSON.parse(t[a]):t[a]);let o=s(),d=n&&n.miss||(()=>Promise.resolve());return o.then(y=>d(y)).then(()=>o)},set(r,s){return t[JSON.stringify(r)]=e.serializable?JSON.stringify(s):s,Promise.resolve(s)},delete(r){return delete t[JSON.stringify(r)],Promise.resolve()},clear(){return t={},Promise.resolve()}}}ae.createInMemoryCache=Jt});var we=I((Vs,Me)=>{Me.exports=Te()});var Ce=I(M=>{"use strict";Object.defineProperty(M,"__esModule",{value:!0});function Xt(e,t,r){let s={"x-algolia-api-key":r,"x-algolia-application-id":t};return{headers(){return e===oe.WithinHeaders?s:{}},queryParameters(){return e===oe.WithinQueryParameters?s:{}}}}function Yt(e){let t=0,r=()=>(t++,new Promise(s=>{setTimeout(()=>{s(e(r))},Math.min(100*t,1e3))}));return e(r)}function ke(e,t=(r,s)=>Promise.resolve()){return Object.assign(e,{wait(r){return ke(e.then(s=>Promise.all([t(s,r),s])).then(s=>s[1]))}})}function Zt(e){let t=e.length-1;for(t;t>0;t--){let r=Math.floor(Math.random()*(t+1)),s=e[t];e[t]=e[r],e[r]=s}return e}function er(e,t){return Object.keys(t!==void 0?t:{}).forEach(r=>{e[r]=t[r](e)}),e}function tr(e,...t){let r=0;return e.replace(/%s/g,()=>encodeURIComponent(t[r++]))}var rr="4.2.0",sr=e=>()=>e.transporter.requester.destroy(),oe={WithinQueryParameters:0,WithinHeaders:1};M.AuthMode=oe;M.addMethods=er;M.createAuth=Xt;M.createRetryablePromise=Yt;M.createWaitablePromise=ke;M.destroy=sr;M.encode=tr;M.shuffle=Zt;M.version=rr});var F=I((Js,Ue)=>{Ue.exports=Ce()});var Ne=I(ie=>{"use strict";Object.defineProperty(ie,"__esModule",{value:!0});var nr={Delete:"DELETE",Get:"GET",Post:"POST",Put:"PUT"};ie.MethodEnum=nr});var B=I((Ys,We)=>{We.exports=Ne()});var Ze=I(A=>{"use strict";Object.defineProperty(A,"__esModule",{value:!0});var He=B();function ce(e,t){let r=e||{},s=r.data||{};return Object.keys(r).forEach(n=>{["timeout","headers","queryParameters","data","cacheable"].indexOf(n)===-1&&(s[n]=r[n])}),{data:Object.entries(s).length>0?s:void 0,timeout:r.timeout||t,headers:r.headers||{},queryParameters:r.queryParameters||{},cacheable:r.cacheable}}var X={Read:1,Write:2,Any:3},U={Up:1,Down:2,Timeouted:3},_e=2*60*1e3;function ue(e,t=U.Up){return g(u({},e),{status:t,lastUpdate:Date.now()})}function Fe(e){return e.status===U.Up||Date.now()-e.lastUpdate>_e}function Be(e){return e.status===U.Timeouted&&Date.now()-e.lastUpdate<=_e}function le(e){return{protocol:e.protocol||"https",url:e.url,accept:e.accept||X.Any}}function ar(e,t){return Promise.all(t.map(r=>e.get(r,()=>Promise.resolve(ue(r))))).then(r=>{let s=r.filter(d=>Fe(d)),n=r.filter(d=>Be(d)),a=[...s,...n],o=a.length>0?a.map(d=>le(d)):t;return{getTimeout(d,y){return(n.length===0&&d===0?1:n.length+3+d)*y},statelessHosts:o}})}var or=({isTimedOut:e,status:t})=>!e&&~~t==0,ir=e=>{let t=e.status;return e.isTimedOut||or(e)||~~(t/100)!=2&&~~(t/100)!=4},cr=({status:e})=>~~(e/100)==2,ur=(e,t)=>ir(e)?t.onRetry(e):cr(e)?t.onSucess(e):t.onFail(e);function Qe(e,t,r,s){let n=[],a=$e(r,s),o=Le(e,s),d=r.method,y=r.method!==He.MethodEnum.Get?{}:u(u({},r.data),s.data),b=u(u(u({"x-algolia-agent":e.userAgent.value},e.queryParameters),y),s.queryParameters),f=0,p=(h,S)=>{let O=h.pop();if(O===void 0)throw Ve(de(n));let P={data:a,headers:o,method:d,url:Ge(O,r.path,b),connectTimeout:S(f,e.timeouts.connect),responseTimeout:S(f,s.timeout)},x=j=>{let T={request:P,response:j,host:O,triesLeft:h.length};return n.push(T),T},v={onSucess:j=>Ke(j),onRetry(j){let T=x(j);return j.isTimedOut&&f++,Promise.all([e.logger.info("Retryable failure",pe(T)),e.hostsCache.set(O,ue(O,j.isTimedOut?U.Timeouted:U.Down))]).then(()=>p(h,S))},onFail(j){throw x(j),ze(j,de(n))}};return e.requester.send(P).then(j=>ur(j,v))};return ar(e.hostsCache,t).then(h=>p([...h.statelessHosts].reverse(),h.getTimeout))}function lr(e){let{hostsCache:t,logger:r,requester:s,requestsCache:n,responsesCache:a,timeouts:o,userAgent:d,hosts:y,queryParameters:b,headers:f}=e,p={hostsCache:t,logger:r,requester:s,requestsCache:n,responsesCache:a,timeouts:o,userAgent:d,headers:f,queryParameters:b,hosts:y.map(h=>le(h)),read(h,S){let O=ce(S,p.timeouts.read),P=()=>Qe(p,p.hosts.filter(j=>(j.accept&X.Read)!=0),h,O);if((O.cacheable!==void 0?O.cacheable:h.cacheable)!==!0)return P();let v={request:h,mappedRequestOptions:O,transporter:{queryParameters:p.queryParameters,headers:p.headers}};return p.responsesCache.get(v,()=>p.requestsCache.get(v,()=>p.requestsCache.set(v,P()).then(j=>Promise.all([p.requestsCache.delete(v),j]),j=>Promise.all([p.requestsCache.delete(v),Promise.reject(j)])).then(([j,T])=>T)),{miss:j=>p.responsesCache.set(v,j)})},write(h,S){return Qe(p,p.hosts.filter(O=>(O.accept&X.Write)!=0),h,ce(S,p.timeouts.write))}};return p}function dr(e){let t={value:`Algolia for JavaScript (${e})`,add(r){let s=`; ${r.segment}${r.version!==void 0?` (${r.version})`:""}`;return t.value.indexOf(s)===-1&&(t.value=`${t.value}${s}`),t}};return t}function Ke(e){try{return JSON.parse(e.content)}catch(t){throw Je(t.message,e)}}function ze({content:e,status:t},r){let s=e;try{s=JSON.parse(e).message}catch(n){}return Xe(s,t,r)}function pr(e,...t){let r=0;return e.replace(/%s/g,()=>encodeURIComponent(t[r++]))}function Ge(e,t,r){let s=Ye(r),n=`${e.protocol}://${e.url}/${t.charAt(0)==="/"?t.substr(1):t}`;return s.length&&(n+=`?${s}`),n}function Ye(e){let t=r=>Object.prototype.toString.call(r)==="[object Object]"||Object.prototype.toString.call(r)==="[object Array]";return Object.keys(e).map(r=>pr("%s=%s",r,t(e[r])?JSON.stringify(e[r]):e[r])).join("&")}function $e(e,t){if(e.method===He.MethodEnum.Get||e.data===void 0&&t.data===void 0)return;let r=Array.isArray(e.data)?e.data:u(u({},e.data),t.data);return JSON.stringify(r)}function Le(e,t){let r=u(u({},e.headers),t.headers),s={};return Object.keys(r).forEach(n=>{let a=r[n];s[n.toLowerCase()]=a}),s}function de(e){return e.map(t=>pe(t))}function pe(e){let t=e.request.headers["x-algolia-api-key"]?{"x-algolia-api-key":"*****"}:{};return g(u({},e),{request:g(u({},e.request),{headers:u(u({},e.request.headers),t)})})}function Xe(e,t,r){return{name:"ApiError",message:e,status:t,transporterStackTrace:r}}function Je(e,t){return{name:"DeserializationError",message:e,response:t}}function Ve(e){return{name:"RetryError",message:"Unreachable hosts - your application id may be incorrect. If the error persists, contact support@algolia.com.",transporterStackTrace:e}}A.CallEnum=X;A.HostStatusEnum=U;A.createApiError=Xe;A.createDeserializationError=Je;A.createMappedRequestOptions=ce;A.createRetryError=Ve;A.createStatefulHost=ue;A.createStatelessHost=le;A.createTransporter=lr;A.createUserAgent=dr;A.deserializeFailure=ze;A.deserializeSuccess=Ke;A.isStatefulHostTimeouted=Be;A.isStatefulHostUp=Fe;A.serializeData=$e;A.serializeHeaders=Le;A.serializeQueryParameters=Ye;A.serializeUrl=Ge;A.stackFrameWithoutCredentials=pe;A.stackTraceWithoutCredentials=de});var K=I((en,et)=>{et.exports=Ze()});var tt=I(w=>{"use strict";Object.defineProperty(w,"__esModule",{value:!0});var N=F(),mr=K(),z=B(),hr=e=>{let t=e.region||"us",r=N.createAuth(N.AuthMode.WithinHeaders,e.appId,e.apiKey),s=mr.createTransporter(g(u({hosts:[{url:`analytics.${t}.algolia.com`}]},e),{headers:u(g(u({},r.headers()),{"content-type":"application/json"}),e.headers),queryParameters:u(u({},r.queryParameters()),e.queryParameters)})),n=e.appId;return N.addMethods({appId:n,transporter:s},e.methods)},yr=e=>(t,r)=>e.transporter.write({method:z.MethodEnum.Post,path:"2/abtests",data:t},r),gr=e=>(t,r)=>e.transporter.write({method:z.MethodEnum.Delete,path:N.encode("2/abtests/%s",t)},r),fr=e=>(t,r)=>e.transporter.read({method:z.MethodEnum.Get,path:N.encode("2/abtests/%s",t)},r),br=e=>t=>e.transporter.read({method:z.MethodEnum.Get,path:"2/abtests"},t),Pr=e=>(t,r)=>e.transporter.write({method:z.MethodEnum.Post,path:N.encode("2/abtests/%s/stop",t)},r);w.addABTest=yr;w.createAnalyticsClient=hr;w.deleteABTest=gr;w.getABTest=fr;w.getABTests=br;w.stopABTest=Pr});var st=I((rn,rt)=>{rt.exports=tt()});var at=I(G=>{"use strict";Object.defineProperty(G,"__esModule",{value:!0});var me=F(),jr=K(),nt=B(),Or=e=>{let t=e.region||"us",r=me.createAuth(me.AuthMode.WithinHeaders,e.appId,e.apiKey),s=jr.createTransporter(g(u({hosts:[{url:`recommendation.${t}.algolia.com`}]},e),{headers:u(g(u({},r.headers()),{"content-type":"application/json"}),e.headers),queryParameters:u(u({},r.queryParameters()),e.queryParameters)}));return me.addMethods({appId:e.appId,transporter:s},e.methods)},Ir=e=>t=>e.transporter.read({method:nt.MethodEnum.Get,path:"1/strategies/personalization"},t),Ar=e=>(t,r)=>e.transporter.write({method:nt.MethodEnum.Post,path:"1/strategies/personalization",data:t},r);G.createRecommendationClient=Or;G.getPersonalizationStrategy=Ir;G.setPersonalizationStrategy=Ar});var it=I((nn,ot)=>{ot.exports=at()});var jt=I(i=>{"use strict";Object.defineProperty(i,"__esModule",{value:!0});var l=F(),q=K(),m=B(),Sr=require("crypto");function Y(e){let t=r=>e.request(r).then(s=>{if(e.batch!==void 0&&e.batch(s.hits),!e.shouldStop(s))return s.cursor?t({cursor:s.cursor}):t({page:(r.page||0)+1})});return t({})}var Dr=e=>{let t=e.appId,r=l.createAuth(e.authMode!==void 0?e.authMode:l.AuthMode.WithinHeaders,t,e.apiKey),s=q.createTransporter(g(u({hosts:[{url:`${t}-dsn.algolia.net`,accept:q.CallEnum.Read},{url:`${t}.algolia.net`,accept:q.CallEnum.Write}].concat(l.shuffle([{url:`${t}-1.algolianet.com`},{url:`${t}-2.algolianet.com`},{url:`${t}-3.algolianet.com`}]))},e),{headers:u(g(u({},r.headers()),{"content-type":"application/x-www-form-urlencoded"}),e.headers),queryParameters:u(u({},r.queryParameters()),e.queryParameters)})),n={transporter:s,appId:t,addAlgoliaAgent(a,o){s.userAgent.add({segment:a,version:o})},clearCache(){return Promise.all([s.requestsCache.clear(),s.responsesCache.clear()]).then(()=>{})}};return l.addMethods(n,e.methods)};function ct(){return{name:"MissingObjectIDError",message:"All objects must have an unique objectID (like a primary key) to be valid. Algolia is also able to generate objectIDs automatically but *it's not recommended*. To do it, use the `{'autoGenerateObjectIDIfNotExist': true}` option."}}function ut(){return{name:"ObjectNotFoundError",message:"Object not found."}}function lt(){return{name:"ValidUntilNotFoundError",message:"ValidUntil not found in given secured api key."}}var Rr=e=>(t,r)=>{let d=r||{},{queryParameters:s}=d,n=R(d,["queryParameters"]),a=u({acl:t},s!==void 0?{queryParameters:s}:{}),o=(y,b)=>l.createRetryablePromise(f=>$(e)(y.key,b).catch(p=>{if(p.status!==404)throw p;return f()}));return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:"1/keys",data:a},n),o)},vr=e=>(t,r,s)=>{let n=q.createMappedRequestOptions(s);return n.queryParameters["X-Algolia-User-ID"]=t,e.transporter.write({method:m.MethodEnum.Post,path:"1/clusters/mapping",data:{cluster:r}},n)},xr=e=>(t,r,s)=>e.transporter.write({method:m.MethodEnum.Post,path:"1/clusters/mapping/batch",data:{users:t,cluster:r}},s),Z=e=>(t,r,s)=>{let n=(a,o)=>L(e)(t,{methods:{waitTask:D}}).waitTask(a.taskID,o);return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/operation",t),data:{operation:"copy",destination:r}},s),n)},qr=e=>(t,r,s)=>Z(e)(t,r,g(u({},s),{scope:[ee.Rules]})),Er=e=>(t,r,s)=>Z(e)(t,r,g(u({},s),{scope:[ee.Settings]})),Tr=e=>(t,r,s)=>Z(e)(t,r,g(u({},s),{scope:[ee.Synonyms]})),Mr=e=>(t,r)=>{let s=(n,a)=>l.createRetryablePromise(o=>$(e)(t,a).then(o).catch(d=>{if(d.status!==404)throw d}));return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Delete,path:l.encode("1/keys/%s",t)},r),s)},wr=()=>(e,t)=>{let r=q.serializeQueryParameters(t),s=Sr.createHmac("sha256",e).update(r).digest("hex");return Buffer.from(s+r).toString("base64")},$=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/keys/%s",t)},r),kr=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:"1/logs"},t),Cr=()=>e=>{let t=Buffer.from(e,"base64").toString("ascii"),r=/validUntil=(\d+)/,s=t.match(r);if(s===null)throw lt();return parseInt(s[1],10)-Math.round(new Date().getTime()/1e3)},Ur=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:"1/clusters/mapping/top"},t),Nr=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/clusters/mapping/%s",t)},r),Wr=e=>t=>{let n=t||{},{retrieveMappings:r}=n,s=R(n,["retrieveMappings"]);return r===!0&&(s.getClusters=!0),e.transporter.read({method:m.MethodEnum.Get,path:"1/clusters/mapping/pending"},s)},L=e=>(t,r={})=>{let s={transporter:e.transporter,appId:e.appId,indexName:t};return l.addMethods(s,r.methods)},Hr=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:"1/keys"},t),_r=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:"1/clusters"},t),Fr=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:"1/indexes"},t),Br=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:"1/clusters/mapping"},t),Kr=e=>(t,r,s)=>{let n=(a,o)=>L(e)(t,{methods:{waitTask:D}}).waitTask(a.taskID,o);return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/operation",t),data:{operation:"move",destination:r}},s),n)},zr=e=>(t,r)=>{let s=(n,a)=>Promise.all(Object.keys(n.taskID).map(o=>L(e)(o,{methods:{waitTask:D}}).waitTask(n.taskID[o],a)));return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:"1/indexes/*/batch",data:{requests:t}},r),s)},Gr=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Post,path:"1/indexes/*/objects",data:{requests:t}},r),$r=e=>(t,r)=>{let s=t.map(n=>g(u({},n),{params:q.serializeQueryParameters(n.params||{})}));return e.transporter.read({method:m.MethodEnum.Post,path:"1/indexes/*/queries",data:{requests:s},cacheable:!0},r)},Lr=e=>(t,r)=>Promise.all(t.map(s=>{let d=s.params,{facetName:n,facetQuery:a}=d,o=R(d,["facetName","facetQuery"]);return L(e)(s.indexName,{methods:{searchForFacetValues:dt}}).searchForFacetValues(n,a,u(u({},r),o))})),Vr=e=>(t,r)=>{let s=q.createMappedRequestOptions(r);return s.queryParameters["X-Algolia-User-ID"]=t,e.transporter.write({method:m.MethodEnum.Delete,path:"1/clusters/mapping"},s)},Qr=e=>(t,r)=>{let s=(n,a)=>l.createRetryablePromise(o=>$(e)(t,a).catch(d=>{if(d.status!==404)throw d;return o()}));return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/keys/%s/restore",t)},r),s)},Jr=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Post,path:"1/clusters/mapping/search",data:{query:t}},r),Xr=e=>(t,r)=>{let s=Object.assign({},r),f=r||{},{queryParameters:n}=f,a=R(f,["queryParameters"]),o=n?{queryParameters:n}:{},d=["acl","indexes","referers","restrictSources","queryParameters","description","maxQueriesPerIPPerHour","maxHitsPerQuery"],y=p=>Object.keys(s).filter(h=>d.indexOf(h)!==-1).every(h=>p[h]===s[h]),b=(p,h)=>l.createRetryablePromise(S=>$(e)(t,h).then(O=>y(O)?Promise.resolve():S()));return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Put,path:l.encode("1/keys/%s",t),data:o},a),b)},pt=e=>(t,r)=>{let s=(n,a)=>D(e)(n.taskID,a);return l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/batch",e.indexName),data:{requests:t}},r),s)},Yr=e=>t=>Y(g(u({},t),{shouldStop:r=>r.cursor===void 0,request:r=>e.transporter.read({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/browse",e.indexName),data:r},t)})),Zr=e=>t=>{let r=u({hitsPerPage:1e3},t);return Y(g(u({},r),{shouldStop:s=>s.hits.lengthg(u({},n),{hits:n.hits.map(a=>(delete a._highlightResult,a))}))}}))},es=e=>t=>{let r=u({hitsPerPage:1e3},t);return Y(g(u({},r),{shouldStop:s=>s.hits.lengthg(u({},n),{hits:n.hits.map(a=>(delete a._highlightResult,a))}))}}))},te=e=>(t,r,s)=>{let y=s||{},{batchSize:n}=y,a=R(y,["batchSize"]),o={taskIDs:[],objectIDs:[]},d=(b=0)=>{let f=[],p;for(p=b;p({action:r,body:h})),a).then(h=>(o.objectIDs=o.objectIDs.concat(h.objectIDs),o.taskIDs.push(h.taskID),p++,d(p)))};return l.createWaitablePromise(d(),(b,f)=>Promise.all(b.taskIDs.map(p=>D(e)(p,f))))},ts=e=>t=>l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/clear",e.indexName)},t),(r,s)=>D(e)(r.taskID,s)),rs=e=>t=>{let a=t||{},{forwardToReplicas:r}=a,s=R(a,["forwardToReplicas"]),n=q.createMappedRequestOptions(s);return r&&(n.queryParameters.forwardToReplicas=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/rules/clear",e.indexName)},n),(o,d)=>D(e)(o.taskID,d))},ss=e=>t=>{let a=t||{},{forwardToReplicas:r}=a,s=R(a,["forwardToReplicas"]),n=q.createMappedRequestOptions(s);return r&&(n.queryParameters.forwardToReplicas=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/synonyms/clear",e.indexName)},n),(o,d)=>D(e)(o.taskID,d))},ns=e=>(t,r)=>l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/deleteByQuery",e.indexName),data:t},r),(s,n)=>D(e)(s.taskID,n)),as=e=>t=>l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Delete,path:l.encode("1/indexes/%s",e.indexName)},t),(r,s)=>D(e)(r.taskID,s)),os=e=>(t,r)=>l.createWaitablePromise(yt(e)([t],r).then(s=>({taskID:s.taskIDs[0]})),(s,n)=>D(e)(s.taskID,n)),yt=e=>(t,r)=>{let s=t.map(n=>({objectID:n}));return te(e)(s,k.DeleteObject,r)},is=e=>(t,r)=>{let o=r||{},{forwardToReplicas:s}=o,n=R(o,["forwardToReplicas"]),a=q.createMappedRequestOptions(n);return s&&(a.queryParameters.forwardToReplicas=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Delete,path:l.encode("1/indexes/%s/rules/%s",e.indexName,t)},a),(d,y)=>D(e)(d.taskID,y))},cs=e=>(t,r)=>{let o=r||{},{forwardToReplicas:s}=o,n=R(o,["forwardToReplicas"]),a=q.createMappedRequestOptions(n);return s&&(a.queryParameters.forwardToReplicas=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Delete,path:l.encode("1/indexes/%s/synonyms/%s",e.indexName,t)},a),(d,y)=>D(e)(d.taskID,y))},us=e=>t=>gt(e)(t).then(()=>!0).catch(r=>{if(r.status!==404)throw r;return!1}),ls=e=>(t,r)=>{let y=r||{},{query:s,paginate:n}=y,a=R(y,["query","paginate"]),o=0,d=()=>ft(e)(s||"",g(u({},a),{page:o})).then(b=>{for(let[f,p]of Object.entries(b.hits))if(t(p))return{object:p,position:parseInt(f,10),page:o};if(o++,n===!1||o>=b.nbPages)throw ut();return d()});return d()},ds=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/indexes/%s/%s",e.indexName,t)},r),ps=()=>(e,t)=>{for(let[r,s]of Object.entries(e.hits))if(s.objectID===t)return parseInt(r,10);return-1},ms=e=>(t,r)=>{let o=r||{},{attributesToRetrieve:s}=o,n=R(o,["attributesToRetrieve"]),a=t.map(d=>u({indexName:e.indexName,objectID:d},s?{attributesToRetrieve:s}:{}));return e.transporter.read({method:m.MethodEnum.Post,path:"1/indexes/*/objects",data:{requests:a}},n)},hs=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/indexes/%s/rules/%s",e.indexName,t)},r),gt=e=>t=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/indexes/%s/settings",e.indexName),data:{getVersion:2}},t),ys=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/indexes/%s/synonyms/%s",e.indexName,t)},r),bt=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Get,path:l.encode("1/indexes/%s/task/%s",e.indexName,t.toString())},r),gs=e=>(t,r)=>l.createWaitablePromise(Pt(e)([t],r).then(s=>({objectID:s.objectIDs[0],taskID:s.taskIDs[0]})),(s,n)=>D(e)(s.taskID,n)),Pt=e=>(t,r)=>{let o=r||{},{createIfNotExists:s}=o,n=R(o,["createIfNotExists"]),a=s?k.PartialUpdateObject:k.PartialUpdateObjectNoCreate;return te(e)(t,a,n)},fs=e=>(t,r)=>{let O=r||{},{safe:s,autoGenerateObjectIDIfNotExist:n,batchSize:a}=O,o=R(O,["safe","autoGenerateObjectIDIfNotExist","batchSize"]),d=(P,x,v,j)=>l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/operation",P),data:{operation:v,destination:x}},j),(T,V)=>D(e)(T.taskID,V)),y=Math.random().toString(36).substring(7),b=`${e.indexName}_tmp_${y}`,f=he({appId:e.appId,transporter:e.transporter,indexName:b}),p=[],h=d(e.indexName,b,"copy",g(u({},o),{scope:["settings","synonyms","rules"]}));p.push(h);let S=(s?h.wait(o):h).then(()=>{let P=f(t,g(u({},o),{autoGenerateObjectIDIfNotExist:n,batchSize:a}));return p.push(P),s?P.wait(o):P}).then(()=>{let P=d(b,e.indexName,"move",o);return p.push(P),s?P.wait(o):P}).then(()=>Promise.all(p)).then(([P,x,v])=>({objectIDs:x.objectIDs,taskIDs:[P.taskID,...x.taskIDs,v.taskID]}));return l.createWaitablePromise(S,(P,x)=>Promise.all(p.map(v=>v.wait(x))))},bs=e=>(t,r)=>ye(e)(t,g(u({},r),{clearExistingRules:!0})),Ps=e=>(t,r)=>ge(e)(t,g(u({},r),{replaceExistingSynonyms:!0})),js=e=>(t,r)=>l.createWaitablePromise(he(e)([t],r).then(s=>({objectID:s.objectIDs[0],taskID:s.taskIDs[0]})),(s,n)=>D(e)(s.taskID,n)),he=e=>(t,r)=>{let o=r||{},{autoGenerateObjectIDIfNotExist:s}=o,n=R(o,["autoGenerateObjectIDIfNotExist"]),a=s?k.AddObject:k.UpdateObject;if(a===k.UpdateObject){for(let d of t)if(d.objectID===void 0)return l.createWaitablePromise(Promise.reject(ct()))}return te(e)(t,a,n)},Os=e=>(t,r)=>ye(e)([t],r),ye=e=>(t,r)=>{let d=r||{},{forwardToReplicas:s,clearExistingRules:n}=d,a=R(d,["forwardToReplicas","clearExistingRules"]),o=q.createMappedRequestOptions(a);return s&&(o.queryParameters.forwardToReplicas=1),n&&(o.queryParameters.clearExistingRules=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/rules/batch",e.indexName),data:t},o),(y,b)=>D(e)(y.taskID,b))},Is=e=>(t,r)=>ge(e)([t],r),ge=e=>(t,r)=>{let d=r||{},{forwardToReplicas:s,replaceExistingSynonyms:n}=d,a=R(d,["forwardToReplicas","replaceExistingSynonyms"]),o=q.createMappedRequestOptions(a);return s&&(o.queryParameters.forwardToReplicas=1),n&&(o.queryParameters.replaceExistingSynonyms=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/synonyms/batch",e.indexName),data:t},o),(y,b)=>D(e)(y.taskID,b))},ft=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/query",e.indexName),data:{query:t},cacheable:!0},r),dt=e=>(t,r,s)=>e.transporter.read({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/facets/%s/query",e.indexName,t),data:{facetQuery:r},cacheable:!0},s),mt=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/rules/search",e.indexName),data:{query:t}},r),ht=e=>(t,r)=>e.transporter.read({method:m.MethodEnum.Post,path:l.encode("1/indexes/%s/synonyms/search",e.indexName),data:{query:t}},r),As=e=>(t,r)=>{let o=r||{},{forwardToReplicas:s}=o,n=R(o,["forwardToReplicas"]),a=q.createMappedRequestOptions(n);return s&&(a.queryParameters.forwardToReplicas=1),l.createWaitablePromise(e.transporter.write({method:m.MethodEnum.Put,path:l.encode("1/indexes/%s/settings",e.indexName),data:t},a),(d,y)=>D(e)(d.taskID,y))},D=e=>(t,r)=>l.createRetryablePromise(s=>bt(e)(t,r).then(n=>n.status!=="published"?s():void 0)),Ss={AddObject:"addObject",Analytics:"analytics",Browser:"browse",DeleteIndex:"deleteIndex",DeleteObject:"deleteObject",EditSettings:"editSettings",ListIndexes:"listIndexes",Logs:"logs",Recommendation:"recommendation",Search:"search",SeeUnretrievableAttributes:"seeUnretrievableAttributes",Settings:"settings",Usage:"usage"},k={AddObject:"addObject",UpdateObject:"updateObject",PartialUpdateObject:"partialUpdateObject",PartialUpdateObjectNoCreate:"partialUpdateObjectNoCreate",DeleteObject:"deleteObject"},ee={Settings:"settings",Synonyms:"synonyms",Rules:"rules"},Ds={None:"none",StopIfEnoughMatches:"stopIfEnoughMatches"},Rs={Synonym:"synonym",OneWaySynonym:"oneWaySynonym",AltCorrection1:"altCorrection1",AltCorrection2:"altCorrection2",Placeholder:"placeholder"};i.ApiKeyACLEnum=Ss;i.BatchActionEnum=k;i.ScopeEnum=ee;i.StrategyEnum=Ds;i.SynonymEnum=Rs;i.addApiKey=Rr;i.assignUserID=vr;i.assignUserIDs=xr;i.batch=pt;i.browseObjects=Yr;i.browseRules=Zr;i.browseSynonyms=es;i.chunkedBatch=te;i.clearObjects=ts;i.clearRules=rs;i.clearSynonyms=ss;i.copyIndex=Z;i.copyRules=qr;i.copySettings=Er;i.copySynonyms=Tr;i.createBrowsablePromise=Y;i.createMissingObjectIDError=ct;i.createObjectNotFoundError=ut;i.createSearchClient=Dr;i.createValidUntilNotFoundError=lt;i.deleteApiKey=Mr;i.deleteBy=ns;i.deleteIndex=as;i.deleteObject=os;i.deleteObjects=yt;i.deleteRule=is;i.deleteSynonym=cs;i.exists=us;i.findObject=ls;i.generateSecuredApiKey=wr;i.getApiKey=$;i.getLogs=kr;i.getObject=ds;i.getObjectPosition=ps;i.getObjects=ms;i.getRule=hs;i.getSecuredApiKeyRemainingValidity=Cr;i.getSettings=gt;i.getSynonym=ys;i.getTask=bt;i.getTopUserIDs=Ur;i.getUserID=Nr;i.hasPendingMappings=Wr;i.initIndex=L;i.listApiKeys=Hr;i.listClusters=_r;i.listIndices=Fr;i.listUserIDs=Br;i.moveIndex=Kr;i.multipleBatch=zr;i.multipleGetObjects=Gr;i.multipleQueries=$r;i.multipleSearchForFacetValues=Lr;i.partialUpdateObject=gs;i.partialUpdateObjects=Pt;i.removeUserID=Vr;i.replaceAllObjects=fs;i.replaceAllRules=bs;i.replaceAllSynonyms=Ps;i.restoreApiKey=Qr;i.saveObject=js;i.saveObjects=he;i.saveRule=Os;i.saveRules=ye;i.saveSynonym=Is;i.saveSynonyms=ge;i.search=ft;i.searchForFacetValues=dt;i.searchRules=mt;i.searchSynonyms=ht;i.searchUserIDs=Jr;i.setSettings=As;i.updateApiKey=Xr;i.waitTask=D});var It=I((on,Ot)=>{Ot.exports=jt()});var At=I(re=>{"use strict";Object.defineProperty(re,"__esModule",{value:!0});function vs(){return{debug(e,t){return Promise.resolve()},info(e,t){return Promise.resolve()},error(e,t){return Promise.resolve()}}}var xs={Debug:1,Info:2,Error:3};re.LogLevelEnum=xs;re.createNullLogger=vs});var Dt=I((un,St)=>{St.exports=At()});var xt=I(fe=>{"use strict";Object.defineProperty(fe,"__esModule",{value:!0});var Rt=require("http"),vt=require("https"),qs=require("url");function Es(){let e={keepAlive:!0},t=new Rt.Agent(e),r=new vt.Agent(e);return{send(s){return new Promise(n=>{let a=qs.parse(s.url),o=a.query===null?a.pathname:`${a.pathname}?${a.query}`,d=u({agent:a.protocol==="https:"?r:t,hostname:a.hostname,path:o,method:s.method,headers:s.headers},a.port!==void 0?{port:a.port||""}:{}),y=(a.protocol==="https:"?vt:Rt).request(d,h=>{let S="";h.on("data",O=>S+=O),h.on("end",()=>{clearTimeout(f),clearTimeout(p),n({status:h.statusCode||0,content:S,isTimedOut:!1})})}),b=(h,S)=>setTimeout(()=>{y.abort(),n({status:0,content:S,isTimedOut:!0})},h*1e3),f=b(s.connectTimeout,"Connection timeout"),p;y.on("error",h=>{clearTimeout(f),clearTimeout(p),n({status:0,content:h.message,isTimedOut:!1})}),y.once("response",()=>{clearTimeout(f),p=b(s.responseTimeout,"Socket timeout")}),s.data!==void 0&&y.write(s.data),y.end()})},destroy(){return t.destroy(),r.destroy(),Promise.resolve()}}}fe.createNodeHttpRequester=Es});var Et=I((dn,qt)=>{qt.exports=xt()});var kt=I((pn,Tt)=>{"use strict";var Mt=Ee(),Ts=we(),W=st(),be=F(),Pe=it(),c=It(),Ms=Dt(),ws=Et(),ks=K();function wt(e,t,r){let s={appId:e,apiKey:t,timeouts:{connect:2,read:5,write:30},requester:ws.createNodeHttpRequester(),logger:Ms.createNullLogger(),responsesCache:Mt.createNullCache(),requestsCache:Mt.createNullCache(),hostsCache:Ts.createInMemoryCache(),userAgent:ks.createUserAgent(be.version).add({segment:"Node.js",version:process.versions.node})};return c.createSearchClient(g(u(u({},s),r),{methods:{search:c.multipleQueries,searchForFacetValues:c.multipleSearchForFacetValues,multipleBatch:c.multipleBatch,multipleGetObjects:c.multipleGetObjects,multipleQueries:c.multipleQueries,copyIndex:c.copyIndex,copySettings:c.copySettings,copyRules:c.copyRules,copySynonyms:c.copySynonyms,moveIndex:c.moveIndex,listIndices:c.listIndices,getLogs:c.getLogs,listClusters:c.listClusters,multipleSearchForFacetValues:c.multipleSearchForFacetValues,getApiKey:c.getApiKey,addApiKey:c.addApiKey,listApiKeys:c.listApiKeys,updateApiKey:c.updateApiKey,deleteApiKey:c.deleteApiKey,restoreApiKey:c.restoreApiKey,assignUserID:c.assignUserID,assignUserIDs:c.assignUserIDs,getUserID:c.getUserID,searchUserIDs:c.searchUserIDs,listUserIDs:c.listUserIDs,getTopUserIDs:c.getTopUserIDs,removeUserID:c.removeUserID,hasPendingMappings:c.hasPendingMappings,generateSecuredApiKey:c.generateSecuredApiKey,getSecuredApiKeyRemainingValidity:c.getSecuredApiKeyRemainingValidity,destroy:be.destroy,initIndex:n=>a=>c.initIndex(n)(a,{methods:{batch:c.batch,delete:c.deleteIndex,getObject:c.getObject,getObjects:c.getObjects,saveObject:c.saveObject,saveObjects:c.saveObjects,search:c.search,searchForFacetValues:c.searchForFacetValues,waitTask:c.waitTask,setSettings:c.setSettings,getSettings:c.getSettings,partialUpdateObject:c.partialUpdateObject,partialUpdateObjects:c.partialUpdateObjects,deleteObject:c.deleteObject,deleteObjects:c.deleteObjects,deleteBy:c.deleteBy,clearObjects:c.clearObjects,browseObjects:c.browseObjects,getObjectPosition:c.getObjectPosition,findObject:c.findObject,exists:c.exists,saveSynonym:c.saveSynonym,saveSynonyms:c.saveSynonyms,getSynonym:c.getSynonym,searchSynonyms:c.searchSynonyms,browseSynonyms:c.browseSynonyms,deleteSynonym:c.deleteSynonym,clearSynonyms:c.clearSynonyms,replaceAllObjects:c.replaceAllObjects,replaceAllSynonyms:c.replaceAllSynonyms,searchRules:c.searchRules,getRule:c.getRule,deleteRule:c.deleteRule,saveRule:c.saveRule,saveRules:c.saveRules,replaceAllRules:c.replaceAllRules,browseRules:c.browseRules,clearRules:c.clearRules}}),initAnalytics:()=>n=>W.createAnalyticsClient(g(u(u({},s),n),{methods:{addABTest:W.addABTest,getABTest:W.getABTest,getABTests:W.getABTests,stopABTest:W.stopABTest,deleteABTest:W.deleteABTest}})),initRecommendation:()=>n=>Pe.createRecommendationClient(g(u(u({},s),n),{methods:{getPersonalizationStrategy:Pe.getPersonalizationStrategy,setPersonalizationStrategy:Pe.setPersonalizationStrategy}}))}}))}wt.version=be.version;Tt.exports=wt});var Ut=I((mn,je)=>{var Ct=kt();je.exports=Ct;je.exports.default=Ct});var Ws={};Vt(Ws,{default:()=>Ks});var Oe=C(require("@yarnpkg/core")),E=C(require("@yarnpkg/core")),Ie=C(require("@yarnpkg/plugin-essentials")),Ht=C(require("semver"));var se=C(require("@yarnpkg/core")),Nt=C(Ut()),Cs="e8e1bd300d860104bb8c58453ffa1eb4",Us="OFCNCOG2CU",Wt=async(e,t)=>{var a;let r=se.structUtils.stringifyIdent(e),n=Ns(t).initIndex("npm-search");try{return((a=(await n.getObject(r,{attributesToRetrieve:["types"]})).types)==null?void 0:a.ts)==="definitely-typed"}catch(o){return!1}},Ns=e=>(0,Nt.default)(Us,Cs,{requester:{async send(r){try{let s=await se.httpUtils.request(r.url,r.data||null,{configuration:e,headers:r.headers});return{content:s.body,isTimedOut:!1,status:s.statusCode}}catch(s){return{content:s.response.body,isTimedOut:!1,status:s.response.statusCode}}}}});var _t=e=>e.scope?`${e.scope}__${e.name}`:`${e.name}`,Hs=async(e,t,r,s)=>{if(r.scope==="types")return;let{project:n}=e,{configuration:a}=n,o=a.makeResolver(),d={project:n,resolver:o,report:new E.ThrowReport};if(!await Wt(r,a))return;let b=_t(r),f=E.structUtils.parseRange(r.range).selector;if(!E.semverUtils.validRange(f)){let P=await o.getCandidates(r,new Map,d);f=E.structUtils.parseRange(P[0].reference).selector}let p=Ht.default.coerce(f);if(p===null)return;let h=`${Ie.suggestUtils.Modifier.CARET}${p.major}`,S=E.structUtils.makeDescriptor(E.structUtils.makeIdent("types",b),h),O=E.miscUtils.mapAndFind(n.workspaces,P=>{var T,V;let x=(T=P.manifest.dependencies.get(r.identHash))==null?void 0:T.descriptorHash,v=(V=P.manifest.devDependencies.get(r.identHash))==null?void 0:V.descriptorHash;if(x!==r.descriptorHash&&v!==r.descriptorHash)return E.miscUtils.mapAndFind.skip;let j=[];for(let Ae of Oe.Manifest.allDependencies){let Se=P.manifest[Ae].get(S.identHash);typeof Se!="undefined"&&j.push([Ae,Se])}return j.length===0?E.miscUtils.mapAndFind.skip:j});if(typeof O!="undefined")for(let[P,x]of O)e.manifest[P].set(x.identHash,x);else{try{if((await o.getCandidates(S,new Map,d)).length===0)return}catch{return}e.manifest[Ie.suggestUtils.Target.DEVELOPMENT].set(S.identHash,S)}},_s=async(e,t,r)=>{if(r.scope==="types")return;let s=_t(r),n=E.structUtils.makeIdent("types",s);for(let a of Oe.Manifest.allDependencies)typeof e.manifest[a].get(n.identHash)!="undefined"&&e.manifest[a].delete(n.identHash)},Fs=(e,t)=>{t.publishConfig&&t.publishConfig.typings&&(t.typings=t.publishConfig.typings),t.publishConfig&&t.publishConfig.types&&(t.types=t.publishConfig.types)},Bs={hooks:{afterWorkspaceDependencyAddition:Hs,afterWorkspaceDependencyRemoval:_s,beforeWorkspacePacking:Fs}},Ks=Bs;return Ws;})(); 7 | return plugin; 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | 3 | plugins: 4 | - path: .yarn/plugins/@yarnpkg/plugin-typescript.cjs 5 | spec: "@yarnpkg/plugin-typescript" 6 | 7 | yarnPath: .yarn/releases/yarn-3.8.3.cjs 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Noel Towa 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🐻‍❄️⚗️ @augu/fastify-nitro 2 | 3 | > _Experimental [Nitro](https://nitro.unjs.io) preset to export a Nitro server as middleware for fastify_ 4 | 5 | **@augu/fastify-nitro** is my little preset for building [Nitro](https://nitro.unjs.io) applications that expose a [fastify](https://fastify.io) server or middleware export. 6 | 7 | > **Note**: Why did you create this? 8 | > 9 | > I made this library to easily integrate fastify with Nitro (or Nuxt 3) so I can have other handlers bound to fastify and I don't really like how server middleware works or is defined, I rather just do it at the application level, not at the meta-framework level. 10 | 11 | ## Usage 12 | 13 | ```shell 14 | $ npm i --save-dev @augu/fastify-nitro 15 | $ yarn add -D @augu/fastify-nitro 16 | ``` 17 | 18 | > **nitro.config.ts** 19 | 20 | ```ts 21 | import { defineNitroConfig } from 'nitropack'; 22 | 23 | export default defineNitroConfig({ 24 | preset: '@augu/fastify-nitro' 25 | }); 26 | ``` 27 | 28 | ## Nuxt Usage 29 | 30 | To use this plugin with Nuxt 3, you just need to use `NITRO_PRESET=@augu/fastify-nitro` or add it in your Nuxt configuration: 31 | 32 | ```ts 33 | export default defineNuxtConfig({ 34 | nitro: { 35 | preset: '@augu/fastify-nitro' 36 | } 37 | }); 38 | ``` 39 | 40 | ## Base URL 41 | 42 | This preset respects the **baseURL** option in the Nitropack configuration. You will need to set the `prefix` to be usuable so fastify knows how to use it! 43 | 44 | > **nitro.config.ts** 45 | 46 | ```ts 47 | import { defineNitroConfig } from 'nitropack'; 48 | 49 | export default defineNitroConfig({ 50 | preset: '@augu/fastify-nitro', 51 | baseURL: '/some-url' 52 | }); 53 | ``` 54 | 55 | > **server.js** 56 | 57 | ```js 58 | const nitroPlugin = await import('./.output/server/index.mjs'); 59 | 60 | app.register(nitroPlugin, { 61 | // It has to be the same as `baseURL` in nitro.config.ts or it will 62 | // error. 63 | prefix: '/some-url' 64 | }); 65 | ``` 66 | 67 | ## Contributing 68 | 69 | Thanks for considering contributing to **@augu/fastify-nitro**! Before you boop your heart out on your keyboard ✧ ─=≡Σ((( つ•̀ω•́)つ, we recommend you to do the following: 70 | 71 | - Read the [Code of Conduct](./.github/CODE_OF_CONDUCT.md) 72 | - Read the [Contributing Guide](./.github/CONTRIBUTING.md) 73 | 74 | If you read both if you're a new time contributor, now you can do the following: 75 | 76 | - [Fork me! *\*♡( ⁎ᵕᴗᵕ⁎ )](https://github.com/auguwu/nitro-preset/fork) 77 | - Clone your fork on your machine: `git clone https://github.com/your-username/fastify-nitro` 78 | - Create a new branch: `git checkout -b some-branch-name` 79 | - Run `corepack enable` and use `yarn` for this project 80 | - BOOP THAT KEYBOARD!!!! ♡┉ˏ͛ (❛ 〰 ❛)ˊˎ┉♡ 81 | - Commit your changes onto your branch: `git commit -am "add features (。>‿‿<。 )"` 82 | - Push it to the fork you created: `git push -u origin some-branch-name` 83 | - Submit a Pull Request and then cry! 。・゚゚・(థ Д థ。)・゚゚・。 84 | 85 | ## License 86 | 87 | **@augu/nitro-preset** is released under the **MIT License** with love by [Noel](https://floofy.dev)! :polar_bear::purple_heart: 88 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@augu/fastify-nitro", 3 | "description": "🐻‍❄️⚗️ Experimental Nitro preset to export a Nitro server as middleware for fastify", 4 | "version": "1.2.0", 5 | "main": "./dist/index.js", 6 | "types": "./dist/index.d.ts", 7 | "repository": "https://github.com/auguwu/nitro-preset", 8 | "bugs": "https://github.com/auguwu/nitro-preset/issues", 9 | "packageManager": "yarn@3.8.3", 10 | "files": [ 11 | "./dist" 12 | ], 13 | "exports": { 14 | ".": { 15 | "require": "./dist/index.js", 16 | "import": "./dist/index.mjs", 17 | "types": "./dist/index.d.ts" 18 | } 19 | }, 20 | "scripts": { 21 | "build": "yarn fmt && yarn lint && rimraf build && tsup", 22 | "lint": "tsx --tsconfig ./scripts/tsconfig.json scripts/eslint.ts", 23 | "fmt": "prettier --write **/*.{ts,js,md,json,yml,yaml} --config ./.prettierrc.json" 24 | }, 25 | "dependencies": { 26 | "@noelware/utils": "2.5.1", 27 | "nitropack": "2.9.7" 28 | }, 29 | "devDependencies": { 30 | "@actions/core": "1.10.1", 31 | "@augu/eslint-config": "5.2.4", 32 | "@augu/tsconfig": "1.2.0", 33 | "@types/eslint": "8.56.10", 34 | "@types/node": "20.14.9", 35 | "@types/prettier": "3.0.0", 36 | "@typescript-eslint/eslint-plugin": "7.14.1", 37 | "@typescript-eslint/parser": "7.14.1", 38 | "eslint": "9.6.0", 39 | "eslint-config-prettier": "9.1.0", 40 | "log-symbols": "6.0.0", 41 | "prettier": "3.3.2", 42 | "rimraf": "5.0.7", 43 | "signale": "1.4.0", 44 | "tsup": "8.1.0", 45 | "tsx": "3.12.7", 46 | "typescript": "5.5.2" 47 | }, 48 | "peerDependencies": { 49 | "fastify": "4.x" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /playground/nitro/nitro.config.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * 🐻‍❄️⚗️ @augu/fastify-nitro: Experimental Nitro preset to export a Nitro server as middleware for fastify 3 | * Copyright (c) 2023 Noel Towa 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in all 13 | * copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | import { defineNitroConfig } from 'nitropack/config'; 25 | import { resolve } from 'path'; 26 | 27 | export default defineNitroConfig({ 28 | preset: resolve(__dirname, '..', '..', 'dist/index.mjs'), 29 | baseURL: '/wuff' 30 | }); 31 | -------------------------------------------------------------------------------- /playground/nitro/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module", 3 | "dependencies": { 4 | "fastify": "^4.12.0" 5 | }, 6 | "devDependencies": { 7 | "nitropack": "^2.1.0" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /playground/nitro/public/wuff.json: -------------------------------------------------------------------------------- 1 | { "wuffs": true } 2 | -------------------------------------------------------------------------------- /playground/nitro/routes/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * 🐻‍❄️⚗️ @augu/fastify-nitro: Experimental Nitro preset to export a Nitro server as middleware for fastify 3 | * Copyright (c) 2023 Noel Towa 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in all 13 | * copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | import { eventHandler } from 'h3'; 25 | 26 | export default eventHandler(() => 'Hello, world!'); 27 | -------------------------------------------------------------------------------- /playground/nitro/server.js: -------------------------------------------------------------------------------- 1 | import fastify from 'fastify'; 2 | 3 | async function main() { 4 | const app = fastify({ logger: true }); 5 | 6 | const { default: nitroPlugin } = await import('./.output/server/index.mjs'); 7 | app.register(nitroPlugin); 8 | 9 | app.get('/woof', (_, res) => res.status(200).send('woof')); 10 | app.listen({ port: 9090 }, (err) => { 11 | if (err !== null) { 12 | console.error(err); 13 | process.exit(1); 14 | } 15 | }); 16 | } 17 | 18 | main().catch((ex) => { 19 | console.error(ex); 20 | process.exit(1); 21 | }); 22 | -------------------------------------------------------------------------------- /playground/nitro/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /playground/nuxt/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log* 3 | .nuxt 4 | .nitro 5 | .cache 6 | .output 7 | .env 8 | dist 9 | .DS_Store 10 | -------------------------------------------------------------------------------- /playground/nuxt/.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=true 2 | strict-peer-dependencies=false 3 | -------------------------------------------------------------------------------- /playground/nuxt/README.md: -------------------------------------------------------------------------------- 1 | # Nuxt 3 Minimal Starter 2 | 3 | Look at the [Nuxt 3 documentation](https://nuxt.com/docs/getting-started/introduction) to learn more. 4 | 5 | ## Setup 6 | 7 | Make sure to install the dependencies: 8 | 9 | ```bash 10 | # yarn 11 | yarn install 12 | 13 | # npm 14 | npm install 15 | 16 | # pnpm 17 | pnpm install 18 | ``` 19 | 20 | ## Development Server 21 | 22 | Start the development server on `http://localhost:3000` 23 | 24 | ```bash 25 | npm run dev 26 | ``` 27 | 28 | ## Production 29 | 30 | Build the application for production: 31 | 32 | ```bash 33 | npm run build 34 | ``` 35 | 36 | Locally preview production build: 37 | 38 | ```bash 39 | npm run preview 40 | ``` 41 | 42 | Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information. 43 | -------------------------------------------------------------------------------- /playground/nuxt/app.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /playground/nuxt/nuxt.config.ts: -------------------------------------------------------------------------------- 1 | import { resolve } from 'path'; 2 | 3 | // https://nuxt.com/docs/api/configuration/nuxt-config 4 | export default defineNuxtConfig({ 5 | nitro: { 6 | preset: resolve(__dirname, '..', '..', 'dist/index.mjs') 7 | } 8 | }); 9 | -------------------------------------------------------------------------------- /playground/nuxt/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nuxt-app", 3 | "private": true, 4 | "type": "module", 5 | "scripts": { 6 | "build": "nuxt build", 7 | "dev": "nuxt dev", 8 | "generate": "nuxt generate", 9 | "preview": "nuxt preview", 10 | "postinstall": "nuxt prepare" 11 | }, 12 | "devDependencies": { 13 | "@types/node": "^20.0.0", 14 | "nuxt": "^3.4.3" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /playground/nuxt/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AugustArchive/fastify-nitro/4b51de3bf676e5f40f7128e2b1dd271772840e4f/playground/nuxt/public/favicon.ico -------------------------------------------------------------------------------- /playground/nuxt/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // https://nuxt.com/docs/guide/concepts/typescript 3 | "extends": "./.nuxt/tsconfig.json" 4 | } 5 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "automerge": true, 3 | "extends": ["config:base", "default:timezone(America/Phoenix)", "docker:disableMajor"], 4 | "vulnerabilityAlerts": { 5 | "labels": ["security"] 6 | }, 7 | "java": { 8 | "packageRules": [ 9 | { 10 | "matchPackagePatterns": ["^org\\.noelware[.:]"], 11 | "matchManagers": ["gradle"], 12 | "registryUrls": ["https://maven.noelware.org", "https://maven.noelware.org/snapshots"] 13 | } 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /scripts/eslint.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * 🐻‍❄️⚗️ @augu/fastify-nitro: Experimental Nitro preset to export a Nitro server as middleware for fastify 3 | * Copyright (c) 2023 Noel 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in all 13 | * copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | import { relative, resolve } from 'path'; 25 | import { warning, error } from '@actions/core'; 26 | import { Signale } from 'signale'; 27 | import { ESLint } from 'eslint'; 28 | 29 | const log = new Signale({ 30 | scope: '@augu/fastify-nitro:eslint', 31 | config: { 32 | displayBadge: true, 33 | displayScope: true, 34 | displayTimestamp: true, 35 | displayDate: true 36 | } 37 | }); 38 | 39 | async function main() { 40 | const symbols = await import('log-symbols').then((f) => f.default); 41 | const eslint = new ESLint({ 42 | useEslintrc: true, 43 | 44 | // if we aren't in ci, use the --fix flag to fix 45 | // the issues 46 | fix: process.env.CI === undefined 47 | }); 48 | 49 | // Lint frontend code 50 | log.info('Linting source code...'); 51 | const results = await eslint.lintFiles('src/**/*.{ts,tsx}'); 52 | for (const result of results) { 53 | const path = relative(resolve(__dirname, '..', 'src'), result.filePath); 54 | const hasErrors = result.errorCount > 0; 55 | const hasWarnings = result.warningCount > 0; 56 | const symbol = hasErrors ? symbols.error : hasWarnings ? symbols.warning : symbols.success; 57 | 58 | log.info(`${symbol} src/${path}`); 59 | for (const message of result.messages) { 60 | const s = message.severity === 1 ? symbols.warning : symbols.error; 61 | if (process.env.CI !== undefined) { 62 | const method = message.severity === 1 ? warning : error; 63 | method(`${s} ${message.message} (${message.ruleId})`, { 64 | endColumn: message.endColumn, 65 | endLine: message.endLine, 66 | file: result.filePath, 67 | startLine: message.line, 68 | startColumn: message.column 69 | }); 70 | } else { 71 | const method = message.severity === 1 ? log.warn : log.error; 72 | method(`${message.message} (${message.ruleId})`); 73 | } 74 | } 75 | } 76 | 77 | log.info('Linting scripts...'); 78 | const results2 = await eslint.lintFiles('scripts/**/*.ts'); 79 | for (const result of results2) { 80 | const path = relative(resolve(__dirname, '..', 'scripts'), result.filePath); 81 | const hasErrors = result.errorCount > 0; 82 | const hasWarnings = result.warningCount > 0; 83 | const symbol = hasErrors ? symbols.error : hasWarnings ? symbols.warning : symbols.success; 84 | 85 | log.info(`${symbol} scripts/${path}`); 86 | for (const message of result.messages) { 87 | const s = message.severity === 1 ? symbols.warning : symbols.error; 88 | if (process.env.CI !== undefined) { 89 | const method = message.severity === 1 ? warning : error; 90 | method(`${s} ${message.message} (${message.ruleId})`, { 91 | endColumn: message.endColumn, 92 | endLine: message.endLine, 93 | file: result.filePath, 94 | startLine: message.line, 95 | startColumn: message.column 96 | }); 97 | } else { 98 | const method = message.severity === 1 ? log.warn : log.error; 99 | method(` * ${s} ${message.message} (${message.ruleId})`); 100 | } 101 | } 102 | } 103 | } 104 | 105 | main().catch((ex) => { 106 | log.error(ex); 107 | process.exit(1); 108 | }); 109 | -------------------------------------------------------------------------------- /scripts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@augu/tsconfig", 3 | "compilerOptions": { 4 | "moduleResolution": "node", 5 | "removeComments": true, 6 | "types": ["node"], 7 | "rootDir": ".", 8 | "noEmit": true // tsx does this, so useless for `tsc` to do it 9 | }, 10 | "exclude": ["node_modules"], 11 | "include": ["**/*.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * 🐻‍❄️⚗️ @augu/fastify-nitro: Experimental Nitro preset to export a Nitro server as middleware for fastify 3 | * Copyright (c) 2023 Noel Towa 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in all 13 | * copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | import { defineNitroPreset } from 'nitropack'; 25 | import { resolve } from 'path'; 26 | 27 | export default defineNitroPreset({ 28 | entry: resolve(__dirname, 'runtime', 'fastify.mjs'), 29 | node: true, 30 | rollupConfig: { 31 | external: ['fastify-plugin'] 32 | } 33 | }); 34 | -------------------------------------------------------------------------------- /src/runtime/fastify.mjs: -------------------------------------------------------------------------------- 1 | /* eslint-ignore */ 2 | 3 | import '#internal/nitro/virtual/polyfill'; 4 | 5 | import { createEvent, sendError } from 'h3'; 6 | import { useRuntimeConfig } from '#internal/nitro/config'; 7 | import { nitroApp } from '#internal/nitro/app'; 8 | import fp from 'fastify-plugin'; 9 | 10 | export default fp( 11 | (instance, { prefix, onError }, done) => { 12 | const { 13 | app: { baseURL } 14 | } = useRuntimeConfig(); 15 | 16 | const url = baseURL.slice(0, -1); 17 | if (prefix !== undefined && prefix !== url) { 18 | return done( 19 | new Error( 20 | `You will need to set 'prefix' to ${url}, not ${prefix} or not set \`prefix\` at all to use the base URL from your Nitropack config` 21 | ) 22 | ); 23 | } 24 | 25 | instance.all(prefix || baseURL.slice(0, -1) || '/', async (req, reply) => { 26 | for (const [name, value] of Object.entries(reply.getHeaders())) { 27 | reply.raw.setHeader(name, value); 28 | } 29 | 30 | // hijack the reply so we can modify the contents of it 31 | reply.hijack(); 32 | 33 | const event = createEvent(req.raw, reply.raw); 34 | try { 35 | await nitroApp.h3App.handler(event); 36 | } catch (e) { 37 | if (!(e instanceof Error)) { 38 | e.unhandled = true; 39 | } 40 | 41 | if (nitroApp.h3App.options.onError) { 42 | await nitroApp.h3App.options.onError(e, event); 43 | } else { 44 | if (e.unhandled || e.fatal) { 45 | typeof onError === 'function' && onError(e, event); 46 | } 47 | 48 | await sendError(event, e, !!nitroApp.h3App.options.debug); 49 | } 50 | } 51 | }); 52 | 53 | done(); 54 | }, 55 | { 56 | fastify: '4.x', 57 | name: 'noel-nitropack' 58 | } 59 | ); 60 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@augu/tsconfig", 3 | "compilerOptions": { 4 | "moduleResolution": "node", 5 | "removeComments": true, 6 | "types": ["node"], 7 | "noEmit": true, // unbuild does this for us 8 | "allowJs": true, 9 | "baseUrl": "." 10 | }, 11 | "exclude": ["node_modules"], 12 | "include": ["**/*.ts"] 13 | } 14 | -------------------------------------------------------------------------------- /tsup.config.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * 🐻‍❄️⚗️ @augu/fastify-nitro: Experimental Nitro preset to export a Nitro server as middleware for fastify 3 | * Copyright (c) 2023 Noel Towa 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in all 13 | * copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | import { defineConfig } from 'tsup'; 25 | 26 | export default defineConfig({ 27 | entry: ['./src/index.ts'], 28 | bundle: true, 29 | clean: true, 30 | dts: true, 31 | format: ['cjs', 'esm'], 32 | banner: { 33 | js: [ 34 | '/*', 35 | ' * 🐻‍❄️⚗️ @augu/nitro-preset: Experimental Nitro preset to export a Nitro server as middleware for fastify', 36 | ' * Copyright (c) 2023 Noel ', 37 | ' *', 38 | ' * Permission is hereby granted, free of charge, to any person obtaining a copy', 39 | ' * of this software and associated documentation files (the "Software"), to deal', 40 | ' * in the Software without restriction, including without limitation the rights', 41 | ' * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell', 42 | ' * copies of the Software, and to permit persons to whom the Software is', 43 | ' * furnished to do so, subject to the following conditions:', 44 | ' *', 45 | ' * The above copyright notice and this permission notice shall be included in all', 46 | ' * copies or substantial portions of the Software.', 47 | ' *', 48 | ' * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR', 49 | ' * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,', 50 | ' * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE', 51 | ' * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER', 52 | ' * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,', 53 | ' * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE', 54 | ' * SOFTWARE.', 55 | ' */' 56 | ].join('\n') 57 | } 58 | }); 59 | --------------------------------------------------------------------------------