Add ProjectStorageDomain with projectStorage sync
CI / check (push) Successful in 48s

This commit is contained in:
edmand46
2026-08-12 23:58:30 +03:00
parent 3ab2d4a6cf
commit fd364fd156
6 changed files with 80 additions and 0 deletions
+5
View File
@@ -35,6 +35,7 @@ import { CatalogDomain } from '../domains/CatalogDomain.js';
import { InventoryDomain } from '../domains/InventoryDomain.js';
import { ConfigDomain } from '../domains/ConfigDomain.js';
import { StorageDomain } from '../domains/StorageDomain.js';
import { ProjectStorageDomain } from '../domains/ProjectStorageDomain.js';
import { StoresDomain } from '../domains/StoresDomain.js';
/** A domain the client can bulk-invalidate (re-login) or reset (logout). */
@@ -55,6 +56,7 @@ export class RudderClient<TConfig extends RemoteConfigShape = RemoteConfigShape>
public readonly inventory: InventoryDomain;
public readonly remoteConfig: ConfigDomain<TConfig>;
public readonly storage: StorageDomain;
public readonly projectStorage: ProjectStorageDomain;
public readonly stores: StoresDomain;
private readonly effectsCenter: EffectsCenter;
@@ -109,6 +111,7 @@ export class RudderClient<TConfig extends RemoteConfigShape = RemoteConfigShape>
this.inventory = new InventoryDomain(ctx, this.catalog);
this.remoteConfig = new ConfigDomain<TConfig>(ctx);
this.storage = new StorageDomain(ctx);
this.projectStorage = new ProjectStorageDomain(ctx);
this.stores = new StoresDomain(ctx, () => {
this.player.invalidate();
this.inventory.invalidate();
@@ -124,6 +127,7 @@ export class RudderClient<TConfig extends RemoteConfigShape = RemoteConfigShape>
this.inventory,
this.remoteConfig,
this.storage,
this.projectStorage,
this.stores,
]);
this.auth = new AuthService<TConfig>(
@@ -231,6 +235,7 @@ export class RudderClient<TConfig extends RemoteConfigShape = RemoteConfigShape>
this.inventory,
this.remoteConfig,
this.storage,
this.projectStorage,
this.stores,
];
}
+26
View File
@@ -0,0 +1,26 @@
import { SyncedState } from '../state/SyncedState.js';
import type { RudderContext } from '../core/context.js';
import { api } from '../generated/api.js';
import type {
GetProjectStorageResponse,
ProjectStorageUpdateItem,
} from '../generated/project-storage.js';
/**
* ProjectStorageDomain — project-wide key/value storage as an observable
* entity, plus its mutations. Synced under revision key `projectStorage`;
* mutations invalidate it so subscribers observe fresh data.
*/
export class ProjectStorageDomain extends SyncedState<GetProjectStorageResponse> {
readonly syncKey = 'projectStorage';
constructor(private readonly ctx: RudderContext) {
super(() => api.getProjectStorage(ctx, { limit: 100 }));
}
/** Saves project storage items, then invalidates. */
async save(items: ProjectStorageUpdateItem[]): Promise<void> {
await api.updateProjectStorage(this.ctx, { items });
this.invalidate();
}
}
+13
View File
@@ -6,6 +6,7 @@ import type { ListCatalogItemsResponse } from './catalog.js';
import type { GetInventoryResponse } from './inventory.js';
import type { GetRankingResponse, SubmitScoreRequest } from './leaderboards.js';
import type { PlayerProfile } from './player.js';
import type { GetProjectStorageResponse, UpdateProjectStorageRequest } from './project-storage.js';
import type { ClaimQuestRequest, ClaimQuestResponse, ListQuestsRequest, ListQuestsResponse } from './quests.js';
import type { ListRemoteConfigsResponse, RemoteConfig } from './remote-config.js';
import type { GetScenarioRunRequest, GetScenarioRunResponse, HandleScenarioCallbackRequest, HandleScenarioCallbackResponse, TriggerScenarioRequest, TriggerScenarioResponse, UpdateScenarioCounterRequest, UpdateScenarioCounterResponse } from './scenarios.js';
@@ -88,6 +89,12 @@ export const api = {
): Promise<PlayerProfile> =>
t.request<PlayerProfile>('GET', '/sdk/v1/player/information'),
getProjectStorage: (
t: Transport,
query?: { types?: string; limit?: number; cursor?: string },
): Promise<GetProjectStorageResponse> =>
t.request<GetProjectStorageResponse>('GET', `/sdk/v1/project-storage${qs([['types', query?.types], ['limit', query?.limit], ['cursor', query?.cursor]])}`),
getRanking: (
t: Transport,
path: { slug: string },
@@ -213,6 +220,12 @@ export const api = {
): Promise<TriggerScenarioResponse> =>
t.request<TriggerScenarioResponse>('POST', '/sdk/v1/scenarios/trigger', body),
updateProjectStorage: (
t: Transport,
body: UpdateProjectStorageRequest,
): Promise<void> =>
t.request<void>('PUT', '/sdk/v1/project-storage', body),
updateScenarioCounter: (
t: Transport,
body: UpdateScenarioCounterRequest,
+1
View File
@@ -7,6 +7,7 @@ export * from './common.js';
export * from './inventory.js';
export * from './leaderboards.js';
export * from './player.js';
export * from './project-storage.js';
export * from './quests.js';
export * from './remote-config.js';
export * from './scenarios.js';
+29
View File
@@ -0,0 +1,29 @@
// Code generated by apigen. DO NOT EDIT.
export interface GetProjectStorageResponse {
"items"?: ProjectStorageItem[];
"nextCursor"?: string;
}
export interface ProjectStorageItem {
"data"?: string;
"expiresAt"?: string;
"id"?: string;
"readPermission"?: "public" | "serverOnly";
"size"?: number;
"type"?: string;
"updatedAt"?: string;
"version"?: number;
"writePermission"?: "public" | "serverOnly";
}
export interface ProjectStorageUpdateItem {
"data"?: string;
"type"?: string;
}
export interface UpdateProjectStorageRequest {
"idempotencyKey"?: string;
"items"?: ProjectStorageUpdateItem[];
}
+6
View File
@@ -48,6 +48,7 @@ export type { CatalogDomain } from './domains/CatalogDomain.js';
export type { InventoryDomain } from './domains/InventoryDomain.js';
export type { ConfigDomain } from './domains/ConfigDomain.js';
export type { StorageDomain } from './domains/StorageDomain.js';
export type { ProjectStorageDomain } from './domains/ProjectStorageDomain.js';
export type { StoresDomain } from './domains/StoresDomain.js';
// Effects
@@ -80,6 +81,11 @@ export type {
} from './generated/stores.js';
export type { RankEntry } from './generated/leaderboards.js';
export type { StorageItem, GetStorageResponse } from './generated/storage.js';
export type {
ProjectStorageItem,
GetProjectStorageResponse,
ProjectStorageUpdateItem,
} from './generated/project-storage.js';
export type { RemoteConfig } from './generated/remote-config.js';
export type {
Quest,