mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Merge branch '1.8.x' into ser-539-permissions
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
name: "Generate Specs"
|
||||
|
||||
env:
|
||||
COMPOSE_FILE: docker-compose.yml
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
type: choice
|
||||
description: "Appwrite version to generate specs for"
|
||||
required: true
|
||||
options:
|
||||
- "1.8.x"
|
||||
- "1.7.x"
|
||||
- "1.6.x"
|
||||
- "1.5.x"
|
||||
- "latest"
|
||||
push:
|
||||
type: boolean
|
||||
description: "Push specs to appwrite/specs repo and create PR"
|
||||
default: true
|
||||
message:
|
||||
type: string
|
||||
description: "Commit message for the specs PR"
|
||||
default: "chore: update API specs and SDK examples"
|
||||
|
||||
jobs:
|
||||
generate:
|
||||
name: Generate Specs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Build and start Appwrite
|
||||
run: |
|
||||
docker compose build
|
||||
docker compose up -d
|
||||
|
||||
- name: Generate specs
|
||||
run: |
|
||||
docker compose exec appwrite specs --version=${{ inputs.version }} --mode=normal --git=no
|
||||
|
||||
- name: Generate SDK examples
|
||||
if: inputs.push
|
||||
run: |
|
||||
docker compose exec appwrite sdks --platform=* --sdk=* --version=${{ inputs.version }} --git=no --mode=examples
|
||||
sudo chown -R $USER:$USER ./docs/examples/
|
||||
|
||||
- name: Push to appwrite/specs and create PR
|
||||
if: inputs.push
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
VERSION="${{ inputs.version }}"
|
||||
MESSAGE="${{ inputs.message }}"
|
||||
GIT_BRANCH="feat-${VERSION}-specs"
|
||||
SPECS_DIR="./app/config/specs"
|
||||
EXAMPLES_DIR="./docs/examples/${VERSION}"
|
||||
TARGET="/tmp/specs-repo"
|
||||
|
||||
sudo chown -R $USER:$USER "${SPECS_DIR}"
|
||||
|
||||
# Clone the specs repo
|
||||
git clone "https://x-access-token:${GH_TOKEN}@github.com/appwrite/specs.git" "${TARGET}"
|
||||
cd "${TARGET}"
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
# Create or checkout the feature branch
|
||||
git checkout -b "${GIT_BRANCH}" || git checkout "${GIT_BRANCH}"
|
||||
|
||||
# Copy spec files
|
||||
mkdir -p "specs/${VERSION}"
|
||||
cp ${GITHUB_WORKSPACE}/${SPECS_DIR}/*${VERSION}*.json "specs/${VERSION}/" 2>/dev/null || true
|
||||
|
||||
# Copy latest specs if version is latest
|
||||
if [ "${VERSION}" = "latest" ]; then
|
||||
cp ${GITHUB_WORKSPACE}/${SPECS_DIR}/*latest*.json "specs/latest/" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Copy SDK examples
|
||||
if [ -d "${GITHUB_WORKSPACE}/docs/examples/${VERSION}" ]; then
|
||||
mkdir -p "examples/${VERSION}"
|
||||
cp -r "${GITHUB_WORKSPACE}/docs/examples/${VERSION}/." "examples/${VERSION}/"
|
||||
fi
|
||||
|
||||
# Commit and push
|
||||
git add -A
|
||||
git diff --cached --quiet && echo "No changes to commit" && exit 0
|
||||
git commit -m "${MESSAGE}"
|
||||
git push -u origin "${GIT_BRANCH}" --force
|
||||
|
||||
# Create or update PR
|
||||
EXISTING_PR=$(gh pr list --repo appwrite/specs --head "${GIT_BRANCH}" --json number --jq '.[0].number' 2>/dev/null || true)
|
||||
if [ -n "${EXISTING_PR}" ]; then
|
||||
echo "PR #${EXISTING_PR} already exists, updated branch"
|
||||
echo "https://github.com/appwrite/specs/pull/${EXISTING_PR}"
|
||||
else
|
||||
gh pr create \
|
||||
--repo "appwrite/specs" \
|
||||
--title "feat: API specs update for version ${VERSION}" \
|
||||
--body "This PR contains API specification updates and SDK examples for version ${VERSION}." \
|
||||
--base "main" \
|
||||
--head "${GIT_BRANCH}"
|
||||
fi
|
||||
|
||||
- name: Stop containers
|
||||
if: always()
|
||||
run: docker compose down
|
||||
+2
-2
@@ -11,7 +11,7 @@ return [
|
||||
[
|
||||
'key' => 'web',
|
||||
'name' => 'Web',
|
||||
'version' => '22.1.0',
|
||||
'version' => '22.3.1',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-web',
|
||||
'package' => 'https://www.npmjs.com/package/appwrite',
|
||||
'enabled' => true,
|
||||
@@ -140,7 +140,7 @@ return [
|
||||
[
|
||||
'key' => 'react-native',
|
||||
'name' => 'React Native',
|
||||
'version' => '0.21.0',
|
||||
'version' => '0.23.1',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-react-native',
|
||||
'package' => 'https://npmjs.com/package/react-native-appwrite',
|
||||
'enabled' => true,
|
||||
|
||||
@@ -11,6 +11,9 @@ use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Database\Validator\CompoundUID;
|
||||
use Appwrite\Utopia\Database\Validator\Queries\Migrations;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Compression\Algorithms\GZIP;
|
||||
use Utopia\Compression\Algorithms\Zstd;
|
||||
use Utopia\Compression\Compression;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Exception\Order as OrderException;
|
||||
@@ -29,9 +32,6 @@ use Utopia\Migration\Sources\Firebase;
|
||||
use Utopia\Migration\Sources\NHost;
|
||||
use Utopia\Migration\Sources\Supabase;
|
||||
use Utopia\Migration\Transfer;
|
||||
use Utopia\Storage\Compression\Algorithms\GZIP;
|
||||
use Utopia\Storage\Compression\Algorithms\Zstd;
|
||||
use Utopia\Storage\Compression\Compression;
|
||||
use Utopia\Storage\Device;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\ArrayList;
|
||||
|
||||
@@ -34,6 +34,7 @@ use Appwrite\Utopia\View;
|
||||
use Executor\Executor;
|
||||
use MaxMind\Db\Reader;
|
||||
use Swoole\Http\Request as SwooleRequest;
|
||||
use Swoole\Table;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Console;
|
||||
use Utopia\Database\Database;
|
||||
@@ -1073,21 +1074,20 @@ Http::init()
|
||||
->inject('queueForCertificates')
|
||||
->inject('platform')
|
||||
->inject('authorization')
|
||||
->action(function (Request $request, Document $console, Database $dbForPlatform, Certificate $queueForCertificates, array $platform, Authorization $authorization) {
|
||||
->inject('certifiedDomains')
|
||||
->action(function (Request $request, Document $console, Database $dbForPlatform, Certificate $queueForCertificates, array $platform, Authorization $authorization, Table $certifiedDomains) {
|
||||
$hostname = $request->getHostname();
|
||||
$cache = Config::getParam('hostnames', []);
|
||||
$platformHostnames = $platform['hostnames'] ?? [];
|
||||
|
||||
// 1. Cache hit
|
||||
if (array_key_exists($hostname, $cache)) {
|
||||
if ($certifiedDomains->exists(md5($hostname))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Domain validation
|
||||
$domain = new Domain(!empty($hostname) ? $hostname : '');
|
||||
if (empty($domain->get()) || !$domain->isKnown() || $domain->isTest()) {
|
||||
$cache[$domain->get()] = false;
|
||||
Config::setParam('hostnames', $cache);
|
||||
$certifiedDomains->set(md5($domain->get()), ['value' => 0]);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1101,7 +1101,7 @@ Http::init()
|
||||
}
|
||||
|
||||
// 4. Check/create rule (requires DB access)
|
||||
$authorization->skip(function () use ($dbForPlatform, $domain, $console, $queueForCertificates, &$cache) {
|
||||
$authorization->skip(function () use ($dbForPlatform, $domain, $console, $queueForCertificates, $certifiedDomains) {
|
||||
try {
|
||||
// TODO: (@Meldiron) Remove after 1.7.x migration
|
||||
$isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5';
|
||||
@@ -1164,8 +1164,7 @@ Http::init()
|
||||
} catch (Duplicate $e) {
|
||||
Console::info('Certificate already exists');
|
||||
} finally {
|
||||
$cache[$domain->get()] = true;
|
||||
Config::setParam('hostnames', $cache);
|
||||
$certifiedDomains->set(md5($domain->get()), ['value' => 1]);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
+23
-16
@@ -37,11 +37,19 @@ use Utopia\System\System;
|
||||
|
||||
const DOMAIN_SYNC_TIMER = 30; // 30 seconds
|
||||
|
||||
$files = null;
|
||||
$files = new Files();
|
||||
$files->load(__DIR__ . '/../public');
|
||||
|
||||
$domains = new Table(1_000_000); // 1 million rows
|
||||
$domains->column('value', Table::TYPE_INT, 1);
|
||||
$domains->create();
|
||||
$riskyDomains = new Table(100_000);
|
||||
$riskyDomains->column('value', Table::TYPE_INT, 1);
|
||||
$riskyDomains->create();
|
||||
|
||||
$certifiedDomains = new Table(100_000);
|
||||
$certifiedDomains->column('value', Table::TYPE_INT, 1);
|
||||
$certifiedDomains->create();
|
||||
|
||||
Http::setResource('riskyDomains', fn () => $riskyDomains);
|
||||
Http::setResource('certifiedDomains', fn () => $certifiedDomains);
|
||||
|
||||
$http = new Server(
|
||||
host: "0.0.0.0",
|
||||
@@ -70,7 +78,7 @@ $totalWorkers = intval(System::getEnv('_APP_CPU_NUM', swoole_cpu_num())) * intva
|
||||
function dispatch(Server $server, int $fd, int $type, $data = null): int
|
||||
{
|
||||
$resolveWorkerId = function (Server $server, $data = null) {
|
||||
global $totalWorkers, $domains;
|
||||
global $totalWorkers, $riskyDomains;
|
||||
|
||||
// If data is not set we can send request to any worker
|
||||
// first we try to pick idle worker, if not we randomly pick a worker
|
||||
@@ -102,7 +110,7 @@ function dispatch(Server $server, int $fd, int $type, $data = null): int
|
||||
$risky = false;
|
||||
if (str_starts_with($request, 'POST') && str_contains($request, '/executions')) {
|
||||
$risky = true;
|
||||
} elseif ($domains->get(md5($domain), 'value') === 1) {
|
||||
} elseif ($riskyDomains->get(md5($domain), 'value') === 1) {
|
||||
// executions request coming from custom domain
|
||||
$risky = true;
|
||||
} else {
|
||||
@@ -164,11 +172,7 @@ $http
|
||||
Constant::OPTION_TASK_WORKER_NUM => 1, // required for the task to fetch domains background
|
||||
]);
|
||||
|
||||
$http->on(Constant::EVENT_WORKER_START, function ($server, $workerId) use (&$files) {
|
||||
if (!$server->taskworker) {
|
||||
$files = new Files();
|
||||
$files->load(__DIR__ . '/../public');
|
||||
}
|
||||
$http->on(Constant::EVENT_WORKER_START, function ($server, $workerId) {
|
||||
});
|
||||
|
||||
$http->on(Constant::EVENT_WORKER_STOP, function ($server, $workerId) {
|
||||
@@ -452,7 +456,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $tot
|
||||
});
|
||||
});
|
||||
|
||||
$http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, SwooleResponse $swooleResponse) use ($register, &$files) {
|
||||
$http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, SwooleResponse $swooleResponse) use ($register, $files) {
|
||||
Span::init('http.request');
|
||||
|
||||
Http::setResource('swooleRequest', fn () => $swooleRequest);
|
||||
@@ -463,7 +467,7 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool
|
||||
|
||||
Span::add('http.method', $request->getMethod());
|
||||
|
||||
if ($files instanceof Files && $files->isFileLoaded($request->getURI())) {
|
||||
if ($files->isFileLoaded($request->getURI())) {
|
||||
$time = (60 * 60 * 24 * 45); // 45 days cache
|
||||
|
||||
$response
|
||||
@@ -582,7 +586,7 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool
|
||||
});
|
||||
|
||||
// Fetch domains every `DOMAIN_SYNC_TIMER` seconds and update in the memory
|
||||
$http->on(Constant::EVENT_TASK, function () use ($register, $domains) {
|
||||
$http->on(Constant::EVENT_TASK, function () use ($register) {
|
||||
$lastSyncUpdate = null;
|
||||
$pools = $register->get('pools');
|
||||
Http::setResource('pools', fn () => $pools);
|
||||
@@ -591,7 +595,10 @@ $http->on(Constant::EVENT_TASK, function () use ($register, $domains) {
|
||||
/** @var Utopia\Database\Database $dbForPlatform */
|
||||
$dbForPlatform = $app->getResource('dbForPlatform');
|
||||
|
||||
Timer::tick(DOMAIN_SYNC_TIMER * 1000, function () use ($dbForPlatform, $domains, &$lastSyncUpdate, $app) {
|
||||
/** @var Table $riskyDomains */
|
||||
$riskyDomains = $app->getResource('riskyDomains');
|
||||
|
||||
Timer::tick(DOMAIN_SYNC_TIMER * 1000, function () use ($dbForPlatform, $riskyDomains, &$lastSyncUpdate, $app) {
|
||||
try {
|
||||
$time = DateTime::now();
|
||||
$limit = 1000;
|
||||
@@ -644,7 +651,7 @@ $http->on(Constant::EVENT_TASK, function () use ($register, $domains) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$domains->set(md5($domain), ['value' => 1]);
|
||||
$riskyDomains->set(md5($domain), ['value' => 1]);
|
||||
}
|
||||
$latestDocument = !empty(array_key_last($results)) ? $results[array_key_last($results)] : null;
|
||||
}
|
||||
|
||||
+2
-1
@@ -51,6 +51,7 @@
|
||||
"utopia-php/auth": "0.5.*",
|
||||
"utopia-php/cache": "1.0.*",
|
||||
"utopia-php/cli": "0.22.*",
|
||||
"utopia-php/compression": "0.1.*",
|
||||
"utopia-php/config": "1.*",
|
||||
"utopia-php/console": "0.1.*",
|
||||
"utopia-php/database": "5.*",
|
||||
@@ -72,7 +73,7 @@
|
||||
"utopia-php/preloader": "0.2.*",
|
||||
"utopia-php/queue": "0.15.*",
|
||||
"utopia-php/registry": "0.5.*",
|
||||
"utopia-php/storage": "0.18.*",
|
||||
"utopia-php/storage": "1.0.*",
|
||||
"utopia-php/system": "0.10.*",
|
||||
"utopia-php/telemetry": "0.2.*",
|
||||
"utopia-php/vcs": "1.*",
|
||||
|
||||
Generated
+48
-53
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "fe847eccf6ba73bfca1e08d26e9fc7ab",
|
||||
"content-hash": "dd9887a50fb434887461a99413007573",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/jwt",
|
||||
@@ -161,16 +161,16 @@
|
||||
},
|
||||
{
|
||||
"name": "appwrite/php-runtimes",
|
||||
"version": "0.19.3",
|
||||
"version": "0.19.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/appwrite/runtimes.git",
|
||||
"reference": "bfe9f3c730c8c203c5e2d80bd5a81c9b1579714e"
|
||||
"reference": "eea9d1b3ca2540eab623b419c8afde09ef406c0b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/appwrite/runtimes/zipball/bfe9f3c730c8c203c5e2d80bd5a81c9b1579714e",
|
||||
"reference": "bfe9f3c730c8c203c5e2d80bd5a81c9b1579714e",
|
||||
"url": "https://api.github.com/repos/appwrite/runtimes/zipball/eea9d1b3ca2540eab623b419c8afde09ef406c0b",
|
||||
"reference": "eea9d1b3ca2540eab623b419c8afde09ef406c0b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -210,9 +210,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/appwrite/runtimes/issues",
|
||||
"source": "https://github.com/appwrite/runtimes/tree/0.19.3"
|
||||
"source": "https://github.com/appwrite/runtimes/tree/0.19.4"
|
||||
},
|
||||
"time": "2026-02-06T10:08:18+00:00"
|
||||
"time": "2026-02-17T10:04:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "brick/math",
|
||||
@@ -3656,20 +3656,20 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/compression",
|
||||
"version": "0.1.3",
|
||||
"version": "0.1.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/compression.git",
|
||||
"reference": "66f093557ba66d98245e562036182016c7dcfe8a"
|
||||
"reference": "68045cb9d714c1259582d2dfd0e76bd34f83e713"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/compression/zipball/66f093557ba66d98245e562036182016c7dcfe8a",
|
||||
"reference": "66f093557ba66d98245e562036182016c7dcfe8a",
|
||||
"url": "https://api.github.com/repos/utopia-php/compression/zipball/68045cb9d714c1259582d2dfd0e76bd34f83e713",
|
||||
"reference": "68045cb9d714c1259582d2dfd0e76bd34f83e713",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.0"
|
||||
"php": ">=8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/pint": "1.2.*",
|
||||
@@ -3696,9 +3696,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/compression/issues",
|
||||
"source": "https://github.com/utopia-php/compression/tree/0.1.3"
|
||||
"source": "https://github.com/utopia-php/compression/tree/0.1.4"
|
||||
},
|
||||
"time": "2025-01-15T15:15:51+00:00"
|
||||
"time": "2026-02-17T05:53:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/config",
|
||||
@@ -3797,16 +3797,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/database",
|
||||
"version": "5.2.0",
|
||||
"version": "5.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/database.git",
|
||||
"reference": "5c89b39de00f2b3126d0fbbdea36786341293df7"
|
||||
"reference": "5e49f32ebb6e40a78209231564c40e5068810429"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/5c89b39de00f2b3126d0fbbdea36786341293df7",
|
||||
"reference": "5c89b39de00f2b3126d0fbbdea36786341293df7",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/5e49f32ebb6e40a78209231564c40e5068810429",
|
||||
"reference": "5e49f32ebb6e40a78209231564c40e5068810429",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3849,9 +3849,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/database/issues",
|
||||
"source": "https://github.com/utopia-php/database/tree/5.2.0"
|
||||
"source": "https://github.com/utopia-php/database/tree/5.3.0"
|
||||
},
|
||||
"time": "2026-02-14T09:37:28+00:00"
|
||||
"time": "2026-02-17T11:50:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/detector",
|
||||
@@ -3948,16 +3948,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/dns",
|
||||
"version": "1.6.2",
|
||||
"version": "1.6.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/dns.git",
|
||||
"reference": "98c70520213a41e2fe1867e5b110273c06bf1cab"
|
||||
"reference": "c46a13c42bc19365985264a6fdaaaf7d8e736d3e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/dns/zipball/98c70520213a41e2fe1867e5b110273c06bf1cab",
|
||||
"reference": "98c70520213a41e2fe1867e5b110273c06bf1cab",
|
||||
"url": "https://api.github.com/repos/utopia-php/dns/zipball/c46a13c42bc19365985264a6fdaaaf7d8e736d3e",
|
||||
"reference": "c46a13c42bc19365985264a6fdaaaf7d8e736d3e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3999,9 +3999,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/dns/issues",
|
||||
"source": "https://github.com/utopia-php/dns/tree/1.6.2"
|
||||
"source": "https://github.com/utopia-php/dns/tree/1.6.3"
|
||||
},
|
||||
"time": "2026-02-13T12:29:08+00:00"
|
||||
"time": "2026-02-17T10:45:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/domains",
|
||||
@@ -4464,16 +4464,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/migration",
|
||||
"version": "1.6.0",
|
||||
"version": "1.6.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/migration.git",
|
||||
"reference": "aa07cf9ae8cc4b8df0ab64588e033693b5ad6849"
|
||||
"reference": "c5c7544d02d2418536d41050794050132f247d62"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/migration/zipball/aa07cf9ae8cc4b8df0ab64588e033693b5ad6849",
|
||||
"reference": "aa07cf9ae8cc4b8df0ab64588e033693b5ad6849",
|
||||
"url": "https://api.github.com/repos/utopia-php/migration/zipball/c5c7544d02d2418536d41050794050132f247d62",
|
||||
"reference": "c5c7544d02d2418536d41050794050132f247d62",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4484,7 +4484,7 @@
|
||||
"php": ">=8.1",
|
||||
"utopia-php/database": "5.*",
|
||||
"utopia-php/dsn": "0.2.*",
|
||||
"utopia-php/storage": "0.18.*"
|
||||
"utopia-php/storage": "1.0.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-pdo": "*",
|
||||
@@ -4513,9 +4513,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/migration/issues",
|
||||
"source": "https://github.com/utopia-php/migration/tree/1.6.0"
|
||||
"source": "https://github.com/utopia-php/migration/tree/1.6.1"
|
||||
},
|
||||
"time": "2026-02-16T07:19:27+00:00"
|
||||
"time": "2026-02-17T05:49:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/mongo",
|
||||
@@ -4953,32 +4953,27 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/storage",
|
||||
"version": "0.18.19",
|
||||
"version": "1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/storage.git",
|
||||
"reference": "9c3f9a471250d22de7d405ee19e23e72b14181ca"
|
||||
"reference": "f672e8865938e5d1d6dc3bd149ceba4e5582199e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/storage/zipball/9c3f9a471250d22de7d405ee19e23e72b14181ca",
|
||||
"reference": "9c3f9a471250d22de7d405ee19e23e72b14181ca",
|
||||
"url": "https://api.github.com/repos/utopia-php/storage/zipball/f672e8865938e5d1d6dc3bd149ceba4e5582199e",
|
||||
"reference": "f672e8865938e5d1d6dc3bd149ceba4e5582199e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-brotli": "*",
|
||||
"ext-curl": "*",
|
||||
"ext-fileinfo": "*",
|
||||
"ext-lz4": "*",
|
||||
"ext-simplexml": "*",
|
||||
"ext-snappy": "*",
|
||||
"ext-xz": "*",
|
||||
"ext-zlib": "*",
|
||||
"ext-zstd": "*",
|
||||
"php": ">=8.1",
|
||||
"utopia-php/framework": "0.*.*",
|
||||
"utopia-php/system": "0.*.*",
|
||||
"utopia-php/telemetry": "0.2.*"
|
||||
"utopia-php/telemetry": "0.2.*",
|
||||
"utopia-php/validators": "0.2.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/pint": "1.2.*",
|
||||
@@ -5005,9 +5000,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/storage/issues",
|
||||
"source": "https://github.com/utopia-php/storage/tree/0.18.19"
|
||||
"source": "https://github.com/utopia-php/storage/tree/1.0.0"
|
||||
},
|
||||
"time": "2025-12-17T13:55:20+00:00"
|
||||
"time": "2026-02-17T04:37:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/system",
|
||||
@@ -5390,16 +5385,16 @@
|
||||
"packages-dev": [
|
||||
{
|
||||
"name": "appwrite/sdk-generator",
|
||||
"version": "1.9.2",
|
||||
"version": "1.9.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/appwrite/sdk-generator.git",
|
||||
"reference": "74de906ea5051030c5299a5d4aa74d963a531130"
|
||||
"reference": "5a8a304e404c84539f3ac6562c736f8c7ef2bef2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/74de906ea5051030c5299a5d4aa74d963a531130",
|
||||
"reference": "74de906ea5051030c5299a5d4aa74d963a531130",
|
||||
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/5a8a304e404c84539f3ac6562c736f8c7ef2bef2",
|
||||
"reference": "5a8a304e404c84539f3ac6562c736f8c7ef2bef2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -5435,9 +5430,9 @@
|
||||
"description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms",
|
||||
"support": {
|
||||
"issues": "https://github.com/appwrite/sdk-generator/issues",
|
||||
"source": "https://github.com/appwrite/sdk-generator/tree/1.9.2"
|
||||
"source": "https://github.com/appwrite/sdk-generator/tree/1.9.3"
|
||||
},
|
||||
"time": "2026-02-16T06:59:54+00:00"
|
||||
"time": "2026-02-17T11:48:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/annotations",
|
||||
@@ -8890,7 +8885,7 @@
|
||||
],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"stability-flags": {},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
|
||||
@@ -13,7 +13,8 @@ const result = await databases.createLongtextAttribute({
|
||||
key: '',
|
||||
required: false,
|
||||
default: '<DEFAULT>', // optional
|
||||
array: false // optional
|
||||
array: false, // optional
|
||||
encrypt: false // optional
|
||||
});
|
||||
|
||||
console.log(result);
|
||||
|
||||
@@ -13,7 +13,8 @@ const result = await databases.createMediumtextAttribute({
|
||||
key: '',
|
||||
required: false,
|
||||
default: '<DEFAULT>', // optional
|
||||
array: false // optional
|
||||
array: false, // optional
|
||||
encrypt: false // optional
|
||||
});
|
||||
|
||||
console.log(result);
|
||||
|
||||
@@ -13,7 +13,8 @@ const result = await databases.createTextAttribute({
|
||||
key: '',
|
||||
required: false,
|
||||
default: '<DEFAULT>', // optional
|
||||
array: false // optional
|
||||
array: false, // optional
|
||||
encrypt: false // optional
|
||||
});
|
||||
|
||||
console.log(result);
|
||||
|
||||
@@ -14,7 +14,8 @@ const result = await databases.createVarcharAttribute({
|
||||
size: 1,
|
||||
required: false,
|
||||
default: '<DEFAULT>', // optional
|
||||
array: false // optional
|
||||
array: false, // optional
|
||||
encrypt: false // optional
|
||||
});
|
||||
|
||||
console.log(result);
|
||||
|
||||
@@ -13,7 +13,8 @@ const result = await tablesDB.createLongtextColumn({
|
||||
key: '',
|
||||
required: false,
|
||||
default: '<DEFAULT>', // optional
|
||||
array: false // optional
|
||||
array: false, // optional
|
||||
encrypt: false // optional
|
||||
});
|
||||
|
||||
console.log(result);
|
||||
|
||||
@@ -13,7 +13,8 @@ const result = await tablesDB.createMediumtextColumn({
|
||||
key: '',
|
||||
required: false,
|
||||
default: '<DEFAULT>', // optional
|
||||
array: false // optional
|
||||
array: false, // optional
|
||||
encrypt: false // optional
|
||||
});
|
||||
|
||||
console.log(result);
|
||||
|
||||
@@ -13,7 +13,8 @@ const result = await tablesDB.createTextColumn({
|
||||
key: '',
|
||||
required: false,
|
||||
default: '<DEFAULT>', // optional
|
||||
array: false // optional
|
||||
array: false, // optional
|
||||
encrypt: false // optional
|
||||
});
|
||||
|
||||
console.log(result);
|
||||
|
||||
@@ -14,7 +14,8 @@ const result = await tablesDB.createVarcharColumn({
|
||||
size: 1,
|
||||
required: false,
|
||||
default: '<DEFAULT>', // optional
|
||||
array: false // optional
|
||||
array: false, // optional
|
||||
encrypt: false // optional
|
||||
});
|
||||
|
||||
console.log(result);
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
|
||||
* Add `--queries` option to `list-keys` command
|
||||
* Add `--key-id` option to `create-key` command
|
||||
* Add `encrypt` param support to new string type attributes
|
||||
* Fix `bignumber.js` bundler conflict by removing direct dependency in favor of transitive dependency from `json-bigint`
|
||||
* Fix missing region in console failUrl for failed deployments
|
||||
|
||||
## 13.3.2
|
||||
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# Change log
|
||||
|
||||
## 0.23.1
|
||||
|
||||
* Add `upsert` method to Realtime `Channels` helper class
|
||||
* Fix `bignumber.js` bundler conflict by removing direct dependency in favor of transitive dependency from `json-bigint`
|
||||
|
||||
## 0.21.0
|
||||
|
||||
* Add `queries` parameter to `client.subscribe()` for filtering Realtime events
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# Change Log
|
||||
|
||||
## 22.3.1
|
||||
|
||||
* Add `upsert` method to Realtime `Channels` helper class
|
||||
* Fix `bignumber.js` bundler conflict with Next.js Turbopack by removing direct dependency in favor of transitive dependency from `json-bigint`
|
||||
|
||||
## 22.1.0
|
||||
|
||||
* Add `queries` parameter to `Realtime.subscribe()` and `client.subscribe()` for server-side query filtering
|
||||
|
||||
@@ -56,7 +56,8 @@ class Get extends Action
|
||||
$isCNAMEValid = !empty(System::getEnv('_APP_DOMAIN_TARGET_CNAME', '')) && $validator->isKnown() && !$validator->isTest();
|
||||
|
||||
$validator = new IP(IP::V4);
|
||||
$isAValid = !empty(System::getEnv('_APP_DOMAIN_TARGET_A', '')) && ($validator->isValid(System::getEnv('_APP_DOMAIN_TARGET_A')));
|
||||
$targetA = \explode(',', System::getEnv('_APP_DOMAIN_TARGET_A', ''))[0];
|
||||
$isAValid = !empty($targetA) && ($validator->isValid($targetA));
|
||||
|
||||
$validator = new IP(IP::V6);
|
||||
$isAAAAValid = !empty(System::getEnv('_APP_DOMAIN_TARGET_AAAA', '')) && $validator->isValid(System::getEnv('_APP_DOMAIN_TARGET_AAAA'));
|
||||
@@ -74,7 +75,7 @@ class Get extends Action
|
||||
$variables = new Document([
|
||||
'_APP_DOMAIN_TARGET_CNAME' => System::getEnv('_APP_DOMAIN_TARGET_CNAME'),
|
||||
'_APP_DOMAIN_TARGET_AAAA' => System::getEnv('_APP_DOMAIN_TARGET_AAAA'),
|
||||
'_APP_DOMAIN_TARGET_A' => System::getEnv('_APP_DOMAIN_TARGET_A'),
|
||||
'_APP_DOMAIN_TARGET_A' => $targetA,
|
||||
'_APP_DOMAIN_TARGET_CAA' => '0 issue "' . System::getEnv('_APP_DOMAIN_TARGET_CAA') . '"',
|
||||
'_APP_STORAGE_LIMIT' => +System::getEnv('_APP_STORAGE_LIMIT'),
|
||||
'_APP_COMPUTE_BUILD_TIMEOUT' => +System::getEnv('_APP_COMPUTE_BUILD_TIMEOUT'),
|
||||
|
||||
@@ -7,6 +7,7 @@ use Appwrite\Event\Realtime;
|
||||
use Appwrite\Permission;
|
||||
use Appwrite\Role;
|
||||
use Exception;
|
||||
use Utopia\Compression\Compression;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Console;
|
||||
use Utopia\Database\Database;
|
||||
@@ -16,7 +17,6 @@ use Utopia\Database\Query;
|
||||
use Utopia\Fetch\Client as FetchClient;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Queue\Message;
|
||||
use Utopia\Storage\Compression\Compression;
|
||||
use Utopia\Storage\Device;
|
||||
use Utopia\System\System;
|
||||
|
||||
|
||||
@@ -130,15 +130,7 @@ class Action extends PlatformAction
|
||||
$resourceType = $rule->getAttribute('deploymentResourceType', '');
|
||||
|
||||
// Ensures different target based on rule's type, as configured by env variables
|
||||
if ($resourceType === 'function') {
|
||||
// For example: fra.appwrite.run
|
||||
foreach (\explode(',', System::getEnv('_APP_DOMAIN_FUNCTIONS', '')) as $targetCNAME) {
|
||||
if (empty($targetCNAME)) {
|
||||
continue;
|
||||
}
|
||||
$targetCNAMEs[] = new Domain($targetCNAME);
|
||||
}
|
||||
} elseif ($resourceType === 'site') {
|
||||
if ($resourceType === 'site') {
|
||||
// For example: appwrite.network
|
||||
foreach (\explode(',', System::getEnv('_APP_DOMAIN_SITES', '')) as $targetCNAME) {
|
||||
if (empty($targetCNAME)) {
|
||||
@@ -146,7 +138,7 @@ class Action extends PlatformAction
|
||||
}
|
||||
$targetCNAMEs[] = new Domain($targetCNAME);
|
||||
}
|
||||
} elseif ($ruleType === 'api') {
|
||||
} elseif ($resourceType === 'function' || $ruleType === 'api') {
|
||||
// For example: fra.cloud.appwrite.io
|
||||
$targetCNAMEs[] = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', ''));
|
||||
} elseif ($ruleType === 'redirect') {
|
||||
@@ -178,13 +170,17 @@ class Action extends PlatformAction
|
||||
}
|
||||
|
||||
// Ensure at least one of CNAME/A/AAAA record points to our servers properly
|
||||
$targetA = System::getEnv('_APP_DOMAIN_TARGET_A', '');
|
||||
if ((new IP(IP::V4))->isValid($targetA)) {
|
||||
$validator = new $dnsValidatorClass($targetA, Record::TYPE_A, $dnsServers);
|
||||
$validators[] = $validator;
|
||||
foreach (\explode(',', System::getEnv('_APP_DOMAIN_TARGET_A', '')) as $targetA) {
|
||||
if (empty($targetA)) {
|
||||
continue;
|
||||
}
|
||||
if ((new IP(IP::V4))->isValid($targetA)) {
|
||||
$validator = new $dnsValidatorClass($targetA, Record::TYPE_A, $dnsServers);
|
||||
$validators[] = $validator;
|
||||
|
||||
if (\is_null($mainValidator)) {
|
||||
$mainValidator = $validator;
|
||||
if (\is_null($mainValidator)) {
|
||||
$mainValidator = $validator;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Database\Validator\CustomId;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Compression\Compression;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
@@ -17,7 +18,6 @@ use Utopia\Database\Helpers\ID;
|
||||
use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Storage\Compression\Compression;
|
||||
use Utopia\Storage\Storage;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\ArrayList;
|
||||
|
||||
@@ -14,6 +14,9 @@ use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Database\Documents\User;
|
||||
use Appwrite\Utopia\Database\Validator\CustomId;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Compression\Algorithms\GZIP;
|
||||
use Utopia\Compression\Algorithms\Zstd;
|
||||
use Utopia\Compression\Compression;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Exception\Duplicate as DuplicateException;
|
||||
@@ -28,9 +31,6 @@ use Utopia\Database\Validator\UID;
|
||||
use Utopia\Http\Adapter\Swoole\Request;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Storage\Compression\Algorithms\GZIP;
|
||||
use Utopia\Storage\Compression\Algorithms\Zstd;
|
||||
use Utopia\Storage\Compression\Compression;
|
||||
use Utopia\Storage\Device;
|
||||
use Utopia\Storage\Storage;
|
||||
use Utopia\Storage\Validator\File;
|
||||
|
||||
@@ -11,6 +11,9 @@ use Appwrite\SDK\MethodType;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Database\Documents\User;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Compression\Algorithms\GZIP;
|
||||
use Utopia\Compression\Algorithms\Zstd;
|
||||
use Utopia\Compression\Compression;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Validator\Authorization;
|
||||
@@ -19,9 +22,6 @@ use Utopia\Database\Validator\UID;
|
||||
use Utopia\Http\Adapter\Swoole\Request;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Storage\Compression\Algorithms\GZIP;
|
||||
use Utopia\Storage\Compression\Algorithms\Zstd;
|
||||
use Utopia\Storage\Compression\Compression;
|
||||
use Utopia\Storage\Device;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\Text;
|
||||
|
||||
@@ -11,6 +11,9 @@ use Appwrite\SDK\MethodType;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Database\Documents\User;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Compression\Algorithms\GZIP;
|
||||
use Utopia\Compression\Algorithms\Zstd;
|
||||
use Utopia\Compression\Compression;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Console;
|
||||
use Utopia\Database\Database;
|
||||
@@ -23,9 +26,6 @@ use Utopia\Http\Adapter\Swoole\Request;
|
||||
use Utopia\Image\Image;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Storage\Compression\Algorithms\GZIP;
|
||||
use Utopia\Storage\Compression\Algorithms\Zstd;
|
||||
use Utopia\Storage\Compression\Compression;
|
||||
use Utopia\Storage\Device;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\HexColor;
|
||||
|
||||
@@ -8,6 +8,9 @@ use Appwrite\Extend\Exception;
|
||||
use Appwrite\OpenSSL\OpenSSL;
|
||||
use Appwrite\Utopia\Database\Documents\User;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Compression\Algorithms\GZIP;
|
||||
use Utopia\Compression\Algorithms\Zstd;
|
||||
use Utopia\Compression\Compression;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
@@ -16,9 +19,6 @@ use Utopia\Database\Validator\UID;
|
||||
use Utopia\Http\Adapter\Swoole\Request;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Storage\Compression\Algorithms\GZIP;
|
||||
use Utopia\Storage\Compression\Algorithms\Zstd;
|
||||
use Utopia\Storage\Compression\Compression;
|
||||
use Utopia\Storage\Device;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\Text;
|
||||
|
||||
@@ -11,6 +11,9 @@ use Appwrite\SDK\MethodType;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Database\Documents\User;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Compression\Algorithms\GZIP;
|
||||
use Utopia\Compression\Algorithms\Zstd;
|
||||
use Utopia\Compression\Compression;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Document;
|
||||
@@ -20,9 +23,6 @@ use Utopia\Database\Validator\UID;
|
||||
use Utopia\Http\Adapter\Swoole\Request;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Storage\Compression\Algorithms\GZIP;
|
||||
use Utopia\Storage\Compression\Algorithms\Zstd;
|
||||
use Utopia\Storage\Compression\Compression;
|
||||
use Utopia\Storage\Device;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\Text;
|
||||
|
||||
@@ -8,13 +8,13 @@ use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\Utopia\Response;
|
||||
use Utopia\Compression\Compression;
|
||||
use Utopia\Database\Database;
|
||||
use Utopia\Database\Helpers\Permission;
|
||||
use Utopia\Database\Validator\Permissions;
|
||||
use Utopia\Database\Validator\UID;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\Storage\Compression\Compression;
|
||||
use Utopia\Storage\Storage;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\ArrayList;
|
||||
|
||||
@@ -63,10 +63,11 @@ class Doctor extends Action
|
||||
}
|
||||
|
||||
$ipv4 = new IP(IP::V4);
|
||||
if (!$ipv4->isValid(System::getEnv('_APP_DOMAIN_TARGET_A'))) {
|
||||
Console::log('🔴 A record target is not valid (' . System::getEnv('_APP_DOMAIN_TARGET_A') . ')');
|
||||
$targetA = \explode(',', System::getEnv('_APP_DOMAIN_TARGET_A', ''))[0];
|
||||
if (!$ipv4->isValid($targetA)) {
|
||||
Console::log('🔴 A record target is not valid (' . $targetA . ')');
|
||||
} else {
|
||||
Console::log('🟢 A record target is valid (' . System::getEnv('_APP_DOMAIN_TARGET_A') . ')');
|
||||
Console::log('🟢 A record target is valid (' . $targetA . ')');
|
||||
}
|
||||
|
||||
$ipv6 = new IP(IP::V6);
|
||||
|
||||
@@ -77,11 +77,13 @@ class SDKs extends Action
|
||||
->param('release', null, new Nullable(new WhiteList(['yes', 'no'])), 'Should we create releases?', optional: true)
|
||||
->param('commit', null, new Nullable(new WhiteList(['yes', 'no'])), 'Actually create releases (yes) or dry-run (no)?', optional: true)
|
||||
->param('sdks', null, new Nullable(new Text(256)), 'Selected SDKs', optional: true)
|
||||
->param('mode', 'full', new WhiteList(['full', 'examples']), 'Generation mode: full (default) or examples (only generate and copy examples)', optional: true)
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
public function action(?string $platform, ?string $sdk, ?string $version, ?string $git, ?string $message, ?string $release, ?string $commit, ?string $sdks): void
|
||||
public function action(?string $platform, ?string $sdk, ?string $version, ?string $git, ?string $message, ?string $release, ?string $commit, ?string $sdks, string $mode): void
|
||||
{
|
||||
$examplesOnly = ($mode === 'examples');
|
||||
$selectedPlatform = $platform;
|
||||
$selectedSDK = $sdk;
|
||||
|
||||
@@ -99,7 +101,7 @@ class SDKs extends Action
|
||||
$createRelease = ($release === 'yes');
|
||||
$commitRelease = ($commit === 'yes');
|
||||
|
||||
if (!$createRelease) {
|
||||
if (!$createRelease && !$examplesOnly) {
|
||||
$git ??= Console::confirm('Should we use git push? (yes/no)');
|
||||
$git = ($git === 'yes');
|
||||
|
||||
@@ -108,6 +110,9 @@ class SDKs extends Action
|
||||
if ($git) {
|
||||
$message ??= Console::confirm('Please enter your commit message:');
|
||||
}
|
||||
} elseif ($examplesOnly) {
|
||||
$git = false;
|
||||
$prUrls = [];
|
||||
}
|
||||
|
||||
if (!\in_array($version, [
|
||||
@@ -293,7 +298,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
throw new \Exception('Language "' . $language['key'] . '" not supported');
|
||||
}
|
||||
|
||||
if ($createRelease) {
|
||||
if ($createRelease && !$examplesOnly) {
|
||||
$releaseVersion = $language['version'];
|
||||
|
||||
$repoName = $language['gitUserName'] . '/' . $language['gitRepoName'];
|
||||
@@ -403,7 +408,9 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
continue;
|
||||
}
|
||||
|
||||
Console::info("Generating {$language['name']} SDK...");
|
||||
Console::info($examplesOnly
|
||||
? "Generating examples for {$language['name']} SDK..."
|
||||
: "Generating {$language['name']} SDK...");
|
||||
|
||||
$sdk = new SDK($config, new Swagger2($spec));
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ use Utopia\Http\Request as UtopiaRequest;
|
||||
use Utopia\Http\Response as UtopiaResponse;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\Nullable;
|
||||
use Utopia\Validator\Text;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
@@ -34,6 +35,9 @@ class Specs extends Action
|
||||
->desc('Generate Appwrite API specifications')
|
||||
->param('version', 'latest', new Text(16), 'Spec version', true)
|
||||
->param('mode', 'normal', new WhiteList(['normal', 'mocks']), 'Spec Mode', true)
|
||||
->param('git', null, new Nullable(new WhiteList(['yes', 'no'])), 'Should we push to the specs repo?', optional: true)
|
||||
->param('message', null, new Nullable(new Text(256)), 'Commit Message', optional: true)
|
||||
->param('branch', null, new Nullable(new Text(256)), 'Target branch for PR (defaults to main)', optional: true)
|
||||
->callback($this->action(...));
|
||||
}
|
||||
|
||||
@@ -230,8 +234,20 @@ class Specs extends Action
|
||||
return $sdkPlatforms;
|
||||
}
|
||||
|
||||
public function action(string $version, string $mode): void
|
||||
public function action(string $version, string $mode, ?string $git, ?string $message, ?string $branch): void
|
||||
{
|
||||
if (\is_null($git)) {
|
||||
$git = Console::confirm('Should we push specs to the appwrite/specs repo? (yes/no)');
|
||||
}
|
||||
|
||||
if ($git === 'yes' && \is_null($message)) {
|
||||
$message = Console::confirm('Please enter your commit message:');
|
||||
}
|
||||
|
||||
if (\is_null($branch)) {
|
||||
$branch = 'main';
|
||||
}
|
||||
|
||||
$appRoutes = Http::getRoutes();
|
||||
|
||||
/** @var AppwriteResponse $response */
|
||||
@@ -249,6 +265,8 @@ class Specs extends Action
|
||||
$authCounts = $this->getAuthCounts();
|
||||
$keys = $this->getKeys();
|
||||
|
||||
$generatedFiles = [];
|
||||
|
||||
foreach ($platforms as $platform) {
|
||||
$routes = [];
|
||||
$models = [];
|
||||
@@ -371,6 +389,7 @@ class Specs extends Action
|
||||
throw new Exception('Failed to save mocks spec file: ' . $path);
|
||||
}
|
||||
|
||||
$generatedFiles[] = realpath($path);
|
||||
Console::success('Saved mocks spec file: ' . realpath($path));
|
||||
|
||||
continue;
|
||||
@@ -382,8 +401,113 @@ class Specs extends Action
|
||||
throw new Exception('Failed to save spec file: ' . $path);
|
||||
}
|
||||
|
||||
$generatedFiles[] = realpath($path);
|
||||
Console::success('Saved spec file: ' . realpath($path));
|
||||
}
|
||||
}
|
||||
|
||||
if ($git === 'yes') {
|
||||
$gitUrl = 'git@github.com:appwrite/specs.git';
|
||||
$gitRepoName = 'appwrite/specs';
|
||||
$gitBranch = 'feat-' . $version . '-specs';
|
||||
$repoBranch = $branch;
|
||||
$target = \realpath(__DIR__ . '/../../../../app') . '/sdks/git/specs/';
|
||||
$examplesDir = \realpath(__DIR__ . '/../../../..') . '/docs/examples/' . $version;
|
||||
|
||||
Console::info("Cloning {$gitRepoName} into {$target}...");
|
||||
|
||||
\exec('rm -rf ' . $target . ' && \
|
||||
mkdir -p ' . $target . ' && \
|
||||
cd ' . $target . ' && \
|
||||
git init && \
|
||||
git config core.ignorecase false && \
|
||||
git config pull.rebase false && \
|
||||
git remote add origin ' . $gitUrl . ' && \
|
||||
git fetch origin && \
|
||||
(git checkout -f ' . $repoBranch . ' 2>/dev/null || git checkout -b ' . $repoBranch . ') && \
|
||||
git pull origin ' . $repoBranch . ' && \
|
||||
(git checkout -f ' . $gitBranch . ' 2>/dev/null || git checkout -b ' . $gitBranch . ') && \
|
||||
(git fetch origin ' . $gitBranch . ' 2>/dev/null || git push -u origin ' . $gitBranch . ') && \
|
||||
git reset --hard origin/' . $gitBranch . ' 2>/dev/null || true
|
||||
');
|
||||
|
||||
// Copy generated spec files into specs/{version}/ subdirectory
|
||||
$specsSubDir = $mocks ? 'mocks' : $version;
|
||||
\exec('mkdir -p ' . \escapeshellarg("{$target}/specs/{$specsSubDir}"));
|
||||
foreach ($generatedFiles as $file) {
|
||||
$fileName = \basename($file);
|
||||
\exec('cp ' . \escapeshellarg($file) . ' ' . \escapeshellarg("{$target}/specs/{$specsSubDir}/{$fileName}"));
|
||||
Console::success("Copied spec file to repo: specs/{$specsSubDir}/{$fileName}");
|
||||
}
|
||||
|
||||
// Regenerate SDK examples for this version
|
||||
Console::info("Regenerating SDK examples for version {$version}...");
|
||||
$sdksCommand = 'php ' . \escapeshellarg(\realpath(__DIR__ . '/../../../../app') . '/cli.php')
|
||||
. ' sdks --platform=* --sdk=* --version=' . \escapeshellarg($version)
|
||||
. ' --git=no --mode=examples 2>&1';
|
||||
\exec($sdksCommand, $sdksOutput, $sdksReturnCode);
|
||||
|
||||
if ($sdksReturnCode !== 0) {
|
||||
Console::warning("SDK examples generation returned non-zero exit code: {$sdksReturnCode}");
|
||||
Console::warning(\implode("\n", $sdksOutput));
|
||||
} else {
|
||||
Console::success("Regenerated SDK examples for version {$version}");
|
||||
}
|
||||
|
||||
// Copy SDK examples for this version
|
||||
if (\is_dir($examplesDir)) {
|
||||
\exec('mkdir -p ' . \escapeshellarg("{$target}/examples/{$version}") . ' && \
|
||||
cp -r ' . \escapeshellarg($examplesDir) . '/. ' . \escapeshellarg("{$target}/examples/{$version}/"));
|
||||
Console::success("Copied SDK examples for version {$version} to repo: examples/{$version}/");
|
||||
} else {
|
||||
Console::warning("No SDK examples found at: {$examplesDir}. Skipping examples copy.");
|
||||
}
|
||||
|
||||
// Git add, commit, and push
|
||||
\exec('cd ' . $target . ' && \
|
||||
git add -A && \
|
||||
git commit -m "' . \addslashes($message) . '" && \
|
||||
git push -u origin ' . $gitBranch . '
|
||||
');
|
||||
|
||||
Console::success("Pushed specs to {$gitRepoName} on branch {$gitBranch}");
|
||||
|
||||
// Create or update PR
|
||||
$prTitle = "feat: API specs update for version {$version}";
|
||||
$prBody = "This PR contains API specification updates and SDK examples for version {$version}.";
|
||||
|
||||
$prCommand = 'cd ' . $target . ' && \
|
||||
gh pr create \
|
||||
--repo "' . $gitRepoName . '" \
|
||||
--title "' . $prTitle . '" \
|
||||
--body "' . $prBody . '" \
|
||||
--base "' . $repoBranch . '" \
|
||||
--head "' . $gitBranch . '" \
|
||||
2>&1';
|
||||
|
||||
$prUrl = '';
|
||||
\exec($prCommand, $prOutput);
|
||||
$prOutput = \implode("\n", $prOutput);
|
||||
|
||||
if (\str_contains($prOutput, 'already exists')) {
|
||||
Console::warning("PR already exists for branch {$gitBranch}");
|
||||
// Try to get the existing PR URL
|
||||
\exec('cd ' . $target . ' && gh pr view --repo "' . $gitRepoName . '" --json url -q .url 2>&1', $existingPrOutput);
|
||||
$prUrl = \trim(\implode("\n", $existingPrOutput));
|
||||
} else {
|
||||
$prUrl = \trim($prOutput);
|
||||
}
|
||||
|
||||
// Clean up temp directory
|
||||
\exec('chmod -R u+w ' . $target . ' && rm -rf ' . $target);
|
||||
Console::success("Removed temp directory '{$target}'");
|
||||
|
||||
if (!empty($prUrl)) {
|
||||
Console::log('');
|
||||
Console::log('Pull Request Summary');
|
||||
Console::log("Specs PR: {$prUrl}");
|
||||
Console::log('');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ use Appwrite\Event\Realtime;
|
||||
use Appwrite\Event\StatsUsage;
|
||||
use Appwrite\Extend\Exception;
|
||||
use Appwrite\Template\Template;
|
||||
use Utopia\Compression\Compression;
|
||||
use Utopia\Config\Config;
|
||||
use Utopia\Console;
|
||||
use Utopia\Database\Database;
|
||||
@@ -39,7 +40,6 @@ use Utopia\Migration\Sources\Supabase;
|
||||
use Utopia\Migration\Transfer;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Queue\Message;
|
||||
use Utopia\Storage\Compression\Compression;
|
||||
use Utopia\Storage\Device;
|
||||
use Utopia\System\System;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Appwrite\Utopia\Response\Model;
|
||||
|
||||
use Appwrite\Utopia\Response;
|
||||
use Appwrite\Utopia\Response\Model;
|
||||
use Utopia\Storage\Compression\Compression;
|
||||
use Utopia\Compression\Compression;
|
||||
|
||||
class Bucket extends Model
|
||||
{
|
||||
|
||||
@@ -4,8 +4,8 @@ namespace Appwrite\Utopia\Response\Model;
|
||||
|
||||
use Appwrite\Utopia\Response;
|
||||
use Appwrite\Utopia\Response\Model;
|
||||
use Utopia\Compression\Compression;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Storage\Compression\Compression;
|
||||
|
||||
class File extends Model
|
||||
{
|
||||
|
||||
@@ -283,6 +283,12 @@ class Project extends Model
|
||||
'example' => ['vip'],
|
||||
'array' => true,
|
||||
])
|
||||
->addRule('status', [
|
||||
'type' => self::TYPE_STRING,
|
||||
'description' => 'Project status.',
|
||||
'default' => 'active',
|
||||
'example' => 'active',
|
||||
])
|
||||
;
|
||||
|
||||
$services = Config::getParam('services', []);
|
||||
|
||||
@@ -57,6 +57,7 @@ class ProjectsConsoleClientTest extends Scope
|
||||
$this->assertNotEmpty($response['body']['$id']);
|
||||
$this->assertEquals('Project Test', $response['body']['name']);
|
||||
$this->assertEquals($team['body']['$id'], $response['body']['teamId']);
|
||||
$this->assertEquals(PROJECT_STATUS_ACTIVE, $response['body']['status']);
|
||||
$this->assertArrayHasKey('platforms', $response['body']);
|
||||
$this->assertArrayHasKey('webhooks', $response['body']);
|
||||
$this->assertArrayHasKey('keys', $response['body']);
|
||||
@@ -76,6 +77,7 @@ class ProjectsConsoleClientTest extends Scope
|
||||
$this->assertNotEmpty($response['body']['$id']);
|
||||
$this->assertEquals('Project Test', $response['body']['name']);
|
||||
$this->assertEquals($team['body']['$id'], $response['body']['teamId']);
|
||||
$this->assertEquals(PROJECT_STATUS_ACTIVE, $response['body']['status']);
|
||||
$this->assertArrayHasKey('platforms', $response['body']);
|
||||
$this->assertArrayHasKey('webhooks', $response['body']);
|
||||
$this->assertArrayHasKey('keys', $response['body']);
|
||||
|
||||
@@ -19,7 +19,7 @@ webapp.com {
|
||||
|
||||
template IN CNAME {
|
||||
match "^stage-function\.webapp\.com\.$"
|
||||
answer "{{ .Name }} 60 IN CNAME functions.localhost."
|
||||
answer "{{ .Name }} 60 IN CNAME cname.localhost."
|
||||
fallthrough
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user