mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
feat(sdks): add isomorphic spec platform
Adds an `isomorphic` virtual SDK platform whose spec is the union of the `client` and `server` specs. Lets a single SDK release (e.g. the web SDK) surface methods from both runtimes — including ones that are hidden from the `server` spec or auth-excluded from it. - `APP_SDK_PLATFORM_ISOMORPHIC` constant - Specs.php emits `swagger2-<v>-isomorphic.json` (and OpenAPI3) using a union filter; `getKeys()` / `getAuthCounts()` extended accordingly - SDKs.php honors an optional `specPlatform` per-SDK config override so a server-family SDK can point at the isomorphic spec - Format/Swagger2 + OpenAPI3 use a shared `effectivePlatforms()` helper so the additional-methods filter expands isomorphic to client+server, preserving rename pairs like `createMfaAuthenticator` ↔ `createMFAAuthenticator`
This commit is contained in:
@@ -103,6 +103,7 @@ const APP_SDK_PLATFORM_SERVER = 'server';
|
||||
const APP_SDK_PLATFORM_CLIENT = 'client';
|
||||
const APP_SDK_PLATFORM_CONSOLE = 'console';
|
||||
const APP_SDK_PLATFORM_STATIC = 'static';
|
||||
const APP_SDK_PLATFORM_ISOMORPHIC = 'isomorphic';
|
||||
const APP_VCS_GITHUB_USERNAME = 'Appwrite';
|
||||
const APP_VCS_GITHUB_EMAIL = 'team@appwrite.io';
|
||||
const APP_VCS_GITHUB_URL = 'https://github.com/TeamAppwrite';
|
||||
|
||||
@@ -308,7 +308,8 @@ class SDKs extends Action
|
||||
} else {
|
||||
Console::log(' Fetching API spec...');
|
||||
|
||||
$specPath = __DIR__ . '/../../../../app/config/specs/swagger2-' . $version . '-' . $language['family'] . '.json';
|
||||
$specPlatform = $language['specPlatform'] ?? $language['family'];
|
||||
$specPath = __DIR__ . '/../../../../app/config/specs/swagger2-' . $version . '-' . $specPlatform . '.json';
|
||||
|
||||
if (!file_exists($specPath)) {
|
||||
throw new \Exception('Spec file not found: ' . $specPath . '. Please run "docker compose exec appwrite specs --version=' . $version . '" first to generate the specs.');
|
||||
|
||||
@@ -79,9 +79,28 @@ class Specs extends Action
|
||||
APP_SDK_PLATFORM_CLIENT,
|
||||
APP_SDK_PLATFORM_SERVER,
|
||||
APP_SDK_PLATFORM_CONSOLE,
|
||||
APP_SDK_PLATFORM_ISOMORPHIC,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Real platforms whose filters apply to a given (possibly virtual) platform.
|
||||
*
|
||||
* The isomorphic platform is a virtual union of `client` and `server` — its spec includes
|
||||
* any route or service that would normally be emitted in either platform's spec. All other
|
||||
* platforms map to themselves.
|
||||
*
|
||||
* @return array<string>
|
||||
*/
|
||||
private static function effectivePlatformsFor(string $platform): array
|
||||
{
|
||||
if ($platform === APP_SDK_PLATFORM_ISOMORPHIC) {
|
||||
return [APP_SDK_PLATFORM_CLIENT, APP_SDK_PLATFORM_SERVER];
|
||||
}
|
||||
|
||||
return [$platform];
|
||||
}
|
||||
|
||||
/**
|
||||
* Platforms to include in PR creation.
|
||||
* Override in a subclass to exclude specific platforms.
|
||||
@@ -121,6 +140,7 @@ class Specs extends Action
|
||||
'client' => 1,
|
||||
'server' => 2,
|
||||
'console' => 1,
|
||||
APP_SDK_PLATFORM_ISOMORPHIC => 1,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -131,7 +151,7 @@ class Specs extends Action
|
||||
*/
|
||||
protected function getKeys(): array
|
||||
{
|
||||
return [
|
||||
$keys = [
|
||||
APP_SDK_PLATFORM_CLIENT => [
|
||||
'Project' => [
|
||||
'type' => 'apiKey',
|
||||
@@ -325,6 +345,12 @@ class Specs extends Action
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
// Isomorphic platform shares the auth surface of both client and server runtimes; the
|
||||
// generated SDK picks one auth path at construction time via its factories.
|
||||
$keys[APP_SDK_PLATFORM_ISOMORPHIC] = $keys[APP_SDK_PLATFORM_CLIENT] + $keys[APP_SDK_PLATFORM_SERVER];
|
||||
|
||||
return $keys;
|
||||
}
|
||||
|
||||
protected function verifyParsedSpec(array $spec): void
|
||||
@@ -542,6 +568,7 @@ class Specs extends Action
|
||||
$routes = [];
|
||||
$models = [];
|
||||
$services = [];
|
||||
$effectivePlatforms = static::effectivePlatformsFor($platform);
|
||||
|
||||
foreach ($appRoutes as $key => $method) {
|
||||
foreach ($method as $route) {
|
||||
@@ -559,7 +586,10 @@ class Specs extends Action
|
||||
/** @var Method $sdk */
|
||||
$hide = $sdk->isHidden();
|
||||
|
||||
if ($hide === true || (\is_array($hide) && \in_array($platform, $hide))) {
|
||||
// A method is hidden from a (possibly virtual) platform when it is hidden
|
||||
// from every real platform that platform expands to. For real platforms
|
||||
// this matches the legacy single-element check.
|
||||
if ($hide === true || (\is_array($hide) && empty(\array_diff($effectivePlatforms, $hide)))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -582,7 +612,7 @@ class Specs extends Action
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!\in_array($platform, $sdkPlatforms)) {
|
||||
if (empty(\array_intersect($effectivePlatforms, $sdkPlatforms))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -601,8 +631,8 @@ class Specs extends Action
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if current platform is included in service's platforms
|
||||
if (!\in_array($platform, $service['platforms'] ?? [])) {
|
||||
// Check if any effective platform is included in service's platforms
|
||||
if (empty(\array_intersect($effectivePlatforms, $service['platforms'] ?? []))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -125,6 +125,22 @@ abstract class Format
|
||||
$this->enumBlacklist = $this->buildEnumBlacklist();
|
||||
}
|
||||
|
||||
/**
|
||||
* Real platforms whose filters apply to this (possibly virtual) format platform.
|
||||
*
|
||||
* The isomorphic platform expands to client + server; all others map to themselves.
|
||||
*
|
||||
* @return array<string>
|
||||
*/
|
||||
protected function effectivePlatforms(): array
|
||||
{
|
||||
if ($this->platform === APP_SDK_PLATFORM_ISOMORPHIC) {
|
||||
return [APP_SDK_PLATFORM_CLIENT, APP_SDK_PLATFORM_SERVER];
|
||||
}
|
||||
|
||||
return [$this->platform];
|
||||
}
|
||||
|
||||
protected function buildEnumBlacklist(): array
|
||||
{
|
||||
$blacklist = [];
|
||||
|
||||
@@ -172,7 +172,7 @@ class OpenAPI3 extends Format
|
||||
$methodSecurities = $methodObj->getAuth();
|
||||
$methodSdkPlatforms = $specs->getSDKPlatformsForRouteSecurity($methodSecurities);
|
||||
|
||||
if (!\in_array($this->platform, $methodSdkPlatforms)) {
|
||||
if (empty(\array_intersect($this->effectivePlatforms(), $methodSdkPlatforms))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ class Swagger2 extends Format
|
||||
$methodSecurities = $methodObj->getAuth();
|
||||
$methodSdkPlatforms = $specs->getSDKPlatformsForRouteSecurity($methodSecurities);
|
||||
|
||||
if (!\in_array($this->platform, $methodSdkPlatforms)) {
|
||||
if (empty(\array_intersect($this->effectivePlatforms(), $methodSdkPlatforms))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user