Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 3 additions & 1 deletion cli/cli/Services/Web/CodeGen/TsProperty.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using cli.Services.Web.Helpers;

namespace cli.Services.Web.CodeGen;

/// <summary>
Expand Down Expand Up @@ -148,7 +150,7 @@ public override void Write(TsCodeWriter writer)
if (Modifiers.HasFlag(TsModifier.Abstract))
writer.Write($"{TsModifierExtensions.Abstract} ");

writer.Write(Name);
writer.Write(StringHelper.QuoteIfNeeded(Name));

if (IsOptional)
writer.Write("?");
Expand Down
4 changes: 3 additions & 1 deletion cli/cli/Services/Web/CodeGen/TsType.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using cli.Services.Web.Helpers;

namespace cli.Services.Web.CodeGen;

/// <summary>
Expand Down Expand Up @@ -322,7 +324,7 @@ public override void Write(TsCodeWriter w)

for (int i = 0; i < _props.Length; i++)
{
w.Write(_props[i].name);
w.Write(StringHelper.QuoteIfNeeded(_props[i].name));

if (_props[i].propType == PropType.Optional)
w.Write("?");
Expand Down
1 change: 1 addition & 0 deletions cli/cli/Services/Web/Helpers/OpenApiMethodNameGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ private static string HttpVerbPrefix(string verb)
"POST" => "Post",
"PUT" => "Put",
"DELETE" => "Delete",
"PATCH" => "Patch",
_ => "Get"
};
}
13 changes: 13 additions & 0 deletions cli/cli/Services/Web/Helpers/StringHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,19 @@ public static string ToSafeIdentifier(string input)
return sanitized;
}

/// <summary>
/// Returns true if the input is NOT a valid unquoted TypeScript identifier.
/// </summary>
public static bool NeedsQuoting(string input)
=> string.IsNullOrEmpty(input) || !Regex.IsMatch(input, @"^[A-Za-z_$][A-Za-z0-9_$]*$");

/// <summary>
/// Returns the property name quoted if it contains characters invalid for
/// an unquoted TypeScript identifier, otherwise returns it as-is.
/// </summary>
public static string QuoteIfNeeded(string name)
=> NeedsQuoting(name) ? $"\"{name}\"" : name;

/// <summary>
/// Converts a string to a PascalCase identifier.
/// </summary>
Expand Down
6 changes: 5 additions & 1 deletion cli/cli/Services/Web/Helpers/WebApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ private static void GenerateApiMethod(OpenApiDocument document, Dictionary<strin
.Where(p => p.In == ParameterLocation.Header)
// Exclude 'X-BEAM-SCOPE' header; it is set by default via the Beam Web SDK.
.Where(p => p.Name != "X-BEAM-SCOPE")
// Only include headers that makeApiRequest supports (currently just X-BEAM-GAMERTAG).
.Where(p => p.Name == "X-BEAM-GAMERTAG")
.ToList();

foreach (var (httpMethod, operation) in pathItem.Operations)
Expand Down Expand Up @@ -247,7 +249,9 @@ private static (bool requiresAuth, string requiresAuthRemarks) DetermineAuth(
var requiresAuth = !serviceType.Equals("basic", StringComparison.InvariantCultureIgnoreCase) ||
serviceName.Contains("inventory", StringComparison.InvariantCultureIgnoreCase) ||
(operation.Security.Count >= 1 &&
operation.Security[0].Any(kvp => kvp.Key.Reference.Id == "user"));
operation.Security[0].Any(kvp =>
kvp.Key.Reference?.Id is "user" or "auth" ||
kvp.Key.Scheme?.Equals("bearer", StringComparison.OrdinalIgnoreCase) == true));
var remarks = requiresAuth
? "@remarks\n**Authentication:**\nThis method requires a valid bearer token in the `Authorization` header.\n\n"
: string.Empty;
Expand Down
21 changes: 21 additions & 0 deletions web/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,27 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- Web SDK: `codegen` script in `package.json` to regenerate TypeScript API types from OpenAPI specs via the CLI.
- Web SDK: New generated APIs: `BillingApi`, `CustomerApi`, `PlayerSessionApi`, `PlayerStatsApi`.
- Web SDK: `BeamWebSocket` now sends a `session-start` frame as the first message after connecting, carrying device and platform info that browsers cannot set via WebSocket upgrade headers.

### Fixed

- Web SDK: Code generator now quotes TypeScript property names that contain invalid identifier characters (e.g., `x5t#S256`).
- Web SDK: Code generator now produces distinct method names for PATCH endpoints instead of colliding with GET.
- `tsdown.config.ts` updated to use `import.meta.url` instead of `__dirname` for ES module compatibility.
- Web SDK: Code generator now correctly emits `w: true` (auth flag) for endpoints that require a bearer token. Previously, after the `ForcePlayerScopedAuth` OpenAPI processor renamed the security scheme from `user` to `auth` and `Reserailize` stripped reference info, `DetermineAuth` failed to detect auth requirements for all `basic` service endpoints — causing the SDK to omit the `Authorization` header on calls like `GET /basic/accounts/me`.
- Web SDK: HTTP response parsing now preserves precision for int64 values (e.g., player IDs, gamer tags). Previously `JSON.parse` rounded large integers before the reviver could convert them to `BigInt`, producing incorrect IDs like `70820408384930820` instead of `70820408384930816`. A new `BeamJsonUtils.parse` pre-quotes integers >10 digits before parsing so they reach the reviver as strings.

### Changed

- Web SDK: Updated auto-generated APIs and schemas to latest OpenAPI specs.
- Web SDK: Web code generator now only emits header parameters that `makeApiRequest` actually supports (currently `X-BEAM-GAMERTAG`); unsupported headers like `X-BEAM-TIMEOUT` are no longer added to generated method signatures.

## [1.0.0] - 2025-11-19

### Added
Expand Down
1 change: 1 addition & 0 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"test": "vitest",
"lint": "eslint --ext .ts src tests",
"format": "prettier --write .",
"codegen": "WEB_DIR=$PWD && cd \"$WEB_DIR/..\" && [ -f build-number.txt ] || echo 0 > build-number.txt && dotnet run -f net10.0 --project ./cli/cli -- --host https://dev.api.beamable.com oapi generate --engine web --conflict-strategy RenameUncommonConflicts --output \"$WEB_DIR/src/__generated__\"",
"doc": "node ./generateDocs.mjs",
"release": "node ./update-version.mjs && pnpm build",
"prepublishOnly": "pnpm build"
Expand Down
5 changes: 3 additions & 2 deletions web/samples/WordWiz/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,6 @@
"vite-plugin-mkcert": "^1.17.8",
"vite-tsconfig-paths": "^5.1.4",
"vitest": "^3.2.4"
}
}
},
"packageManager": "pnpm@10.33.0"
}
Loading
Loading