Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
9d57630
Add ServerClient to web SDK with type-gated admin methods
ChiragAgg5k Apr 27, 2026
e6a42d1
Validate web server SDK build
ChiragAgg5k Apr 30, 2026
c241caa
Unify web client auth factories
ChiragAgg5k Apr 30, 2026
d1823d7
Address web client review feedback
ChiragAgg5k Apr 30, 2026
32058bf
Fix web client setter runtime behavior
ChiragAgg5k Apr 30, 2026
c71be4a
Preserve fluent setter mutation behavior
ChiragAgg5k Apr 30, 2026
7b644b0
Treat dev keys as browser auth
ChiragAgg5k Apr 30, 2026
a4bd8ff
Avoid unused web auth type imports
ChiragAgg5k Apr 30, 2026
7225395
Allow dual-platform web auth methods
ChiragAgg5k Apr 30, 2026
071a493
Avoid unused auth imports in dual services
ChiragAgg5k Apr 30, 2026
dfc32b2
Restore console auth factory options
ChiragAgg5k May 4, 2026
bfbfb17
Rename web auth type aliases by platform
ChiragAgg5k May 4, 2026
e70155e
Remove client-platform web runtime fallback
ChiragAgg5k May 4, 2026
65137fe
Clean examples before generation
ChiragAgg5k May 4, 2026
3eba0b2
Rename browser client factory
ChiragAgg5k May 4, 2026
f699aef
Fix web client runtime default
ChiragAgg5k May 4, 2026
000b946
Treat web JWT auth as server auth
ChiragAgg5k May 4, 2026
8dded00
refactor(web): address review feedback on typed client
ChiragAgg5k May 4, 2026
51446b5
formatting
ChiragAgg5k May 4, 2026
1dc15b2
refactor(web): move auth detection and this-gate logic into Twig filters
ChiragAgg5k May 4, 2026
2b73513
formatting
ChiragAgg5k May 4, 2026
73f9020
refactor(web): consolidate auth tiers into ClientAuth and ServerAuth
ChiragAgg5k May 4, 2026
7d2e645
refactor(web): guard fromJWT to server/console + expose selfSigned param
ChiragAgg5k May 4, 2026
a47f9d7
refactor(web): spec-drive client config and auth setters
ChiragAgg5k May 4, 2026
8907d83
fix(web): drop duplicate forwardeduseragent setter on server build
ChiragAgg5k May 4, 2026
73f0a60
Preserve legacy web client setters
ChiragAgg5k May 6, 2026
1b06c8d
Merge remote-tracking branch 'origin/master' into feat/web-isomorphic…
ChiragAgg5k May 6, 2026
fd3a3a6
Hide unauthorized web service methods
ChiragAgg5k May 6, 2026
982a36c
Merge remote-tracking branch 'origin/master' into feat/web-isomorphic…
ChiragAgg5k May 6, 2026
23661a6
Hide internal web client helpers
ChiragAgg5k May 6, 2026
294cc8b
Remove web client header workaround
ChiragAgg5k May 6, 2026
5c7b728
Generate web client base params from headers
ChiragAgg5k May 6, 2026
8427261
Extract web client setter return types
ChiragAgg5k May 6, 2026
4cf2907
Update web test auth headers fixture
ChiragAgg5k May 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/sdk-build-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ jobs:
platform: client

# Server SDKs
- sdk: web
platform: server

- sdk: node
platform: server

Expand Down
153 changes: 153 additions & 0 deletions src/SDK/Language/Web.php
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,147 @@ public function getSubSchema(array $property, array $spec, string $methodName =
return $this->getTypeName($property);
}

/**
* Determine whether a method supports client-side platforms.
*/
protected function methodSupportsClient(array $method): bool
{
return in_array('client', $method['platforms'] ?? [], true);
}

/**
* Determine whether a method supports server/console platforms.
*/
protected function methodSupportsServer(array $method): bool
{
$platforms = $method['platforms'] ?? [];
return in_array('server', $platforms, true) || in_array('console', $platforms, true);
}

/**
* Compute auth-related flags for a Web service.
*
* @return array<string, mixed>
*/
public function webServiceAuth(array $service): array
{
$hasClientTier = false;
$hasServerTier = false;
$hasServerOnly = false;
$hasClientOnly = false;
$hasUpload = false;
$serverOnlyMethods = [];
$clientOnlyMethods = [];

foreach ($service['methods'] ?? [] as $method) {
$hasClient = $this->methodSupportsClient($method);
$hasServer = $this->methodSupportsServer($method);
$methodName = $this->toCamelCase($method['name'] ?? '');

if ($hasClient) {
$hasClientTier = true;
}
if ($hasServer) {
$hasServerTier = true;
}
if ($hasServer && !$hasClient) {
$hasServerOnly = true;
$serverOnlyMethods[] = $methodName;
}
if ($hasClient && !$hasServer) {
$hasClientOnly = true;
$clientOnlyMethods[] = $methodName;
}
if (in_array('multipart/form-data', $method['consumes'] ?? [], true)) {
$hasUpload = true;
}
}

$hasMixedTier = $hasClientTier && $hasServerTier;

return [
'hasClientTier' => $hasClientTier,
'hasServerTier' => $hasServerTier,
'hasMixedTier' => $hasMixedTier,
'needsServerAuth' => $hasServerTier && (!$hasMixedTier || $hasServerOnly),
'needsClientAuth' => $hasClientTier && (!$hasMixedTier || $hasClientOnly),
'hasUpload' => $hasUpload,
'serverOnlyMethods' => array_values(array_unique($serverOnlyMethods)),
'clientOnlyMethods' => array_values(array_unique($clientOnlyMethods)),
];
}

/**
* Build the TypeScript `this:` gate string for a method in a Web service.
*/
public function webMethodThisGate(array $method, array $service): string
{
$auth = $this->webServiceAuth($service);
if (!$auth['hasMixedTier']) {
return '';
}

$serviceName = $this->toPascalCase($service['name'] ?? '');

if (!$this->methodSupportsClient($method)) {
return 'this: ' . $serviceName . '<ServerAuth>, ';
}
if (!$this->methodSupportsServer($method)) {
return 'this: ' . $serviceName . '<ClientAuth>, ';
}

return '';
}

public function webClientBaseParams(array $headers): array
{
$params = [
'Project' => [
'name' => 'projectId',
'required' => true,
'setter' => 'setProject',
],
'Locale' => [
'name' => 'locale',
'required' => false,
'setter' => 'setLocale',
],
'Mode' => [
'name' => 'mode',
'required' => false,
'setter' => 'setMode',
],
'Platform' => [
'name' => 'platform',
'required' => false,
'setter' => 'setPlatform',
],
];

$baseParams = [];
foreach ($headers as $header) {
$key = $header['key'] ?? '';
if (isset($params[$key])) {
$baseParams[] = $params[$key];
}
}

return $baseParams;
}

public function webClientSetterReturnType(array $header): string
{
return match ($header['key'] ?? '') {
'Key' => "ClientRuntime<'apiKey'>",
'Cookie' => "ClientRuntime<'cookie'>",
'JWT' => "ClientRuntime<'jwt'>",
'Session' => "ClientRuntime<'session'>",
'DevKey' => "ClientRuntime<'devKey'>",
'ImpersonateUserId', 'ImpersonateUserEmail', 'ImpersonateUserPhone' => "ClientRuntime<'impersonation'>",
default => 'this',
};
}

public function getFilters(): array
{
return \array_merge(parent::getFilters(), [
Expand Down Expand Up @@ -536,6 +677,18 @@ public function getFilters(): array

return $condition;
}, ['is_safe' => ['html']]),
new TwigFilter('webServiceAuth', function (array $service) {
return $this->webServiceAuth($service);
}),
new TwigFilter('webMethodThisGate', function (array $method, array $service) {
return $this->webMethodThisGate($method, $service);
}, ['is_safe' => ['html']]),
new TwigFilter('webClientBaseParams', function (array $headers) {
return $this->webClientBaseParams($headers);
}),
new TwigFilter('webClientSetterReturnType', function (array $header) {
return $this->webClientSetterReturnType($header);
}, ['is_safe' => ['html']]),
new TwigFilter('comment2', function ($value) {
$value = explode("\n", $value);
foreach ($value as $key => $line) {
Expand Down
Loading
Loading