From 1f231b37463f8693e1c0dc3aac9386baa00ee2ad Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Sat, 17 Oct 2026 09:38:34 +0100 Subject: [PATCH] chore: remove the Deno SDK target sdk-for-deno has not been generated or published since 2025-09-15, its README marks it deprecated in favour of npm:node-appwrite, and appwrite/appwrite no longer lists it. Keeping the language class, templates and e2e tests around only costs maintenance on every shared JS change. --- AGENTS.md | 2 +- src/SDK/Language/Deno.php | 208 ---- .../deno/.github/workflows/autoclose.yml | 12 - templates/deno/.github/workflows/stale.yml | 9 - templates/deno/CHANGELOG.md.twig | 1 - templates/deno/LICENSE.twig | 1 - templates/deno/README.md.twig | 41 - templates/deno/docs/example.md.twig | 28 - templates/deno/mod.ts.twig | 37 - templates/deno/src/client.ts.twig | 246 ---- templates/deno/src/enums/enum.ts.twig | 6 - templates/deno/src/exception.ts.twig | 17 - templates/deno/src/id.ts.twig | 30 - templates/deno/src/inputFile.ts.twig | 46 - templates/deno/src/models.d.ts.twig | 65 - templates/deno/src/operator.ts.twig | 308 ----- templates/deno/src/permission.ts.twig | 22 - templates/deno/src/query.ts.twig | 1065 ----------------- templates/deno/src/role.ts.twig | 100 -- templates/deno/src/service.ts.twig | 12 - templates/deno/src/services/service.ts.twig | 348 ------ templates/deno/test/id.test.ts.twig | 8 - templates/deno/test/operator.test.ts.twig | 130 -- templates/deno/test/permission.test.ts.twig | 12 - templates/deno/test/query.test.ts.twig | 770 ------------ templates/deno/test/role.test.ts.twig | 16 - .../deno/test/services/service.test.ts.twig | 100 -- tests/e2e/Deno1193Test.php | 63 - tests/e2e/Deno1303Test.php | 63 - tests/e2e/languages/deno/tests.ts | 403 ------- tests/generation/GenerationTest.php | 5 +- 31 files changed, 2 insertions(+), 4172 deletions(-) delete mode 100644 src/SDK/Language/Deno.php delete mode 100644 templates/deno/.github/workflows/autoclose.yml delete mode 100644 templates/deno/.github/workflows/stale.yml delete mode 100644 templates/deno/CHANGELOG.md.twig delete mode 100644 templates/deno/LICENSE.twig delete mode 100644 templates/deno/README.md.twig delete mode 100644 templates/deno/docs/example.md.twig delete mode 100644 templates/deno/mod.ts.twig delete mode 100644 templates/deno/src/client.ts.twig delete mode 100644 templates/deno/src/enums/enum.ts.twig delete mode 100644 templates/deno/src/exception.ts.twig delete mode 100644 templates/deno/src/id.ts.twig delete mode 100644 templates/deno/src/inputFile.ts.twig delete mode 100644 templates/deno/src/models.d.ts.twig delete mode 100644 templates/deno/src/operator.ts.twig delete mode 100644 templates/deno/src/permission.ts.twig delete mode 100644 templates/deno/src/query.ts.twig delete mode 100644 templates/deno/src/role.ts.twig delete mode 100644 templates/deno/src/service.ts.twig delete mode 100644 templates/deno/src/services/service.ts.twig delete mode 100644 templates/deno/test/id.test.ts.twig delete mode 100644 templates/deno/test/operator.test.ts.twig delete mode 100644 templates/deno/test/permission.test.ts.twig delete mode 100644 templates/deno/test/query.test.ts.twig delete mode 100644 templates/deno/test/role.test.ts.twig delete mode 100644 templates/deno/test/services/service.test.ts.twig delete mode 100644 tests/e2e/Deno1193Test.php delete mode 100644 tests/e2e/Deno1303Test.php delete mode 100644 tests/e2e/languages/deno/tests.ts diff --git a/AGENTS.md b/AGENTS.md index 1aaaef4a07..4f2e05f460 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -16,7 +16,7 @@ The generator does not auto-discover templates. Every output file must have an e | Parent | Children affected | |--------|------------------| -| `JS` | `Web`, `Deno` | +| `JS` | `Web` | | `Web` | `Node`, `ReactNative` | | `Dart` | `Flutter` | | `Swift` | `Apple` | diff --git a/src/SDK/Language/Deno.php b/src/SDK/Language/Deno.php deleted file mode 100644 index 27536f4f51..0000000000 --- a/src/SDK/Language/Deno.php +++ /dev/null @@ -1,208 +0,0 @@ - 'default', - 'destination' => 'mod.ts', - 'template' => 'deno/mod.ts.twig', - ], - [ - 'scope' => 'default', - 'destination' => 'src/client.ts', - 'template' => 'deno/src/client.ts.twig', - ], - [ - 'scope' => 'default', - 'destination' => 'src/permission.ts', - 'template' => 'deno/src/permission.ts.twig', - ], - [ - 'scope' => 'default', - 'destination' => 'test/permission.test.ts', - 'template' => 'deno/test/permission.test.ts.twig', - ], - [ - 'scope' => 'default', - 'destination' => 'src/role.ts', - 'template' => 'deno/src/role.ts.twig', - ], - [ - 'scope' => 'default', - 'destination' => 'test/role.test.ts', - 'template' => 'deno/test/role.test.ts.twig', - ], - [ - 'scope' => 'default', - 'destination' => 'src/id.ts', - 'template' => 'deno/src/id.ts.twig', - ], - [ - 'scope' => 'default', - 'destination' => 'test/id.test.ts', - 'template' => 'deno/test/id.test.ts.twig', - ], - [ - 'scope' => 'default', - 'destination' => 'src/query.ts', - 'template' => 'deno/src/query.ts.twig', - ], - [ - 'scope' => 'default', - 'destination' => 'src/operator.ts', - 'template' => 'deno/src/operator.ts.twig', - ], - [ - 'scope' => 'default', - 'destination' => 'test/query.test.ts', - 'template' => 'deno/test/query.test.ts.twig', - ], - [ - 'scope' => 'default', - 'destination' => 'test/operator.test.ts', - 'template' => 'deno/test/operator.test.ts.twig', - ], - [ - 'scope' => 'default', - 'destination' => 'src/inputFile.ts', - 'template' => 'deno/src/inputFile.ts.twig', - ], - [ - 'scope' => 'default', - 'destination' => '/src/service.ts', - 'template' => 'deno/src/service.ts.twig', - ], - [ - 'scope' => 'default', - 'destination' => '/src/models.d.ts', - 'template' => 'deno/src/models.d.ts.twig', - ], - [ - 'scope' => 'default', - 'destination' => '/src/exception.ts', - 'template' => 'deno/src/exception.ts.twig', - ], - [ - 'scope' => 'service', - 'destination' => '/src/services/{{service.name | caseKebab}}.ts', - 'template' => 'deno/src/services/service.ts.twig', - ], - [ - 'scope' => 'service', - 'destination' => '/test/services/{{service.name | caseKebab}}.test.ts', - 'template' => 'deno/test/services/service.test.ts.twig', - ], - [ - 'scope' => 'default', - 'destination' => 'README.md', - 'template' => 'deno/README.md.twig', - ], - [ - 'scope' => 'default', - 'destination' => 'CHANGELOG.md', - 'template' => 'deno/CHANGELOG.md.twig', - ], - [ - 'scope' => 'default', - 'destination' => 'LICENSE', - 'template' => 'deno/LICENSE.twig', - ], - [ - 'scope' => 'method', - 'destination' => 'docs/examples/{{service.name | caseLower}}/{{(method | methodName) | caseKebab}}.md', - 'template' => 'deno/docs/example.md.twig', - ], - [ - 'scope' => 'enum', - 'destination' => 'src/enums/{{ enum.title | caseKebab }}.ts', - 'template' => 'deno/src/enums/enum.ts.twig', - ], - ]; - } - - #[Override] - public function getTypeName(Schema|Parameter $parameter, ?Specification $spec = null): string - { - $schema = $this->getSchema($parameter); - if (($type = $this->getEnumTypeName($parameter, $spec)) !== null) { - return $type; - } - - $model = $this->getSchemaModel($parameter); - if ($model !== null) { - $type = 'Models.' . $this->toPascalCase($model); - return $schema instanceof ArraySchema ? $type . '[]' : $type; - } - return match ($this->getSchemaType($parameter)) { - self::TYPE_INTEGER, self::TYPE_NUMBER => 'number', - self::TYPE_STRING => 'string', - self::TYPE_FILE => 'InputFile', - self::TYPE_BOOLEAN => 'boolean', - self::TYPE_ARRAY => $this->getTypeName($this->getArraySchema($parameter) ?? $schema) . '[]', - self::TYPE_OBJECT => 'object', - default => 'unknown', - }; - } - - public function getParamExample(Schema|Parameter $param, string $lang = ''): string - { - $type = $this->getSchemaType($param); - $example = $this->getSchemaExample($param); - - $hasExample = !empty($example) || $example === 0 || $example === false; - - if (!$hasExample) { - return match ($type) { - self::TYPE_ARRAY => '[]', - self::TYPE_FILE => 'InputFile.fromPath(\'/path/to/file.png\', \'file.png\')', - self::TYPE_INTEGER, self::TYPE_NUMBER, self::TYPE_BOOLEAN => $this->getScalarExampleFallback($param), - self::TYPE_OBJECT => '{}', - self::TYPE_STRING => "''", - }; - } - - return match ($type) { - self::TYPE_ARRAY => $this->isPermissionString($example) ? $this->getPermissionExample($example) : $example, - self::TYPE_INTEGER, self::TYPE_NUMBER => $example, - self::TYPE_FILE => 'InputFile.fromPath(\'/path/to/file.png\', \'file.png\')', - self::TYPE_BOOLEAN => ($example) ? 'true' : 'false', - self::TYPE_OBJECT => ($example === '{}') - ? '{}' - : (($formatted = json_encode(json_decode((string) $example, true), JSON_PRETTY_PRINT)) - ? preg_replace('/\n/', "\n ", $formatted) - : $example), - self::TYPE_STRING => "'{$example}'", - }; - } -} diff --git a/templates/deno/.github/workflows/autoclose.yml b/templates/deno/.github/workflows/autoclose.yml deleted file mode 100644 index 5d4a75cc69..0000000000 --- a/templates/deno/.github/workflows/autoclose.yml +++ /dev/null @@ -1,12 +0,0 @@ -name: Auto-close External Pull Requests - -on: - pull_request_target: - types: [opened, reopened] - -jobs: - auto_close: - if: github.head_ref != 'dev' - uses: appwrite/.github/.github/workflows/autoclose.yml@dd94e24bffbb6941e79ce3a26c01db22a774b1a1 # main - secrets: - GH_AUTO_CLOSE_PR_TOKEN: ${{ secrets.GH_AUTO_CLOSE_PR_TOKEN }} diff --git a/templates/deno/.github/workflows/stale.yml b/templates/deno/.github/workflows/stale.yml deleted file mode 100644 index 02b8ea906c..0000000000 --- a/templates/deno/.github/workflows/stale.yml +++ /dev/null @@ -1,9 +0,0 @@ -name: Mark stale issues - -on: - schedule: - - cron: "0 0 * * *" # Midnight Runtime - -jobs: - stale: - uses: appwrite/.github/.github/workflows/stale.yml@dd94e24bffbb6941e79ce3a26c01db22a774b1a1 # main diff --git a/templates/deno/CHANGELOG.md.twig b/templates/deno/CHANGELOG.md.twig deleted file mode 100644 index dfcefd0336..0000000000 --- a/templates/deno/CHANGELOG.md.twig +++ /dev/null @@ -1 +0,0 @@ -{{sdk.changelog | raw}} \ No newline at end of file diff --git a/templates/deno/LICENSE.twig b/templates/deno/LICENSE.twig deleted file mode 100644 index 854eb19494..0000000000 --- a/templates/deno/LICENSE.twig +++ /dev/null @@ -1 +0,0 @@ -{{sdk.licenseContent | raw}} \ No newline at end of file diff --git a/templates/deno/README.md.twig b/templates/deno/README.md.twig deleted file mode 100644 index f39cc82991..0000000000 --- a/templates/deno/README.md.twig +++ /dev/null @@ -1,41 +0,0 @@ -# {{ spec.info.title }} {{sdk.name}} SDK - -![License](https://img.shields.io/badge/license-{{ spec.info.license.name|replace({'-': '--', '_': '__'})|url_encode }}-blue.svg?style=flat-square) -![Version](https://img.shields.io/badge/api%20version-{{ spec.info.version|url_encode }}-blue.svg?style=flat-square) -{% if sdk.twitterHandle %} -[![X Account](https://img.shields.io/badge/follow-%40{{ sdk.twitterHandle|replace({'-': '--', '_': '__'})|url_encode }}-000000?logo=x&style=flat-square)](https://x.com/{{ sdk.twitterHandle }}) -{% endif %} -{% if sdk.discordChannel %} -[![Discord](https://img.shields.io/discord/{{ sdk.discordChannel }}?label=discord&style=flat-square)]({{ sdk.discordUrl }}) -{% endif %} -{% if sdk.warning %} - -{{ sdk.warning|raw }} -{% endif %} - -{{ sdk.description }} - -{% if sdk.coverImage %} -![{{ spec.info.title }}]({{ sdk.coverImage }}) -{% endif %} - -## Installation - -```javascript -import * as sdk from "https://deno.land/x/{{ spec.info.title | caseKebab }}/mod.ts"; -``` - -{% if sdk.gettingStarted %} - -{{ sdk.gettingStarted|raw }} -{% endif %} - -> Minimal supported version for Deno SDK is 1.19.0. - -## Contribution - -This library is auto-generated by Appwrite custom [SDK Generator](https://github.com/appwrite/sdk-generator). To learn more about how you can help us improve this SDK, please check the [contribution guide](https://github.com/appwrite/sdk-generator/blob/master/CONTRIBUTING.md) before sending a pull-request. - -## License - -Please see the [{{spec.info.license.name}} license]({{spec.info.license.url}}) file for more information. \ No newline at end of file diff --git a/templates/deno/docs/example.md.twig b/templates/deno/docs/example.md.twig deleted file mode 100644 index 36ef2e1136..0000000000 --- a/templates/deno/docs/example.md.twig +++ /dev/null @@ -1,28 +0,0 @@ -```ts -import { Client, {{ service.name | caseUcfirst }}{% for parameter in (method | parameters('all')) %}{% if (parameter | enumValues) | length > 0%}, {{ (parameter | enumName) | caseUcfirst}}{% endif %}{% endfor %}{% if (method | parameters('all')) | hasPermissionParam %}, Permission, Role{% endif %} } from "https://deno.land/x/{{ spec.info.title | caseDash }}/mod.ts"; - -const client = new Client() - {%~ if [(method | securitySchemes)]|length > 0 %} - .setEndpoint('{{ endpointDocs | raw }}') // Your API Endpoint - {%~ for node in [(method | securitySchemes)] %} - {%~ for key,header in node|keys %} - .set{{header}}('{{node[header].extensions['x-appwrite']['demo'] | raw }}'){% if loop.last %};{% endif%} // {{node[header].description}} - {%~ endfor %} - {%~ endfor %} - {%~ endif %} - -const {{ service.name | caseCamel | escapeKeyword }} = new {{service.name | caseUcfirst}}(client{% if [] | length %}{% for parameter in [] %}, {{ parameter | paramExample }}{% endfor %}{% endif %}); - -{% if (method | methodType) == 'location' %}const result = {% elseif (method | methodType) != 'webAuth' %}const response = await {% endif %}{{ service.name | caseCamel | escapeKeyword }}.{{ (method | methodName) | caseCamel }}({% if (method | parameters('all')) | length == 0 %}); -{% else %}{ -{%~ for parameter in (method | parameters('all')) %} -{%~ if parameter.required %} - {{ parameter.name | caseCamel | escapeKeyword }}: {% if (parameter | enumValues) | length > 0 %}{{ (parameter | enumName) }}.{{ ((parameter | enumKeys)[0] ?? (parameter | enumValues)[0]) | caseEnumKey }}{% else%}{{ parameter | paramExample }}{% endif %}{% if not loop.last %},{% endif %} - -{%~ else %} - {{ parameter.name | caseCamel | escapeKeyword }}: {% if (parameter | enumValues) | length > 0 %}{{ (parameter | enumName) }}.{{ ((parameter | enumKeys)[0] ?? (parameter | enumValues)[0]) | caseEnumKey }}{% else%}{{ parameter | paramExample }}{% endif %}{% if not loop.last %},{% endif %} // optional -{%~ endif %} -{%~ endfor -%} -}); -{% endif %} -``` diff --git a/templates/deno/mod.ts.twig b/templates/deno/mod.ts.twig deleted file mode 100644 index 4f72937454..0000000000 --- a/templates/deno/mod.ts.twig +++ /dev/null @@ -1,37 +0,0 @@ -import { Client } from "./src/client.ts"; -import { Query, QueryBuilder, flattenParam } from "./src/query.ts"; -import { Permission } from "./src/permission.ts"; -import { Role } from "./src/role.ts"; -import { ID } from "./src/id.ts"; -import { Operator, Condition } from "./src/operator.ts"; -import { InputFile } from "./src/inputFile.ts"; -import { {{spec.info.title | caseUcfirst}}Exception } from "./src/exception.ts"; -{% for service in services %} -import { {{service.name | caseUcfirst}} } from "./src/services/{{service.name | caseKebab}}.ts"; -{% endfor %} -{% for enum in allEnums %} -import { {{enum.title | caseUcfirst}} } from "./src/enums/{{enum.title | caseKebab}}.ts"; -{% endfor %} - -export { - Client, - Query, - QueryBuilder, - flattenParam, - Permission, - Role, - ID, - Operator, - Condition, - InputFile, - {{spec.info.title | caseUcfirst}}Exception, -{% for service in services %} - {{service.name | caseUcfirst}}, -{% endfor %} -{% for enum in allEnums %} - {{enum.title | caseUcfirst}}, -{% endfor %} -}; - -export type { Models } from "./src/models.d.ts"; -export type { QueryTypes, QueryTypesList, QueryInput } from "./src/query.ts"; diff --git a/templates/deno/src/client.ts.twig b/templates/deno/src/client.ts.twig deleted file mode 100644 index 410954b721..0000000000 --- a/templates/deno/src/client.ts.twig +++ /dev/null @@ -1,246 +0,0 @@ -import { {{ spec.info.title | caseUcfirst}}Exception } from './exception.ts'; -import { flattenParam } from './query.ts'; - -export interface Payload { - [key: string]: any; -} - -type DefaultsShape = string | { items: DefaultsShape }; - -type DefaultsModel = { - defaults?: Record; - properties?: Record; -}; - -type Defaults = { - root: DefaultsShape; - models: Record; -}; - -export function applyDefaults(value: T, tree: Defaults): T { - return fillDefaults(value, tree.root, tree.models) as T; -} - -function cloneDefault(value: unknown): unknown { - if (Array.isArray(value)) { - return value.map(cloneDefault); - } - if (typeof value === 'object' && value !== null) { - const copy: Record = {}; - for (const [key, member] of Object.entries(value)) { - copy[key] = cloneDefault(member); - } - return copy; - } - return value; -} - -function fillDefaults( - value: unknown, - shape: DefaultsShape, - models: Record, -): unknown { - if (typeof shape !== 'string') { - if (!Array.isArray(value)) { - return value; - } - const items = shape.items; - return value.map((item) => fillDefaults(item, items, models)); - } - const model = models[shape]; - if (!model || typeof value !== 'object' || value === null) { - return value; - } - if (Array.isArray(value)) { - return value; - } - const result: Record = { ...model.defaults, ...value }; - // Each item gets its own copy of a filled-in list or object, so mutating one doesn't change the rest - for (const key of Object.keys(model.defaults ?? {})) { - if (!Object.prototype.hasOwnProperty.call(value, key)) { - result[key] = cloneDefault(result[key]); - } - } - for (const [key, child] of Object.entries(model.properties ?? {})) { - if (key in result) { - result[key] = fillDefaults(result[key], child, models); - } - } - return result; -} - -export class Client { - static CHUNK_SIZE = 5*1024*1024; // 5MB - static DENO_READ_CHUNK_SIZE = 16384; // 16kb; refference: https://github.com/denoland/deno/discussions/9906 - - endpoint: string = '{{(spec | endpoint)}}'; - config: Payload = { -{% for headerKey, header in globalHeaders %} - '{{ headerKey | caseLower }}': '', -{% endfor %} - }; - headers: Payload = { - 'content-type': '', - 'user-agent' : `{{spec.info.title | caseUcfirst}}{{ language.name | caseUcfirst }}SDK/{{ sdk.version }} (${Deno.build.os}; ${Deno.build.arch})`, - 'x-sdk-name': '{{ sdk.name }}', - 'x-sdk-platform': '{{ sdk.platform }}', - 'x-sdk-language': '{{ language.name | caseLower }}', - 'x-sdk-version': '{{ sdk.version }}', -{% for key,header in defaultHeaders %} - '{{key}}':'{{header}}', -{% endfor %} - }; - -{% for headerKey, header in globalHeaders %} - /** - * Set {{headerKey | caseUcfirst}} - * -{% if header.description %} - * {{header.description}} - * -{% endif %} - * @param string value - * - * @return self - */ - set{{headerKey | caseUcfirst}}(value: string): this { - {%~ if (headerKey != 'Project') %} - this.addHeader('{{ header.name }}', value); - {%~ endif %} - this.config['{{ headerKey | caseLower }}'] = value; - - return this; - } - -{% endfor %} - - /*** - * @param endpoint - * @return this - */ - setEndpoint(endpoint: string): this { - if (!endpoint || typeof endpoint !== 'string') { - throw new {{spec.info.title | caseUcfirst}}Exception('Endpoint must be a valid string'); - } - - if (!endpoint.startsWith('http://') && !endpoint.startsWith('https://')) { - throw new {{spec.info.title | caseUcfirst}}Exception('Invalid endpoint URL: ' + endpoint); - } - - this.endpoint = endpoint; - return this; - } - - /** - * @param key string - * @param value string - */ - addHeader(key: string, value: string): this { - this.headers[key.toLowerCase()] = value; - - return this; - } - - getHeaders(): Payload { - return { ...this.headers }; - } - - async call(method: string, path: string = "", headers: Payload = {}, params: Payload = {}, responseType: string = "json") { - for (const key of Object.keys(params)) { - params[key] = flattenParam(params[key]); - } - - headers = {...this.headers, ...headers}; - const url = new URL(this.endpoint + path); - - let body: string | FormData | undefined = undefined; - - if (method.toUpperCase() === "GET") { - for (const [key, value] of Object.entries(Client.flatten(params))) { - url.searchParams.append(key, value); - } - } else if (headers["content-type"]?.toLowerCase().startsWith("multipart/form-data")) { - delete headers["content-type"]; - const formData = new FormData(); - - const flatParams = Client.flatten(params); - - for (const [key, value] of Object.entries(flatParams)) { - if (value && value.type && value.type === "file") { - formData.append(key, value.file, value.filename); - } else { - formData.append(key, value); - } - } - - body = formData; - } else { - body = JSON.stringify(params); - } - - let response = undefined; - try { - response = await fetch(url.toString(), { - redirect: responseType === "location" ? "manual" : "follow", - method: method.toUpperCase(), - headers, - body - }); - - const warnings = response.headers.get('x-{{ spec.info.title | lower }}-warning'); - if (warnings) { - warnings.split(';').forEach((warning: string) => console.warn('Warning: ' + warning)); - } - } catch (error) { - throw new {{spec.info.title | caseUcfirst}}Exception(error instanceof Error ? error.message : String(error)); - } - - if (response.status >= 400) { - const text = await response.text(); - let json = undefined; - try { - json = JSON.parse(text); - } catch (error) { - throw new {{spec.info.title | caseUcfirst}}Exception(text, response.status, "", text); - } - throw new {{spec.info.title | caseUcfirst}}Exception(json.message, json.code, json.type, text); - } - - if (responseType === "arraybuffer") { - const data = await response.arrayBuffer(); - return data; - } - - if (responseType === "location") { - return response.headers.get("location"); - } - - if (responseType === "text") { - return await response.text(); - } - - const text = await response.text(); - let json = undefined; - try { - json = JSON.parse(text); - } catch (error) { - return text; - } - return json; - } - - static flatten(data: Payload, prefix = ''): Payload { - let output: Payload = {}; - - for (const [key, value] of Object.entries(data)) { - let finalKey = prefix ? prefix + '[' + key +']' : key; - if (Array.isArray(value)) { - output = { ...output, ...Client.flatten(value, finalKey) }; - } else { - output[finalKey] = value; - } - } - - return output; - } -} diff --git a/templates/deno/src/enums/enum.ts.twig b/templates/deno/src/enums/enum.ts.twig deleted file mode 100644 index 9e0d1fc360..0000000000 --- a/templates/deno/src/enums/enum.ts.twig +++ /dev/null @@ -1,6 +0,0 @@ -export enum {{ enum.title | caseUcfirst | overrideIdentifier }} { - {%~ for value in enum.enum %} - {%~ set key = enum.enumKeys is empty ? value : enum.enumKeys[loop.index0] %} - {{ key | caseEnumKey }} = '{{ value }}', - {%~ endfor %} -} \ No newline at end of file diff --git a/templates/deno/src/exception.ts.twig b/templates/deno/src/exception.ts.twig deleted file mode 100644 index 5822dd705f..0000000000 --- a/templates/deno/src/exception.ts.twig +++ /dev/null @@ -1,17 +0,0 @@ -export class {{ spec.info.title | caseUcfirst}}Exception { - message: string; - code: number; - response: any; - type: string; - - constructor(message: string, code: number = 0, type: string = "", response: any = "") { - this.message = message; - this.code = code; - this.type = type; - this.response = response; - } - - public toString(): string { - return `${this.message} - ${this.code} - ${this.type} - ${JSON.stringify(this.response)}`; - } -} diff --git a/templates/deno/src/id.ts.twig b/templates/deno/src/id.ts.twig deleted file mode 100644 index 4556ccb223..0000000000 --- a/templates/deno/src/id.ts.twig +++ /dev/null @@ -1,30 +0,0 @@ -export class ID { - // Generate an hex ID based on timestamp - // Recreated from https://www.php.net/manual/en/function.uniqid.php - static #hexTimestamp(): string { - const now = new Date(); - const sec = Math.floor(now.getTime() / 1000); - const msec = now.getMilliseconds(); - - // Convert to hexadecimal - const hexTimestamp = sec.toString(16) + msec.toString(16).padStart(5, '0'); - return hexTimestamp; - } - - public static custom(id: string): string { - return id - } - - // Generate a unique ID with padding to have a longer ID - public static unique(padding: number = 7): string { - const baseId = ID.#hexTimestamp(); - let randomPadding = ''; - - for (let i = 0; i < padding; i++) { - const randomHexDigit = Math.floor(Math.random() * 16).toString(16); - randomPadding += randomHexDigit; - } - - return baseId + randomPadding; - } -} diff --git a/templates/deno/src/inputFile.ts.twig b/templates/deno/src/inputFile.ts.twig deleted file mode 100644 index b122302845..0000000000 --- a/templates/deno/src/inputFile.ts.twig +++ /dev/null @@ -1,46 +0,0 @@ -const _bufferToString = (buffer: Uint8Array): ReadableStream => { - return new ReadableStream({ - start(controller) { - controller.enqueue(buffer); - controller.close(); - } - }); -}; - -export class InputFile { - stream: ReadableStream; // Content of file as a stream - size: number; // Total final size of the file content - filename: string; // File name - - static fromPath = (filePath: string, filename: string): InputFile => { - const file = Deno.openSync(filePath); - const stream = file.readable; - const size = Deno.statSync(filePath).size; - return new InputFile(stream, filename, size); - }; - - static fromBlob = async (blob: Blob, filename: string) => { - const arrayBuffer = await blob.arrayBuffer(); - const buffer = new Uint8Array(arrayBuffer); - return InputFile.fromBuffer(buffer, filename); - }; - - static fromBuffer = (buffer: Uint8Array, filename: string): InputFile => { - const stream = _bufferToString(buffer); - const size = buffer.byteLength; - return new InputFile(stream, filename, size); - }; - - static fromPlainText = (content: string, filename: string): InputFile => { - const buffer = new TextEncoder().encode(content); - const stream = _bufferToString(buffer); - const size = buffer.byteLength; - return new InputFile(stream, filename, size); - }; - - constructor(stream: ReadableStream, filename: string, size: number) { - this.stream = stream; - this.filename = filename; - this.size = size; - } -} \ No newline at end of file diff --git a/templates/deno/src/models.d.ts.twig b/templates/deno/src/models.d.ts.twig deleted file mode 100644 index 1f67665574..0000000000 --- a/templates/deno/src/models.d.ts.twig +++ /dev/null @@ -1,65 +0,0 @@ -{# Macros cannot see the template context, so the definitions are passed in. #} -{% macro sub_schema(property, definition, definitions) %} -{% apply spaceless %} - {% if (property | schemaModel) %} - {% if _self.get_generics_sub(definition, definitions) %} - {{(property | schemaModel) | caseUcfirst}}<{{ _self.get_generics_sub(definition, definitions) }}>{% if (property | schemaType) == 'array' %}[]{% endif %} - {% else %} - {{(property | schemaModel) | caseUcfirst}}{% if (property | schemaType) == 'array' %}[]{% endif %} - {% endif %} - {% elseif (property | schemaModels) %} - ({% for subProperty in (property | schemaModels) %}{{subProperty | caseUcfirst}}{% if loop.last == false %} | {% endif %}{% endfor %}){% if (property | schemaType) == 'array' %}[]{% endif %} - {% else %} - {{property | typeName}} - {% endif %} -{% endapply %} -{% endmacro %} -{% macro get_generics(definition, definitions) %} -{% apply spaceless %} - {% for property in definition.properties %} - {% if definitions[(property | schemaModel)].additionalProperties ?? false %} - {{(property | schemaModel) | caseUcfirst}} extends Models.{{(property | schemaModel) | caseUcfirst}} - {% endif %} - {% if definitions[(property | schemaModel)] is defined %} - {{_self.get_generics(definitions[(property | schemaModel)], definitions)}} - {% endif %} - {% endfor %} -{% endapply %} -{% endmacro %} -{% macro get_generics_sub(definition, definitions, output = false) %} -{% apply spaceless %} - {% for property in definition.properties %} - {% if (definitions[(property | schemaModel)].additionalProperties ?? false) and output %} - {{(property | schemaModel) | caseUcfirst}} - {% endif %} - {% if definitions[(property | schemaModel)] is defined %} - {{_self.get_generics_sub(definitions[(property | schemaModel)], definitions, true)}} - {% endif %} - {% endfor %} -{% endapply %} -{% endmacro %} -{% set importedEnums = [] %} -{% for modelEnum in responseEnums | merge(requestModels is empty ? [] : requestModelEnums) %} -{% if (modelEnum.title | caseUcfirst) not in importedEnums %} -import type { {{ modelEnum.title | caseUcfirst }} } from "./enums/{{ modelEnum.title | caseKebab }}.ts"; -{% set importedEnums = importedEnums | merge([modelEnum.title | caseUcfirst]) %} -{% endif %} -{% endfor %} -{% if importedEnums is not empty %} - -{% endif %} -export namespace Models { -{% for definitionName, definition in definitions | merge(requestModels) %} - /** - * {{ definition.description }} - */ - export type {{ definitionName | caseUcfirst }}{% if _self.get_generics(definition, definitions) %}<{{_self.get_generics(definition, definitions)}}>{% endif %} = { -{% for property in definition.properties %} - /** - * {{ property.description }} - */ - {{ (property | schemaName) | escapeKeyword }}{% if not (property | schemaRequired) %}?{% endif %}: {{_self.sub_schema(property, definition, definitions)}}{% if (property | schemaNullable) %} | null{% endif %}; -{% endfor %} - } -{% endfor %} -} \ No newline at end of file diff --git a/templates/deno/src/operator.ts.twig b/templates/deno/src/operator.ts.twig deleted file mode 100644 index 2386a6c414..0000000000 --- a/templates/deno/src/operator.ts.twig +++ /dev/null @@ -1,308 +0,0 @@ -type OperatorValuesSingle = string | number | boolean; -export type OperatorValuesList = string[] | number[] | boolean[] | any[]; -export type OperatorValues = OperatorValuesSingle | OperatorValuesList; - -export enum Condition { - Equal = "equal", - NotEqual = "notEqual", - GreaterThan = "greaterThan", - GreaterThanEqual = "greaterThanEqual", - LessThan = "lessThan", - LessThanEqual = "lessThanEqual", - Contains = "contains", - IsNull = "isNull", - IsNotNull = "isNotNull", -} - -/** - * Helper class to generate operator strings for atomic operations. - */ -export class Operator { - method: string; - values: OperatorValuesList | undefined; - - /** - * Constructor for Operator class. - * - * @param {string} method - * @param {OperatorValues} values - */ - constructor( - method: string, - values?: OperatorValues - ) { - this.method = method; - - if (values !== undefined) { - if (Array.isArray(values)) { - this.values = values; - } else { - this.values = [values] as OperatorValuesList; - } - } - } - - /** - * Convert the operator object to a JSON string. - * - * @returns {string} - */ - toString(): string { - return JSON.stringify({ - method: this.method, - values: this.values, - }); - } - - /** - * Increment a numeric attribute by a specified value. - * - * @param {number} value - * @param {number} max - * @returns {string} - */ - static increment = (value: number = 1, max?: number): string => { - if (isNaN(value) || !isFinite(value)) { - throw new Error("Value cannot be NaN or Infinity"); - } - if (max !== undefined && (isNaN(max) || !isFinite(max))) { - throw new Error("Max cannot be NaN or Infinity"); - } - const values: any[] = [value]; - if (max !== undefined) { - values.push(max); - } - return new Operator("increment", values).toString(); - }; - - /** - * Decrement a numeric attribute by a specified value. - * - * @param {number} value - * @param {number} min - * @returns {string} - */ - static decrement = (value: number = 1, min?: number): string => { - if (isNaN(value) || !isFinite(value)) { - throw new Error("Value cannot be NaN or Infinity"); - } - if (min !== undefined && (isNaN(min) || !isFinite(min))) { - throw new Error("Min cannot be NaN or Infinity"); - } - const values: any[] = [value]; - if (min !== undefined) { - values.push(min); - } - return new Operator("decrement", values).toString(); - }; - - /** - * Multiply a numeric attribute by a specified factor. - * - * @param {number} factor - * @param {number} max - * @returns {string} - */ - static multiply = (factor: number, max?: number): string => { - if (isNaN(factor) || !isFinite(factor)) { - throw new Error("Factor cannot be NaN or Infinity"); - } - if (max !== undefined && (isNaN(max) || !isFinite(max))) { - throw new Error("Max cannot be NaN or Infinity"); - } - const values: any[] = [factor]; - if (max !== undefined) { - values.push(max); - } - return new Operator("multiply", values).toString(); - }; - - /** - * Divide a numeric attribute by a specified divisor. - * - * @param {number} divisor - * @param {number} min - * @returns {string} - */ - static divide = (divisor: number, min?: number): string => { - if (isNaN(divisor) || !isFinite(divisor)) { - throw new Error("Divisor cannot be NaN or Infinity"); - } - if (min !== undefined && (isNaN(min) || !isFinite(min))) { - throw new Error("Min cannot be NaN or Infinity"); - } - if (divisor === 0) { - throw new Error("Divisor cannot be zero"); - } - const values: any[] = [divisor]; - if (min !== undefined) { - values.push(min); - } - return new Operator("divide", values).toString(); - }; - - /** - * Apply modulo operation on a numeric attribute. - * - * @param {number} divisor - * @returns {string} - */ - static modulo = (divisor: number): string => { - if (isNaN(divisor) || !isFinite(divisor)) { - throw new Error("Divisor cannot be NaN or Infinity"); - } - if (divisor === 0) { - throw new Error("Divisor cannot be zero"); - } - return new Operator("modulo", [divisor]).toString(); - }; - - /** - * Raise a numeric attribute to a specified power. - * - * @param {number} exponent - * @param {number} max - * @returns {string} - */ - static power = (exponent: number, max?: number): string => { - if (isNaN(exponent) || !isFinite(exponent)) { - throw new Error("Exponent cannot be NaN or Infinity"); - } - if (max !== undefined && (isNaN(max) || !isFinite(max))) { - throw new Error("Max cannot be NaN or Infinity"); - } - const values: any[] = [exponent]; - if (max !== undefined) { - values.push(max); - } - return new Operator("power", values).toString(); - }; - - /** - * Append values to an array attribute. - * - * @param {any[]} values - * @returns {string} - */ - static arrayAppend = (values: any[]): string => - new Operator("arrayAppend", values).toString(); - - /** - * Prepend values to an array attribute. - * - * @param {any[]} values - * @returns {string} - */ - static arrayPrepend = (values: any[]): string => - new Operator("arrayPrepend", values).toString(); - - /** - * Insert a value at a specific index in an array attribute. - * - * @param {number} index - * @param {any} value - * @returns {string} - */ - static arrayInsert = (index: number, value: any): string => - new Operator("arrayInsert", [index, value]).toString(); - - /** - * Remove a value from an array attribute. - * - * @param {any} value - * @returns {string} - */ - static arrayRemove = (value: any): string => - new Operator("arrayRemove", [value]).toString(); - - /** - * Remove duplicate values from an array attribute. - * - * @returns {string} - */ - static arrayUnique = (): string => - new Operator("arrayUnique", []).toString(); - - /** - * Keep only values that exist in both the current array and the provided array. - * - * @param {any[]} values - * @returns {string} - */ - static arrayIntersect = (values: any[]): string => - new Operator("arrayIntersect", values).toString(); - - /** - * Remove values from the array that exist in the provided array. - * - * @param {any[]} values - * @returns {string} - */ - static arrayDiff = (values: any[]): string => - new Operator("arrayDiff", values).toString(); - - /** - * Filter array values based on a condition. - * - * @param {Condition} condition - * @param {any} value - * @returns {string} - */ - static arrayFilter = (condition: Condition, value?: any): string => { - const values: any[] = [condition as string, value === undefined ? null : value]; - return new Operator("arrayFilter", values).toString(); - }; - - /** - * Concatenate a value to a string or array attribute. - * - * @param {any} value - * @returns {string} - */ - static stringConcat = (value: any): string => - new Operator("stringConcat", [value]).toString(); - - /** - * Replace occurrences of a search string with a replacement string. - * - * @param {string} search - * @param {string} replace - * @returns {string} - */ - static stringReplace = (search: string, replace: string): string => - new Operator("stringReplace", [search, replace]).toString(); - - /** - * Toggle a boolean attribute. - * - * @returns {string} - */ - static toggle = (): string => - new Operator("toggle", []).toString(); - - /** - * Add days to a date attribute. - * - * @param {number} days - * @returns {string} - */ - static dateAddDays = (days: number): string => - new Operator("dateAddDays", [days]).toString(); - - /** - * Subtract days from a date attribute. - * - * @param {number} days - * @returns {string} - */ - static dateSubDays = (days: number): string => - new Operator("dateSubDays", [days]).toString(); - - /** - * Set a date attribute to the current date and time. - * - * @returns {string} - */ - static dateSetNow = (): string => - new Operator("dateSetNow", []).toString(); -} diff --git a/templates/deno/src/permission.ts.twig b/templates/deno/src/permission.ts.twig deleted file mode 100644 index bfc330a166..0000000000 --- a/templates/deno/src/permission.ts.twig +++ /dev/null @@ -1,22 +0,0 @@ -export class Permission { - - static read = (role: string): string => { - return `read("${role}")` - } - - static write = (role: string): string => { - return `write("${role}")` - } - - static create = (role: string): string => { - return `create("${role}")` - } - - static update = (role: string): string => { - return `update("${role}")` - } - - static delete = (role: string): string => { - return `delete("${role}")` - } -} diff --git a/templates/deno/src/query.ts.twig b/templates/deno/src/query.ts.twig deleted file mode 100644 index dee23706be..0000000000 --- a/templates/deno/src/query.ts.twig +++ /dev/null @@ -1,1065 +0,0 @@ -type QueryTypesSingle = string | number | boolean; -export type QueryTypesList = string[] | number[] | boolean[] | Query[] | any[]; -export type QueryTypes = QueryTypesSingle | QueryTypesList; -type AttributesTypes = string | string[]; - -export class Query { - method: string; - attribute: AttributesTypes | undefined; - values: QueryTypesList | undefined; - - constructor( - method: string, - attribute?: AttributesTypes, - values?: QueryTypes - ) { - this.method = method; - this.attribute = attribute; - - if (values !== undefined) { - if (Array.isArray(values)) { - this.values = values; - } else { - this.values = [values] as QueryTypesList; - } - } - } - - toString(): string { - return JSON.stringify({ - method: this.method, - attribute: this.attribute, - values: this.values, - }); - } - - static equal = (attribute: string, value: QueryTypes): string => - new Query("equal", attribute, value).toString(); - - static notEqual = (attribute: string, value: QueryTypes): string => - new Query("notEqual", attribute, value).toString(); - - /** - * Filter resources where attribute matches a regular expression pattern. - * - * @param {string} attribute The attribute to filter on. - * @param {string} pattern The regular expression pattern to match. - * @returns {string} - */ - static regex = (attribute: string, pattern: string): string => - new Query("regex", attribute, pattern).toString(); - - static lessThan = (attribute: string, value: QueryTypes): string => - new Query("lessThan", attribute, value).toString(); - - static lessThanEqual = (attribute: string, value: QueryTypes): string => - new Query("lessThanEqual", attribute, value).toString(); - - static greaterThan = (attribute: string, value: QueryTypes): string => - new Query("greaterThan", attribute, value).toString(); - - static greaterThanEqual = (attribute: string, value: QueryTypes): string => - new Query("greaterThanEqual", attribute, value).toString(); - - static isNull = (attribute: string): string => - new Query("isNull", attribute).toString(); - - static isNotNull = (attribute: string): string => - new Query("isNotNull", attribute).toString(); - - /** - * Filter resources where the specified attributes exist. - * - * @param {string[]} attributes The list of attributes that must exist. - * @returns {string} - */ - static exists = (attributes: string[]): string => - new Query("exists", undefined, attributes).toString(); - - /** - * Filter resources where the specified attributes do not exist. - * - * @param {string[]} attributes The list of attributes that must not exist. - * @returns {string} - */ - static notExists = (attributes: string[]): string => - new Query("notExists", undefined, attributes).toString(); - - static between = ( - attribute: string, - start: string | number, - end: string | number - ) => new Query("between", attribute, [start, end] as QueryTypesList).toString(); - - static startsWith = (attribute: string, value: string): string => - new Query("startsWith", attribute, value).toString(); - - static endsWith = (attribute: string, value: string): string => - new Query("endsWith", attribute, value).toString(); - - static select = (attributes: string[]): string => - new Query("select", undefined, attributes).toString(); - - static search = (attribute: string, value: string): string => - new Query("search", attribute, value).toString(); - - static orderDesc = (attribute: string): string => - new Query("orderDesc", attribute).toString(); - - static orderAsc = (attribute: string): string => - new Query("orderAsc", attribute).toString(); - - static orderRandom = (): string => - new Query("orderRandom").toString(); - - static cursorAfter = (documentId: string): string => - new Query("cursorAfter", undefined, documentId).toString(); - - static cursorBefore = (documentId: string): string => - new Query("cursorBefore", undefined, documentId).toString(); - - static limit = (limit: number): string => - new Query("limit", undefined, limit).toString(); - - static offset = (offset: number): string => - new Query("offset", undefined, offset).toString(); - - /** - * Filter resources where attribute contains the specified value. - * For string attributes, checks if the string contains the substring. - * - * Note: For array attributes, use {@link containsAny} or {@link containsAll} instead. - * @param {string} attribute - * @param {string | string[]} value - * @returns {string} - */ - static contains = (attribute: string, value: string | any[]): string => - new Query("contains", attribute, value).toString(); - - /** - * Filter resources where attribute contains ANY of the specified values. - * For array and relationship attributes, matches documents where the attribute - * contains at least one of the given values. - * - * @param {string} attribute - * @param {any[]} value - * @returns {string} - */ - static containsAny = (attribute: string, value: any[]): string => - new Query("containsAny", attribute, value).toString(); - - /** - * Filter resources where attribute contains ALL of the specified values. - * For array and relationship attributes, matches documents where the attribute - * contains every one of the given values. - * - * @param {string} attribute - * @param {any[]} value - * @returns {string} - */ - static containsAll = (attribute: string, value: any[]): string => - new Query("containsAll", attribute, value).toString(); - - /** - * Filter resources where attribute does not contain the specified value. - * - * @param {string} attribute - * @param {string | string[]} value - * @returns {string} - */ - static notContains = (attribute: string, value: string | any[]): string => - new Query("notContains", attribute, value).toString(); - - /** - * Filter resources by searching attribute for value (inverse of search). - * A fulltext index on attribute is required for this query to work. - * - * @param {string} attribute - * @param {string} value - * @returns {string} - */ - static notSearch = (attribute: string, value: string): string => - new Query("notSearch", attribute, value).toString(); - - /** - * Filter resources where attribute is not between start and end (exclusive). - * - * @param {string} attribute - * @param {string | number} start - * @param {string | number} end - * @returns {string} - */ - static notBetween = (attribute: string, start: string | number, end: string | number): string => - new Query("notBetween", attribute, [start, end] as QueryTypesList).toString(); - - /** - * Filter resources where attribute does not start with value. - * - * @param {string} attribute - * @param {string} value - * @returns {string} - */ - static notStartsWith = (attribute: string, value: string): string => - new Query("notStartsWith", attribute, value).toString(); - - /** - * Filter resources where attribute does not end with value. - * - * @param {string} attribute - * @param {string} value - * @returns {string} - */ - static notEndsWith = (attribute: string, value: string): string => - new Query("notEndsWith", attribute, value).toString(); - - /** - * Filter resources where document was created before date. - * - * @param {string} value - * @returns {string} - */ - static createdBefore = (value: string): string => - Query.lessThan("$createdAt", value); - - /** - * Filter resources where document was created after date. - * - * @param {string} value - * @returns {string} - */ - static createdAfter = (value: string): string => - Query.greaterThan("$createdAt", value); - - /** - * Filter resources where document was created between dates. - * - * @param {string} start - * @param {string} end - * @returns {string} - */ - static createdBetween = (start: string, end: string): string => - Query.between("$createdAt", start, end); - - /** - * Filter resources where document was updated before date. - * - * @param {string} value - * @returns {string} - */ - static updatedBefore = (value: string): string => - Query.lessThan("$updatedAt", value); - - /** - * Filter resources where document was updated after date. - * - * @param {string} value - * @returns {string} - */ - static updatedAfter = (value: string): string => - Query.greaterThan("$updatedAt", value); - - /** - * Filter resources where document was updated between dates. - * - * @param {string} start - * @param {string} end - * @returns {string} - */ - static updatedBetween = (start: string, end: string): string => - Query.between("$updatedAt", start, end); - - static or = (queries: string[]) => - new Query("or", undefined, queries.map((query) => JSON.parse(query))).toString(); - - static and = (queries: string[]) => - new Query("and", undefined, queries.map((query) => JSON.parse(query))).toString(); - - /** - * Filter array elements where at least one element matches all the specified queries. - * - * @param {string} attribute The attribute containing the array to filter on. - * @param {string[]} queries The list of query strings to match against array elements. - * @returns {string} - */ - static elemMatch = (attribute: string, queries: string[]): string => - new Query( - "elemMatch", - attribute, - queries.map((query) => JSON.parse(query)) - ).toString(); - - /** - * Constrain populated related documents on a relationship attribute. - * - * @param {string} attribute The relationship attribute to query. - * @param {string[]} queries Filter, order, select, and pagination queries applied to related documents. - * @returns {string} - */ - static relationship = (attribute: string, queries: string[]): string => - new Query( - "relationship", - attribute, - queries.map((query) => JSON.parse(query)) - ).toString(); - - /** - * Filter resources where attribute is at a specific distance from the given coordinates. - * - * @param {string} attribute - * @param {any[]} values - * @param {number} distance - * @param {boolean} meters - * @returns {string} - */ - static distanceEqual = (attribute: string, values: any[], distance: number, meters: boolean = true): string => - new Query("distanceEqual", attribute, [[values, distance, meters]]).toString(); - - /** - * Filter resources where attribute is not at a specific distance from the given coordinates. - * - * @param {string} attribute - * @param {any[]} values - * @param {number} distance - * @param {boolean} meters - * @returns {string} - */ - static distanceNotEqual = (attribute: string, values: any[], distance: number, meters: boolean = true): string => - new Query("distanceNotEqual", attribute, [[values, distance, meters]]).toString(); - - /** - * Filter resources where attribute is at a distance greater than the specified value from the given coordinates. - * - * @param {string} attribute - * @param {any[]} values - * @param {number} distance - * @param {boolean} meters - * @returns {string} - */ - static distanceGreaterThan = (attribute: string, values: any[], distance: number, meters: boolean = true): string => - new Query("distanceGreaterThan", attribute, [[values, distance, meters]]).toString(); - - /** - * Filter resources where attribute is at a distance less than the specified value from the given coordinates. - * - * @param {string} attribute - * @param {any[]} values - * @param {number} distance - * @param {boolean} meters - * @returns {string} - */ - static distanceLessThan = (attribute: string, values: any[], distance: number, meters: boolean = true): string => - new Query("distanceLessThan", attribute, [[values, distance, meters]]).toString(); - - /** - * Filter resources using vector dot product similarity. - * - * @param {string} attribute - * @param {number[]} vector - * @returns {string} - */ - static vectorDot = (attribute: string, vector: number[]): string => - new Query("vectorDot", attribute, [vector]).toString(); - - /** - * Filter resources using vector cosine similarity. - * - * @param {string} attribute - * @param {number[]} vector - * @returns {string} - */ - static vectorCosine = (attribute: string, vector: number[]): string => - new Query("vectorCosine", attribute, [vector]).toString(); - - /** - * Filter resources using vector Euclidean distance. - * - * @param {string} attribute - * @param {number[]} vector - * @returns {string} - */ - static vectorEuclidean = (attribute: string, vector: number[]): string => - new Query("vectorEuclidean", attribute, [vector]).toString(); - - /** - * Filter resources where attribute intersects with the given geometry. - * - * @param {string} attribute - * @param {any[]} values - * @returns {string} - */ - static intersects = (attribute: string, values: any[]): string => - new Query("intersects", attribute, [values]).toString(); - - /** - * Filter resources where attribute does not intersect with the given geometry. - * - * @param {string} attribute - * @param {any[]} values - * @returns {string} - */ - static notIntersects = (attribute: string, values: any[]): string => - new Query("notIntersects", attribute, [values]).toString(); - - /** - * Filter resources where attribute crosses the given geometry. - * - * @param {string} attribute - * @param {any[]} values - * @returns {string} - */ - static crosses = (attribute: string, values: any[]): string => - new Query("crosses", attribute, [values]).toString(); - - /** - * Filter resources where attribute does not cross the given geometry. - * - * @param {string} attribute - * @param {any[]} values - * @returns {string} - */ - static notCrosses = (attribute: string, values: any[]): string => - new Query("notCrosses", attribute, [values]).toString(); - - /** - * Filter resources where attribute overlaps with the given geometry. - * - * @param {string} attribute - * @param {any[]} values - * @returns {string} - */ - static overlaps = (attribute: string, values: any[]): string => - new Query("overlaps", attribute, [values]).toString(); - - /** - * Filter resources where attribute does not overlap with the given geometry. - * - * @param {string} attribute - * @param {any[]} values - * @returns {string} - */ - static notOverlaps = (attribute: string, values: any[]): string => - new Query("notOverlaps", attribute, [values]).toString(); - - /** - * Filter resources where attribute touches the given geometry. - * - * @param {string} attribute - * @param {any[]} values - * @returns {string} - */ - static touches = (attribute: string, values: any[]): string => - new Query("touches", attribute, [values]).toString(); - - /** - * Filter resources where attribute does not touch the given geometry. - * - * @param {string} attribute - * @param {any[]} values - * @returns {string} - */ - static notTouches = (attribute: string, values: any[]): string => - new Query("notTouches", attribute, [values]).toString(); - - /** - * Count documents, optionally aliased. - */ - static count = (attribute: string = "*", alias: string = ""): string => - new Query("count", attribute, alias !== "" ? alias : undefined).toString(); - - /** - * Count distinct values of attribute, optionally aliased. - */ - static countDistinct = (attribute: string, alias: string = ""): string => - new Query("countDistinct", attribute, alias !== "" ? alias : undefined).toString(); - - static sum = (attribute: string, alias: string = ""): string => - new Query("sum", attribute, alias !== "" ? alias : undefined).toString(); - - static avg = (attribute: string, alias: string = ""): string => - new Query("avg", attribute, alias !== "" ? alias : undefined).toString(); - - static min = (attribute: string, alias: string = ""): string => - new Query("min", attribute, alias !== "" ? alias : undefined).toString(); - - static max = (attribute: string, alias: string = ""): string => - new Query("max", attribute, alias !== "" ? alias : undefined).toString(); - - static stddev = (attribute: string, alias: string = ""): string => - new Query("stddev", attribute, alias !== "" ? alias : undefined).toString(); - - static stddevPop = (attribute: string, alias: string = ""): string => - new Query("stddevPop", attribute, alias !== "" ? alias : undefined).toString(); - - static stddevSamp = (attribute: string, alias: string = ""): string => - new Query("stddevSamp", attribute, alias !== "" ? alias : undefined).toString(); - - static variance = (attribute: string, alias: string = ""): string => - new Query("variance", attribute, alias !== "" ? alias : undefined).toString(); - - static varPop = (attribute: string, alias: string = ""): string => - new Query("varPop", attribute, alias !== "" ? alias : undefined).toString(); - - static varSamp = (attribute: string, alias: string = ""): string => - new Query("varSamp", attribute, alias !== "" ? alias : undefined).toString(); - - static bitAnd = (attribute: string, alias: string = ""): string => - new Query("bitAnd", attribute, alias !== "" ? alias : undefined).toString(); - - static bitOr = (attribute: string, alias: string = ""): string => - new Query("bitOr", attribute, alias !== "" ? alias : undefined).toString(); - - static bitXor = (attribute: string, alias: string = ""): string => - new Query("bitXor", attribute, alias !== "" ? alias : undefined).toString(); - - /** - * Group results by attributes. - */ - static groupBy = (attributes: string[]): string => - new Query("groupBy", undefined, attributes).toString(); - - /** - * Filter grouped results. `queries` are nested like `and`/`or`. - */ - static having = (queries: string[]): string => - new Query( - "having", - undefined, - queries.map((query) => JSON.parse(query)) - ).toString(); - - static distinct = (): string => - new Query("distinct").toString(); - - /** - * Column-to-column join ON condition. - */ - static on = ( - left: string, - right: string, - operator: string = "=" - ): string => - new Query("on", undefined, [left, operator, right]).toString(); - - /** - * Inner join. `table` is the joined collection/table ID. - */ - static join = ( - table: string, - leftOrAliasOrOn: string | string[], - rightOrOn: string | string[] = "", - operator: string = "=", - alias: string = "" - ): string => - Query.createJoin("join", table, leftOrAliasOrOn, rightOrOn, operator, alias); - - static leftJoin = ( - table: string, - leftOrAliasOrOn: string | string[], - rightOrOn: string | string[] = "", - operator: string = "=", - alias: string = "" - ): string => - Query.createJoin("leftJoin", table, leftOrAliasOrOn, rightOrOn, operator, alias); - - static rightJoin = ( - table: string, - leftOrAliasOrOn: string | string[], - rightOrOn: string | string[] = "", - operator: string = "=", - alias: string = "" - ): string => - Query.createJoin("rightJoin", table, leftOrAliasOrOn, rightOrOn, operator, alias); - - static fullOuterJoin = ( - table: string, - leftOrAliasOrOn: string | string[], - rightOrOn: string | string[] = "", - operator: string = "=", - alias: string = "" - ): string => - Query.createJoin("fullOuterJoin", table, leftOrAliasOrOn, rightOrOn, operator, alias); - - static crossJoin = (table: string, alias: string = ""): string => - new Query("crossJoin", table, alias !== "" ? alias : undefined).toString(); - - static covers = (attribute: string, values: any[]): string => - new Query("covers", attribute, [values]).toString(); - - static notCovers = (attribute: string, values: any[]): string => - new Query("notCovers", attribute, [values]).toString(); - - static spatialEquals = (attribute: string, values: any[]): string => - new Query("spatialEquals", attribute, [values]).toString(); - - static notSpatialEquals = (attribute: string, values: any[]): string => - new Query("notSpatialEquals", attribute, [values]).toString(); - - /** - * Return limit and offset queries for 1-based page pagination. - */ - static page = (page: number, perPage: number = 25): string[] => { - if (page < 1) { - throw new Error("Page must be >= 1, got " + page); - } - if (perPage < 1) { - throw new Error("Per page must be >= 1, got " + perPage); - } - return [Query.limit(perPage), Query.offset((page - 1) * perPage)]; - }; - - static builder = (): Query.Builder => new Query.Builder(); - - private static createJoin( - method: string, - table: string, - leftOrAliasOrOn: string | string[], - rightOrOn: string | string[] = "", - operator: string = "=", - alias: string = "" - ): string { - if (Array.isArray(leftOrAliasOrOn)) { - return Query.nestedJoin(method, table, "", leftOrAliasOrOn); - } - if (Array.isArray(rightOrOn)) { - return Query.nestedJoin(method, table, leftOrAliasOrOn, rightOrOn); - } - return new Query( - method, - table, - alias !== "" - ? [leftOrAliasOrOn, operator, rightOrOn, alias] - : [leftOrAliasOrOn, operator, rightOrOn] - ).toString(); - } - - private static nestedJoin( - method: string, - table: string, - alias: string, - on: string[] - ): string { - const values: any[] = []; - if (alias !== "") { - values.push(alias); - } - for (const query of on) { - values.push(JSON.parse(query)); - } - return new Query(method, table, values).toString(); - } -} - -export type QueryInput = - | string - | Query - | Query.Builder - | QueryInput[]; - -/** - * Fluent collector of Query fragments. Call {@link Query.Builder.build} to - * produce the `string[]` expected by list/createQuery methods. - */ -export namespace Query { - export class Builder { - private readonly queries: string[] = []; - - build(): string[] { - return [...this.queries]; - } - - equal(attribute: string, value: QueryTypes): this { - return this.push(Query.equal(attribute, value)); - } - - notEqual(attribute: string, value: QueryTypes): this { - return this.push(Query.notEqual(attribute, value)); - } - - lessThan(attribute: string, value: QueryTypes): this { - return this.push(Query.lessThan(attribute, value)); - } - - lessThanEqual(attribute: string, value: QueryTypes): this { - return this.push(Query.lessThanEqual(attribute, value)); - } - - greaterThan(attribute: string, value: QueryTypes): this { - return this.push(Query.greaterThan(attribute, value)); - } - - greaterThanEqual(attribute: string, value: QueryTypes): this { - return this.push(Query.greaterThanEqual(attribute, value)); - } - - search(attribute: string, value: string): this { - return this.push(Query.search(attribute, value)); - } - - isNull(attribute: string): this { - return this.push(Query.isNull(attribute)); - } - - isNotNull(attribute: string): this { - return this.push(Query.isNotNull(attribute)); - } - - between(attribute: string, start: string | number, end: string | number): this { - return this.push(Query.between(attribute, start, end)); - } - - startsWith(attribute: string, value: string): this { - return this.push(Query.startsWith(attribute, value)); - } - - endsWith(attribute: string, value: string): this { - return this.push(Query.endsWith(attribute, value)); - } - - select(attributes: string[]): this { - return this.push(Query.select(attributes)); - } - - cursorAfter(documentId: string): this { - return this.push(Query.cursorAfter(documentId)); - } - - cursorBefore(documentId: string): this { - return this.push(Query.cursorBefore(documentId)); - } - - orderAsc(attribute: string): this { - return this.push(Query.orderAsc(attribute)); - } - - orderDesc(attribute: string): this { - return this.push(Query.orderDesc(attribute)); - } - - orderRandom(): this { - return this.push(Query.orderRandom()); - } - - limit(limit: number): this { - return this.push(Query.limit(limit)); - } - - offset(offset: number): this { - return this.push(Query.offset(offset)); - } - - contains(attribute: string, value: string | any[]): this { - return this.push(Query.contains(attribute, value)); - } - - containsAny(attribute: string, value: any[]): this { - return this.push(Query.containsAny(attribute, value)); - } - - containsAll(attribute: string, value: any[]): this { - return this.push(Query.containsAll(attribute, value)); - } - - notContains(attribute: string, value: string | any[]): this { - return this.push(Query.notContains(attribute, value)); - } - - notSearch(attribute: string, value: string): this { - return this.push(Query.notSearch(attribute, value)); - } - - notBetween(attribute: string, start: string | number, end: string | number): this { - return this.push(Query.notBetween(attribute, start, end)); - } - - notStartsWith(attribute: string, value: string): this { - return this.push(Query.notStartsWith(attribute, value)); - } - - notEndsWith(attribute: string, value: string): this { - return this.push(Query.notEndsWith(attribute, value)); - } - - regex(attribute: string, pattern: string): this { - return this.push(Query.regex(attribute, pattern)); - } - - exists(attributes: string[]): this { - return this.push(Query.exists(attributes)); - } - - notExists(attributes: string[]): this { - return this.push(Query.notExists(attributes)); - } - - createdBefore(value: string): this { - return this.push(Query.createdBefore(value)); - } - - createdAfter(value: string): this { - return this.push(Query.createdAfter(value)); - } - - createdBetween(start: string, end: string): this { - return this.push(Query.createdBetween(start, end)); - } - - updatedBefore(value: string): this { - return this.push(Query.updatedBefore(value)); - } - - updatedAfter(value: string): this { - return this.push(Query.updatedAfter(value)); - } - - updatedBetween(start: string, end: string): this { - return this.push(Query.updatedBetween(start, end)); - } - - or(queries: string[]): this { - return this.push(Query.or(queries)); - } - - and(queries: string[]): this { - return this.push(Query.and(queries)); - } - - elemMatch(attribute: string, queries: string[]): this { - return this.push(Query.elemMatch(attribute, queries)); - } - - relationship(attribute: string, queries: string[]): this { - return this.push(Query.relationship(attribute, queries)); - } - - distanceEqual(attribute: string, values: any[], distance: number, meters: boolean = true): this { - return this.push(Query.distanceEqual(attribute, values, distance, meters)); - } - - distanceNotEqual(attribute: string, values: any[], distance: number, meters: boolean = true): this { - return this.push(Query.distanceNotEqual(attribute, values, distance, meters)); - } - - distanceGreaterThan(attribute: string, values: any[], distance: number, meters: boolean = true): this { - return this.push(Query.distanceGreaterThan(attribute, values, distance, meters)); - } - - distanceLessThan(attribute: string, values: any[], distance: number, meters: boolean = true): this { - return this.push(Query.distanceLessThan(attribute, values, distance, meters)); - } - - intersects(attribute: string, values: any[]): this { - return this.push(Query.intersects(attribute, values)); - } - - notIntersects(attribute: string, values: any[]): this { - return this.push(Query.notIntersects(attribute, values)); - } - - crosses(attribute: string, values: any[]): this { - return this.push(Query.crosses(attribute, values)); - } - - notCrosses(attribute: string, values: any[]): this { - return this.push(Query.notCrosses(attribute, values)); - } - - overlaps(attribute: string, values: any[]): this { - return this.push(Query.overlaps(attribute, values)); - } - - notOverlaps(attribute: string, values: any[]): this { - return this.push(Query.notOverlaps(attribute, values)); - } - - touches(attribute: string, values: any[]): this { - return this.push(Query.touches(attribute, values)); - } - - notTouches(attribute: string, values: any[]): this { - return this.push(Query.notTouches(attribute, values)); - } - - count(attribute: string = "*", alias: string = ""): this { - return this.push(Query.count(attribute, alias)); - } - - countDistinct(attribute: string, alias: string = ""): this { - return this.push(Query.countDistinct(attribute, alias)); - } - - sum(attribute: string, alias: string = ""): this { - return this.push(Query.sum(attribute, alias)); - } - - avg(attribute: string, alias: string = ""): this { - return this.push(Query.avg(attribute, alias)); - } - - min(attribute: string, alias: string = ""): this { - return this.push(Query.min(attribute, alias)); - } - - max(attribute: string, alias: string = ""): this { - return this.push(Query.max(attribute, alias)); - } - - stddev(attribute: string, alias: string = ""): this { - return this.push(Query.stddev(attribute, alias)); - } - - stddevPop(attribute: string, alias: string = ""): this { - return this.push(Query.stddevPop(attribute, alias)); - } - - stddevSamp(attribute: string, alias: string = ""): this { - return this.push(Query.stddevSamp(attribute, alias)); - } - - variance(attribute: string, alias: string = ""): this { - return this.push(Query.variance(attribute, alias)); - } - - varPop(attribute: string, alias: string = ""): this { - return this.push(Query.varPop(attribute, alias)); - } - - varSamp(attribute: string, alias: string = ""): this { - return this.push(Query.varSamp(attribute, alias)); - } - - bitAnd(attribute: string, alias: string = ""): this { - return this.push(Query.bitAnd(attribute, alias)); - } - - bitOr(attribute: string, alias: string = ""): this { - return this.push(Query.bitOr(attribute, alias)); - } - - bitXor(attribute: string, alias: string = ""): this { - return this.push(Query.bitXor(attribute, alias)); - } - - groupBy(attributes: string[]): this { - return this.push(Query.groupBy(attributes)); - } - - having(queries: string[]): this { - return this.push(Query.having(queries)); - } - - distinct(): this { - return this.push(Query.distinct()); - } - - join(table: string, leftOrAliasOrOn: string | string[], rightOrOn: string | string[] = "", operator: string = "=", alias: string = ""): this { - return this.push(Query.join(table, leftOrAliasOrOn, rightOrOn, operator, alias)); - } - - leftJoin(table: string, leftOrAliasOrOn: string | string[], rightOrOn: string | string[] = "", operator: string = "=", alias: string = ""): this { - return this.push(Query.leftJoin(table, leftOrAliasOrOn, rightOrOn, operator, alias)); - } - - rightJoin(table: string, leftOrAliasOrOn: string | string[], rightOrOn: string | string[] = "", operator: string = "=", alias: string = ""): this { - return this.push(Query.rightJoin(table, leftOrAliasOrOn, rightOrOn, operator, alias)); - } - - fullOuterJoin(table: string, leftOrAliasOrOn: string | string[], rightOrOn: string | string[] = "", operator: string = "=", alias: string = ""): this { - return this.push(Query.fullOuterJoin(table, leftOrAliasOrOn, rightOrOn, operator, alias)); - } - - crossJoin(table: string, alias: string = ""): this { - return this.push(Query.crossJoin(table, alias)); - } - - vectorDot(attribute: string, vector: number[]): this { - return this.push(Query.vectorDot(attribute, vector)); - } - - vectorCosine(attribute: string, vector: number[]): this { - return this.push(Query.vectorCosine(attribute, vector)); - } - - vectorEuclidean(attribute: string, vector: number[]): this { - return this.push(Query.vectorEuclidean(attribute, vector)); - } - - covers(attribute: string, values: any[]): this { - return this.push(Query.covers(attribute, values)); - } - - notCovers(attribute: string, values: any[]): this { - return this.push(Query.notCovers(attribute, values)); - } - - spatialEquals(attribute: string, values: any[]): this { - return this.push(Query.spatialEquals(attribute, values)); - } - - notSpatialEquals(attribute: string, values: any[]): this { - return this.push(Query.notSpatialEquals(attribute, values)); - } - - page(page: number, perPage: number = 25): this { - return this.push(Query.page(page, perPage)); - } - - private push(query: string | string[]): this { - if (Array.isArray(query)) { - this.queries.push(...query); - } else { - this.queries.push(query); - } - return this; - } -} -} - -export function normalizeQueries(queries?: QueryInput | null): string[] { - if (queries == null) { - return []; - } - if (queries instanceof Query.Builder) { - return queries.build(); - } - if (!Array.isArray(queries)) { - if (queries instanceof Query) { - return [queries.toString()]; - } - if (typeof queries === "string") { - return [queries]; - } - return []; - } - - const out: string[] = []; - for (const item of queries) { - out.push(...normalizeQueries(item)); - } - return out; -} - -function isQueryValue(value: unknown): value is Query | Query.Builder { - return value instanceof Query.Builder || value instanceof Query; -} - -export function flattenParam(value: unknown): unknown { - if (isQueryValue(value)) { - return normalizeQueries(value); - } - if (!Array.isArray(value)) { - return value; - } - - const out: unknown[] = []; - for (const item of value) { - if (isQueryValue(item)) { - out.push(...normalizeQueries(item)); - } else { - out.push(flattenParam(item)); - } - } - return out; -} - -export const QueryBuilder = Query.Builder; -export type QueryBuilder = Query.Builder; diff --git a/templates/deno/src/role.ts.twig b/templates/deno/src/role.ts.twig deleted file mode 100644 index 79f8c6b622..0000000000 --- a/templates/deno/src/role.ts.twig +++ /dev/null @@ -1,100 +0,0 @@ -/** - * Helper class to generate role strings for `Permission`. - */ -export class Role { - - /** - * Grants access to anyone. - * - * This includes authenticated and unauthenticated users. - * - * @returns {string} - */ - public static any(): string { - return 'any' - } - - /** - * Grants access to a specific user by user ID. - * - * You can optionally pass verified or unverified for - * `status` to target specific types of users. - * - * @param {string} id - * @param {string} status - * @returns {string} - */ - public static user(id: string, status: string = ''): string { - if (status === '') { - return `user:${id}` - } - return `user:${id}/${status}` - } - - /** - * Grants access to any authenticated or anonymous user. - * - * You can optionally pass verified or unverified for - * `status` to target specific types of users. - * - * @param {string} status - * @returns {string} - */ - public static users(status: string = ''): string { - if (status === '') { - return 'users' - } - return `users/${status}` - } - - /** - * Grants access to any guest user without a session. - * - * Authenticated users don't have access to this role. - * - * @returns {string} - */ - public static guests(): string { - return 'guests' - } - - /** - * Grants access to a team by team ID. - * - * You can optionally pass a role for `role` to target - * team members with the specified role. - * - * @param {string} id - * @param {string} role - * @returns {string} - */ - public static team(id: string, role: string = ''): string { - if (role === '') { - return `team:${id}` - } - return `team:${id}/${role}` - } - - /** - * Grants access to a specific member of a team. - * - * When the member is removed from the team, they will - * no longer have access. - * - * @param {string} id - * @returns {string} - */ - public static member(id: string): string { - return `member:${id}` - } - - /** - * Grants access to a user with the specified label. - * - * @param {string} name - * @returns {string} - */ - public static label(name: string): string { - return `label:${name}` - } -} \ No newline at end of file diff --git a/templates/deno/src/service.ts.twig b/templates/deno/src/service.ts.twig deleted file mode 100644 index 300fa827ae..0000000000 --- a/templates/deno/src/service.ts.twig +++ /dev/null @@ -1,12 +0,0 @@ -import { Client } from "./client.ts"; - -export abstract class Service { - client: Client; - - /** - * @param client - */ - constructor(client: Client) { - this.client = client; - } -} \ No newline at end of file diff --git a/templates/deno/src/services/service.ts.twig b/templates/deno/src/services/service.ts.twig deleted file mode 100644 index 64ab7d2bb8..0000000000 --- a/templates/deno/src/services/service.ts.twig +++ /dev/null @@ -1,348 +0,0 @@ -{# Macros cannot see the template context, so the definitions are passed in. #} -{% macro get_generics(name, definitions, output = false, first = false) %} -{% apply spaceless %} - {% if first and definitions[name].additionalProperties %} - {{ name | caseUcfirst }} extends Models.{{ name | caseUcfirst }} - {% endif %} - {% for property in definitions[name].properties ?? [] %} - {% if definitions[(property | schemaModel)].additionalProperties ?? false and output %} - {{ (property | schemaModel) | caseUcfirst }} extends Models.{{ (property | schemaModel) | caseUcfirst }} - {% endif %} - {% if definitions[(property | schemaModel)] is defined %} - {{ _self.get_generics((property | schemaModel), definitions, true) }} - {% endif %} - {% endfor %} -{% endapply %} -{% endmacro %} -{% macro get_generics_return(name, definitions) %} -{% apply spaceless %} - {% for property in definitions[name].properties ?? [] %} - {% if definitions[(property | schemaModel)].additionalProperties ?? false %} - {{ (property | schemaModel) | caseUcfirst }} - {% endif %} - {% if definitions[(property | schemaModel)] is defined %} - {{ _self.get_generics_return((property | schemaModel), definitions) }} - {% endif %} - {% endfor %} -{% endapply %} -{% endmacro %} -import { basename } from "https://deno.land/std@0.122.0/path/mod.ts"; -import { Service } from '../service.ts'; -{% set usesDefaults = false %} -{% for method in (service | operations) %} -{% if 'multipart/form-data' not in (method | consumes) and (method | responseDefaults(spec, 8)) is not empty %}{% set usesDefaults = true %}{% endif %} -{% endfor %} -import { Payload, Client{% if usesDefaults %}, applyDefaults{% endif %} } from '../client.ts'; -import { InputFile } from '../inputFile.ts'; -import { AppwriteException } from '../exception.ts'; -import type { Models } from '../models.d.ts'; -import { Query } from '../query.ts'; -{% set added = [] %} -{% for method in (service | operations) %} -{% for parameter in (method | parameters('all')) %} -{% if (parameter | enumValues) is not empty %} -{% if (parameter | enumName) not in added %} -import { {{ (parameter | enumName) | caseUcfirst }} } from '../enums/{{ (parameter | enumName) | caseKebab }}.ts'; -{% set added = added|merge([(parameter | enumName)]) %} -{% endif %} -{% endif %} -{% endfor %} -{% endfor %} - -export type UploadProgress = { - $id: string; - progress: number; - sizeUploaded: number; - chunksTotal: number; - chunksUploaded: number; -} - -export class {{ service.name | caseUcfirst }} extends Service { - - constructor(client: Client) - { - super(client); - } - -{% for method in (service | operations) %} -{% set generics = _self.get_generics((method | responseModel), definitions, true, true) %} -{% set generics_return = _self.get_generics_return((method | responseModel), definitions) %} - /** -{% if method.description %} -{{ method.description | wrap(75, ' * ') }} - * -{% endif %} -{% for parameter in (method | parameters('all'))%} - * @param {{ '{' }}{{ parameter | typeName }}{{ '}' }} {{ parameter.name | caseCamel | escapeKeyword }} -{% endfor %} - * @throws {AppwriteException} - * @returns {Promise} - {%~ if method.deprecated %} - {%~ if (method | appwrite('deprecated', {})['since'] ?? '') and (method | appwrite('deprecated', {})['replaceWith'] ?? '') %} - * @deprecated This API has been deprecated since {{ (method | appwrite('deprecated', {})['since'] ?? '') }}. Please use `{{ (method | appwrite('deprecated', {})['replaceWith'] ?? '') | capitalizeFirst }}` instead. - {%~ else %} - * @deprecated This API has been deprecated. - {%~ endif %} - {%~ endif %} - */ - async {{ (method | methodName) | caseCamel }}{% if generics %}<{{generics}}>{% endif %}({% for parameter in (method | parameters('all')) %}{{ parameter.name | caseCamel | escapeKeyword }}{% if not parameter.required or (parameter | schemaNullable) %}?{% endif %}: {{ parameter | typeName }}{% if parameter | schemaNullable %} | null{% endif %}{% if not loop.last %}, {% endif %}{% endfor %}{% if 'multipart/form-data' in (method | consumes) %}, onProgress = (progress: UploadProgress) => {}{% endif %}): Promise<{% if (method | methodType) == 'webAuth' %}string{% elseif (method | methodType) == 'location' %}ArrayBuffer{% elseif (method | textResponse) %}string{% else %}{% if (method | responseModel) and (method | responseModel) != 'any' %}{% if not definitions[(method | responseModel)].additionalProperties %}Models.{% endif %}{{(method | responseModel) | caseUcfirst}}{% if generics_return %}<{{generics_return}}>{% endif %}{% else %}{}{% endif %}{% endif %}> { -{% for parameter in (method | parameters('all')) %} -{% if parameter.required %} - {{ parameter | jsRequiredGuard((parameter.name | caseCamel | escapeKeyword), 8) | raw }} - throw new {{spec.info.title | caseUcfirst}}Exception('Missing required parameter: "{{ parameter.name | caseCamel | escapeKeyword }}"'); - } - -{% endif %} -{% endfor %} - let apiPath = '{{ method.path }}'{% for parameter in (method | parameters('path')) %}.replace('{{ '{' }}{{ parameter.name }}{{ '}' }}', {% if (parameter | configKey(method)) %}this.client.config['{{ (parameter | configKey(method)) | caseLower }}']{% else %}{{ parameter.name | caseCamel | escapeKeyword }}{% endif %}){% endfor %}; - {%~ for security in (method | securityQueries) %} - apiPath += `{% if loop.first %}?{% else %}&{% endif %}{{ security.name }}=${encodeURIComponent(this.client.config['{{ security.name | caseLower }}'])}`; - {%~ endfor %} - const apiPayload: Payload = {}; - -{% for parameter in (method | parameters('query')) %} - if (typeof {{ parameter.name | caseCamel | escapeKeyword }} !== 'undefined') { -{% set multipart = (method | consumes)[0] == "multipart/form-data" %} -{% if multipart and (parameter | schemaType) == "object" %} - apiPayload['{{ parameter.name }}'] = JSON.stringify({{ parameter.name | caseCamel | escapeKeyword }}); -{% else %} - apiPayload['{{ parameter.name }}'] = {{ parameter.name | caseCamel | escapeKeyword }}{% if multipart and (parameter | schemaType) not in ["string", "array", "file"] %}.toString(){% endif %}; -{% endif %} } - -{% endfor %} -{% for parameter in (method | parameters('body')) %} - if (typeof {{ parameter.name | caseCamel | escapeKeyword }} !== 'undefined') { -{% set multipart = (method | consumes)[0] == "multipart/form-data" %} -{% if multipart and (parameter | schemaType) == "object" %} - apiPayload['{{ parameter.name }}'] = JSON.stringify({{ parameter.name | caseCamel | escapeKeyword }}); -{% else %} - apiPayload['{{ parameter.name }}'] = {{ parameter.name | caseCamel | escapeKeyword }}{% if multipart and (parameter | schemaType) not in ["string", "array", "file"] %}.toString(){% endif %}; -{% endif %} } -{% endfor %} -{% if 'multipart/form-data' in (method | consumes) %} -{% for parameter in (method | parameters('all')) %} -{% if (parameter | schemaType) == 'file' %} - - const apiHeaders: { [header: string]: string } = { - {%~ for key, security in (method | securityHeaders) %} - '{{ security.name }}': this.client.config['{{ key | caseLower }}'], - {%~ endfor %} -{% for parameter in (method | parameters('header')) %} - '{{ parameter.name }}': ${{ parameter.name | caseCamel | escapeKeyword }}, -{% endfor %} -{% for key, header in (method | methodHeaders) %} - '{{ key }}': '{{ header }}', -{% endfor %} - }; - -{% if not parameter.required or (parameter | schemaNullable) %} - if (!{{ parameter.name | caseCamel | escapeKeyword }}) { - return await this.client.call('{{ method.method.value | caseLower }}', apiPath, apiHeaders, apiPayload{% if (method | textResponse) %}, 'text'{% endif %}); - } - -{% endif %} -{% if (method | textResponse) %} - apiPayload['{{ parameter.name }}'] = { type: 'file', file: new File([await new Response({{ parameter.name | caseCamel | escapeKeyword }}.stream).arrayBuffer()], {{ parameter.name | caseCamel | escapeKeyword }}.filename), filename: {{ parameter.name | caseCamel | escapeKeyword }}.filename }; - - return await this.client.call('{{ method.method.value | caseLower }}', apiPath, apiHeaders, apiPayload, 'text'); -{% else %} - const size = {{ parameter.name | caseCamel | escapeKeyword }}.size; - - let id: string | undefined = undefined; - let response: any = undefined; - - let chunksUploaded = 0; - -{% set uploadIdParameter = method | uploadIdParameter %} -{% if uploadIdParameter %} - id = {{ uploadIdParameter.name | caseCamel | escapeKeyword }}; - if (id) { - try { - response = await this.client.call( - 'get', - apiPath + '/' + id, - apiHeaders - ); - chunksUploaded = response.chunksUploaded; - } catch(e) { - } - } -{% endif %} - - const totalChunks = Math.ceil(size / Client.CHUNK_SIZE); - const chunks: { index: number; start: number; end: number; data: Uint8Array }[] = []; - let currentChunk = 0; - let currentPosition = 0; - let uploadableChunk = new Uint8Array(Client.CHUNK_SIZE); - - const queueChunk = () => { - if (currentChunk < chunksUploaded) { - currentChunk++; - currentPosition = 0; - uploadableChunk = new Uint8Array(Client.CHUNK_SIZE); - return; - } - - const start = currentChunk * Client.CHUNK_SIZE; - const end = Math.min(start + currentPosition, size); - const data = currentPosition >= Client.CHUNK_SIZE - ? uploadableChunk - : uploadableChunk.slice(0, currentPosition); - - chunks.push({ index: currentChunk, start, end, data }); - currentChunk++; - currentPosition = 0; - uploadableChunk = new Uint8Array(Client.CHUNK_SIZE); - }; - - for await (const chunk of {{ parameter.name | caseCamel | escapeKeyword }}.stream) { - let i = 0; - for(const b of chunk) { - uploadableChunk[currentPosition] = chunk[i]; - currentPosition++; - - if(currentPosition >= Client.CHUNK_SIZE) { - queueChunk(); - } - - i++; - } - } - - // An empty file still has to be sent, as a single empty chunk. - if (currentPosition > 0 || (size === 0 && chunksUploaded === 0)) { - queueChunk(); - } - - if (chunks.length === 0) { - return response; - } - - if (chunks.length === 1 && chunks[0].index === 0) { - apiPayload['{{ parameter.name }}'] = { type: 'file', file: new File([chunks[0].data as BlobPart], {{ parameter.name | caseCamel | escapeKeyword }}.filename), filename: {{ parameter.name | caseCamel | escapeKeyword }}.filename }; - response = await this.client.call('{{ method.method.value | caseLower }}', apiPath, apiHeaders, apiPayload{% if (method | methodType) == 'location' %}, 'arraybuffer'{% elseif (method | methodType) == 'webAuth' %}, 'location'{% endif %}); - - if (onProgress !== null) { - onProgress({ - $id: response['$id'], - progress: 100, - sizeUploaded: size, - chunksTotal: response['chunksTotal'] ?? totalChunks, - chunksUploaded: response['chunksUploaded'] ?? 1 - }); - } - - return response; - } - - const uploadChunk = async (chunk: typeof chunks[0]) => { - const chunkHeaders = { ...apiHeaders }; - chunkHeaders['content-range'] = 'bytes ' + chunk.start + '-' + (chunk.end - 1) + '/' + size; - if (id) { - chunkHeaders['x-{{spec.info.title | caseLower }}-id'] = id; - } - - const chunkPayload = { ...apiPayload }; - chunkPayload['{{ parameter.name }}'] = { type: 'file', file: new File([chunk.data as BlobPart], {{ parameter.name | caseCamel | escapeKeyword }}.filename), filename: {{ parameter.name | caseCamel | escapeKeyword }}.filename }; - - return await this.client.call('{{ method.method.value | caseLower }}', apiPath, chunkHeaders, chunkPayload{% if (method | methodType) == 'location' %}, 'arraybuffer'{% elseif (method | methodType) == 'webAuth' %}, 'location'{% endif %}); - }; - - response = await uploadChunk(chunks[0]); - - if (!id) { - id = response['$id']; - } - - let completedCount = chunks[0].index + 1; - let uploadedBytes = chunks[0].end; - - if (onProgress !== null) { - onProgress({ - $id: response['$id'], - progress: uploadedBytes / size * 100, - sizeUploaded: uploadedBytes, - chunksTotal: response['chunksTotal'] ?? totalChunks, - chunksUploaded: response['chunksUploaded'] ?? completedCount - }); - } - - const CONCURRENCY = 8; - let nextChunk = 1; - let lastResponse = response; - let finalResponse = null; - - const isUploadComplete = (chunkResponse: any) => { - const chunksUploaded = chunkResponse?.chunksUploaded; - const chunksTotal = chunkResponse?.chunksTotal ?? totalChunks; - return typeof chunksUploaded === 'number' && typeof chunksTotal === 'number' && chunksUploaded >= chunksTotal; - }; - - const uploadNext = async () => { - while (nextChunk < chunks.length) { - const chunk = chunks[nextChunk++]; - const chunkResponse = await uploadChunk(chunk); - completedCount++; - uploadedBytes += chunk.end - chunk.start; - - lastResponse = chunkResponse; - if (isUploadComplete(chunkResponse)) { - finalResponse = chunkResponse; - } - - if (onProgress !== null) { - onProgress({ - $id: id!, - progress: uploadedBytes / size * 100, - sizeUploaded: uploadedBytes, - chunksTotal: chunkResponse['chunksTotal'] ?? totalChunks, - chunksUploaded: chunkResponse['chunksUploaded'] ?? completedCount - }); - } - } - }; - - await Promise.all(Array.from({ length: Math.min(CONCURRENCY, chunks.length - 1) }, uploadNext)); - - response = finalResponse ?? lastResponse; - - return response; -{% endif %} -{% endif %} -{% endfor %} -{% else %} -{% set defaults = method | responseDefaults(spec, 8) %} - {{ defaults is empty ? 'return' : 'const response =' }} await this.client.call( - '{{ method.method.value | caseLower }}', - apiPath, - { - {%~ for key, security in (method | securityHeaders) %} - '{{ security.name }}': this.client.config['{{ key | caseLower }}'], - {%~ endfor %} - {%~ for parameter in (method | parameters('header')) -%} - '{{ parameter.name }}': ${{ parameter.name | caseCamel | escapeKeyword }}, - {%~ endfor -%} - {%~ for key, header in (method | methodHeaders) %} - '{{ key }}': '{{ header }}', - {%~ endfor %} - }, - apiPayload, - {%~ if (method | methodType) == 'location' %} - 'arraybuffer' - {%~ elseif (method | methodType) == 'webAuth' %} - 'location' - {%~ elseif (method | textResponse) %} - 'text' - {%~ else %} - 'json' - {%~ endif %} - ); -{% if defaults is not empty %} - const defaults = {{ defaults | raw }}; - - return applyDefaults(response, defaults); -{% endif %} -{% endif %} - } -{% endfor %} -} diff --git a/templates/deno/test/id.test.ts.twig b/templates/deno/test/id.test.ts.twig deleted file mode 100644 index abb0d2294a..0000000000 --- a/templates/deno/test/id.test.ts.twig +++ /dev/null @@ -1,8 +0,0 @@ -import {assertEquals} from "https://deno.land/std@0.204.0/assert/mod.ts"; -import {describe, it as test} from "https://deno.land/std@0.149.0/testing/bdd.ts"; -import {ID} from "../src/id.ts"; - -describe("ID", () => { - test('unique', () => assertEquals(ID.unique().length, 20)); - test('custom', () => assertEquals(ID.custom('custom'), 'custom')); -}); diff --git a/templates/deno/test/operator.test.ts.twig b/templates/deno/test/operator.test.ts.twig deleted file mode 100644 index 5f8a7c3486..0000000000 --- a/templates/deno/test/operator.test.ts.twig +++ /dev/null @@ -1,130 +0,0 @@ -import {describe, it as test} from "https://deno.land/std@0.149.0/testing/bdd.ts"; -import {assertEquals} from "https://deno.land/std@0.204.0/assert/assert_equals.ts"; -import {Operator, Condition} from "../src/operator.ts"; - -describe('Operator', () => { - test('increment', () => assertEquals( - Operator.increment().toString(), - '{"method":"increment","values":[1]}', - )); - - test('increment with max', () => assertEquals( - Operator.increment(5, 100).toString(), - '{"method":"increment","values":[5,100]}', - )); - - test('decrement', () => assertEquals( - Operator.decrement().toString(), - '{"method":"decrement","values":[1]}', - )); - - test('decrement with min', () => assertEquals( - Operator.decrement(3, 0).toString(), - '{"method":"decrement","values":[3,0]}', - )); - - test('multiply', () => assertEquals( - Operator.multiply(2).toString(), - '{"method":"multiply","values":[2]}', - )); - - test('multiply with max', () => assertEquals( - Operator.multiply(3, 1000).toString(), - '{"method":"multiply","values":[3,1000]}', - )); - - test('divide', () => assertEquals( - Operator.divide(2).toString(), - '{"method":"divide","values":[2]}', - )); - - test('divide with min', () => assertEquals( - Operator.divide(4, 1).toString(), - '{"method":"divide","values":[4,1]}', - )); - - test('modulo', () => assertEquals( - Operator.modulo(5).toString(), - '{"method":"modulo","values":[5]}', - )); - - test('power', () => assertEquals( - Operator.power(2).toString(), - '{"method":"power","values":[2]}', - )); - - test('power with max', () => assertEquals( - Operator.power(3, 100).toString(), - '{"method":"power","values":[3,100]}', - )); - - test('arrayAppend', () => assertEquals( - Operator.arrayAppend(['item1', 'item2']).toString(), - '{"method":"arrayAppend","values":["item1","item2"]}', - )); - - test('arrayPrepend', () => assertEquals( - Operator.arrayPrepend(['first', 'second']).toString(), - '{"method":"arrayPrepend","values":["first","second"]}', - )); - - test('arrayInsert', () => assertEquals( - Operator.arrayInsert(0, 'newItem').toString(), - '{"method":"arrayInsert","values":[0,"newItem"]}', - )); - - test('arrayRemove', () => assertEquals( - Operator.arrayRemove('oldItem').toString(), - '{"method":"arrayRemove","values":["oldItem"]}', - )); - - test('arrayUnique', () => assertEquals( - Operator.arrayUnique().toString(), - '{"method":"arrayUnique","values":[]}', - )); - - test('arrayIntersect', () => assertEquals( - Operator.arrayIntersect(['a', 'b', 'c']).toString(), - '{"method":"arrayIntersect","values":["a","b","c"]}', - )); - - test('arrayDiff', () => assertEquals( - Operator.arrayDiff(['x', 'y']).toString(), - '{"method":"arrayDiff","values":["x","y"]}', - )); - - test('arrayFilter', () => assertEquals( - Operator.arrayFilter(Condition.Equal, 'test').toString(), - '{"method":"arrayFilter","values":["equal","test"]}', - )); - - test('stringConcat', () => assertEquals( - Operator.stringConcat('suffix').toString(), - '{"method":"stringConcat","values":["suffix"]}', - )); - - test('stringReplace', () => assertEquals( - Operator.stringReplace('old', 'new').toString(), - '{"method":"stringReplace","values":["old","new"]}', - )); - - test('toggle', () => assertEquals( - Operator.toggle().toString(), - '{"method":"toggle","values":[]}', - )); - - test('dateAddDays', () => assertEquals( - Operator.dateAddDays(7).toString(), - '{"method":"dateAddDays","values":[7]}', - )); - - test('dateSubDays', () => assertEquals( - Operator.dateSubDays(3).toString(), - '{"method":"dateSubDays","values":[3]}', - )); - - test('dateSetNow', () => assertEquals( - Operator.dateSetNow().toString(), - '{"method":"dateSetNow","values":[]}', - )); -}) diff --git a/templates/deno/test/permission.test.ts.twig b/templates/deno/test/permission.test.ts.twig deleted file mode 100644 index a9366fd43f..0000000000 --- a/templates/deno/test/permission.test.ts.twig +++ /dev/null @@ -1,12 +0,0 @@ -import { assertEquals } from "https://deno.land/std@0.204.0/assert/mod.ts"; -import { describe, it as test } from "https://deno.land/std@0.149.0/testing/bdd.ts"; -import {Permission} from "../src/permission.ts"; -import {Role} from "../src/role.ts"; - -describe('Permission', () => { - test('read', () => assertEquals(Permission.read(Role.any()), 'read("any")')); - test('write', () => assertEquals(Permission.write(Role.any()), 'write("any")')); - test('create', () => assertEquals(Permission.create(Role.any()), 'create("any")')); - test('update', () => assertEquals(Permission.update(Role.any()), 'update("any")')); - test('delete', () => assertEquals(Permission.delete(Role.any()), 'delete("any")')); -}) diff --git a/templates/deno/test/query.test.ts.twig b/templates/deno/test/query.test.ts.twig deleted file mode 100644 index cab6a094d2..0000000000 --- a/templates/deno/test/query.test.ts.twig +++ /dev/null @@ -1,770 +0,0 @@ -import {describe, it as test} from "https://deno.land/std@0.149.0/testing/bdd.ts"; -import {assertEquals} from "https://deno.land/std@0.204.0/assert/assert_equals.ts"; -import {Query, QueryTypes, flattenParam, normalizeQueries} from "../src/query.ts"; - -type BasicFilterQueryTest = { - description: string; - value: QueryTypes; - expectedValues: unknown[]; -} - -const parsed = (query: string) => JSON.parse(query); - -const tests: BasicFilterQueryTest[] = [ - { - description: 'with a string', - value: 's', - expectedValues: ['s'] - }, - { - description: 'with a integer', - value: 1, - expectedValues: [1] - }, - { - description: 'with a double', - value: 1.2, - expectedValues: [1.2] - }, - { - description: 'with a whole number double', - value: 1.0, - expectedValues: [1] - }, - { - description: 'with a bool', - value: false, - expectedValues: [false] - }, - { - description: 'with a list', - value: ['a', 'b', 'c'], - expectedValues: ['a', 'b', 'c'] - } -]; - -describe('Query', () => { - describe('basic filter equal', () => { - for (const t of tests) { - test(t.description, () => - assertEquals( - parsed(Query.equal("attr", t.value).toString()), - { - method: 'equal', - attribute: 'attr', - values: t.expectedValues, - }, - ) - ) - } - }) - - describe('basic filter notEqual', () => { - for (const t of tests) { - test(t.description, () => - assertEquals( - parsed(Query.notEqual("attr", t.value).toString()), - { - method: 'notEqual', - attribute: 'attr', - values: t.expectedValues, - }, - ) - ) - } - }); - - describe('basic filter lessThan', () => { - for (const t of tests) { - test(t.description, () => - assertEquals( - parsed(Query.lessThan("attr", t.value).toString()), - { - method: 'lessThan', - attribute: 'attr', - values: t.expectedValues, - }, - ) - ) - } - }); - - describe('basic filter lessThanEqual', () => { - for (const t of tests) { - test(t.description, () => - assertEquals( - parsed(Query.lessThanEqual("attr", t.value).toString()), - { - method: 'lessThanEqual', - attribute: 'attr', - values: t.expectedValues, - }, - ) - ) - } - }); - - describe('basic filter greaterThan', () => { - for (const t of tests) { - test(t.description, () => - assertEquals( - parsed(Query.greaterThan("attr", t.value).toString()), - { - method: 'greaterThan', - attribute: 'attr', - values: t.expectedValues, - }, - ) - ) - } - }); - - describe('basic filter greaterThanEqual', () => { - for (const t of tests) { - test(t.description, () => - assertEquals( - parsed(Query.greaterThanEqual("attr", t.value).toString()), - { - method: 'greaterThanEqual', - attribute: 'attr', - values: t.expectedValues, - }, - ) - ) - } - }); - - test('search', () => assertEquals( - parsed(Query.search('attr', 'keyword1 keyword2').toString()), - { - method: 'search', - attribute: 'attr', - values: ['keyword1 keyword2'], - }, - )); - - test('isNull', () => assertEquals( - parsed(Query.isNull('attr').toString()), - { - method: 'isNull', - attribute: 'attr', - }, - )); - - test('isNotNull', () => assertEquals( - parsed(Query.isNotNull('attr').toString()), - { - method: 'isNotNull', - attribute: 'attr', - }, - )); - - describe('between', () => { - test('with integers', () => assertEquals( - parsed(Query.between('attr', 1, 2).toString()), - { - method: 'between', - attribute: 'attr', - values: [1, 2], - }, - )); - test('with doubles', () => assertEquals( - parsed(Query.between('attr', 1.2, 2.2).toString()), - { - method: 'between', - attribute: 'attr', - values: [1.2, 2.2], - }, - )); - test('with strings', () => assertEquals( - parsed(Query.between('attr', "a", "z").toString()), - { - method: 'between', - attribute: 'attr', - values: ['a', 'z'], - }, - )); - }); - - test('select', () => assertEquals( - parsed(Query.select(['attr1', 'attr2']).toString()), - { - method: 'select', - values: ['attr1', 'attr2'], - }, - )); - - test('orderAsc', () => assertEquals( - parsed(Query.orderAsc('attr').toString()), - { - method: 'orderAsc', - attribute: 'attr', - }, - )); - - test('orderDesc', () => assertEquals( - parsed(Query.orderDesc('attr').toString()), - { - method: 'orderDesc', - attribute: 'attr', - }, - )); - - test('orderRandom', () => assertEquals( - parsed(Query.orderRandom().toString()), - { - method: 'orderRandom', - }, - )); - - test('cursorBefore', () => assertEquals( - parsed(Query.cursorBefore('attr').toString()), - { - method: 'cursorBefore', - values: ['attr'], - }, - )); - - test('cursorAfter', () => assertEquals( - parsed(Query.cursorAfter('attr').toString()), - { - method: 'cursorAfter', - values: ['attr'], - }, - )); - - test('limit', () => assertEquals( - parsed(Query.limit(1).toString()), - { - method: 'limit', - values: [1], - }, - )); - - test('offset', () => assertEquals( - parsed(Query.offset(1).toString()), - { - method: 'offset', - values: [1], - }, - )); - - test('notContains', () => assertEquals( - parsed(Query.notContains('attr', 'value').toString()), - { - method: 'notContains', - attribute: 'attr', - values: ['value'], - }, - )); - - test('notSearch', () => assertEquals( - parsed(Query.notSearch('attr', 'keyword1 keyword2').toString()), - { - method: 'notSearch', - attribute: 'attr', - values: ['keyword1 keyword2'], - }, - )); - - describe('notBetween', () => { - test('with integers', () => assertEquals( - parsed(Query.notBetween('attr', 1, 2).toString()), - { - method: 'notBetween', - attribute: 'attr', - values: [1, 2], - }, - )); - test('with doubles', () => assertEquals( - parsed(Query.notBetween('attr', 1.2, 2.2).toString()), - { - method: 'notBetween', - attribute: 'attr', - values: [1.2, 2.2], - }, - )); - test('with strings', () => assertEquals( - parsed(Query.notBetween('attr', "a", "z").toString()), - { - method: 'notBetween', - attribute: 'attr', - values: ['a', 'z'], - }, - )); - }); - - test('notStartsWith', () => assertEquals( - parsed(Query.notStartsWith('attr', 'prefix').toString()), - { - method: 'notStartsWith', - attribute: 'attr', - values: ['prefix'], - }, - )); - - test('notEndsWith', () => assertEquals( - parsed(Query.notEndsWith('attr', 'suffix').toString()), - { - method: 'notEndsWith', - attribute: 'attr', - values: ['suffix'], - }, - )); - - test('regex', () => assertEquals( - parsed(Query.regex('attr', 'pattern.*').toString()), - { - method: 'regex', - attribute: 'attr', - values: ['pattern.*'], - }, - )); - - test('exists', () => assertEquals( - parsed(Query.exists(['attr1', 'attr2']).toString()), - { - method: 'exists', - values: ['attr1', 'attr2'], - }, - )); - - test('notExists', () => assertEquals( - parsed(Query.notExists(['attr1', 'attr2']).toString()), - { - method: 'notExists', - values: ['attr1', 'attr2'], - }, - )); - - test('elemMatch', () => { - const inner1 = Query.equal('name', 'Alice'); - const inner2 = Query.greaterThan('age', 18); - const result = Query.elemMatch('friends', [inner1, inner2]); - const parsed = JSON.parse(result); - - assertEquals(parsed.method, 'elemMatch'); - assertEquals(parsed.attribute, 'friends'); - assertEquals(parsed.values.length, 2); - assertEquals(parsed.values[0].method, 'equal'); - assertEquals(parsed.values[0].attribute, 'name'); - assertEquals(parsed.values[0].values, ['Alice']); - assertEquals(parsed.values[1].method, 'greaterThan'); - assertEquals(parsed.values[1].attribute, 'age'); - assertEquals(parsed.values[1].values, [18]); - }); - - test('relationship', () => { - const inner1 = Query.equal('approved', true); - const inner2 = Query.limit(2); - const result = Query.relationship('comments', [inner1, inner2]); - const parsed = JSON.parse(result); - - assertEquals(parsed.method, 'relationship'); - assertEquals(parsed.attribute, 'comments'); - assertEquals(parsed.values.length, 2); - assertEquals(parsed.values[0].method, 'equal'); - assertEquals(parsed.values[0].attribute, 'approved'); - assertEquals(parsed.values[0].values, [true]); - assertEquals(parsed.values[1].method, 'limit'); - assertEquals(parsed.values[1].values, [2]); - }); - - test('createdBefore', () => assertEquals( - parsed(Query.createdBefore('2023-01-01').toString()), - { - method: 'lessThan', - attribute: '$createdAt', - values: ['2023-01-01'], - }, - )); - - test('createdAfter', () => assertEquals( - parsed(Query.createdAfter('2023-01-01').toString()), - { - method: 'greaterThan', - attribute: '$createdAt', - values: ['2023-01-01'], - }, - )); - - test('createdBetween', () => assertEquals( - parsed(Query.createdBetween('2023-01-01', '2023-12-31').toString()), - { - method: 'between', - attribute: '$createdAt', - values: ['2023-01-01', '2023-12-31'], - }, - )); - - test('updatedBefore', () => assertEquals( - parsed(Query.updatedBefore('2023-01-01').toString()), - { - method: 'lessThan', - attribute: '$updatedAt', - values: ['2023-01-01'], - }, - )); - - test('updatedAfter', () => assertEquals( - parsed(Query.updatedAfter('2023-01-01').toString()), - { - method: 'greaterThan', - attribute: '$updatedAt', - values: ['2023-01-01'], - }, - )); - - test('updatedBetween', () => assertEquals( - parsed(Query.updatedBetween('2023-01-01', '2023-12-31').toString()), - { - method: 'between', - attribute: '$updatedAt', - values: ['2023-01-01', '2023-12-31'], - }, - )); - - test('count with alias', () => assertEquals( - parsed(Query.count('*', 'total').toString()), - { - method: 'count', - attribute: '*', - values: ['total'], - }, - )); - - test('count without alias', () => assertEquals( - parsed(Query.count().toString()), - { - method: 'count', - attribute: '*', - }, - )); - - test('countDistinct', () => assertEquals( - parsed(Query.countDistinct('year', 'uniqueYears').toString()), - { - method: 'countDistinct', - attribute: 'year', - values: ['uniqueYears'], - }, - )); - - test('sum', () => assertEquals( - parsed(Query.sum('price', 'total').toString()), - { - method: 'sum', - attribute: 'price', - values: ['total'], - }, - )); - - test('avg', () => assertEquals( - parsed(Query.avg('price', 'avgPrice').toString()), - { - method: 'avg', - attribute: 'price', - values: ['avgPrice'], - }, - )); - - test('min', () => assertEquals( - parsed(Query.min('price', 'lowest').toString()), - { - method: 'min', - attribute: 'price', - values: ['lowest'], - }, - )); - - test('max', () => assertEquals( - parsed(Query.max('price', 'highest').toString()), - { - method: 'max', - attribute: 'price', - values: ['highest'], - }, - )); - - test('stddev', () => assertEquals( - parsed(Query.stddev('price', 'sd').toString()), - { - method: 'stddev', - attribute: 'price', - values: ['sd'], - }, - )); - - test('stddevPop', () => assertEquals( - parsed(Query.stddevPop('price', 'sdp').toString()), - { - method: 'stddevPop', - attribute: 'price', - values: ['sdp'], - }, - )); - - test('stddevSamp', () => assertEquals( - parsed(Query.stddevSamp('price', 'sds').toString()), - { - method: 'stddevSamp', - attribute: 'price', - values: ['sds'], - }, - )); - - test('variance', () => assertEquals( - parsed(Query.variance('price', 'var').toString()), - { - method: 'variance', - attribute: 'price', - values: ['var'], - }, - )); - - test('varPop', () => assertEquals( - parsed(Query.varPop('price', 'vp').toString()), - { - method: 'varPop', - attribute: 'price', - values: ['vp'], - }, - )); - - test('varSamp', () => assertEquals( - parsed(Query.varSamp('price', 'vs').toString()), - { - method: 'varSamp', - attribute: 'price', - values: ['vs'], - }, - )); - - test('bitAnd', () => assertEquals( - parsed(Query.bitAnd('flags', 'band').toString()), - { - method: 'bitAnd', - attribute: 'flags', - values: ['band'], - }, - )); - - test('bitOr', () => assertEquals( - parsed(Query.bitOr('flags', 'bor').toString()), - { - method: 'bitOr', - attribute: 'flags', - values: ['bor'], - }, - )); - - test('bitXor', () => assertEquals( - parsed(Query.bitXor('flags', 'bxor').toString()), - { - method: 'bitXor', - attribute: 'flags', - values: ['bxor'], - }, - )); - - test('groupBy', () => assertEquals( - parsed(Query.groupBy(['status', 'year']).toString()), - { - method: 'groupBy', - values: ['status', 'year'], - }, - )); - - test('having nests parsed queries', () => { - const having = JSON.parse(Query.having([Query.greaterThan('total', 1)])); - assertEquals(having.method, 'having'); - assertEquals(having.values[0].method, 'greaterThan'); - assertEquals(having.values[0].attribute, 'total'); - assertEquals(having.values[0].values, [1]); - }); - - test('distinct', () => assertEquals( - parsed(Query.distinct().toString()), - { - method: 'distinct', - }, - )); - - test('join', () => assertEquals( - parsed(Query.join('orders', '$id', 'customerId').toString()), - { - method: 'join', - attribute: 'orders', - values: ['$id', '=', 'customerId'], - }, - )); - - test('leftJoin with alias', () => assertEquals( - parsed(Query.leftJoin('orders', '$id', 'customerId', '=', 'ord').toString()), - { - method: 'leftJoin', - attribute: 'orders', - values: ['$id', '=', 'customerId', 'ord'], - }, - )); - - test('rightJoin', () => assertEquals( - parsed(Query.rightJoin('orders', '$id', 'customerId').toString()), - { - method: 'rightJoin', - attribute: 'orders', - values: ['$id', '=', 'customerId'], - }, - )); - - test('fullOuterJoin', () => assertEquals( - parsed(Query.fullOuterJoin('orders', '$id', 'customerId').toString()), - { - method: 'fullOuterJoin', - attribute: 'orders', - values: ['$id', '=', 'customerId'], - }, - )); - - test('on', () => assertEquals( - parsed(Query.on('$id', 'customerId').toString()), - { - method: 'on', - values: ['$id', '=', 'customerId'], - }, - )); - - test('nested leftJoin', () => { - const query = JSON.parse(Query.leftJoin('orders', 'ord', [ - Query.on('$id', 'customerId'), - Query.equal('ord.status', 'paid'), - ]).toString()); - assertEquals(query.method, 'leftJoin'); - assertEquals(query.attribute, 'orders'); - assertEquals(query.values[0], 'ord'); - assertEquals(query.values[1].method, 'on'); - assertEquals(query.values[2].method, 'equal'); - }); - - test('crossJoin', () => assertEquals( - parsed(Query.crossJoin('orders', 'ord').toString()), - { - method: 'crossJoin', - attribute: 'orders', - values: ['ord'], - }, - )); - - test('vectorDot', () => assertEquals( - parsed(Query.vectorDot('embedding', [0.1, 0.2]).toString()), - { - method: 'vectorDot', - attribute: 'embedding', - values: [[0.1, 0.2]], - }, - )); - - test('notCovers', () => assertEquals( - parsed(Query.notCovers('location', [1, 2]).toString()), - { - method: 'notCovers', - attribute: 'location', - values: [[1, 2]], - }, - )); - - test('spatialEquals', () => assertEquals( - parsed(Query.spatialEquals('location', [1, 2]).toString()), - { - method: 'spatialEquals', - attribute: 'location', - values: [[1, 2]], - }, - )); - - test('notSpatialEquals', () => assertEquals( - parsed(Query.notSpatialEquals('location', [1, 2]).toString()), - { - method: 'notSpatialEquals', - attribute: 'location', - values: [[1, 2]], - }, - )); - - test('page', () => { - const queries = Query.page(2, 10).map(parsed); - assertEquals(queries, [ - { method: 'limit', values: [10] }, - { method: 'offset', values: [10] }, - ]); - }); - - test('builder build', () => { - const built = Query.builder() - .equal('status', 'published') - .leftJoin('orders', '$id', 'customerId', '=', 'ord') - .count('*', 'total') - .groupBy(['status']) - .limit(25) - .build(); - - assertEquals(built, [ - Query.equal('status', 'published'), - Query.leftJoin('orders', '$id', 'customerId', '=', 'ord'), - Query.count('*', 'total'), - Query.groupBy(['status']), - Query.limit(25), - ]); - }); - - test('normalize builder wrapped in array', () => { - const builder = Query.builder().equal('status', 'active').limit(10); - assertEquals(normalizeQueries([builder]), builder.build()); - assertEquals(normalizeQueries([builder.build()]), builder.build()); - assertEquals(normalizeQueries(builder), builder.build()); - }); - - test('normalize page wrapped in array', () => { - assertEquals(normalizeQueries([Query.equal('status', 'active'), Query.page(2, 10)]), [ - Query.equal('status', 'active'), - Query.limit(10), - Query.offset(10), - ]); - }); - - test('flattenParam spreads wrapped builder', () => { - assertEquals(flattenParam([Query.builder().limit(1)]), [Query.limit(1)]); - }); - - test('flattenParam keeps nested numeric arrays', () => { - const geometry = [[1, 2], [3, 4]]; - assertEquals(flattenParam(geometry), geometry); - }); - - test('flattenParam keeps query string list', () => { - assertEquals(flattenParam([Query.limit(1)]), [Query.limit(1)]); - }); - - test('flattenParam keeps nested string arrays', () => { - assertEquals(flattenParam([['a', 'b']]), [['a', 'b']]); - }); - - test('flattenParam builds builders nested in arrays', () => { - assertEquals(flattenParam([[Query.builder().limit(1)]]), [[Query.limit(1)]]); - }); - - test('flattenParam builds a builder value', () => { - assertEquals(flattenParam(Query.builder().equal('status', 'active').limit(1)), [ - Query.equal('status', 'active'), - Query.limit(1), - ]); - }); - - test('flattenParam splices builders among query strings', () => { - assertEquals(flattenParam([Query.equal('status', 'active'), Query.builder().limit(1).offset(2)]), [ - Query.equal('status', 'active'), - Query.limit(1), - Query.offset(2), - ]); - }); -}) diff --git a/templates/deno/test/role.test.ts.twig b/templates/deno/test/role.test.ts.twig deleted file mode 100644 index e3f155da0d..0000000000 --- a/templates/deno/test/role.test.ts.twig +++ /dev/null @@ -1,16 +0,0 @@ -import { assertEquals } from "https://deno.land/std@0.204.0/assert/mod.ts"; -import { describe, it as test } from "https://deno.land/std@0.149.0/testing/bdd.ts"; -import {Role} from "../src/role.ts"; - -describe('Role', () => { - test('any', () => assertEquals(Role.any(), 'any')); - test('user without status', () => assertEquals(Role.user('custom'), 'user:custom')); - test('user with status', () => assertEquals(Role.user('custom', 'verified'), 'user:custom/verified')); - test('users without status', () => assertEquals(Role.users(), 'users')); - test('users with status', () => assertEquals(Role.users('verified'), 'users/verified')); - test('guests', () => assertEquals(Role.guests(), 'guests')); - test('team without role', () => assertEquals(Role.team('custom'), 'team:custom')) - test('team with role', () => assertEquals(Role.team('custom', 'owner'), 'team:custom/owner')) - test('member', () => assertEquals(Role.member('custom'), 'member:custom')) - test('label', () => assertEquals(Role.label('admin'), 'label:admin')) -}) diff --git a/templates/deno/test/services/service.test.ts.twig b/templates/deno/test/services/service.test.ts.twig deleted file mode 100644 index 3e41dbd547..0000000000 --- a/templates/deno/test/services/service.test.ts.twig +++ /dev/null @@ -1,100 +0,0 @@ -import {afterEach, describe, it as test} from "https://deno.land/std@0.204.0/testing/bdd.ts"; -import {restore, stub} from "https://deno.land/std@0.204.0/testing/mock.ts"; -import {assertEquals} from "https://deno.land/std@0.204.0/assert/assert_equals.ts"; -import { {{ service.name | caseUcfirst }} } from "../../src/services/{{ service.name | caseKebab }}.ts"; -import {Client} from "../../src/client.ts"; -import {InputFile} from "../../src/inputFile.ts" -{% set added = [] %} -{% set usesModels = false %} -{% for method in (service | operations) %} -{% for parameter in (method | parameters('all')) | filter((param) => param.required) %} -{% if (parameter | schemaType) != 'array' and (parameter | enumValues) is not empty and (parameter | enumName) not in added %} -import { {{ (parameter | enumName) | caseUcfirst }} } from "../../src/enums/{{ (parameter | enumName) | caseKebab }}.ts"; -{% set added = added | merge([(parameter | enumName)]) %} -{% endif %} -{% if (parameter | schemaType) != 'array' and (parameter | schemaModel) %}{% set usesModels = true %}{% endif %} -{% endfor %} -{% endfor %} -{% if usesModels %} -import type { Models } from "../../src/models.d.ts"; -{% endif %} -{% macro value(parameter, requestModels) %} -{%- if (parameter | schemaType) == 'array' -%} -[] -{%- elseif (parameter | schemaModel) -%} -{ {% for property in (requestModels[(parameter | schemaModel)].properties ?? []) | filter((param) => param | schemaRequired) %}'{{ property | schemaName }}': {{ _self.value(property, requestModels) }}{% if not loop.last %}, {% endif %}{% endfor %} }{% if requestModels[(parameter | schemaModel)] is not defined %} as Models.{{ (parameter | schemaModel) | caseUcfirst }}{% endif %} -{%- elseif (parameter | schemaType) == 'object' -%} -{} -{%- elseif (parameter | schemaType) == 'file' -%} -InputFile.fromBuffer(new Uint8Array(0), 'image.png') -{%- elseif (parameter | schemaType) == 'boolean' -%} -true -{%- elseif (parameter | enumValues) is not empty -%} -{{ (parameter | enumName) | caseUcfirst }}.{{ (parameter | enumKeys)[0] | caseEnumKey }} -{%- elseif (parameter | schemaType) == 'string' -%} -'{% if (parameter | schemaExample) is not empty %}{{ (parameter | schemaExample) | escapeDollarSign }}{% else %}{{ parameter.name ?? (parameter | schemaName) }}{% endif %}' -{%- elseif (parameter | schemaType) == 'integer' -%} -1 -{%- elseif (parameter | schemaType) == 'number' -%} -1.0 -{%- else -%} -{{ parameter | schemaExample }} -{%- endif -%} -{% endmacro %} - -describe('{{ service.name | caseUcfirst }} service', () => { - const client = new Client(); - const {{ service.name | caseCamel }} = new {{ service.name | caseUcfirst }}(client); - - afterEach(() => restore()) - - {% for method in (service | operations) ~%} - test('test method {{ (method | methodName) | caseCamel }}()', async () => { - {% set responseModels = method | getValidResponseModels %} - {% set responseModelName = '' %} - {% if responseModels|length > 1 %} - {% set responseModelName = responseModels|last %} - {% elseif (method | responseModel) and (method | responseModel) != 'any' %} - {% set responseModelName = (method | responseModel) %} - {% endif %} - {%~ if (method | methodType) == 'webAuth' %} - const data = 'https://example.com/'; - {%~ elseif (method | methodType) == 'location' %} - const data = new Uint8Array(0); - {%~ else %} - {%- if responseModelName %} - const data = { - {%- for definitionName, definition in definitions ~%}{%~ if definitionName == responseModelName -%}{%~ for property in definition.properties | filter((param) => param | schemaRequired) ~%} - '{{(property | schemaName) | escapeDollarSign}}': {% if (property | schemaType) == 'object' %}{}{% elseif (property | schemaType) == 'array' %}[]{% elseif (property | schemaType) == 'string' %}'{{(property | schemaExample) | escapeDollarSign}}'{% elseif (property | schemaType) == 'boolean' %}true{% else %}{{(property | schemaExample)}}{% endif %},{%~ endfor ~%}{% set break = true %}{%- else -%}{% set continue = true %}{%- endif -%}{%~ endfor -%} - }; - {%~ else %} - const data = ''; - {%~ endif %} - {%~ endif %} - - {%~ if (method | methodType) == 'webAuth' %} - const stubbedFetch = stub(globalThis, 'fetch', () => Promise.resolve(new Response(null, { status: 301, headers: { location: data } }))); - {%~ elseif (method | methodType) == 'location' %} - const stubbedFetch = stub(globalThis, 'fetch', () => Promise.resolve(new Response(data.buffer))); - {%~ elseif responseModelName %} - const stubbedFetch = stub(globalThis, 'fetch', () => Promise.resolve(new Response(JSON.stringify(data), { headers: { 'content-type': 'application/json' } }))); - {%~ else %} - const stubbedFetch = stub(globalThis, 'fetch', () => Promise.resolve(new Response(data))) - {%~ endif %} - - const response = await {{ service.name | caseCamel }}.{{ (method | methodName) | caseCamel }}({%~ for parameter in (method | parameters('all')) | filter((param) => param.required) ~%} - {{ _self.value(parameter, requestModels) }},{%~ endfor ~%} - ); - - {%~ if (method | methodType) == 'location' %} - assertEquals(response.byteLength, 0); - {%~ elseif (method | methodType) == 'webAuth' or (method | textResponse) %} - assertEquals(response, data); - {%~ else %} - assertEquals(response, data); - {%~ endif %} - stubbedFetch.restore(); - }); - - {% endfor %} -}) diff --git a/tests/e2e/Deno1193Test.php b/tests/e2e/Deno1193Test.php deleted file mode 100644 index 619907ec68..0000000000 --- a/tests/e2e/Deno1193Test.php +++ /dev/null @@ -1,63 +0,0 @@ -( - appwrite.InputFile.fromPath("./tests/resources/file.png", "file.png") - ); - console.log(profile.prefs.result); - - console.log(new TextDecoder().decode(await general.download())); - - response = await general.enum(appwrite.MockType.First); - // @ts-ignore - console.log(response.result); - - // Request model tests - response = await general.createPlayer({ id: 'player1', name: 'John Doe', score: 100 }); - // @ts-ignore - console.log(response.result); - - response = await general.createPlayers([ - { id: 'player1', name: 'John Doe', score: 100 }, - { id: 'player2', name: 'Jane Doe', score: 200 } - ]); - // @ts-ignore - console.log(response.result); - - const preset = await general.getPreset(); - console.log(`preset: name=${preset.name}, count=${preset.count}, enabled=${preset.enabled}`); - const presets = await general.listPresets(); - for (const item of presets.presets) { - console.log(`preset: name=${item.name}, count=${item.count}, enabled=${item.enabled}`); - } - console.log(`empty presets: ${(await general.listEmptyPresets()).presets.length}`); - presets.presets[0].tags.push('mutated'); - console.log(`preset tags shared: ${presets.presets[1].tags.length}`); - console.log(`nested builder: ${JSON.stringify(appwrite.flattenParam([[Query.builder().limit(1)]])) === JSON.stringify([[Query.limit(1)]]) ? 'passed' : 'failed'}`); - const verified: appwrite.Models.Preset["verified"] = preset.verified ?? null; - console.log(`preset verified: ${verified}`); - console.log(`preset scopes: ${(preset.scopes ?? []).join(',')}`); - - response = await general.nullable("required", null, undefined, undefined, null); - console.log(response.result); - - try { - response = await general.error400(); - } catch (error) { - console.log(error.message); - console.log(error.response); - } - - try { - response = await general.error500(); - } catch (error) { - console.log(error.message); - console.log(error.response); - } - - try { - response = await general.error502(); - } catch (error) { - console.log(error.message); - console.log(error.response); - } - - try { - client.setEndpoint("htp://cloud.appwrite.io/v1"); - } catch (error) { - console.log(error.message); - } - - await general.empty(); - - const url = await general.oauth2( - 'clientId', - ['test'], - '123456', - 'https://localhost', - 'https://localhost' - ) - console.log(url) - - // Query helper tests - console.log(Query.equal("released", [true])); - console.log(Query.equal("title", ["Spiderman", "Dr. Strange"])); - console.log(Query.notEqual("title", "Spiderman")); - console.log(Query.lessThan("releasedYear", 1990)); - console.log(Query.greaterThan("releasedYear", 1990)); - console.log(Query.search("name", "john")); - console.log(Query.isNull("name")); - console.log(Query.isNotNull("name")); - console.log(Query.between("age", 50, 100)); - console.log(Query.between("age", 50.5, 100.5)); - console.log(Query.between("name", "Anna", "Brad")); - console.log(Query.startsWith("name", "Ann")); - console.log(Query.endsWith("name", "nne")); - console.log(Query.select(["name", "age"])); - console.log(Query.orderAsc("title")); - console.log(Query.orderDesc("title")); - console.log(Query.orderRandom()); - console.log(Query.cursorAfter("my_movie_id")); - console.log(Query.cursorBefore("my_movie_id")); - console.log(Query.limit(50)); - console.log(Query.offset(20)); - console.log(Query.contains("title", "Spider")); - console.log(Query.contains("labels", "first")); - console.log(Query.containsAny("labels", ["first", "second"])); - console.log(Query.containsAll("labels", ["first", "second"])); - - // New query methods - console.log(Query.notContains("title", "Spider")); - console.log(Query.notSearch("name", "john")); - console.log(Query.notBetween("age", 50, 100)); - console.log(Query.notStartsWith("name", "Ann")); - console.log(Query.notEndsWith("name", "nne")); - console.log(Query.createdBefore("2023-01-01")); - console.log(Query.createdAfter("2023-01-01")); - console.log(Query.createdBetween("2023-01-01", "2023-12-31")); - console.log(Query.updatedBefore("2023-01-01")); - console.log(Query.updatedAfter("2023-01-01")); - console.log(Query.updatedBetween("2023-01-01", "2023-12-31")); - - // Spatial Distance query tests - console.log(Query.distanceEqual("location", [[40.7128, -74], [40.7128, -74]], 1000)); - console.log(Query.distanceEqual("location", [40.7128, -74], 1000, true)); - console.log(Query.distanceNotEqual("location", [40.7128, -74], 1000)); - console.log(Query.distanceNotEqual("location", [40.7128, -74], 1000, true)); - console.log(Query.distanceGreaterThan("location", [40.7128, -74], 1000)); - console.log(Query.distanceGreaterThan("location", [40.7128, -74], 1000, true)); - console.log(Query.distanceLessThan("location", [40.7128, -74], 1000)); - console.log(Query.distanceLessThan("location", [40.7128, -74], 1000, true)); - console.log(Query.vectorDot("embedding", [0.1, 0.2, 0.3])); - console.log(Query.vectorCosine("embedding", [0.1, 0.2, 0.3])); - console.log(Query.vectorEuclidean("embedding", [0.1, 0.2, 0.3])); - - // Spatial query tests - console.log(Query.intersects("location", [40.7128, -74])); - console.log(Query.notIntersects("location", [40.7128, -74])); - console.log(Query.crosses("location", [40.7128, -74])); - console.log(Query.notCrosses("location", [40.7128, -74])); - console.log(Query.overlaps("location", [40.7128, -74])); - console.log(Query.notOverlaps("location", [40.7128, -74])); - console.log(Query.touches("location", [40.7128, -74])); - console.log(Query.notTouches("location", [40.7128, -74])); - console.log(Query.contains("location", [[40.7128, -74], [40.7128, -74]])); - console.log(Query.notContains("location", [[40.7128, -74], [40.7128, -74]])); - console.log(Query.equal("location", [[40.7128, -74], [40.7128, -74]])); - console.log(Query.notEqual("location", [[40.7128, -74], [40.7128, -74]])); - - console.log(Query.or([ - Query.equal("released", true), - Query.lessThan("releasedYear", 1990) - ])); - console.log(Query.and([ - Query.equal("released", false), - Query.greaterThan("releasedYear", 2015) - ])); - - // regex, exists, notExists, elemMatch - console.log(Query.regex("name", "pattern.*")); - console.log(Query.exists(["attr1", "attr2"])); - console.log(Query.notExists(["attr1", "attr2"])); - console.log(Query.elemMatch("friends", [ - Query.equal("name", "Alice"), - Query.greaterThan("age", 18) - ])); - console.log(Query.relationship("comments", [ - Query.equal("approved", true), - Query.limit(2) - ])); - const queryTransport = await general.listRows([ - Query.count("*", "total"), - Query.join("orders", "$id", "customerId"), - Query.groupBy(["status"]), - Query.distinct(), - Query.covers("location", [1, 2]), - Query.countDistinct("year", "uniqueYears"), - Query.sum("price", "total"), - Query.avg("price", "avgPrice"), - Query.min("price", "lowest"), - Query.max("price", "highest"), - Query.stddev("price", "sd"), - Query.stddevPop("price", "sdp"), - Query.stddevSamp("price", "sds"), - Query.variance("price", "var"), - Query.varPop("price", "vp"), - Query.varSamp("price", "vs"), - Query.bitAnd("flags", "band"), - Query.bitOr("flags", "bor"), - Query.bitXor("flags", "bxor"), - Query.having([Query.greaterThan("total", 1)]), - Query.leftJoin("orders", "$id", "customerId", "=", "ord"), - Query.rightJoin("orders", "$id", "customerId"), - Query.fullOuterJoin("orders", "$id", "customerId"), - Query.crossJoin("orders", "ord"), - Query.on("$id", "customerId"), - Query.leftJoin("orders", "ord", [ - Query.on("$id", "customerId"), - Query.equal("ord.status", "paid"), - ]), - Query.notCovers("location", [1, 2]), - Query.spatialEquals("location", [1, 2]), - Query.notSpatialEquals("location", [1, 2]), - ...Query.page(2, 10), - Query.builder().limit(1), - ]); - console.log(queryTransport.result); - - // Permission & Role helper tests - console.log(Permission.read(Role.any())); - console.log(Permission.write(Role.user(ID.custom("userid")))); - console.log(Permission.create(Role.users())); - console.log(Permission.update(Role.guests())); - console.log(Permission.delete(Role.team("teamId", "owner"))); - console.log(Permission.delete(Role.team("teamId"))); - console.log(Permission.create(Role.member("memberId"))); - console.log(Permission.update(Role.users("verified"))); - console.log(Permission.update(Role.user(ID.custom("userid"), "unverified"))); - console.log(Permission.create(Role.label("admin"))); - - // ID helper tests - console.log(ID.unique()); - console.log(ID.custom("custom_id")); - - // Operator helper tests - console.log(Operator.increment(1)); - console.log(Operator.increment(5, 100)); - console.log(Operator.decrement(1)); - console.log(Operator.decrement(3, 0)); - console.log(Operator.multiply(2)); - console.log(Operator.multiply(3, 1000)); - console.log(Operator.divide(2)); - console.log(Operator.divide(4, 1)); - console.log(Operator.modulo(5)); - console.log(Operator.power(2)); - console.log(Operator.power(3, 100)); - console.log(Operator.arrayAppend(["item1", "item2"])); - console.log(Operator.arrayPrepend(["first", "second"])); - console.log(Operator.arrayInsert(0, "newItem")); - console.log(Operator.arrayRemove("oldItem")); - console.log(Operator.arrayUnique()); - console.log(Operator.arrayIntersect(["a", "b", "c"])); - console.log(Operator.arrayDiff(["x", "y"])); - console.log(Operator.arrayFilter(Condition.Equal, "test")); - console.log(Operator.stringConcat("suffix")); - console.log(Operator.stringReplace("old", "new")); - console.log(Operator.toggle()); - console.log(Operator.dateAddDays(7)); - console.log(Operator.dateSubDays(3)); - console.log(Operator.dateSetNow()); - - response = await general.headers(); - // @ts-ignore - console.log(response.result); -} - -start().catch((err) => { - console.error(err); -}); diff --git a/tests/generation/GenerationTest.php b/tests/generation/GenerationTest.php index 0c7e488490..91e2b9d391 100644 --- a/tests/generation/GenerationTest.php +++ b/tests/generation/GenerationTest.php @@ -11,7 +11,6 @@ use Appwrite\SDK\Language\Apple; use Appwrite\SDK\Language\CLI; use Appwrite\SDK\Language\Dart; -use Appwrite\SDK\Language\Deno; use Appwrite\SDK\Language\DotNet; use Appwrite\SDK\Language\Flutter; use Appwrite\SDK\Language\Go; @@ -95,7 +94,6 @@ final class GenerationTest extends TestCase 'web' => ['src/enums/webhook-event.ts', 'UserCreated', 'src/enums/localized-status.ts', 'Value1', 'src/enums/province-type.ts', 'Capital'], 'node' => ['src/enums/webhook-event.ts', 'UserCreated', 'src/enums/localized-status.ts', 'Value1', 'src/enums/province-type.ts', 'Capital'], 'react-native' => ['src/enums/webhook-event.ts', 'UserCreated', 'src/enums/localized-status.ts', 'Value1', 'src/enums/province-type.ts', 'Capital'], - 'deno' => ['src/enums/webhook-event.ts', 'UserCreated', 'src/enums/localized-status.ts', 'Value1', 'src/enums/province-type.ts', 'Capital'], 'php' => ['src/Appwrite/Enums/WebhookEvent.php', 'USERCREATED', 'src/Appwrite/Enums/LocalizedStatus.php', 'public static function VALUE1', 'src/Appwrite/Enums/ProvinceType.php', 'public static function CAPITAL'], 'python' => ['appwrite/enums/webhook_event.py', 'USERCREATED = "user.created"', 'appwrite/enums/localized_status.py', 'VALUE1 = "រាជធានី"', 'appwrite/enums/province_type.py', 'CAPITAL = "រាជធានី"'], 'ruby' => ['lib/appwrite/enums/webhook_event.rb', "USERCREATED = 'user.created'", 'lib/appwrite/enums/localized_status.rb', "VALUE1 = 'រាជធានី'", 'lib/appwrite/enums/province_type.rb', "CAPITAL = 'រាជធានី'"], @@ -128,7 +126,6 @@ private static function languageClasses(): array 'php' => PHP::class, 'web' => Web::class, 'node' => Node::class, - 'deno' => Deno::class, 'cli' => CLI::class, 'ruby' => Ruby::class, 'python' => Python::class, @@ -520,7 +517,7 @@ public function testJavascriptDefaultsAndExamplesKeepTheirTypes(): void { $defaults = []; $examples = []; - foreach (['web', 'node', 'react-native', 'deno'] as $name) { + foreach (['web', 'node', 'react-native'] as $name) { foreach (self::PLATFORMS as $platform) { $files = $this->generate($name, $platform); $general = $files['src/services/general.ts'] ?? '';