diff --git a/bindings/nodejs/generated.d.ts b/bindings/nodejs/generated.d.ts index 62e61e97052a..6f7db8c76cad 100644 --- a/bindings/nodejs/generated.d.ts +++ b/bindings/nodejs/generated.d.ts @@ -28,6 +28,60 @@ export class ExternalObject { [K: symbol]: T } } +export interface StatOptions { + /** + * Sets version for this operation. + * Retrieves data of a specified version of the given path. + */ + version?: string + /** + * Sets if-match condition for this operation. + * If file exists and its etag doesn't match, an error will be returned. + */ + ifMatch?: string + /** + * Sets if-none-match condition for this operation. + * If file exists and its etag matches, an error will be returned. + */ + ifNoneMatch?: string + /** + * Sets if-modified-since condition for this operation. + * If file exists and hasn't been modified since the specified time, an error will be returned. + * ISO 8601 formatted date string + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString + */ + ifModifiedSince?: string + /** + * Sets if-unmodified-since condition for this operation. + * If file exists and has been modified since the specified time, an error will be returned. + * ISO 8601 formatted date string + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString + */ + ifUnmodifiedSince?: string + /** + * Specifies the content-type header for presigned operations. + * Only meaningful when used along with presign. + */ + overrideContentType?: string + /** + * Specifies the cache-control header for presigned operations. + * Only meaningful when used along with presign. + */ + overrideCacheControl?: string + /** + * Specifies the content-disposition header for presigned operations. + * Only meaningful when used along with presign. + */ + overrideContentDisposition?: string +} +export const enum EntryMode { + /** FILE means the path has data to read. */ + FILE = 0, + /** DIR means the path can be listed. */ + DIR = 1, + /** Unknown means we don't know what we can do on this path. */ + Unknown = 2 +} export interface ListOptions { limit?: number recursive?: boolean @@ -89,6 +143,18 @@ export class Capability { get statWithIfMatch(): boolean /** If operator supports stat with if not match. */ get statWithIfNoneMatch(): boolean + /** If operator supports stat with if modified since. */ + get statWithIfModifiedSince(): boolean + /** If operator supports stat with if unmodified since. */ + get statWithIfUnmodifiedSince(): boolean + /** If operator supports stat with versions. */ + get statWithVersion(): boolean + /** If operator supports stat with override content type. */ + get statWithOverrideContentType(): boolean + /** If operator supports stat with override cache control. */ + get statWithOverrideCacheControl(): boolean + /** If operator supports stat with override content disposition. */ + get statWithOverrideContentDisposition(): boolean /** If operator supports read. */ get read(): boolean /** If operator supports read with if matched. */ @@ -189,7 +255,7 @@ export class Operator { * } * ``` */ - stat(path: string): Promise + stat(path: string, options?: StatOptions | undefined | null): Promise /** * Get current path's metadata **without cache** directly and synchronously. * @@ -201,7 +267,7 @@ export class Operator { * } * ``` */ - statSync(path: string): Metadata + statSync(path: string, options?: StatOptions | undefined | null): Metadata /** * Check if this operator can work correctly. * @@ -557,6 +623,10 @@ export class Metadata { * We will output this time in RFC3339 format like `1996-12-19T16:39:57+08:00`. */ get lastModified(): string | null + /** mode represent this entry's mode. */ + get mode(): EntryMode | null + /** Retrieves the `version` of the file, if available. */ + get version(): string | null } /** * BlockingReader is designed to read data from a given path in a blocking diff --git a/bindings/nodejs/generated.js b/bindings/nodejs/generated.js index e3fb40ca78be..0633155a251c 100644 --- a/bindings/nodejs/generated.js +++ b/bindings/nodejs/generated.js @@ -329,11 +329,12 @@ if (!nativeBinding) { throw new Error(`Failed to load native binding`) } -const { Capability, Operator, Entry, Metadata, BlockingReader, Reader, BlockingWriter, Writer, Lister, BlockingLister, Layer, RetryLayer } = nativeBinding +const { Capability, Operator, Entry, EntryMode, Metadata, BlockingReader, Reader, BlockingWriter, Writer, Lister, BlockingLister, Layer, RetryLayer } = nativeBinding module.exports.Capability = Capability module.exports.Operator = Operator module.exports.Entry = Entry +module.exports.EntryMode = EntryMode module.exports.Metadata = Metadata module.exports.BlockingReader = BlockingReader module.exports.Reader = Reader diff --git a/bindings/nodejs/package.json b/bindings/nodejs/package.json index 27a333aa8229..ebf224100e6a 100644 --- a/bindings/nodejs/package.json +++ b/bindings/nodejs/package.json @@ -73,7 +73,7 @@ "prettier": "^2.8.4", "typedoc": "^0.28", "typescript": "^5.0.2", - "vitest": "^3.0.8" + "vitest": "^3.2.3" }, "engines": { "node": ">= 10" diff --git a/bindings/nodejs/pnpm-lock.yaml b/bindings/nodejs/pnpm-lock.yaml index a93e31ec21aa..7a14d67cc8a1 100644 --- a/bindings/nodejs/pnpm-lock.yaml +++ b/bindings/nodejs/pnpm-lock.yaml @@ -39,8 +39,8 @@ devDependencies: specifier: ^5.0.2 version: 5.3.3 vitest: - specifier: ^3.0.8 - version: 3.0.8(@types/node@18.19.3) + specifier: ^3.2.3 + version: 3.2.3(@types/node@18.19.3) packages: @@ -660,7 +660,7 @@ packages: dev: true /@esbuild/android-arm64@0.19.8: - resolution: {integrity: sha512-B8JbS61bEunhfx8kasogFENgQfr/dIp+ggYXwTqdbMAgGDhRa3AaPpQMuQU0rNxDLECj6FhDzk1cF9WHMVwrtA==, tarball: https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.8.tgz} + resolution: {integrity: sha512-B8JbS61bEunhfx8kasogFENgQfr/dIp+ggYXwTqdbMAgGDhRa3AaPpQMuQU0rNxDLECj6FhDzk1cF9WHMVwrtA==} engines: {node: '>=12'} cpu: [arm64] os: [android] @@ -669,7 +669,7 @@ packages: optional: true /@esbuild/android-arm@0.19.8: - resolution: {integrity: sha512-31E2lxlGM1KEfivQl8Yf5aYU/mflz9g06H6S15ITUFQueMFtFjESRMoDSkvMo8thYvLBax+VKTPlpnx+sPicOA==, tarball: https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.8.tgz} + resolution: {integrity: sha512-31E2lxlGM1KEfivQl8Yf5aYU/mflz9g06H6S15ITUFQueMFtFjESRMoDSkvMo8thYvLBax+VKTPlpnx+sPicOA==} engines: {node: '>=12'} cpu: [arm] os: [android] @@ -678,7 +678,7 @@ packages: optional: true /@esbuild/android-x64@0.19.8: - resolution: {integrity: sha512-rdqqYfRIn4jWOp+lzQttYMa2Xar3OK9Yt2fhOhzFXqg0rVWEfSclJvZq5fZslnz6ypHvVf3CT7qyf0A5pM682A==, tarball: https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.8.tgz} + resolution: {integrity: sha512-rdqqYfRIn4jWOp+lzQttYMa2Xar3OK9Yt2fhOhzFXqg0rVWEfSclJvZq5fZslnz6ypHvVf3CT7qyf0A5pM682A==} engines: {node: '>=12'} cpu: [x64] os: [android] @@ -687,7 +687,7 @@ packages: optional: true /@esbuild/darwin-arm64@0.19.8: - resolution: {integrity: sha512-RQw9DemMbIq35Bprbboyf8SmOr4UXsRVxJ97LgB55VKKeJOOdvsIPy0nFyF2l8U+h4PtBx/1kRf0BelOYCiQcw==, tarball: https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.8.tgz} + resolution: {integrity: sha512-RQw9DemMbIq35Bprbboyf8SmOr4UXsRVxJ97LgB55VKKeJOOdvsIPy0nFyF2l8U+h4PtBx/1kRf0BelOYCiQcw==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] @@ -696,7 +696,7 @@ packages: optional: true /@esbuild/darwin-x64@0.19.8: - resolution: {integrity: sha512-3sur80OT9YdeZwIVgERAysAbwncom7b4bCI2XKLjMfPymTud7e/oY4y+ci1XVp5TfQp/bppn7xLw1n/oSQY3/Q==, tarball: https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.8.tgz} + resolution: {integrity: sha512-3sur80OT9YdeZwIVgERAysAbwncom7b4bCI2XKLjMfPymTud7e/oY4y+ci1XVp5TfQp/bppn7xLw1n/oSQY3/Q==} engines: {node: '>=12'} cpu: [x64] os: [darwin] @@ -705,7 +705,7 @@ packages: optional: true /@esbuild/freebsd-arm64@0.19.8: - resolution: {integrity: sha512-WAnPJSDattvS/XtPCTj1tPoTxERjcTpH6HsMr6ujTT+X6rylVe8ggxk8pVxzf5U1wh5sPODpawNicF5ta/9Tmw==, tarball: https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.8.tgz} + resolution: {integrity: sha512-WAnPJSDattvS/XtPCTj1tPoTxERjcTpH6HsMr6ujTT+X6rylVe8ggxk8pVxzf5U1wh5sPODpawNicF5ta/9Tmw==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] @@ -714,7 +714,7 @@ packages: optional: true /@esbuild/freebsd-x64@0.19.8: - resolution: {integrity: sha512-ICvZyOplIjmmhjd6mxi+zxSdpPTKFfyPPQMQTK/w+8eNK6WV01AjIztJALDtwNNfFhfZLux0tZLC+U9nSyA5Zg==, tarball: https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.8.tgz} + resolution: {integrity: sha512-ICvZyOplIjmmhjd6mxi+zxSdpPTKFfyPPQMQTK/w+8eNK6WV01AjIztJALDtwNNfFhfZLux0tZLC+U9nSyA5Zg==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] @@ -723,7 +723,7 @@ packages: optional: true /@esbuild/linux-arm64@0.19.8: - resolution: {integrity: sha512-z1zMZivxDLHWnyGOctT9JP70h0beY54xDDDJt4VpTX+iwA77IFsE1vCXWmprajJGa+ZYSqkSbRQ4eyLCpCmiCQ==, tarball: https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.8.tgz} + resolution: {integrity: sha512-z1zMZivxDLHWnyGOctT9JP70h0beY54xDDDJt4VpTX+iwA77IFsE1vCXWmprajJGa+ZYSqkSbRQ4eyLCpCmiCQ==} engines: {node: '>=12'} cpu: [arm64] os: [linux] @@ -732,7 +732,7 @@ packages: optional: true /@esbuild/linux-arm@0.19.8: - resolution: {integrity: sha512-H4vmI5PYqSvosPaTJuEppU9oz1dq2A7Mr2vyg5TF9Ga+3+MGgBdGzcyBP7qK9MrwFQZlvNyJrvz6GuCaj3OukQ==, tarball: https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.8.tgz} + resolution: {integrity: sha512-H4vmI5PYqSvosPaTJuEppU9oz1dq2A7Mr2vyg5TF9Ga+3+MGgBdGzcyBP7qK9MrwFQZlvNyJrvz6GuCaj3OukQ==} engines: {node: '>=12'} cpu: [arm] os: [linux] @@ -741,7 +741,7 @@ packages: optional: true /@esbuild/linux-ia32@0.19.8: - resolution: {integrity: sha512-1a8suQiFJmZz1khm/rDglOc8lavtzEMRo0v6WhPgxkrjcU0LkHj+TwBrALwoz/OtMExvsqbbMI0ChyelKabSvQ==, tarball: https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.8.tgz} + resolution: {integrity: sha512-1a8suQiFJmZz1khm/rDglOc8lavtzEMRo0v6WhPgxkrjcU0LkHj+TwBrALwoz/OtMExvsqbbMI0ChyelKabSvQ==} engines: {node: '>=12'} cpu: [ia32] os: [linux] @@ -750,7 +750,7 @@ packages: optional: true /@esbuild/linux-loong64@0.19.8: - resolution: {integrity: sha512-fHZWS2JJxnXt1uYJsDv9+b60WCc2RlvVAy1F76qOLtXRO+H4mjt3Tr6MJ5l7Q78X8KgCFudnTuiQRBhULUyBKQ==, tarball: https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.8.tgz} + resolution: {integrity: sha512-fHZWS2JJxnXt1uYJsDv9+b60WCc2RlvVAy1F76qOLtXRO+H4mjt3Tr6MJ5l7Q78X8KgCFudnTuiQRBhULUyBKQ==} engines: {node: '>=12'} cpu: [loong64] os: [linux] @@ -759,7 +759,7 @@ packages: optional: true /@esbuild/linux-mips64el@0.19.8: - resolution: {integrity: sha512-Wy/z0EL5qZYLX66dVnEg9riiwls5IYnziwuju2oUiuxVc+/edvqXa04qNtbrs0Ukatg5HEzqT94Zs7J207dN5Q==, tarball: https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.8.tgz} + resolution: {integrity: sha512-Wy/z0EL5qZYLX66dVnEg9riiwls5IYnziwuju2oUiuxVc+/edvqXa04qNtbrs0Ukatg5HEzqT94Zs7J207dN5Q==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] @@ -768,7 +768,7 @@ packages: optional: true /@esbuild/linux-ppc64@0.19.8: - resolution: {integrity: sha512-ETaW6245wK23YIEufhMQ3HSeHO7NgsLx8gygBVldRHKhOlD1oNeNy/P67mIh1zPn2Hr2HLieQrt6tWrVwuqrxg==, tarball: https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.8.tgz} + resolution: {integrity: sha512-ETaW6245wK23YIEufhMQ3HSeHO7NgsLx8gygBVldRHKhOlD1oNeNy/P67mIh1zPn2Hr2HLieQrt6tWrVwuqrxg==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] @@ -777,7 +777,7 @@ packages: optional: true /@esbuild/linux-riscv64@0.19.8: - resolution: {integrity: sha512-T2DRQk55SgoleTP+DtPlMrxi/5r9AeFgkhkZ/B0ap99zmxtxdOixOMI570VjdRCs9pE4Wdkz7JYrsPvsl7eESg==, tarball: https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.8.tgz} + resolution: {integrity: sha512-T2DRQk55SgoleTP+DtPlMrxi/5r9AeFgkhkZ/B0ap99zmxtxdOixOMI570VjdRCs9pE4Wdkz7JYrsPvsl7eESg==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] @@ -786,7 +786,7 @@ packages: optional: true /@esbuild/linux-s390x@0.19.8: - resolution: {integrity: sha512-NPxbdmmo3Bk7mbNeHmcCd7R7fptJaczPYBaELk6NcXxy7HLNyWwCyDJ/Xx+/YcNH7Im5dHdx9gZ5xIwyliQCbg==, tarball: https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.8.tgz} + resolution: {integrity: sha512-NPxbdmmo3Bk7mbNeHmcCd7R7fptJaczPYBaELk6NcXxy7HLNyWwCyDJ/Xx+/YcNH7Im5dHdx9gZ5xIwyliQCbg==} engines: {node: '>=12'} cpu: [s390x] os: [linux] @@ -795,7 +795,7 @@ packages: optional: true /@esbuild/linux-x64@0.19.8: - resolution: {integrity: sha512-lytMAVOM3b1gPypL2TRmZ5rnXl7+6IIk8uB3eLsV1JwcizuolblXRrc5ShPrO9ls/b+RTp+E6gbsuLWHWi2zGg==, tarball: https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.8.tgz} + resolution: {integrity: sha512-lytMAVOM3b1gPypL2TRmZ5rnXl7+6IIk8uB3eLsV1JwcizuolblXRrc5ShPrO9ls/b+RTp+E6gbsuLWHWi2zGg==} engines: {node: '>=12'} cpu: [x64] os: [linux] @@ -804,7 +804,7 @@ packages: optional: true /@esbuild/netbsd-x64@0.19.8: - resolution: {integrity: sha512-hvWVo2VsXz/8NVt1UhLzxwAfo5sioj92uo0bCfLibB0xlOmimU/DeAEsQILlBQvkhrGjamP0/el5HU76HAitGw==, tarball: https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.8.tgz} + resolution: {integrity: sha512-hvWVo2VsXz/8NVt1UhLzxwAfo5sioj92uo0bCfLibB0xlOmimU/DeAEsQILlBQvkhrGjamP0/el5HU76HAitGw==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] @@ -813,7 +813,7 @@ packages: optional: true /@esbuild/openbsd-x64@0.19.8: - resolution: {integrity: sha512-/7Y7u77rdvmGTxR83PgaSvSBJCC2L3Kb1M/+dmSIvRvQPXXCuC97QAwMugBNG0yGcbEGfFBH7ojPzAOxfGNkwQ==, tarball: https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.8.tgz} + resolution: {integrity: sha512-/7Y7u77rdvmGTxR83PgaSvSBJCC2L3Kb1M/+dmSIvRvQPXXCuC97QAwMugBNG0yGcbEGfFBH7ojPzAOxfGNkwQ==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] @@ -822,7 +822,7 @@ packages: optional: true /@esbuild/sunos-x64@0.19.8: - resolution: {integrity: sha512-9Lc4s7Oi98GqFA4HzA/W2JHIYfnXbUYgekUP/Sm4BG9sfLjyv6GKKHKKVs83SMicBF2JwAX6A1PuOLMqpD001w==, tarball: https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.8.tgz} + resolution: {integrity: sha512-9Lc4s7Oi98GqFA4HzA/W2JHIYfnXbUYgekUP/Sm4BG9sfLjyv6GKKHKKVs83SMicBF2JwAX6A1PuOLMqpD001w==} engines: {node: '>=12'} cpu: [x64] os: [sunos] @@ -831,7 +831,7 @@ packages: optional: true /@esbuild/win32-arm64@0.19.8: - resolution: {integrity: sha512-rq6WzBGjSzihI9deW3fC2Gqiak68+b7qo5/3kmB6Gvbh/NYPA0sJhrnp7wgV4bNwjqM+R2AApXGxMO7ZoGhIJg==, tarball: https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.8.tgz} + resolution: {integrity: sha512-rq6WzBGjSzihI9deW3fC2Gqiak68+b7qo5/3kmB6Gvbh/NYPA0sJhrnp7wgV4bNwjqM+R2AApXGxMO7ZoGhIJg==} engines: {node: '>=12'} cpu: [arm64] os: [win32] @@ -840,7 +840,7 @@ packages: optional: true /@esbuild/win32-ia32@0.19.8: - resolution: {integrity: sha512-AIAbverbg5jMvJznYiGhrd3sumfwWs8572mIJL5NQjJa06P8KfCPWZQ0NwZbPQnbQi9OWSZhFVSUWjjIrn4hSw==, tarball: https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.8.tgz} + resolution: {integrity: sha512-AIAbverbg5jMvJznYiGhrd3sumfwWs8572mIJL5NQjJa06P8KfCPWZQ0NwZbPQnbQi9OWSZhFVSUWjjIrn4hSw==} engines: {node: '>=12'} cpu: [ia32] os: [win32] @@ -849,7 +849,7 @@ packages: optional: true /@esbuild/win32-x64@0.19.8: - resolution: {integrity: sha512-bfZ0cQ1uZs2PqpulNL5j/3w+GDhP36k1K5c38QdQg+Swy51jFZWWeIkteNsufkQxp986wnqRRsb/bHbY1WQ7TA==, tarball: https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.8.tgz} + resolution: {integrity: sha512-bfZ0cQ1uZs2PqpulNL5j/3w+GDhP36k1K5c38QdQg+Swy51jFZWWeIkteNsufkQxp986wnqRRsb/bHbY1WQ7TA==} engines: {node: '>=12'} cpu: [x64] os: [win32] @@ -858,7 +858,7 @@ packages: optional: true /@gerrit0/mini-shiki@3.2.3: - resolution: {integrity: sha512-yemSYr0Oiqk5NAQRfbD5DKUTlThiZw1MxTMx/YpQTg6m4QRJDtV2JTYSuNevgx1ayy/O7x+uwDjh3IgECGFY/Q==, tarball: https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.2.3.tgz} + resolution: {integrity: sha512-yemSYr0Oiqk5NAQRfbD5DKUTlThiZw1MxTMx/YpQTg6m4QRJDtV2JTYSuNevgx1ayy/O7x+uwDjh3IgECGFY/Q==} dependencies: '@shikijs/engine-oniguruma': 3.2.2 '@shikijs/langs': 3.2.2 @@ -878,7 +878,7 @@ packages: dev: true /@rollup/rollup-android-arm-eabi@4.7.0: - resolution: {integrity: sha512-rGku10pL1StFlFvXX5pEv88KdGW6DHUghsxyP/aRYb9eH+74jTGJ3U0S/rtlsQ4yYq1Hcc7AMkoJOb1xu29Fxw==, tarball: https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.7.0.tgz} + resolution: {integrity: sha512-rGku10pL1StFlFvXX5pEv88KdGW6DHUghsxyP/aRYb9eH+74jTGJ3U0S/rtlsQ4yYq1Hcc7AMkoJOb1xu29Fxw==} cpu: [arm] os: [android] requiresBuild: true @@ -886,7 +886,7 @@ packages: optional: true /@rollup/rollup-android-arm64@4.7.0: - resolution: {integrity: sha512-/EBw0cuJ/KVHiU2qyVYUhogXz7W2vXxBzeE9xtVIMC+RyitlY2vvaoysMUqASpkUtoNIHlnKTu/l7mXOPgnKOA==, tarball: https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.7.0.tgz} + resolution: {integrity: sha512-/EBw0cuJ/KVHiU2qyVYUhogXz7W2vXxBzeE9xtVIMC+RyitlY2vvaoysMUqASpkUtoNIHlnKTu/l7mXOPgnKOA==} cpu: [arm64] os: [android] requiresBuild: true @@ -894,7 +894,7 @@ packages: optional: true /@rollup/rollup-darwin-arm64@4.7.0: - resolution: {integrity: sha512-4VXG1bgvClJdbEYYjQ85RkOtwN8sqI3uCxH0HC5w9fKdqzRzgG39K7GAehATGS8jghA7zNoS5CjSKkDEqWmNZg==, tarball: https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.7.0.tgz} + resolution: {integrity: sha512-4VXG1bgvClJdbEYYjQ85RkOtwN8sqI3uCxH0HC5w9fKdqzRzgG39K7GAehATGS8jghA7zNoS5CjSKkDEqWmNZg==} cpu: [arm64] os: [darwin] requiresBuild: true @@ -902,7 +902,7 @@ packages: optional: true /@rollup/rollup-darwin-x64@4.7.0: - resolution: {integrity: sha512-/ImhO+T/RWJ96hUbxiCn2yWI0/MeQZV/aeukQQfhxiSXuZJfyqtdHPUPrc84jxCfXTxbJLmg4q+GBETeb61aNw==, tarball: https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.7.0.tgz} + resolution: {integrity: sha512-/ImhO+T/RWJ96hUbxiCn2yWI0/MeQZV/aeukQQfhxiSXuZJfyqtdHPUPrc84jxCfXTxbJLmg4q+GBETeb61aNw==} cpu: [x64] os: [darwin] requiresBuild: true @@ -910,7 +910,7 @@ packages: optional: true /@rollup/rollup-linux-arm-gnueabihf@4.7.0: - resolution: {integrity: sha512-zhye8POvTyUXlKbfPBVqoHy3t43gIgffY+7qBFqFxNqVtltQLtWeHNAbrMnXiLIfYmxcoL/feuLDote2tx+Qbg==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.7.0.tgz} + resolution: {integrity: sha512-zhye8POvTyUXlKbfPBVqoHy3t43gIgffY+7qBFqFxNqVtltQLtWeHNAbrMnXiLIfYmxcoL/feuLDote2tx+Qbg==} cpu: [arm] os: [linux] requiresBuild: true @@ -918,7 +918,7 @@ packages: optional: true /@rollup/rollup-linux-arm64-gnu@4.7.0: - resolution: {integrity: sha512-RAdr3OJnUum6Vs83cQmKjxdTg31zJnLLTkjhcFt0auxM6jw00GD6IPFF42uasYPr/wGC6TRm7FsQiJyk0qIEfg==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.7.0.tgz} + resolution: {integrity: sha512-RAdr3OJnUum6Vs83cQmKjxdTg31zJnLLTkjhcFt0auxM6jw00GD6IPFF42uasYPr/wGC6TRm7FsQiJyk0qIEfg==} cpu: [arm64] os: [linux] requiresBuild: true @@ -926,7 +926,7 @@ packages: optional: true /@rollup/rollup-linux-arm64-musl@4.7.0: - resolution: {integrity: sha512-nhWwYsiJwZGq7SyR3afS3EekEOsEAlrNMpPC4ZDKn5ooYSEjDLe9W/xGvoIV8/F/+HNIY6jY8lIdXjjxfxopXw==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.7.0.tgz} + resolution: {integrity: sha512-nhWwYsiJwZGq7SyR3afS3EekEOsEAlrNMpPC4ZDKn5ooYSEjDLe9W/xGvoIV8/F/+HNIY6jY8lIdXjjxfxopXw==} cpu: [arm64] os: [linux] requiresBuild: true @@ -934,7 +934,7 @@ packages: optional: true /@rollup/rollup-linux-riscv64-gnu@4.7.0: - resolution: {integrity: sha512-rlfy5RnQG1aop1BL/gjdH42M2geMUyVQqd52GJVirqYc787A/XVvl3kQ5NG/43KXgOgE9HXgCaEH05kzQ+hLoA==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.7.0.tgz} + resolution: {integrity: sha512-rlfy5RnQG1aop1BL/gjdH42M2geMUyVQqd52GJVirqYc787A/XVvl3kQ5NG/43KXgOgE9HXgCaEH05kzQ+hLoA==} cpu: [riscv64] os: [linux] requiresBuild: true @@ -942,7 +942,7 @@ packages: optional: true /@rollup/rollup-linux-x64-gnu@4.7.0: - resolution: {integrity: sha512-cCkoGlGWfBobdDtiiypxf79q6k3/iRVGu1HVLbD92gWV5WZbmuWJCgRM4x2N6i7ljGn1cGytPn9ZAfS8UwF6vg==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.7.0.tgz} + resolution: {integrity: sha512-cCkoGlGWfBobdDtiiypxf79q6k3/iRVGu1HVLbD92gWV5WZbmuWJCgRM4x2N6i7ljGn1cGytPn9ZAfS8UwF6vg==} cpu: [x64] os: [linux] requiresBuild: true @@ -950,7 +950,7 @@ packages: optional: true /@rollup/rollup-linux-x64-musl@4.7.0: - resolution: {integrity: sha512-R2oBf2p/Arc1m+tWmiWbpHBjEcJnHVnv6bsypu4tcKdrYTpDfl1UT9qTyfkIL1iiii5D4WHxUHCg5X0pzqmxFg==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.7.0.tgz} + resolution: {integrity: sha512-R2oBf2p/Arc1m+tWmiWbpHBjEcJnHVnv6bsypu4tcKdrYTpDfl1UT9qTyfkIL1iiii5D4WHxUHCg5X0pzqmxFg==} cpu: [x64] os: [linux] requiresBuild: true @@ -958,7 +958,7 @@ packages: optional: true /@rollup/rollup-win32-arm64-msvc@4.7.0: - resolution: {integrity: sha512-CPtgaQL1aaPc80m8SCVEoxFGHxKYIt3zQYC3AccL/SqqiWXblo3pgToHuBwR8eCP2Toa+X1WmTR/QKFMykws7g==, tarball: https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.7.0.tgz} + resolution: {integrity: sha512-CPtgaQL1aaPc80m8SCVEoxFGHxKYIt3zQYC3AccL/SqqiWXblo3pgToHuBwR8eCP2Toa+X1WmTR/QKFMykws7g==} cpu: [arm64] os: [win32] requiresBuild: true @@ -966,7 +966,7 @@ packages: optional: true /@rollup/rollup-win32-ia32-msvc@4.7.0: - resolution: {integrity: sha512-pmioUlttNh9GXF5x2CzNa7Z8kmRTyhEzzAC+2WOOapjewMbl+3tGuAnxbwc5JyG8Jsz2+hf/QD/n5VjimOZ63g==, tarball: https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.7.0.tgz} + resolution: {integrity: sha512-pmioUlttNh9GXF5x2CzNa7Z8kmRTyhEzzAC+2WOOapjewMbl+3tGuAnxbwc5JyG8Jsz2+hf/QD/n5VjimOZ63g==} cpu: [ia32] os: [win32] requiresBuild: true @@ -974,7 +974,7 @@ packages: optional: true /@rollup/rollup-win32-x64-msvc@4.7.0: - resolution: {integrity: sha512-SeZzC2QhhdBQUm3U0c8+c/P6UlRyBcLL2Xp5KX7z46WXZxzR8RJSIWL9wSUeBTgxog5LTPJuPj0WOT9lvrtP7Q==, tarball: https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.7.0.tgz} + resolution: {integrity: sha512-SeZzC2QhhdBQUm3U0c8+c/P6UlRyBcLL2Xp5KX7z46WXZxzR8RJSIWL9wSUeBTgxog5LTPJuPj0WOT9lvrtP7Q==} cpu: [x64] os: [win32] requiresBuild: true @@ -982,33 +982,33 @@ packages: optional: true /@shikijs/engine-oniguruma@3.2.2: - resolution: {integrity: sha512-vyXRnWVCSvokwbaUD/8uPn6Gqsf5Hv7XwcW4AgiU4Z2qwy19sdr6VGzMdheKKN58tJOOe5MIKiNb901bgcUXYQ==, tarball: https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.2.2.tgz} + resolution: {integrity: sha512-vyXRnWVCSvokwbaUD/8uPn6Gqsf5Hv7XwcW4AgiU4Z2qwy19sdr6VGzMdheKKN58tJOOe5MIKiNb901bgcUXYQ==} dependencies: '@shikijs/types': 3.2.2 '@shikijs/vscode-textmate': 10.0.2 dev: true /@shikijs/langs@3.2.2: - resolution: {integrity: sha512-NY0Urg2dV9ETt3JIOWoMPuoDNwte3geLZ4M1nrPHbkDS8dWMpKcEwlqiEIGqtwZNmt5gKyWpR26ln2Bg2ecPgw==, tarball: https://registry.npmjs.org/@shikijs/langs/-/langs-3.2.2.tgz} + resolution: {integrity: sha512-NY0Urg2dV9ETt3JIOWoMPuoDNwte3geLZ4M1nrPHbkDS8dWMpKcEwlqiEIGqtwZNmt5gKyWpR26ln2Bg2ecPgw==} dependencies: '@shikijs/types': 3.2.2 dev: true /@shikijs/themes@3.2.2: - resolution: {integrity: sha512-Zuq4lgAxVKkb0FFdhHSdDkALuRpsj1so1JdihjKNQfgM78EHxV2JhO10qPsMrm01FkE3mDRTdF68wfmsqjt6HA==, tarball: https://registry.npmjs.org/@shikijs/themes/-/themes-3.2.2.tgz} + resolution: {integrity: sha512-Zuq4lgAxVKkb0FFdhHSdDkALuRpsj1so1JdihjKNQfgM78EHxV2JhO10qPsMrm01FkE3mDRTdF68wfmsqjt6HA==} dependencies: '@shikijs/types': 3.2.2 dev: true /@shikijs/types@3.2.2: - resolution: {integrity: sha512-a5TiHk7EH5Lso8sHcLHbVNNhWKP0Wi3yVnXnu73g86n3WoDgEra7n3KszyeCGuyoagspQ2fzvy4cpSc8pKhb0A==, tarball: https://registry.npmjs.org/@shikijs/types/-/types-3.2.2.tgz} + resolution: {integrity: sha512-a5TiHk7EH5Lso8sHcLHbVNNhWKP0Wi3yVnXnu73g86n3WoDgEra7n3KszyeCGuyoagspQ2fzvy4cpSc8pKhb0A==} dependencies: '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 dev: true /@shikijs/vscode-textmate@10.0.2: - resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==, tarball: https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz} + resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} dev: true /@smithy/abort-controller@2.0.15: @@ -1485,7 +1485,7 @@ packages: dev: true /@swc/core-darwin-arm64@1.3.100: - resolution: {integrity: sha512-XVWFsKe6ei+SsDbwmsuRkYck1SXRpO60Hioa4hoLwR8fxbA9eVp6enZtMxzVVMBi8ej5seZ4HZQeAWepbukiBw==, tarball: https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.100.tgz} + resolution: {integrity: sha512-XVWFsKe6ei+SsDbwmsuRkYck1SXRpO60Hioa4hoLwR8fxbA9eVp6enZtMxzVVMBi8ej5seZ4HZQeAWepbukiBw==} engines: {node: '>=10'} cpu: [arm64] os: [darwin] @@ -1494,7 +1494,7 @@ packages: optional: true /@swc/core-darwin-x64@1.3.100: - resolution: {integrity: sha512-KF/MXrnH1nakm1wbt4XV8FS7kvqD9TGmVxeJ0U4bbvxXMvzeYUurzg3AJUTXYmXDhH/VXOYJE5N5RkwZZPs5iA==, tarball: https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.100.tgz} + resolution: {integrity: sha512-KF/MXrnH1nakm1wbt4XV8FS7kvqD9TGmVxeJ0U4bbvxXMvzeYUurzg3AJUTXYmXDhH/VXOYJE5N5RkwZZPs5iA==} engines: {node: '>=10'} cpu: [x64] os: [darwin] @@ -1503,7 +1503,7 @@ packages: optional: true /@swc/core-linux-arm64-gnu@1.3.100: - resolution: {integrity: sha512-p8hikNnAEJrw5vHCtKiFT4hdlQxk1V7vqPmvUDgL/qe2menQDK/i12tbz7/3BEQ4UqUPnvwpmVn2d19RdEMNxw==, tarball: https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.100.tgz} + resolution: {integrity: sha512-p8hikNnAEJrw5vHCtKiFT4hdlQxk1V7vqPmvUDgL/qe2menQDK/i12tbz7/3BEQ4UqUPnvwpmVn2d19RdEMNxw==} engines: {node: '>=10'} cpu: [arm64] os: [linux] @@ -1512,7 +1512,7 @@ packages: optional: true /@swc/core-linux-arm64-musl@1.3.100: - resolution: {integrity: sha512-BWx/0EeY89WC4q3AaIaBSGfQxkYxIlS3mX19dwy2FWJs/O+fMvF9oLk/CyJPOZzbp+1DjGeeoGFuDYpiNO91JA==, tarball: https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.100.tgz} + resolution: {integrity: sha512-BWx/0EeY89WC4q3AaIaBSGfQxkYxIlS3mX19dwy2FWJs/O+fMvF9oLk/CyJPOZzbp+1DjGeeoGFuDYpiNO91JA==} engines: {node: '>=10'} cpu: [arm64] os: [linux] @@ -1521,7 +1521,7 @@ packages: optional: true /@swc/core-linux-x64-gnu@1.3.100: - resolution: {integrity: sha512-XUdGu3dxAkjsahLYnm8WijPfKebo+jHgHphDxaW0ovI6sTdmEGFDew7QzKZRlbYL2jRkUuuKuDGvD6lO5frmhA==, tarball: https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.100.tgz} + resolution: {integrity: sha512-XUdGu3dxAkjsahLYnm8WijPfKebo+jHgHphDxaW0ovI6sTdmEGFDew7QzKZRlbYL2jRkUuuKuDGvD6lO5frmhA==} engines: {node: '>=10'} cpu: [x64] os: [linux] @@ -1530,7 +1530,7 @@ packages: optional: true /@swc/core-linux-x64-musl@1.3.100: - resolution: {integrity: sha512-PhoXKf+f0OaNW/GCuXjJ0/KfK9EJX7z2gko+7nVnEA0p3aaPtbP6cq1Ubbl6CMoPL+Ci3gZ7nYumDqXNc3CtLQ==, tarball: https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.100.tgz} + resolution: {integrity: sha512-PhoXKf+f0OaNW/GCuXjJ0/KfK9EJX7z2gko+7nVnEA0p3aaPtbP6cq1Ubbl6CMoPL+Ci3gZ7nYumDqXNc3CtLQ==} engines: {node: '>=10'} cpu: [x64] os: [linux] @@ -1539,7 +1539,7 @@ packages: optional: true /@swc/core-win32-arm64-msvc@1.3.100: - resolution: {integrity: sha512-PwLADZN6F9cXn4Jw52FeP/MCLVHm8vwouZZSOoOScDtihjY495SSjdPnlosMaRSR4wJQssGwiD/4MbpgQPqbAw==, tarball: https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.100.tgz} + resolution: {integrity: sha512-PwLADZN6F9cXn4Jw52FeP/MCLVHm8vwouZZSOoOScDtihjY495SSjdPnlosMaRSR4wJQssGwiD/4MbpgQPqbAw==} engines: {node: '>=10'} cpu: [arm64] os: [win32] @@ -1548,7 +1548,7 @@ packages: optional: true /@swc/core-win32-ia32-msvc@1.3.100: - resolution: {integrity: sha512-0f6nicKSLlDKlyPRl2JEmkpBV4aeDfRQg6n8mPqgL7bliZIcDahG0ej+HxgNjZfS3e0yjDxsNRa6sAqWU2Z60A==, tarball: https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.100.tgz} + resolution: {integrity: sha512-0f6nicKSLlDKlyPRl2JEmkpBV4aeDfRQg6n8mPqgL7bliZIcDahG0ej+HxgNjZfS3e0yjDxsNRa6sAqWU2Z60A==} engines: {node: '>=10'} cpu: [ia32] os: [win32] @@ -1557,7 +1557,7 @@ packages: optional: true /@swc/core-win32-x64-msvc@1.3.100: - resolution: {integrity: sha512-b7J0rPoMkRTa3XyUGt8PwCaIBuYWsL2DqbirrQKRESzgCvif5iNpqaM6kjIjI/5y5q1Ycv564CB51YDpiS8EtQ==, tarball: https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.100.tgz} + resolution: {integrity: sha512-b7J0rPoMkRTa3XyUGt8PwCaIBuYWsL2DqbirrQKRESzgCvif5iNpqaM6kjIjI/5y5q1Ycv564CB51YDpiS8EtQ==} engines: {node: '>=10'} cpu: [x64] os: [win32] @@ -1597,12 +1597,22 @@ packages: resolution: {integrity: sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==} dev: true + /@types/chai@5.2.2: + resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==} + dependencies: + '@types/deep-eql': 4.0.2 + dev: true + + /@types/deep-eql@4.0.2: + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + dev: true + /@types/estree@1.0.6: resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} dev: true /@types/hast@3.0.4: - resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==, tarball: https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz} + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} dependencies: '@types/unist': 3.0.3 dev: true @@ -1630,66 +1640,68 @@ packages: dev: true /@types/unist@3.0.3: - resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==, tarball: https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz} + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} dev: true - /@vitest/expect@3.0.8: - resolution: {integrity: sha512-Xu6TTIavTvSSS6LZaA3EebWFr6tsoXPetOWNMOlc7LO88QVVBwq2oQWBoDiLCN6YTvNYsGSjqOO8CAdjom5DCQ==} + /@vitest/expect@3.2.3: + resolution: {integrity: sha512-W2RH2TPWVHA1o7UmaFKISPvdicFJH+mjykctJFoAkUw+SPTJTGjUNdKscFBrqM7IPnCVu6zihtKYa7TkZS1dkQ==} dependencies: - '@vitest/spy': 3.0.8 - '@vitest/utils': 3.0.8 + '@types/chai': 5.2.2 + '@vitest/spy': 3.2.3 + '@vitest/utils': 3.2.3 chai: 5.2.0 tinyrainbow: 2.0.0 dev: true - /@vitest/mocker@3.0.8(vite@5.0.6): - resolution: {integrity: sha512-n3LjS7fcW1BCoF+zWZxG7/5XvuYH+lsFg+BDwwAz0arIwHQJFUEsKBQ0BLU49fCxuM/2HSeBPHQD8WjgrxMfow==} + /@vitest/mocker@3.2.3(vite@5.0.6): + resolution: {integrity: sha512-cP6fIun+Zx8he4rbWvi+Oya6goKQDZK+Yq4hhlggwQBbrlOQ4qtZ+G4nxB6ZnzI9lyIb+JnvyiJnPC2AGbKSPA==} peerDependencies: msw: ^2.4.9 - vite: ^5.0.0 || ^6.0.0 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 peerDependenciesMeta: msw: optional: true vite: optional: true dependencies: - '@vitest/spy': 3.0.8 + '@vitest/spy': 3.2.3 estree-walker: 3.0.3 magic-string: 0.30.17 vite: 5.0.6(@types/node@18.19.3) dev: true - /@vitest/pretty-format@3.0.8: - resolution: {integrity: sha512-BNqwbEyitFhzYMYHUVbIvepOyeQOSFA/NeJMIP9enMntkkxLgOcgABH6fjyXG85ipTgvero6noreavGIqfJcIg==} + /@vitest/pretty-format@3.2.3: + resolution: {integrity: sha512-yFglXGkr9hW/yEXngO+IKMhP0jxyFw2/qys/CK4fFUZnSltD+MU7dVYGrH8rvPcK/O6feXQA+EU33gjaBBbAng==} dependencies: tinyrainbow: 2.0.0 dev: true - /@vitest/runner@3.0.8: - resolution: {integrity: sha512-c7UUw6gEcOzI8fih+uaAXS5DwjlBaCJUo7KJ4VvJcjL95+DSR1kova2hFuRt3w41KZEFcOEiq098KkyrjXeM5w==} + /@vitest/runner@3.2.3: + resolution: {integrity: sha512-83HWYisT3IpMaU9LN+VN+/nLHVBCSIUKJzGxC5RWUOsK1h3USg7ojL+UXQR3b4o4UBIWCYdD2fxuzM7PQQ1u8w==} dependencies: - '@vitest/utils': 3.0.8 + '@vitest/utils': 3.2.3 pathe: 2.0.3 + strip-literal: 3.0.0 dev: true - /@vitest/snapshot@3.0.8: - resolution: {integrity: sha512-x8IlMGSEMugakInj44nUrLSILh/zy1f2/BgH0UeHpNyOocG18M9CWVIFBaXPt8TrqVZWmcPjwfG/ht5tnpba8A==} + /@vitest/snapshot@3.2.3: + resolution: {integrity: sha512-9gIVWx2+tysDqUmmM1L0hwadyumqssOL1r8KJipwLx5JVYyxvVRfxvMq7DaWbZZsCqZnu/dZedaZQh4iYTtneA==} dependencies: - '@vitest/pretty-format': 3.0.8 + '@vitest/pretty-format': 3.2.3 magic-string: 0.30.17 pathe: 2.0.3 dev: true - /@vitest/spy@3.0.8: - resolution: {integrity: sha512-MR+PzJa+22vFKYb934CejhR4BeRpMSoxkvNoDit68GQxRLSf11aT6CTj3XaqUU9rxgWJFnqicN/wxw6yBRkI1Q==} + /@vitest/spy@3.2.3: + resolution: {integrity: sha512-JHu9Wl+7bf6FEejTCREy+DmgWe+rQKbK+y32C/k5f4TBIAlijhJbRBIRIOCEpVevgRsCQR2iHRUH2/qKVM/plw==} dependencies: - tinyspy: 3.0.2 + tinyspy: 4.0.3 dev: true - /@vitest/utils@3.0.8: - resolution: {integrity: sha512-nkBC3aEhfX2PdtQI/QwAWp8qZWwzASsU4Npbcd5RdMPBSSLCpkZp52P3xku3s3uA0HIEhGvEcF8rNkBsz9dQ4Q==} + /@vitest/utils@3.2.3: + resolution: {integrity: sha512-4zFBCU5Pf+4Z6v+rwnZ1HU1yzOKKvDkMXZrymE2PBlbjKJRlrOxbvpfPSvJTGRIwGoahaOGvp+kbCoxifhzJ1Q==} dependencies: - '@vitest/pretty-format': 3.0.8 + '@vitest/pretty-format': 3.2.3 loupe: 3.1.3 tinyrainbow: 2.0.0 dev: true @@ -1714,7 +1726,7 @@ packages: dev: true /argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==, tarball: https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz} + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} dev: true /assertion-error@2.0.1: @@ -1728,7 +1740,7 @@ packages: dev: true /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==, tarball: https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz} + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} dev: true /benchmark@2.1.4: @@ -1758,7 +1770,7 @@ packages: dev: true /brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==, tarball: https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz} + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} dependencies: balanced-match: 1.0.2 dev: true @@ -1836,8 +1848,8 @@ packages: ms: 2.1.2 dev: true - /debug@4.4.0: - resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + /debug@4.4.1: + resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -1863,12 +1875,12 @@ packages: dev: true /entities@4.5.0: - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==, tarball: https://registry.npmjs.org/entities/-/entities-4.5.0.tgz} + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} dev: true - /es-module-lexer@1.6.0: - resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==} + /es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} dev: true /esbuild@0.19.8: @@ -1907,8 +1919,8 @@ packages: '@types/estree': 1.0.6 dev: true - /expect-type@1.2.0: - resolution: {integrity: sha512-80F22aiJ3GLyVnS/B3HzgR6RelZVumzj9jkL0Rhz4h0xYbNW9PjlQz5h3J/SShErbXBc295vseR4/MIbVmUbeA==} + /expect-type@1.2.1: + resolution: {integrity: sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==} engines: {node: '>=12.0.0'} dev: true @@ -1923,6 +1935,17 @@ packages: strnum: 1.0.5 dev: true + /fdir@6.4.6(picomatch@4.0.2): + resolution: {integrity: sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + dependencies: + picomatch: 4.0.2 + dev: true + /fs-extra@10.1.0: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} @@ -1933,7 +1956,7 @@ packages: dev: true /fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==, tarball: https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz} + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] requiresBuild: true @@ -1949,6 +1972,10 @@ packages: engines: {node: '>=8'} dev: true + /js-tokens@9.0.1: + resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} + dev: true + /json2csv@5.0.7: resolution: {integrity: sha512-YRZbUnyaJZLZUJSRi2G/MqahCyRv9n/ds+4oIetjDF3jWQA7AG7iSeKTiZiCNqtMZM7HDyt0e/W6lEnoGEmMGA==} engines: {node: '>= 10', npm: '>= 6.13.0'} @@ -1979,7 +2006,7 @@ packages: dev: true /linkify-it@5.0.0: - resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==, tarball: https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz} + resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} dependencies: uc.micro: 2.1.0 dev: true @@ -2007,7 +2034,7 @@ packages: dev: true /lunr@2.3.9: - resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==, tarball: https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz} + resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} dev: true /magic-string@0.30.17: @@ -2017,7 +2044,7 @@ packages: dev: true /markdown-it@14.1.0: - resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==, tarball: https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz} + resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} hasBin: true dependencies: argparse: 2.0.1 @@ -2029,7 +2056,7 @@ packages: dev: true /mdurl@2.0.0: - resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==, tarball: https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz} + resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} dev: true /mimic-fn@2.1.0: @@ -2038,7 +2065,7 @@ packages: dev: true /minimatch@9.0.5: - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==, tarball: https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz} + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} dependencies: brace-expansion: 2.0.1 @@ -2078,6 +2105,11 @@ packages: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} dev: true + /picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + dev: true + /pirates@4.0.6: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} @@ -2103,7 +2135,7 @@ packages: dev: true /punycode.js@2.3.1: - resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==, tarball: https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz} + resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} engines: {node: '>=6'} dev: true @@ -2174,8 +2206,8 @@ packages: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} dev: true - /std-env@3.8.1: - resolution: {integrity: sha512-vj5lIj3Mwf9D79hBkltk5qmkFI+biIKWS2IBxEyEU3AX1tUf7AoL8nSazCOiiqQsGKIq01SClsKEzweu34uwvA==} + /std-env@3.9.0: + resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} dev: true /string-width@4.2.3: @@ -2194,6 +2226,12 @@ packages: ansi-regex: 5.0.1 dev: true + /strip-literal@3.0.0: + resolution: {integrity: sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==} + dependencies: + js-tokens: 9.0.1 + dev: true + /strnum@1.0.5: resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} dev: true @@ -2206,8 +2244,16 @@ packages: resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} dev: true - /tinypool@1.0.2: - resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} + /tinyglobby@0.2.14: + resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} + engines: {node: '>=12.0.0'} + dependencies: + fdir: 6.4.6(picomatch@4.0.2) + picomatch: 4.0.2 + dev: true + + /tinypool@1.1.0: + resolution: {integrity: sha512-7CotroY9a8DKsKprEy/a14aCCm8jYVmR7aFy4fpkZM8sdpNJbKkixuNjgM50yCmip2ezc8z4N7k3oe2+rfRJCQ==} engines: {node: ^18.0.0 || >=20.0.0} dev: true @@ -2216,8 +2262,8 @@ packages: engines: {node: '>=14.0.0'} dev: true - /tinyspy@3.0.2: - resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} + /tinyspy@4.0.3: + resolution: {integrity: sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==} engines: {node: '>=14.0.0'} dev: true @@ -2235,7 +2281,7 @@ packages: dev: true /typedoc@0.28.2(typescript@5.3.3): - resolution: {integrity: sha512-9Giuv+eppFKnJ0oi+vxqLM817b/IrIsEMYgy3jj6zdvppAfDqV3d6DXL2vXUg2TnlL62V48th25Zf/tcQKAJdg==, tarball: https://registry.npmjs.org/typedoc/-/typedoc-0.28.2.tgz} + resolution: {integrity: sha512-9Giuv+eppFKnJ0oi+vxqLM817b/IrIsEMYgy3jj6zdvppAfDqV3d6DXL2vXUg2TnlL62V48th25Zf/tcQKAJdg==} engines: {node: '>= 18', pnpm: '>= 10'} hasBin: true peerDependencies: @@ -2256,7 +2302,7 @@ packages: dev: true /uc.micro@2.1.0: - resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==, tarball: https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz} + resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} dev: true /undici-types@5.26.5: @@ -2273,14 +2319,14 @@ packages: hasBin: true dev: true - /vite-node@3.0.8(@types/node@18.19.3): - resolution: {integrity: sha512-6PhR4H9VGlcwXZ+KWCdMqbtG649xCPZqfI9j2PsK1FcXgEzro5bGHcVKFCTqPLaNKZES8Evqv4LwvZARsq5qlg==} + /vite-node@3.2.3(@types/node@18.19.3): + resolution: {integrity: sha512-gc8aAifGuDIpZHrPjuHyP4dpQmYXqWw7D1GmDnWeNWP654UEXzVfQ5IHPSK5HaHkwB/+p1atpYpSdw/2kOv8iQ==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true dependencies: cac: 6.7.14 - debug: 4.4.0 - es-module-lexer: 1.6.0 + debug: 4.4.1 + es-module-lexer: 1.7.0 pathe: 2.0.3 vite: 5.0.6(@types/node@18.19.3) transitivePeerDependencies: @@ -2330,16 +2376,16 @@ packages: fsevents: 2.3.3 dev: true - /vitest@3.0.8(@types/node@18.19.3): - resolution: {integrity: sha512-dfqAsNqRGUc8hB9OVR2P0w8PZPEckti2+5rdZip0WIz9WW0MnImJ8XiR61QhqLa92EQzKP2uPkzenKOAHyEIbA==} + /vitest@3.2.3(@types/node@18.19.3): + resolution: {integrity: sha512-E6U2ZFXe3N/t4f5BwUaVCKRLHqUpk1CBWeMh78UT4VaTPH/2dyvH6ALl29JTovEPu9dVKr/K/J4PkXgrMbw4Ww==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@types/debug': ^4.1.12 '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - '@vitest/browser': 3.0.8 - '@vitest/ui': 3.0.8 + '@vitest/browser': 3.2.3 + '@vitest/ui': 3.2.3 happy-dom: '*' jsdom: '*' peerDependenciesMeta: @@ -2358,26 +2404,29 @@ packages: jsdom: optional: true dependencies: + '@types/chai': 5.2.2 '@types/node': 18.19.3 - '@vitest/expect': 3.0.8 - '@vitest/mocker': 3.0.8(vite@5.0.6) - '@vitest/pretty-format': 3.0.8 - '@vitest/runner': 3.0.8 - '@vitest/snapshot': 3.0.8 - '@vitest/spy': 3.0.8 - '@vitest/utils': 3.0.8 + '@vitest/expect': 3.2.3 + '@vitest/mocker': 3.2.3(vite@5.0.6) + '@vitest/pretty-format': 3.2.3 + '@vitest/runner': 3.2.3 + '@vitest/snapshot': 3.2.3 + '@vitest/spy': 3.2.3 + '@vitest/utils': 3.2.3 chai: 5.2.0 - debug: 4.4.0 - expect-type: 1.2.0 + debug: 4.4.1 + expect-type: 1.2.1 magic-string: 0.30.17 pathe: 2.0.3 - std-env: 3.8.1 + picomatch: 4.0.2 + std-env: 3.9.0 tinybench: 2.9.0 tinyexec: 0.3.2 - tinypool: 1.0.2 + tinyglobby: 0.2.14 + tinypool: 1.1.0 tinyrainbow: 2.0.0 vite: 5.0.6(@types/node@18.19.3) - vite-node: 3.0.8(@types/node@18.19.3) + vite-node: 3.2.3(@types/node@18.19.3) why-is-node-running: 2.3.0 transitivePeerDependencies: - less @@ -2409,7 +2458,7 @@ packages: dev: true /yaml@2.7.1: - resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==, tarball: https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz} + resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==} engines: {node: '>= 14'} hasBin: true dev: true diff --git a/bindings/nodejs/src/capability.rs b/bindings/nodejs/src/capability.rs index 72fbb2c17324..a0e904415d0d 100644 --- a/bindings/nodejs/src/capability.rs +++ b/bindings/nodejs/src/capability.rs @@ -54,6 +54,42 @@ impl Capability { self.0.stat_with_if_none_match } + /// If operator supports stat with if modified since. + #[napi(getter)] + pub fn stat_with_if_modified_since(&self) -> bool { + self.0.stat_with_if_modified_since + } + + /// If operator supports stat with if unmodified since. + #[napi(getter)] + pub fn stat_with_if_unmodified_since(&self) -> bool { + self.0.stat_with_if_unmodified_since + } + + /// If operator supports stat with versions. + #[napi(getter)] + pub fn stat_with_version(&self) -> bool { + self.0.stat_with_version + } + + /// If operator supports stat with override content type. + #[napi(getter)] + pub fn stat_with_override_content_type(&self) -> bool { + self.0.stat_with_override_content_type + } + + /// If operator supports stat with override cache control. + #[napi(getter)] + pub fn stat_with_override_cache_control(&self) -> bool { + self.0.stat_with_override_cache_control + } + + /// If operator supports stat with override content disposition. + #[napi(getter)] + pub fn stat_with_override_content_disposition(&self) -> bool { + self.0.stat_with_override_content_disposition + } + /// If operator supports read. #[napi(getter)] pub fn read(&self) -> bool { diff --git a/bindings/nodejs/src/lib.rs b/bindings/nodejs/src/lib.rs index 2aa1e023d175..2a71d22381c7 100644 --- a/bindings/nodejs/src/lib.rs +++ b/bindings/nodejs/src/lib.rs @@ -27,8 +27,10 @@ use std::time::Duration; use futures::AsyncReadExt; use futures::TryStreamExt; use napi::bindgen_prelude::*; +use opendal::options::StatOptions; mod capability; +mod options; #[napi] pub struct Operator { @@ -93,8 +95,17 @@ impl Operator { /// } /// ``` #[napi] - pub async fn stat(&self, path: String) -> Result { - let meta = self.async_op.stat(&path).await.map_err(format_napi_error)?; + pub async fn stat( + &self, + path: String, + options: Option, + ) -> Result { + let options = options.map_or_else(StatOptions::default, StatOptions::from); + let meta = self + .async_op + .stat_options(&path, options) + .await + .map_err(format_napi_error)?; Ok(Metadata(meta)) } @@ -109,8 +120,16 @@ impl Operator { /// } /// ``` #[napi] - pub fn stat_sync(&self, path: String) -> Result { - let meta = self.blocking_op.stat(&path).map_err(format_napi_error)?; + pub fn stat_sync( + &self, + path: String, + options: Option, + ) -> Result { + let options = options.map_or_else(StatOptions::default, StatOptions::from); + let meta = self + .blocking_op + .stat_options(&path, options) + .map_err(format_napi_error)?; Ok(Metadata(meta)) } @@ -644,6 +663,26 @@ impl Entry { } } +#[napi] +pub enum EntryMode { + /// FILE means the path has data to read. + FILE, + /// DIR means the path can be listed. + DIR, + /// Unknown means we don't know what we can do on this path. + Unknown, +} + +impl From for EntryMode { + fn from(mode: opendal::EntryMode) -> Self { + match mode { + opendal::EntryMode::FILE => EntryMode::FILE, + opendal::EntryMode::DIR => EntryMode::DIR, + opendal::EntryMode::Unknown => EntryMode::Unknown, + } + } +} + /// Metadata carries all metadata associated with a path. #[napi] pub struct Metadata(opendal::Metadata); @@ -699,6 +738,18 @@ impl Metadata { pub fn last_modified(&self) -> Option { self.0.last_modified().map(|ta| ta.to_rfc3339()) } + + /// mode represent this entry's mode. + #[napi(getter)] + pub fn mode(&self) -> Option { + Some(self.0.mode().into()) + } + + /// Retrieves the `version` of the file, if available. + #[napi(getter)] + pub fn version(&self) -> Option { + self.0.version().map(|v| v.to_string()) + } } #[napi(object)] diff --git a/bindings/nodejs/src/options.rs b/bindings/nodejs/src/options.rs new file mode 100644 index 000000000000..93657d45a8a2 --- /dev/null +++ b/bindings/nodejs/src/options.rs @@ -0,0 +1,96 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +use opendal::raw::parse_datetime_from_rfc3339; + +#[napi(object)] +#[derive(Debug)] +pub struct StatOptions { + /** + * Sets version for this operation. + * Retrieves data of a specified version of the given path. + */ + pub version: Option, + + /** + * Sets if-match condition for this operation. + * If file exists and its etag doesn't match, an error will be returned. + */ + pub if_match: Option, + + /** + * Sets if-none-match condition for this operation. + * If file exists and its etag matches, an error will be returned. + */ + pub if_none_match: Option, + + /** + * Sets if-modified-since condition for this operation. + * If file exists and hasn't been modified since the specified time, an error will be returned. + * ISO 8601 formatted date string + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString + */ + pub if_modified_since: Option, + + /** + * Sets if-unmodified-since condition for this operation. + * If file exists and has been modified since the specified time, an error will be returned. + * ISO 8601 formatted date string + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString + */ + pub if_unmodified_since: Option, + + /** + * Specifies the content-type header for presigned operations. + * Only meaningful when used along with presign. + */ + pub override_content_type: Option, + + /** + * Specifies the cache-control header for presigned operations. + * Only meaningful when used along with presign. + */ + pub override_cache_control: Option, + + /** + * Specifies the content-disposition header for presigned operations. + * Only meaningful when used along with presign. + */ + pub override_content_disposition: Option, +} + +impl From for opendal::options::StatOptions { + fn from(value: StatOptions) -> Self { + let if_modified_since = value + .if_modified_since + .and_then(|v| parse_datetime_from_rfc3339(&v).ok()); + let if_unmodified_since = value + .if_unmodified_since + .and_then(|v| parse_datetime_from_rfc3339(&v).ok()); + + Self { + if_modified_since, + if_unmodified_since, + version: value.version, + if_match: value.if_match, + if_none_match: value.if_none_match, + override_content_type: value.override_content_type, + override_cache_control: value.override_cache_control, + override_content_disposition: value.override_content_disposition, + } + } +} diff --git a/bindings/nodejs/tests/suites/asyncStatOptions.suite.mjs b/bindings/nodejs/tests/suites/asyncStatOptions.suite.mjs new file mode 100644 index 000000000000..a22586eac391 --- /dev/null +++ b/bindings/nodejs/tests/suites/asyncStatOptions.suite.mjs @@ -0,0 +1,174 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { randomUUID } from 'node:crypto' +import { test, describe, expect } from 'vitest' +import { EntryMode } from '../../index.mjs' +import { generateFixedBytes, sleep } from '../utils.mjs' + +/** + * @param {import("../../index").Operator} op + */ +export function run(op) { + const capability = op.capability() + + describe.skipIf(!capability.write || !capability.stat)('async statOptions tests', () => { + test.skipIf(!capability.statWithIfMatch)('stat with ifMatch', async () => { + const filename = `random_file_${randomUUID()}` + const content = generateFixedBytes(5 * 1024 * 1024) + + await op.write(filename, content) + const meta = await op.stat(filename) + + const invalidOptions = { + ifMatch: '"invalid_etag"', + } + + await expect(op.stat(filename, invalidOptions)).rejects.toThrowError('ConditionNotMatch') + + const res = await op.stat(filename, { + ifMatch: meta.etag, + }) + + expect(res.etag).toBe(meta.etag) + + await op.delete(filename) + }) + + test.skipIf(!capability.statWithIfNoneMatch)('stat with ifNoneMatch', async () => { + const size = 5 * 1024 * 1024 + const filename = `random_file_${randomUUID()}` + const content = generateFixedBytes(size) + + await op.write(filename, content) + const meta = await op.stat(filename) + + expect(meta.mode).toBe(EntryMode.FILE) + expect(meta.contentLength).toBe(BigInt(size)) + + await expect(op.stat(filename, { ifNoneMatch: meta.etag })).rejects.toThrowError('ConditionNotMatch') + + const res = await op.stat(filename, { + ifNoneMatch: '"invalid_etag"', + }) + + expect(res.mode).toBe(meta.mode) + expect(res.contentLength).toBe(BigInt(meta.contentLength)) + + await op.delete(filename) + }) + + test.skipIf(!capability.statWithIfModifiedSince)('stat with ifModifiedSince', async () => { + const size = 5 * 1024 * 1024 + const filename = `random_file_${randomUUID()}` + const content = generateFixedBytes(size) + + await op.write(filename, content) + const meta = await op.stat(filename) + + expect(meta.mode).toBe(EntryMode.FILE) + expect(meta.contentLength).toBe(BigInt(size)) + + const sinceMinus = new Date(meta.lastModified) + sinceMinus.setSeconds(sinceMinus.getSeconds() - 1) + const metaMinus = await op.stat(filename, { ifModifiedSince: sinceMinus.toISOString() }) + expect(metaMinus.lastModified).toBe(meta.lastModified) + + await sleep(1000) + + const sinceAdd = new Date(meta.lastModified) + sinceAdd.setSeconds(sinceAdd.getSeconds() + 1) + + await expect(op.stat(filename, { ifModifiedSince: sinceAdd.toISOString() })).rejects.toThrowError( + 'ConditionNotMatch', + ) + + await op.delete(filename) + }) + + test.skipIf(!capability.statWithIfUnmodifiedSince)('stat with ifUnmodifiedSince', async () => { + const size = 5 * 1024 * 1024 + const filename = `random_file_${randomUUID()}` + const content = generateFixedBytes(size) + + await op.write(filename, content) + const meta = await op.stat(filename) + + expect(meta.mode).toBe(EntryMode.FILE) + expect(meta.contentLength).toBe(BigInt(size)) + + const sinceMinus = new Date(meta.lastModified) + sinceMinus.setSeconds(sinceMinus.getSeconds() - 1) + + await expect(op.stat(filename, { ifUnmodifiedSince: sinceMinus.toISOString() })).rejects.toThrowError( + 'ConditionNotMatch', + ) + + await sleep(1000) + + const sinceAdd = new Date(meta.lastModified) + sinceAdd.setSeconds(sinceAdd.getSeconds() + 1) + + const metaAdd = await op.stat(filename, { ifUnmodifiedSince: sinceAdd.toISOString() }) + expect(metaAdd.lastModified).toBe(meta.lastModified) + + await op.delete(filename) + }) + + test.skipIf(!capability.statWithVersion)('stat with version', async () => { + const size = 5 * 1024 * 1024 + const filename = `random_file_${randomUUID()}` + const content = generateFixedBytes(size) + + await op.write(filename, content) + const first_meta = await op.stat(filename) + const first_version = first_meta.version + + const first_versioning_meta = await op.stat(filename, { version: first_version }) + expect(first_versioning_meta).toBe(first_meta) + + await op.write(filename, content) + const second_meta = await op.stat(filename) + const second_version = second_meta.version + expect(second_version).not.toBe(first_version) + + const meta = await op.stat(filename, { version: first_version }) + expect(meta).toBe(first_meta) + + await op.delete(filename) + }) + + test.skipIf(!capability.statWithVersion)('stat with not existing version', async () => { + const size = 5 * 1024 * 1024 + const filename = `random_file_${randomUUID()}` + const content = generateFixedBytes(size) + + await op.write(filename, content) + const meta = await op.stat(filename) + const version = meta.version + + const filename2 = `random_file_${randomUUID()}` + await op.write(filename2, content) + await expect(op.stat(filename2, { version })).rejects.toThrowError('NotFound') + + await op.delete(filename) + await op.delete(filename2) + }) + }) +} diff --git a/bindings/nodejs/tests/suites/index.mjs b/bindings/nodejs/tests/suites/index.mjs index 920f816cf1da..dea86b72e682 100644 --- a/bindings/nodejs/tests/suites/index.mjs +++ b/bindings/nodejs/tests/suites/index.mjs @@ -24,6 +24,8 @@ import { checkRandomRootEnabled, generateRandomRoot, loadConfigFromEnv } from '. import { run as AsyncIOTestRun } from './async.suite.mjs' import { run as ServicesTestRun } from './services.suite.mjs' import { run as SyncIOTestRun } from './sync.suite.mjs' +import { run as AsyncStatOptionsTestRun } from './asyncStatOptions.suite.mjs' +import { run as SyncStatOptionsTestRun } from './syncStatOptions.suite.mjs' export function runner(testName, scheme) { if (!scheme) { @@ -53,5 +55,7 @@ export function runner(testName, scheme) { AsyncIOTestRun(operator) ServicesTestRun(operator) SyncIOTestRun(operator) + AsyncStatOptionsTestRun(operator) + SyncStatOptionsTestRun(operator) }) } diff --git a/bindings/nodejs/tests/suites/syncStatOptions.suite.mjs b/bindings/nodejs/tests/suites/syncStatOptions.suite.mjs new file mode 100644 index 000000000000..428e94cb27cc --- /dev/null +++ b/bindings/nodejs/tests/suites/syncStatOptions.suite.mjs @@ -0,0 +1,171 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { randomUUID } from 'node:crypto' +import { test, describe, expect } from 'vitest' +import { EntryMode } from '../../index.mjs' +import { generateFixedBytes } from '../utils.mjs' + +/** + * @param {import("../../index").Operator} op + */ +export function run(op) { + const capability = op.capability() + + describe.skipIf(!capability.write || !capability.stat)('sync statOptions tests', () => { + test.skipIf(!capability.statWithIfMatch)('stat with ifMatch', () => { + const filename = `random_file_${randomUUID()}` + const content = generateFixedBytes(5 * 1024 * 1024) + + op.writeSync(filename, content) + const meta = op.statSync(filename) + + const invalidOptions = { + ifMatch: "'invalid_etag'", + } + + expect(() => op.statSync(filename, invalidOptions)).toThrowError('ConditionNotMatch') + + const res = op.statSync(filename, { + ifMatch: meta.etag, + }) + + expect(res.etag).toBe(meta.etag) + op.deleteSync(filename) + }) + + test.skipIf(!capability.statWithIfNoneMatch)('stat with ifNoneMatch', () => { + const size = 5 * 1024 * 1024 + const filename = `random_file_${randomUUID()}` + const content = generateFixedBytes(size) + + op.writeSync(filename, content) + const meta = op.statSync(filename) + + expect(meta.mode).toBe(EntryMode.FILE) + expect(meta.contentLength).toBe(BigInt(size)) + + expect(() => op.statSync(filename, { ifNoneMatch: meta.etag })).toThrowError('ConditionNotMatch') + + const res = op.statSync(filename, { + ifNoneMatch: '"invalid_etag"', + }) + + expect(res.mode).toBe(meta.mode) + expect(res.contentLength).toBe(BigInt(size)) + op.deleteSync(filename) + }) + + test.skipIf(!capability.statWithIfModifiedSince)('stat with ifModifiedSince', () => { + const size = 5 * 1024 * 1024 + const filename = `random_file_${randomUUID()}` + const content = generateFixedBytes(size) + + op.writeSync(filename, content) + const meta = op.statSync(filename) + + expect(meta.mode).toBe(EntryMode.FILE) + expect(meta.contentLength).toBe(BigInt(size)) + + const sinceMinus = new Date(meta.lastModified) + sinceMinus.setSeconds(sinceMinus.getSeconds() - 1) + const metaMinus = op.statSync(filename, { ifModifiedSince: sinceMinus.toISOString() }) + expect(metaMinus.lastModified).toBe(meta.lastModified) + + setTimeout(() => { + const sinceAdd = new Date(meta.lastModified) + sinceAdd.setSeconds(sinceAdd.getSeconds() + 1) + expect(() => op.statSync(filename, { ifModifiedSince: sinceAdd.toISOString() })).toThrowError( + 'ConditionNotMatch', + ) + + op.deleteSync(filename) + }, 1000) + }) + + test.skipIf(!capability.statWithIfUnmodifiedSince)('stat with ifUnmodifiedSince', () => { + const size = 5 * 1024 * 1024 + const filename = `random_file_${randomUUID()}` + const content = generateFixedBytes(size) + + op.writeSync(filename, content) + const meta = op.statSync(filename) + + expect(meta.mode).toBe(EntryMode.FILE) + expect(meta.contentLength).toBe(BigInt(size)) + + const sinceMinus = new Date(meta.lastModified) + sinceMinus.setSeconds(sinceMinus.getSeconds() - 1) + + expect(() => + op.statSync(filename, { ifUnmodifiedSince: sinceMinus.toISOString() }).toThrowError('ConditionNotMatch'), + ) + + setTimeout(() => { + const sinceAdd = new Date(meta.lastModified) + sinceAdd.setSeconds(sinceAdd.getSeconds() + 1) + + const metaAdd = op.statSync(filename, { ifUnmodifiedSince: sinceAdd.toISOString() }) + expect(metaAdd.lastModified).toBe(meta.lastModified) + + op.deleteSync(filename) + }, 1000) + }) + + test.skipIf(!capability.statWithVersion)('stat with version', () => { + const size = 5 * 1024 * 1024 + const filename = `random_file_${randomUUID()}` + const content = generateFixedBytes(size) + + op.writeSync(filename, content) + const first_meta = op.statSync(filename) + const first_version = first_meta.version + + const first_versioning_meta = op.statSync(filename, { version: first_version }) + expect(first_versioning_meta).toBe(first_meta) + + op.writeSync(filename, content) + const second_meta = op.statSync(filename) + const second_version = second_meta.version + expect(second_version).not.toBe(first_version) + + const meta = op.statSync(filename, { version: first_version }) + expect(meta).toBe(first_meta) + + op.deleteSync(filename) + }) + + test.skipIf(!capability.statWithVersion)('stat with not existing version', () => { + const size = 5 * 1024 * 1024 + const filename = `random_file_${randomUUID()}` + const content = generateFixedBytes(size) + + op.writeSync(filename, content) + const meta = op.statSync(filename) + const version = meta.version + + const filename2 = `random_file_${randomUUID()}` + op.writeSync(filename2, content) + expect(() => op.statSync(filename2, { version })).toThrowError('NotFound') + + op.deleteSync(filename) + op.deleteSync(filename2) + }) + }) +} diff --git a/bindings/nodejs/tests/utils.mjs b/bindings/nodejs/tests/utils.mjs index bf685612e031..b3b428ecfeb5 100644 --- a/bindings/nodejs/tests/utils.mjs +++ b/bindings/nodejs/tests/utils.mjs @@ -53,3 +53,7 @@ export function loadConfigFromEnv(scheme) { .map(([key, value]) => [key.replace(prefix, ''), value]), ) } + +export function sleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)) +} diff --git a/bindings/nodejs/vitest.config.mjs b/bindings/nodejs/vitest.config.mjs index 3ddd781fc8d8..94618cf606f6 100644 --- a/bindings/nodejs/vitest.config.mjs +++ b/bindings/nodejs/vitest.config.mjs @@ -28,7 +28,14 @@ export default defineConfig({ globals: true, environment: 'node', dir: 'tests', - reporters: 'basic', testTimeout: 300 * 1000, + reporters: [ + [ + 'default', + { + summary: false, + }, + ], + ], }, })