dreamboard 0.1.25 → 0.1.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-H3O43F5P.js → chunk-3JGO32FA.js} +1229 -348
- package/dist/chunk-3JGO32FA.js.map +1 -0
- package/dist/{chunk-MG6EVR7P.js → chunk-VRJ4FOH2.js} +1898 -519
- package/dist/chunk-VRJ4FOH2.js.map +1 -0
- package/dist/{chunk-2RCUHMGL.js → chunk-YI5DUODD.js} +191 -61
- package/dist/chunk-YI5DUODD.js.map +1 -0
- package/dist/dev-host/dev-api-proxy-plugin.ts +27 -1
- package/dist/dev-host/dev-author-dom-warnings.ts +101 -0
- package/dist/dev-host/dev-hmr-guard-plugin.ts +47 -0
- package/dist/dev-host/dev-host-controller.ts +21 -5
- package/dist/dev-host/host-main.css +131 -89
- package/dist/dev-host/host-main.tsx +320 -136
- package/dist/dev-host/plugin-main.ts +9 -3
- package/dist/dev-host/start-dev-server.ts +2 -0
- package/dist/{dist-FRURQI7Q.js → dist-JNA2CLKS.js} +2 -2
- package/dist/{dist-FEPN3BDN.js → dist-JO2OGKJD.js} +35 -15
- package/dist/dist-JO2OGKJD.js.map +1 -0
- package/dist/index.js +3 -3
- package/dist/internal.js +142 -53
- package/dist/internal.js.map +1 -1
- package/dist/runtime-packages/ui-host-runtime/src/session-ingress-controller.ts +20 -9
- package/package.json +3 -3
- package/dist/chunk-2RCUHMGL.js.map +0 -1
- package/dist/chunk-H3O43F5P.js.map +0 -1
- package/dist/chunk-MG6EVR7P.js.map +0 -1
- package/dist/dist-FEPN3BDN.js.map +0 -1
- /package/dist/{dist-FRURQI7Q.js.map → dist-JNA2CLKS.js.map} +0 -0
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
} from "./chunk-4S67A2YA.js";
|
|
33
33
|
import {
|
|
34
34
|
createClient
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-3JGO32FA.js";
|
|
36
36
|
import {
|
|
37
37
|
CLIENT_PROBLEM_TYPES,
|
|
38
38
|
SERVER_PROBLEM_TYPES,
|
|
@@ -72,7 +72,7 @@ import {
|
|
|
72
72
|
validatePlayerAction,
|
|
73
73
|
zGameTopologyManifest,
|
|
74
74
|
zProblemDetails
|
|
75
|
-
} from "./chunk-
|
|
75
|
+
} from "./chunk-YI5DUODD.js";
|
|
76
76
|
import {
|
|
77
77
|
__export
|
|
78
78
|
} from "./chunk-D4HDZEJT.js";
|
|
@@ -1660,6 +1660,7 @@ function normalizeProjectConfig(config) {
|
|
|
1660
1660
|
return {
|
|
1661
1661
|
gameId: config.gameId,
|
|
1662
1662
|
slug: config.slug,
|
|
1663
|
+
environment: config.environment,
|
|
1663
1664
|
authoring: config.authoring,
|
|
1664
1665
|
compile: config.compile,
|
|
1665
1666
|
localMaintainerRegistry: config.localMaintainerRegistry,
|
|
@@ -1859,6 +1860,191 @@ function getAccessTokenExpiry(accessToken) {
|
|
|
1859
1860
|
}
|
|
1860
1861
|
}
|
|
1861
1862
|
|
|
1863
|
+
// src/auth/local-dev-session.ts
|
|
1864
|
+
var DEFAULT_DEV_EMAIL = "test@test.com";
|
|
1865
|
+
var DEFAULT_DEV_PASSWORD = "dreamboard-local-dev-password";
|
|
1866
|
+
var DEFAULT_LOCAL_SERVICE_ROLE_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU";
|
|
1867
|
+
async function repairLocalDevSession() {
|
|
1868
|
+
const localConfig = ENVIRONMENT_CONFIGS.local;
|
|
1869
|
+
if (!localConfig?.supabaseUrl || !localConfig.supabaseAnonKey) {
|
|
1870
|
+
return null;
|
|
1871
|
+
}
|
|
1872
|
+
if (!isLocalSupabaseUrl(localConfig.supabaseUrl)) {
|
|
1873
|
+
return null;
|
|
1874
|
+
}
|
|
1875
|
+
const email = valueOrUndefined(process.env.DREAMBOARD_DEV_EMAIL) ?? DEFAULT_DEV_EMAIL;
|
|
1876
|
+
const password = valueOrUndefined(process.env.DREAMBOARD_DEV_PASSWORD) ?? DEFAULT_DEV_PASSWORD;
|
|
1877
|
+
const serviceRoleKey = valueOrUndefined(process.env.SUPABASE_SERVICE_ROLE_KEY) ?? valueOrUndefined(process.env.DREAMBOARD_LOCAL_SUPABASE_SERVICE_ROLE_KEY) ?? DEFAULT_LOCAL_SERVICE_ROLE_KEY;
|
|
1878
|
+
const authBaseUrl = `${localConfig.supabaseUrl.replace(/\/$/, "")}/auth/v1`;
|
|
1879
|
+
const authHeaders = {
|
|
1880
|
+
apikey: localConfig.supabaseAnonKey,
|
|
1881
|
+
"Content-Type": "application/json"
|
|
1882
|
+
};
|
|
1883
|
+
const adminHeaders = {
|
|
1884
|
+
apikey: serviceRoleKey,
|
|
1885
|
+
Authorization: `Bearer ${serviceRoleKey}`,
|
|
1886
|
+
"Content-Type": "application/json"
|
|
1887
|
+
};
|
|
1888
|
+
let session = await signIn({
|
|
1889
|
+
authBaseUrl,
|
|
1890
|
+
headers: authHeaders,
|
|
1891
|
+
email,
|
|
1892
|
+
password
|
|
1893
|
+
});
|
|
1894
|
+
if (!session) {
|
|
1895
|
+
await ensureLocalUser({
|
|
1896
|
+
authBaseUrl,
|
|
1897
|
+
headers: adminHeaders,
|
|
1898
|
+
email,
|
|
1899
|
+
password
|
|
1900
|
+
});
|
|
1901
|
+
session = await signIn({
|
|
1902
|
+
authBaseUrl,
|
|
1903
|
+
headers: authHeaders,
|
|
1904
|
+
email,
|
|
1905
|
+
password
|
|
1906
|
+
});
|
|
1907
|
+
}
|
|
1908
|
+
if (!session?.access_token || !session.refresh_token) {
|
|
1909
|
+
return null;
|
|
1910
|
+
}
|
|
1911
|
+
const credentials = {
|
|
1912
|
+
accessToken: session.access_token,
|
|
1913
|
+
refreshToken: session.refresh_token
|
|
1914
|
+
};
|
|
1915
|
+
await setCredentials(credentials);
|
|
1916
|
+
const globalConfig = await loadGlobalConfig();
|
|
1917
|
+
await saveGlobalConfig({
|
|
1918
|
+
...globalConfig,
|
|
1919
|
+
environment: "local"
|
|
1920
|
+
});
|
|
1921
|
+
return credentials;
|
|
1922
|
+
}
|
|
1923
|
+
function shouldRepairLocalDevSession(options) {
|
|
1924
|
+
const localConfig = ENVIRONMENT_CONFIGS.local;
|
|
1925
|
+
if (!localConfig) {
|
|
1926
|
+
return false;
|
|
1927
|
+
}
|
|
1928
|
+
return Boolean(options.supabaseUrl && isLocalSupabaseUrl(options.supabaseUrl)) && options.apiBaseUrl === localConfig.apiBaseUrl;
|
|
1929
|
+
}
|
|
1930
|
+
async function signIn(options) {
|
|
1931
|
+
const response = await postAuth(options, "/token?grant_type=password", {
|
|
1932
|
+
email: options.email,
|
|
1933
|
+
password: options.password
|
|
1934
|
+
});
|
|
1935
|
+
return response.ok ? response.data : null;
|
|
1936
|
+
}
|
|
1937
|
+
async function ensureLocalUser(options) {
|
|
1938
|
+
const existing = await findAdminUserByEmail(options);
|
|
1939
|
+
if (existing?.id) {
|
|
1940
|
+
await updateAdminUser(options, existing.id);
|
|
1941
|
+
return;
|
|
1942
|
+
}
|
|
1943
|
+
const created = await adminFetch(options, "/admin/users", {
|
|
1944
|
+
method: "POST",
|
|
1945
|
+
body: JSON.stringify({
|
|
1946
|
+
email: options.email,
|
|
1947
|
+
password: options.password,
|
|
1948
|
+
email_confirm: true,
|
|
1949
|
+
user_metadata: {
|
|
1950
|
+
display_name: "Dreamboard Local Dev"
|
|
1951
|
+
}
|
|
1952
|
+
})
|
|
1953
|
+
});
|
|
1954
|
+
if (created.ok) {
|
|
1955
|
+
return;
|
|
1956
|
+
}
|
|
1957
|
+
const retried = await findAdminUserByEmail(options);
|
|
1958
|
+
if (retried?.id) {
|
|
1959
|
+
await updateAdminUser(options, retried.id);
|
|
1960
|
+
return;
|
|
1961
|
+
}
|
|
1962
|
+
throw new Error(
|
|
1963
|
+
`Failed to create local Supabase user ${options.email} (${created.status}): ${JSON.stringify(
|
|
1964
|
+
created.data
|
|
1965
|
+
)}`
|
|
1966
|
+
);
|
|
1967
|
+
}
|
|
1968
|
+
async function updateAdminUser(options, userId) {
|
|
1969
|
+
const updated = await adminFetch(
|
|
1970
|
+
options,
|
|
1971
|
+
`/admin/users/${encodeURIComponent(userId)}`,
|
|
1972
|
+
{
|
|
1973
|
+
method: "PUT",
|
|
1974
|
+
body: JSON.stringify({
|
|
1975
|
+
password: options.password,
|
|
1976
|
+
email_confirm: true,
|
|
1977
|
+
user_metadata: {
|
|
1978
|
+
display_name: "Dreamboard Local Dev"
|
|
1979
|
+
}
|
|
1980
|
+
})
|
|
1981
|
+
}
|
|
1982
|
+
);
|
|
1983
|
+
if (!updated.ok) {
|
|
1984
|
+
throw new Error(
|
|
1985
|
+
`Failed to update local Supabase user ${options.email} (${updated.status}): ${JSON.stringify(
|
|
1986
|
+
updated.data
|
|
1987
|
+
)}`
|
|
1988
|
+
);
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
async function findAdminUserByEmail(options) {
|
|
1992
|
+
const response = await adminFetch(
|
|
1993
|
+
options,
|
|
1994
|
+
"/admin/users?page=1&per_page=200",
|
|
1995
|
+
{
|
|
1996
|
+
method: "GET"
|
|
1997
|
+
}
|
|
1998
|
+
);
|
|
1999
|
+
if (!response.ok) {
|
|
2000
|
+
throw new Error(
|
|
2001
|
+
`Failed to list local Supabase users (${response.status}): ${JSON.stringify(
|
|
2002
|
+
response.data
|
|
2003
|
+
)}`
|
|
2004
|
+
);
|
|
2005
|
+
}
|
|
2006
|
+
const users = response.data?.users ?? [];
|
|
2007
|
+
return users.find(
|
|
2008
|
+
(user) => user.email?.toLowerCase() === options.email.toLowerCase()
|
|
2009
|
+
) ?? null;
|
|
2010
|
+
}
|
|
2011
|
+
async function postAuth(options, path29, body) {
|
|
2012
|
+
const response = await fetch(`${options.authBaseUrl}${path29}`, {
|
|
2013
|
+
method: "POST",
|
|
2014
|
+
headers: options.headers,
|
|
2015
|
+
body: JSON.stringify(body)
|
|
2016
|
+
});
|
|
2017
|
+
return {
|
|
2018
|
+
ok: response.ok,
|
|
2019
|
+
status: response.status,
|
|
2020
|
+
data: await readJson(response)
|
|
2021
|
+
};
|
|
2022
|
+
}
|
|
2023
|
+
async function adminFetch(options, path29, init2) {
|
|
2024
|
+
const response = await fetch(`${options.authBaseUrl}${path29}`, {
|
|
2025
|
+
...init2,
|
|
2026
|
+
headers: options.headers
|
|
2027
|
+
});
|
|
2028
|
+
return {
|
|
2029
|
+
ok: response.ok,
|
|
2030
|
+
status: response.status,
|
|
2031
|
+
data: await readJson(response)
|
|
2032
|
+
};
|
|
2033
|
+
}
|
|
2034
|
+
async function readJson(response) {
|
|
2035
|
+
const text = await response.text();
|
|
2036
|
+
if (text.trim().length === 0) return null;
|
|
2037
|
+
return JSON.parse(text);
|
|
2038
|
+
}
|
|
2039
|
+
function isLocalSupabaseUrl(rawUrl) {
|
|
2040
|
+
const url = new URL(rawUrl);
|
|
2041
|
+
return url.hostname === "127.0.0.1" || url.hostname === "localhost";
|
|
2042
|
+
}
|
|
2043
|
+
function valueOrUndefined(value) {
|
|
2044
|
+
const trimmed = value?.trim();
|
|
2045
|
+
return trimmed && trimmed.length > 0 ? trimmed : void 0;
|
|
2046
|
+
}
|
|
2047
|
+
|
|
1862
2048
|
// src/config/resolve.ts
|
|
1863
2049
|
var LOGIN_HINT = "Run `dreamboard login` to authenticate again.";
|
|
1864
2050
|
function resolveConfig(globalConfig, flags, project, credentials) {
|
|
@@ -1866,14 +2052,15 @@ function resolveConfig(globalConfig, flags, project, credentials) {
|
|
|
1866
2052
|
assertPublicRuntimeFlags(flags);
|
|
1867
2053
|
}
|
|
1868
2054
|
const envEnvironment = IS_PUBLISHED_BUILD ? void 0 : environmentFromProcess();
|
|
1869
|
-
const
|
|
2055
|
+
const projectEnvironment = IS_PUBLISHED_BUILD ? void 0 : project?.environment;
|
|
2056
|
+
const environment = IS_PUBLISHED_BUILD ? PUBLISHED_ENVIRONMENT : flags.env || envEnvironment || projectEnvironment || globalConfig.environment || "dev";
|
|
1870
2057
|
const envConfig = ENVIRONMENT_CONFIGS[environment];
|
|
1871
2058
|
const publishedEnvConfig = ENVIRONMENT_CONFIGS[PUBLISHED_ENVIRONMENT];
|
|
1872
|
-
const hasExplicitEnvironmentOverride = !IS_PUBLISHED_BUILD && Boolean(flags.env || envEnvironment);
|
|
2059
|
+
const hasExplicitEnvironmentOverride = !IS_PUBLISHED_BUILD && Boolean(flags.env || envEnvironment || projectEnvironment);
|
|
1873
2060
|
const resolvedApiBaseUrl = IS_PUBLISHED_BUILD ? publishedEnvConfig?.apiBaseUrl ?? DEFAULT_API_BASE_URL : hasExplicitEnvironmentOverride ? envConfig?.apiBaseUrl || DEFAULT_API_BASE_URL : project?.apiBaseUrl || envConfig?.apiBaseUrl || DEFAULT_API_BASE_URL;
|
|
1874
|
-
const apiBaseUrl =
|
|
2061
|
+
const apiBaseUrl = valueOrUndefined2(process.env.DREAMBOARD_API_BASE_URL) ?? resolvedApiBaseUrl;
|
|
1875
2062
|
const resolvedWebBaseUrl = IS_PUBLISHED_BUILD ? publishedEnvConfig?.webBaseUrl ?? DEFAULT_WEB_BASE_URL : hasExplicitEnvironmentOverride ? envConfig?.webBaseUrl || DEFAULT_WEB_BASE_URL : project?.webBaseUrl || envConfig?.webBaseUrl || DEFAULT_WEB_BASE_URL;
|
|
1876
|
-
const webBaseUrl =
|
|
2063
|
+
const webBaseUrl = valueOrUndefined2(process.env.DREAMBOARD_WEB_BASE_URL) ?? resolvedWebBaseUrl;
|
|
1877
2064
|
const supabaseUrl = envConfig?.supabaseUrl;
|
|
1878
2065
|
const supabaseAnonKey = envConfig?.supabaseAnonKey;
|
|
1879
2066
|
const snapshot = buildCredentialSnapshot(flags, credentials);
|
|
@@ -1889,10 +2076,10 @@ function resolveConfig(globalConfig, flags, project, credentials) {
|
|
|
1889
2076
|
};
|
|
1890
2077
|
}
|
|
1891
2078
|
function buildCredentialSnapshot(flags, storedCredentials) {
|
|
1892
|
-
const flagToken =
|
|
1893
|
-
const agentEnvToken =
|
|
1894
|
-
const envToken =
|
|
1895
|
-
const envRefreshToken =
|
|
2079
|
+
const flagToken = valueOrUndefined2(flags.token);
|
|
2080
|
+
const agentEnvToken = valueOrUndefined2(process.env.DREAMBOARD_AGENT_TOKEN);
|
|
2081
|
+
const envToken = valueOrUndefined2(process.env.DREAMBOARD_TOKEN);
|
|
2082
|
+
const envRefreshToken = valueOrUndefined2(
|
|
1896
2083
|
process.env.DREAMBOARD_REFRESH_TOKEN
|
|
1897
2084
|
);
|
|
1898
2085
|
if (IS_PUBLISHED_BUILD) {
|
|
@@ -1924,7 +2111,7 @@ function buildCredentialSnapshot(flags, storedCredentials) {
|
|
|
1924
2111
|
};
|
|
1925
2112
|
}
|
|
1926
2113
|
function environmentFromProcess() {
|
|
1927
|
-
const value =
|
|
2114
|
+
const value = valueOrUndefined2(process.env.DREAMBOARD_ENV);
|
|
1928
2115
|
if (!value) return void 0;
|
|
1929
2116
|
if (value === "local" || value === "dev" || value === "prod") {
|
|
1930
2117
|
return value;
|
|
@@ -1940,7 +2127,7 @@ function assertPublicRuntimeFlags(flags) {
|
|
|
1940
2127
|
"The published Dreamboard CLI is production-only and does not accept `--env`."
|
|
1941
2128
|
);
|
|
1942
2129
|
}
|
|
1943
|
-
if (
|
|
2130
|
+
if (valueOrUndefined2(flags.token) || argv2.includes("--token")) {
|
|
1944
2131
|
throw new Error(
|
|
1945
2132
|
"Direct JWT injection is not supported in the published Dreamboard CLI. Use `dreamboard login` so the CLI can store and refresh your session."
|
|
1946
2133
|
);
|
|
@@ -1981,6 +2168,12 @@ async function ensureEffectiveAccessToken(config) {
|
|
|
1981
2168
|
const expiry = getAccessTokenExpiry(config.authToken);
|
|
1982
2169
|
const isExpired = expiry !== null && expiry.getTime() <= Date.now();
|
|
1983
2170
|
if (isExpired) {
|
|
2171
|
+
if (shouldRepairLocalDevSession(config)) {
|
|
2172
|
+
const repaired = await repairLocalDevSession();
|
|
2173
|
+
if (repaired) {
|
|
2174
|
+
return repaired.accessToken;
|
|
2175
|
+
}
|
|
2176
|
+
}
|
|
1984
2177
|
throw new Error(
|
|
1985
2178
|
`Access token refresh failed: ${result.message}. ${LOGIN_HINT}`
|
|
1986
2179
|
);
|
|
@@ -1993,6 +2186,12 @@ async function ensureEffectiveAccessToken(config) {
|
|
|
1993
2186
|
}
|
|
1994
2187
|
} catch (error) {
|
|
1995
2188
|
if (error instanceof PermanentRefreshError) {
|
|
2189
|
+
if (shouldRepairLocalDevSession(config)) {
|
|
2190
|
+
const repaired = await repairLocalDevSession();
|
|
2191
|
+
if (repaired) {
|
|
2192
|
+
return repaired.accessToken;
|
|
2193
|
+
}
|
|
2194
|
+
}
|
|
1996
2195
|
throw new Error(formatStoredSessionInvalidMessage(error.message));
|
|
1997
2196
|
}
|
|
1998
2197
|
throw error;
|
|
@@ -2029,7 +2228,7 @@ function requireAuth(config) {
|
|
|
2029
2228
|
);
|
|
2030
2229
|
}
|
|
2031
2230
|
}
|
|
2032
|
-
function
|
|
2231
|
+
function valueOrUndefined2(value) {
|
|
2033
2232
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
2034
2233
|
}
|
|
2035
2234
|
function isInvalidRefreshTokenMessage(message) {
|
|
@@ -2122,7 +2321,8 @@ var joinCommandArgsSchema = configFlagsSchema.extend({
|
|
|
2122
2321
|
});
|
|
2123
2322
|
var loginCommandArgsSchema = configFlagsSchema;
|
|
2124
2323
|
var configCommandArgsSchema = configFlagsSchema.extend({
|
|
2125
|
-
action: external_exports.string().optional().default("show")
|
|
2324
|
+
action: external_exports.string().optional().default("show"),
|
|
2325
|
+
scope: external_exports.enum(["global", "workspace"]).optional().default("global")
|
|
2126
2326
|
});
|
|
2127
2327
|
var authCommandArgsSchema = external_exports.object({
|
|
2128
2328
|
action: external_exports.enum(["set", "clear", "login", "env", "status"]),
|
|
@@ -8724,7 +8924,7 @@ function validateSlotHostsAndHomes(manifest) {
|
|
|
8724
8924
|
}
|
|
8725
8925
|
slotIdsByHostKey.set(`die:${seed.id}`, new Set(slotIds));
|
|
8726
8926
|
}
|
|
8727
|
-
const validateHome = (home,
|
|
8927
|
+
const validateHome = (home, path29) => {
|
|
8728
8928
|
if (home?.type !== "slot") {
|
|
8729
8929
|
return;
|
|
8730
8930
|
}
|
|
@@ -8732,13 +8932,13 @@ function validateSlotHostsAndHomes(manifest) {
|
|
|
8732
8932
|
const slotIds = slotIdsByHostKey.get(hostKey);
|
|
8733
8933
|
if (!slotIds) {
|
|
8734
8934
|
issues.push(
|
|
8735
|
-
`${
|
|
8935
|
+
`${path29}.host: Unknown strict slot host '${home.host.kind}:${home.host.id}'. Hosts must be singleton piece/die seeds whose type declares slots.`
|
|
8736
8936
|
);
|
|
8737
8937
|
return;
|
|
8738
8938
|
}
|
|
8739
8939
|
if (!slotIds.has(home.slotId)) {
|
|
8740
8940
|
issues.push(
|
|
8741
|
-
`${
|
|
8941
|
+
`${path29}.slotId: Unknown slot '${home.slotId}' for host '${home.host.kind}:${home.host.id}'.`
|
|
8742
8942
|
);
|
|
8743
8943
|
}
|
|
8744
8944
|
};
|
|
@@ -8804,20 +9004,20 @@ function validatePlayerScopedSeedHomes(manifest) {
|
|
|
8804
9004
|
const zoneScopeById = new Map(
|
|
8805
9005
|
(manifest.zones ?? []).map((zone) => [zone.id, zone.scope])
|
|
8806
9006
|
);
|
|
8807
|
-
const validateSeedHome = (seed,
|
|
9007
|
+
const validateSeedHome = (seed, path29, label) => {
|
|
8808
9008
|
const authoredId = seed.id ?? seed.typeId;
|
|
8809
9009
|
if (seed.ownerId) {
|
|
8810
9010
|
return;
|
|
8811
9011
|
}
|
|
8812
9012
|
if (homeTargetsBoard(seed.home) && boardScopeById.get(seed.home.boardId) === "perPlayer") {
|
|
8813
9013
|
issues.push(
|
|
8814
|
-
`${
|
|
9014
|
+
`${path29}.boardId: ${label} '${authoredId}' requires ownerId because board '${seed.home.boardId}' has scope 'perPlayer'. Add ownerId to resolve the player-scoped destination.`
|
|
8815
9015
|
);
|
|
8816
9016
|
return;
|
|
8817
9017
|
}
|
|
8818
9018
|
if (seed.home?.type === "zone" && zoneScopeById.get(seed.home.zoneId) === "perPlayer") {
|
|
8819
9019
|
issues.push(
|
|
8820
|
-
`${
|
|
9020
|
+
`${path29}.zoneId: ${label} '${authoredId}' requires ownerId because zone '${seed.home.zoneId}' has scope 'perPlayer'. Add ownerId to resolve the player-scoped destination.`
|
|
8821
9021
|
);
|
|
8822
9022
|
}
|
|
8823
9023
|
};
|
|
@@ -9265,7 +9465,11 @@ var WORKSPACE_CODEGEN_OWNERSHIP = {
|
|
|
9265
9465
|
"app/game.ts",
|
|
9266
9466
|
"app/setup-profiles.ts",
|
|
9267
9467
|
"app/reducer-support.ts",
|
|
9268
|
-
"app/derived.ts"
|
|
9468
|
+
"app/derived.ts",
|
|
9469
|
+
"ui/interaction-routes.tsx",
|
|
9470
|
+
"ui/setup-screen.tsx",
|
|
9471
|
+
"ui/styles.ts",
|
|
9472
|
+
"ui/ui-contract-typing-smoke.tsx"
|
|
9269
9473
|
],
|
|
9270
9474
|
seedFilePatterns: [{ prefix: "app/phases/", suffix: ".ts" }]
|
|
9271
9475
|
},
|
|
@@ -9293,30 +9497,30 @@ function normalizeProjectPath(filePath) {
|
|
|
9293
9497
|
return filePath.replace(/^\.\//, "").replace(/^\/+/, "").replace(/\\/g, "/");
|
|
9294
9498
|
}
|
|
9295
9499
|
function isAllowedGamePath(filePath) {
|
|
9296
|
-
const
|
|
9297
|
-
if (WORKSPACE_CODEGEN_OWNERSHIP.allowedPaths.rootFiles.includes(
|
|
9500
|
+
const path29 = normalizeProjectPath(filePath);
|
|
9501
|
+
if (WORKSPACE_CODEGEN_OWNERSHIP.allowedPaths.rootFiles.includes(path29)) {
|
|
9298
9502
|
return true;
|
|
9299
9503
|
}
|
|
9300
9504
|
return WORKSPACE_CODEGEN_OWNERSHIP.allowedPaths.directoryPrefixes.some(
|
|
9301
|
-
(prefix) =>
|
|
9505
|
+
(prefix) => path29.startsWith(prefix)
|
|
9302
9506
|
);
|
|
9303
9507
|
}
|
|
9304
9508
|
function isAuthoritativeGeneratedPath(filePath) {
|
|
9305
|
-
const
|
|
9306
|
-
return WORKSPACE_CODEGEN_OWNERSHIP.dynamic.generatedFiles.includes(
|
|
9509
|
+
const path29 = normalizeProjectPath(filePath);
|
|
9510
|
+
return WORKSPACE_CODEGEN_OWNERSHIP.dynamic.generatedFiles.includes(path29);
|
|
9307
9511
|
}
|
|
9308
9512
|
function isDynamicSeedPath(filePath) {
|
|
9309
|
-
const
|
|
9310
|
-
if (WORKSPACE_CODEGEN_OWNERSHIP.dynamic.seedFiles.includes(
|
|
9513
|
+
const path29 = normalizeProjectPath(filePath);
|
|
9514
|
+
if (WORKSPACE_CODEGEN_OWNERSHIP.dynamic.seedFiles.includes(path29)) {
|
|
9311
9515
|
return true;
|
|
9312
9516
|
}
|
|
9313
9517
|
return WORKSPACE_CODEGEN_OWNERSHIP.dynamic.seedFilePatterns.some(
|
|
9314
|
-
(pattern) =>
|
|
9518
|
+
(pattern) => path29.startsWith(pattern.prefix) && path29.endsWith(pattern.suffix)
|
|
9315
9519
|
);
|
|
9316
9520
|
}
|
|
9317
9521
|
function isLibraryPath(filePath) {
|
|
9318
|
-
const
|
|
9319
|
-
return isAuthoritativeGeneratedPath(
|
|
9522
|
+
const path29 = normalizeProjectPath(filePath);
|
|
9523
|
+
return isAuthoritativeGeneratedPath(path29);
|
|
9320
9524
|
}
|
|
9321
9525
|
|
|
9322
9526
|
// ../../packages/workspace-codegen/src/seeds.ts
|
|
@@ -9332,9 +9536,11 @@ import {
|
|
|
9332
9536
|
createClientParamSchemasByPhase,
|
|
9333
9537
|
} from "@dreamboard/app-sdk/reducer";
|
|
9334
9538
|
import type {
|
|
9335
|
-
|
|
9336
|
-
|
|
9337
|
-
|
|
9539
|
+
CardInputZoneIdsOfDefinition,
|
|
9540
|
+
ClientParamsOfInteractionOfDefinition,
|
|
9541
|
+
DefaultedClientParamKeysOfInteractionOfDefinition,
|
|
9542
|
+
InputKeysWithCollectorKindOfDefinition,
|
|
9543
|
+
InteractionIdOfDefinition,
|
|
9338
9544
|
InteractionIdOfDefinitionPhase,
|
|
9339
9545
|
PhaseNamesOfDefinition,
|
|
9340
9546
|
StageNamesOfDefinitionPhase,
|
|
@@ -9342,42 +9548,47 @@ import type {
|
|
|
9342
9548
|
ViewOfDefinition,
|
|
9343
9549
|
} from "@dreamboard/app-sdk/reducer";
|
|
9344
9550
|
import {
|
|
9345
|
-
|
|
9346
|
-
|
|
9347
|
-
|
|
9348
|
-
|
|
9349
|
-
|
|
9350
|
-
|
|
9351
|
-
|
|
9352
|
-
|
|
9353
|
-
|
|
9354
|
-
|
|
9355
|
-
|
|
9356
|
-
|
|
9357
|
-
|
|
9358
|
-
|
|
9359
|
-
|
|
9360
|
-
|
|
9361
|
-
|
|
9362
|
-
|
|
9363
|
-
|
|
9364
|
-
|
|
9365
|
-
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
|
|
9369
|
-
|
|
9370
|
-
|
|
9371
|
-
|
|
9372
|
-
|
|
9373
|
-
|
|
9374
|
-
|
|
9375
|
-
|
|
9376
|
-
|
|
9377
|
-
|
|
9551
|
+
type BoardSpaceIdOf,
|
|
9552
|
+
type InteractionDescriptor,
|
|
9553
|
+
} from "@dreamboard/ui-sdk";
|
|
9554
|
+
import {
|
|
9555
|
+
createWorkspaceUIContract,
|
|
9556
|
+
type BoardHexGridProps as BoardHexGridPropsGeneric,
|
|
9557
|
+
type BoardHexViewProps as BoardHexViewPropsGeneric,
|
|
9558
|
+
type BoardSpaceTargetProps as BoardSpaceTargetPropsGeneric,
|
|
9559
|
+
type ClientParamSchemaMap,
|
|
9560
|
+
type DreamboardUI,
|
|
9561
|
+
type ResourceCounterComponents,
|
|
9562
|
+
type TypedGame,
|
|
9563
|
+
type UIContract,
|
|
9564
|
+
type UIRootProps,
|
|
9565
|
+
type WorkspaceBoardSurface,
|
|
9566
|
+
type WorkspaceBoardTargetInputSlot,
|
|
9567
|
+
type WorkspaceCardCollectionSurface,
|
|
9568
|
+
type WorkspaceCardInputSlot,
|
|
9569
|
+
type WorkspaceFormInputSlot,
|
|
9570
|
+
type WorkspaceHandSurface,
|
|
9571
|
+
type WorkspaceInteractionSlotComponent,
|
|
9572
|
+
type WorkspacePileSurface,
|
|
9573
|
+
type ZoneCardRenderItem,
|
|
9574
|
+
type ZoneListProps,
|
|
9575
|
+
} from "@dreamboard/ui-sdk/workspace-contract";
|
|
9576
|
+
import { type ButtonHTMLAttributes, type ReactElement, type ReactNode } from "react";
|
|
9577
|
+
import {
|
|
9578
|
+
boardHelpers,
|
|
9579
|
+
literals,
|
|
9580
|
+
staticBoards,
|
|
9581
|
+
type BoardBaseId,
|
|
9582
|
+
type CardId,
|
|
9583
|
+
type CardProperties,
|
|
9584
|
+
type CardType,
|
|
9585
|
+
type EdgeId,
|
|
9378
9586
|
type PlayerId,
|
|
9379
9587
|
type ResourceId,
|
|
9380
9588
|
type SpaceId,
|
|
9589
|
+
type TiledBoardId,
|
|
9590
|
+
type TiledEdgeState,
|
|
9591
|
+
type TiledVertexState,
|
|
9381
9592
|
type VertexId,
|
|
9382
9593
|
type ZoneId as ManifestZoneId,
|
|
9383
9594
|
} from "../manifest-contract";
|
|
@@ -9466,6 +9677,14 @@ type PlayerCardZoneId = {
|
|
|
9466
9677
|
: Z;
|
|
9467
9678
|
}[(typeof literals.playerZoneIds)[number]];
|
|
9468
9679
|
|
|
9680
|
+
type SharedCardZoneId = {
|
|
9681
|
+
[Z in (typeof literals.sharedZoneIds)[number]]: (typeof literals.cardSetIdsBySharedZoneId)[Z] extends readonly []
|
|
9682
|
+
? never
|
|
9683
|
+
: Z;
|
|
9684
|
+
}[(typeof literals.sharedZoneIds)[number]];
|
|
9685
|
+
|
|
9686
|
+
type CardZoneId = PlayerCardZoneId | SharedCardZoneId;
|
|
9687
|
+
|
|
9469
9688
|
/** JS-friendly keys for per-player zones that can contain cards. */
|
|
9470
9689
|
export type WorkspacePlayerCardZoneKey = CamelCase<PlayerCardZoneId>;
|
|
9471
9690
|
|
|
@@ -9473,6 +9692,11 @@ export type WorkspacePlayerCardZoneKey = CamelCase<PlayerCardZoneId>;
|
|
|
9473
9692
|
export type InteractionDescriptorFor<Key extends InteractionKey> =
|
|
9474
9693
|
InteractionDescriptor<Key>;
|
|
9475
9694
|
|
|
9695
|
+
export type InteractionItem<Key extends InteractionKey> = {
|
|
9696
|
+
readonly interaction: Key;
|
|
9697
|
+
readonly descriptor: InteractionDescriptorFor<Key>;
|
|
9698
|
+
};
|
|
9699
|
+
|
|
9476
9700
|
/**
|
|
9477
9701
|
* Params shape for a phase-qualified interaction key. Drives strong typing
|
|
9478
9702
|
* for component-first interaction state, forms, and submits.
|
|
@@ -9488,60 +9712,528 @@ type InteractionParamsShape<Key extends InteractionKey> =
|
|
|
9488
9712
|
? InteractionParamsOf<Key>
|
|
9489
9713
|
: Record<string, unknown>;
|
|
9490
9714
|
|
|
9715
|
+
type InteractionCollectorKind =
|
|
9716
|
+
| "form"
|
|
9717
|
+
| "board-vertex"
|
|
9718
|
+
| "board-edge"
|
|
9719
|
+
| "board-tile"
|
|
9720
|
+
| "board-space"
|
|
9721
|
+
| "card"
|
|
9722
|
+
| "prompt";
|
|
9723
|
+
|
|
9724
|
+
type AuthoredInteractionInputKeysOf<Key extends InteractionKey> =
|
|
9725
|
+
InputKeysWithCollectorKindOfDefinition<
|
|
9726
|
+
GameDefinition,
|
|
9727
|
+
PhaseOfInteractionKey<Key>,
|
|
9728
|
+
IdOfInteractionKey<Key>,
|
|
9729
|
+
InteractionCollectorKind
|
|
9730
|
+
> extends infer Input
|
|
9731
|
+
? string extends Input
|
|
9732
|
+
? never
|
|
9733
|
+
: Input & string
|
|
9734
|
+
: never;
|
|
9735
|
+
|
|
9491
9736
|
type InteractionInputKeysOf<Key extends InteractionKey> =
|
|
9492
|
-
string extends keyof InteractionParamsOf<Key>
|
|
9493
|
-
|
|
9494
|
-
|
|
9737
|
+
| (string extends keyof InteractionParamsOf<Key>
|
|
9738
|
+
? never
|
|
9739
|
+
: keyof InteractionParamsOf<Key> & string)
|
|
9740
|
+
| AuthoredInteractionInputKeysOf<Key>
|
|
9741
|
+
| (InteractionDefaultedKeysOf<Key> & string);
|
|
9495
9742
|
|
|
9496
9743
|
type InteractionHandleDefaultedKeys<Key extends InteractionKey> = Extract<
|
|
9497
9744
|
InteractionDefaultedKeysOf<Key>,
|
|
9498
9745
|
keyof InteractionParamsShape<Key> & string
|
|
9499
9746
|
>;
|
|
9500
9747
|
|
|
9501
|
-
type RequiredInteractionInputKeysOf<Key extends InteractionKey> =
|
|
9502
|
-
InteractionInputKeysOf<Key
|
|
9503
|
-
InteractionHandleDefaultedKeys<Key>
|
|
9504
|
-
>;
|
|
9748
|
+
type RequiredInteractionInputKeysOf<Key extends InteractionKey> =
|
|
9749
|
+
InteractionInputKeysOf<Key>;
|
|
9505
9750
|
|
|
9506
9751
|
export type RequiredInteractionInputKey<Key extends InteractionKey> =
|
|
9507
9752
|
RequiredInteractionInputKeysOf<Key>;
|
|
9508
9753
|
|
|
9509
|
-
|
|
9510
|
-
|
|
9511
|
-
?
|
|
9754
|
+
type InteractionSlotComponent<Props = object> = (
|
|
9755
|
+
props: Props extends { children: unknown }
|
|
9756
|
+
? Props
|
|
9757
|
+
: Props & { children?: ReactNode },
|
|
9758
|
+
) => ReactElement | null;
|
|
9759
|
+
|
|
9760
|
+
type InteractionDefaultInputSlot = {
|
|
9761
|
+
readonly Default: InteractionSlotComponent;
|
|
9762
|
+
};
|
|
9763
|
+
|
|
9764
|
+
type InteractionValueInputSlot<Value = unknown> = {
|
|
9765
|
+
readonly Value: InteractionSlotComponent<{
|
|
9766
|
+
children: (value: unknown | undefined) => ReactNode;
|
|
9767
|
+
}>;
|
|
9768
|
+
};
|
|
9769
|
+
|
|
9770
|
+
type InteractionFormInputSlot<Value = unknown> = {
|
|
9771
|
+
readonly Field: InteractionSlotComponent;
|
|
9772
|
+
readonly Options: InteractionSlotComponent<{
|
|
9773
|
+
children: (option: { value: Value; label: string }) => ReactNode;
|
|
9774
|
+
}>;
|
|
9775
|
+
};
|
|
9776
|
+
|
|
9777
|
+
type DreamboardSlotBrand<Meta> = {
|
|
9778
|
+
readonly __dreamboardSlot: Meta;
|
|
9779
|
+
};
|
|
9780
|
+
|
|
9781
|
+
type InteractionCardTargetInputSlot<Card extends string = string> = {
|
|
9782
|
+
readonly Card: InteractionSlotComponent<
|
|
9783
|
+
{ value: string; swipe?: "auto" | "off" } & Omit<
|
|
9784
|
+
ButtonHTMLAttributes<HTMLButtonElement>,
|
|
9785
|
+
| "children"
|
|
9786
|
+
| "disabled"
|
|
9787
|
+
| "aria-disabled"
|
|
9788
|
+
| "aria-pressed"
|
|
9789
|
+
| "onClick"
|
|
9790
|
+
| "type"
|
|
9791
|
+
| "value"
|
|
9792
|
+
>
|
|
9793
|
+
>;
|
|
9794
|
+
readonly Cards: InteractionSlotComponent<{
|
|
9795
|
+
children: (card: { id: Card }) => ReactNode;
|
|
9796
|
+
}>;
|
|
9797
|
+
};
|
|
9798
|
+
|
|
9799
|
+
type InteractionBoardTargetInputSlot<Target extends string = string> = {
|
|
9800
|
+
readonly Target: InteractionSlotComponent<
|
|
9801
|
+
{ value: string } & Omit<
|
|
9802
|
+
ButtonHTMLAttributes<HTMLButtonElement>,
|
|
9803
|
+
| "children"
|
|
9804
|
+
| "disabled"
|
|
9805
|
+
| "aria-disabled"
|
|
9806
|
+
| "aria-pressed"
|
|
9807
|
+
| "onClick"
|
|
9808
|
+
| "type"
|
|
9809
|
+
| "value"
|
|
9810
|
+
>
|
|
9811
|
+
>;
|
|
9812
|
+
};
|
|
9813
|
+
|
|
9814
|
+
type InteractionBoardSpaceTargetInputSlot<Space extends string = string> =
|
|
9815
|
+
InteractionBoardTargetInputSlot<Space>;
|
|
9816
|
+
|
|
9817
|
+
type InteractionBoardEdgeTargetInputSlot<Edge extends string = string> =
|
|
9818
|
+
InteractionBoardTargetInputSlot<Edge>;
|
|
9819
|
+
|
|
9820
|
+
type InteractionBoardVertexTargetInputSlot<Vertex extends string = string> =
|
|
9821
|
+
InteractionBoardTargetInputSlot<Vertex>;
|
|
9822
|
+
|
|
9823
|
+
type InteractionBoardTileTargetInputSlot<Tile extends string = string> =
|
|
9824
|
+
InteractionBoardTargetInputSlot<Tile>;
|
|
9825
|
+
|
|
9826
|
+
type InteractionSubmitSlot = {
|
|
9827
|
+
readonly Button: InteractionSlotComponent<
|
|
9828
|
+
Omit<
|
|
9829
|
+
ButtonHTMLAttributes<HTMLButtonElement>,
|
|
9830
|
+
"children" | "disabled" | "type" | "value"
|
|
9831
|
+
>
|
|
9832
|
+
>;
|
|
9833
|
+
};
|
|
9834
|
+
|
|
9835
|
+
type InteractionInputValue<
|
|
9836
|
+
Key extends InteractionKey,
|
|
9837
|
+
Input extends InteractionInputKeysOf<Key>,
|
|
9838
|
+
> = InteractionParamsShape<Key>[Input & keyof InteractionParamsShape<Key>];
|
|
9839
|
+
|
|
9840
|
+
type InteractionSlotValue<Value> = Value extends readonly (infer Item)[]
|
|
9841
|
+
? InteractionSlotValue<Item>
|
|
9842
|
+
: Value extends { spaceId: infer Space extends string }
|
|
9843
|
+
? Space
|
|
9844
|
+
: Value extends { edgeId: infer Edge extends string }
|
|
9845
|
+
? Edge
|
|
9846
|
+
: Value extends { vertexId: infer Vertex extends string }
|
|
9847
|
+
? Vertex
|
|
9848
|
+
: Value extends { tileId: infer Tile extends string }
|
|
9849
|
+
? Tile
|
|
9850
|
+
: Value extends { cardId: infer Card extends string }
|
|
9851
|
+
? Card
|
|
9852
|
+
: Value;
|
|
9853
|
+
|
|
9854
|
+
type InteractionSlotStringValue<Value> = Extract<
|
|
9855
|
+
InteractionSlotValue<Value>,
|
|
9856
|
+
string
|
|
9857
|
+
>;
|
|
9858
|
+
|
|
9859
|
+
type FormInteractionInputKey<Key extends InteractionKey> =
|
|
9860
|
+
InputKeysWithCollectorKindOfDefinition<
|
|
9861
|
+
GameDefinition,
|
|
9862
|
+
PhaseOfInteractionKey<Key>,
|
|
9863
|
+
IdOfInteractionKey<Key>,
|
|
9864
|
+
"form" | "prompt"
|
|
9865
|
+
> &
|
|
9866
|
+
InteractionInputKeysOf<Key>;
|
|
9867
|
+
|
|
9868
|
+
type CardTargetInteractionInputKey<Key extends InteractionKey> =
|
|
9869
|
+
InputKeysWithCollectorKindOfDefinition<
|
|
9870
|
+
GameDefinition,
|
|
9871
|
+
PhaseOfInteractionKey<Key>,
|
|
9872
|
+
IdOfInteractionKey<Key>,
|
|
9873
|
+
"card"
|
|
9874
|
+
> &
|
|
9875
|
+
InteractionInputKeysOf<Key>;
|
|
9876
|
+
|
|
9877
|
+
type CardTargetZoneIds<
|
|
9878
|
+
Key extends InteractionKey,
|
|
9879
|
+
Input extends InteractionInputKeysOf<Key>,
|
|
9880
|
+
> =
|
|
9881
|
+
CardInputZoneIdsOfDefinition<
|
|
9882
|
+
GameDefinition,
|
|
9883
|
+
PhaseOfInteractionKey<Key>,
|
|
9884
|
+
IdOfInteractionKey<Key>,
|
|
9885
|
+
Input & string
|
|
9886
|
+
> extends infer Zone extends string
|
|
9887
|
+
? Extract<Zone, WorkspaceZoneId>
|
|
9888
|
+
: never;
|
|
9889
|
+
|
|
9890
|
+
type BoardSpaceTargetInteractionInputKey<Key extends InteractionKey> =
|
|
9891
|
+
InputKeysWithCollectorKindOfDefinition<
|
|
9892
|
+
GameDefinition,
|
|
9893
|
+
PhaseOfInteractionKey<Key>,
|
|
9894
|
+
IdOfInteractionKey<Key>,
|
|
9895
|
+
"board-space"
|
|
9896
|
+
> &
|
|
9897
|
+
InteractionInputKeysOf<Key>;
|
|
9898
|
+
|
|
9899
|
+
type BoardEdgeTargetInteractionInputKey<Key extends InteractionKey> =
|
|
9900
|
+
InputKeysWithCollectorKindOfDefinition<
|
|
9901
|
+
GameDefinition,
|
|
9902
|
+
PhaseOfInteractionKey<Key>,
|
|
9903
|
+
IdOfInteractionKey<Key>,
|
|
9904
|
+
"board-edge"
|
|
9905
|
+
> &
|
|
9906
|
+
InteractionInputKeysOf<Key>;
|
|
9907
|
+
|
|
9908
|
+
type BoardVertexTargetInteractionInputKey<Key extends InteractionKey> =
|
|
9909
|
+
InputKeysWithCollectorKindOfDefinition<
|
|
9910
|
+
GameDefinition,
|
|
9911
|
+
PhaseOfInteractionKey<Key>,
|
|
9912
|
+
IdOfInteractionKey<Key>,
|
|
9913
|
+
"board-vertex"
|
|
9914
|
+
> &
|
|
9915
|
+
InteractionInputKeysOf<Key>;
|
|
9916
|
+
|
|
9917
|
+
type BoardTileTargetInteractionInputKey<Key extends InteractionKey> =
|
|
9918
|
+
InputKeysWithCollectorKindOfDefinition<
|
|
9919
|
+
GameDefinition,
|
|
9920
|
+
PhaseOfInteractionKey<Key>,
|
|
9921
|
+
IdOfInteractionKey<Key>,
|
|
9922
|
+
"board-tile"
|
|
9923
|
+
> &
|
|
9924
|
+
InteractionInputKeysOf<Key>;
|
|
9925
|
+
|
|
9926
|
+
type InteractionDefaultSlotFor<
|
|
9927
|
+
Key extends InteractionKey,
|
|
9928
|
+
Input extends InteractionInputKeysOf<Key>,
|
|
9929
|
+
> = Input extends InteractionHandleDefaultedKeys<Key>
|
|
9930
|
+
? InteractionDefaultInputSlot
|
|
9931
|
+
: object;
|
|
9932
|
+
|
|
9933
|
+
export type InteractionInputSlot<
|
|
9934
|
+
Key extends InteractionKey,
|
|
9935
|
+
Input extends InteractionInputKeysOf<Key>,
|
|
9936
|
+
> = InteractionValueInputSlot<InteractionInputValue<Key, Input>> &
|
|
9937
|
+
InteractionDefaultSlotFor<Key, Input> &
|
|
9938
|
+
(Input extends CardTargetInteractionInputKey<Key>
|
|
9939
|
+
? InteractionCardTargetInputSlot<
|
|
9940
|
+
InteractionSlotStringValue<InteractionInputValue<Key, Input>>
|
|
9941
|
+
>
|
|
9942
|
+
: Input extends BoardSpaceTargetInteractionInputKey<Key>
|
|
9943
|
+
? InteractionBoardSpaceTargetInputSlot<
|
|
9944
|
+
InteractionSlotStringValue<InteractionInputValue<Key, Input>>
|
|
9945
|
+
>
|
|
9946
|
+
: Input extends BoardEdgeTargetInteractionInputKey<Key>
|
|
9947
|
+
? InteractionBoardEdgeTargetInputSlot<
|
|
9948
|
+
InteractionSlotStringValue<InteractionInputValue<Key, Input>>
|
|
9949
|
+
>
|
|
9950
|
+
: Input extends BoardVertexTargetInteractionInputKey<Key>
|
|
9951
|
+
? InteractionBoardVertexTargetInputSlot<
|
|
9952
|
+
InteractionSlotStringValue<InteractionInputValue<Key, Input>>
|
|
9953
|
+
>
|
|
9954
|
+
: Input extends BoardTileTargetInteractionInputKey<Key>
|
|
9955
|
+
? InteractionBoardTileTargetInputSlot<
|
|
9956
|
+
InteractionSlotStringValue<InteractionInputValue<Key, Input>>
|
|
9957
|
+
>
|
|
9958
|
+
: Input extends FormInteractionInputKey<Key>
|
|
9959
|
+
? InteractionFormInputSlot<InteractionInputValue<Key, Input>>
|
|
9960
|
+
: never);
|
|
9961
|
+
|
|
9962
|
+
type FormSurfaceInputSlot<
|
|
9963
|
+
Key extends InteractionKey,
|
|
9964
|
+
Input extends FormInteractionInputKey<Key>,
|
|
9965
|
+
> = InteractionValueInputSlot<InteractionInputValue<Key, Input>> &
|
|
9966
|
+
InteractionDefaultSlotFor<Key, Input> &
|
|
9967
|
+
InteractionFormInputSlot<InteractionInputValue<Key, Input>> &
|
|
9968
|
+
DreamboardSlotBrand<{
|
|
9969
|
+
readonly kind: "form";
|
|
9970
|
+
readonly interaction: Key;
|
|
9971
|
+
readonly input: Input;
|
|
9972
|
+
}>;
|
|
9973
|
+
|
|
9974
|
+
type CardSurfaceInputSlot<Zones extends string> =
|
|
9975
|
+
InteractionValueInputSlot<unknown> &
|
|
9976
|
+
InteractionCardTargetInputSlot<WorkspaceCardId & string> &
|
|
9977
|
+
DreamboardSlotBrand<{
|
|
9978
|
+
readonly kind: "card";
|
|
9979
|
+
readonly zones: Zones;
|
|
9980
|
+
readonly selection: "one" | "many";
|
|
9981
|
+
}>;
|
|
9982
|
+
|
|
9983
|
+
type BoardSurfaceInputSlot<
|
|
9984
|
+
Kind extends "space" | "edge" | "vertex" | "tile",
|
|
9985
|
+
Target extends string = string,
|
|
9986
|
+
> =
|
|
9987
|
+
InteractionValueInputSlot<unknown> &
|
|
9988
|
+
InteractionBoardTargetInputSlot<Target> &
|
|
9989
|
+
DreamboardSlotBrand<{
|
|
9990
|
+
readonly kind: "board";
|
|
9991
|
+
readonly targetKind: Kind;
|
|
9992
|
+
}>;
|
|
9993
|
+
|
|
9994
|
+
type InteractionCollectorSlot<
|
|
9995
|
+
Key extends InteractionKey,
|
|
9996
|
+
Input extends InteractionInputKeysOf<Key>,
|
|
9997
|
+
> = Input extends CardTargetInteractionInputKey<Key>
|
|
9998
|
+
? CardSurfaceInputSlot<CardTargetZoneIds<Key, Input>>
|
|
9999
|
+
: Input extends BoardSpaceTargetInteractionInputKey<Key>
|
|
10000
|
+
? BoardSurfaceInputSlot<"space", string>
|
|
10001
|
+
: Input extends BoardEdgeTargetInteractionInputKey<Key>
|
|
10002
|
+
? BoardSurfaceInputSlot<"edge", string>
|
|
10003
|
+
: Input extends BoardVertexTargetInteractionInputKey<Key>
|
|
10004
|
+
? BoardSurfaceInputSlot<"vertex", string>
|
|
10005
|
+
: Input extends BoardTileTargetInteractionInputKey<Key>
|
|
10006
|
+
? BoardSurfaceInputSlot<"tile", string>
|
|
10007
|
+
: Input extends FormInteractionInputKey<Key>
|
|
10008
|
+
? FormSurfaceInputSlot<Key, Input>
|
|
10009
|
+
: never;
|
|
10010
|
+
|
|
10011
|
+
type InteractionKeysWithInput<Input extends InteractionInputKey> = {
|
|
10012
|
+
[Key in InteractionKey]: Input extends InteractionInputKeysOf<Key>
|
|
10013
|
+
? Key
|
|
9512
10014
|
: never;
|
|
9513
10015
|
}[InteractionKey];
|
|
9514
10016
|
|
|
9515
|
-
|
|
9516
|
-
|
|
9517
|
-
|
|
10017
|
+
type InteractionInputSlotByName<Input extends InteractionInputKey> =
|
|
10018
|
+
InteractionInputSlot<
|
|
10019
|
+
InteractionKeysWithInput<Input>,
|
|
10020
|
+
Input & InteractionInputKeysOf<InteractionKeysWithInput<Input>>
|
|
10021
|
+
>;
|
|
10022
|
+
|
|
10023
|
+
type InteractionFormInputSlotByName<Input extends InteractionInputKey> =
|
|
10024
|
+
InteractionInputSlot<
|
|
10025
|
+
{
|
|
10026
|
+
[Key in InteractionKey]: Input extends FormInteractionInputKey<Key>
|
|
10027
|
+
? Key
|
|
10028
|
+
: never;
|
|
10029
|
+
}[InteractionKey],
|
|
10030
|
+
Input &
|
|
10031
|
+
InteractionInputKeysOf<
|
|
10032
|
+
{
|
|
10033
|
+
[Key in InteractionKey]: Input extends FormInteractionInputKey<Key>
|
|
10034
|
+
? Key
|
|
10035
|
+
: never;
|
|
10036
|
+
}[InteractionKey]
|
|
10037
|
+
>
|
|
10038
|
+
>;
|
|
10039
|
+
|
|
10040
|
+
type InteractionInputsForCollectorKind<
|
|
10041
|
+
Key extends InteractionKey,
|
|
10042
|
+
CollectorKind extends InteractionCollectorKind,
|
|
10043
|
+
> = {
|
|
10044
|
+
[Input in InteractionInputKeysOf<Key>]: CollectorKind extends "form"
|
|
10045
|
+
? Input extends FormInteractionInputKey<Key>
|
|
10046
|
+
? Input
|
|
10047
|
+
: never
|
|
10048
|
+
: CollectorKind extends "card"
|
|
10049
|
+
? Input extends CardTargetInteractionInputKey<Key>
|
|
10050
|
+
? Input
|
|
10051
|
+
: never
|
|
10052
|
+
: CollectorKind extends "board-space"
|
|
10053
|
+
? Input extends BoardSpaceTargetInteractionInputKey<Key>
|
|
10054
|
+
? Input
|
|
10055
|
+
: never
|
|
10056
|
+
: CollectorKind extends "board-edge"
|
|
10057
|
+
? Input extends BoardEdgeTargetInteractionInputKey<Key>
|
|
10058
|
+
? Input
|
|
10059
|
+
: never
|
|
10060
|
+
: CollectorKind extends "board-vertex"
|
|
10061
|
+
? Input extends BoardVertexTargetInteractionInputKey<Key>
|
|
10062
|
+
? Input
|
|
10063
|
+
: never
|
|
10064
|
+
: CollectorKind extends "board-tile"
|
|
10065
|
+
? Input extends BoardTileTargetInteractionInputKey<Key>
|
|
10066
|
+
? Input
|
|
10067
|
+
: never
|
|
10068
|
+
: never;
|
|
10069
|
+
}[InteractionInputKeysOf<Key>];
|
|
10070
|
+
|
|
10071
|
+
type InteractionKeysForCollectorKind<
|
|
10072
|
+
CollectorKind extends InteractionCollectorKind,
|
|
10073
|
+
> = {
|
|
10074
|
+
[Key in InteractionKey]: InteractionInputsForCollectorKind<
|
|
10075
|
+
Key,
|
|
10076
|
+
CollectorKind
|
|
10077
|
+
> extends never
|
|
10078
|
+
? never
|
|
10079
|
+
: Key;
|
|
10080
|
+
}[InteractionKey];
|
|
10081
|
+
|
|
10082
|
+
type InteractionInputSlotByCollectorKind<
|
|
10083
|
+
CollectorKind extends InteractionCollectorKind,
|
|
10084
|
+
> = InteractionInputSlot<
|
|
10085
|
+
InteractionKeysForCollectorKind<CollectorKind>,
|
|
10086
|
+
InteractionInputsForCollectorKind<
|
|
10087
|
+
InteractionKeysForCollectorKind<CollectorKind>,
|
|
10088
|
+
CollectorKind
|
|
10089
|
+
>
|
|
9518
10090
|
>;
|
|
9519
10091
|
|
|
9520
|
-
export type
|
|
9521
|
-
|
|
9522
|
-
|
|
10092
|
+
export type InteractionFormSurface<Key extends InteractionKey> = {
|
|
10093
|
+
readonly Root: InteractionSlotComponent;
|
|
10094
|
+
readonly Form: DreamboardUI<typeof uiContract>["Interaction"]["Form"];
|
|
10095
|
+
readonly Dialog: DreamboardUI<typeof uiContract>["Interaction"]["Dialog"];
|
|
10096
|
+
readonly State: DreamboardUI<typeof uiContract>["Interaction"]["State"];
|
|
10097
|
+
readonly Arm: DreamboardUI<typeof uiContract>["Interaction"]["Trigger"];
|
|
10098
|
+
readonly Submit: DreamboardUI<typeof uiContract>["Interaction"]["Submit"];
|
|
10099
|
+
readonly Field: <Input extends FormInteractionInputKey<Key>>(
|
|
10100
|
+
props: { input: Input; children?: ReactNode },
|
|
10101
|
+
) => ReactElement | null;
|
|
10102
|
+
readonly slot: {
|
|
10103
|
+
readonly [Input in FormInteractionInputKey<Key>]: FormSurfaceInputSlot<
|
|
10104
|
+
Key,
|
|
10105
|
+
Input
|
|
10106
|
+
>;
|
|
9523
10107
|
};
|
|
10108
|
+
};
|
|
10109
|
+
|
|
10110
|
+
type BoardSurfaceSpaceProps<Target extends string> = {
|
|
10111
|
+
value: Target;
|
|
10112
|
+
children?: ReactNode;
|
|
10113
|
+
} & Omit<BoardSpaceTargetPropsGeneric<Target>, "value" | "children">;
|
|
10114
|
+
|
|
10115
|
+
export type BoardSurfaceBoardId = BoardBaseId & string;
|
|
9524
10116
|
|
|
9525
|
-
|
|
9526
|
-
[
|
|
10117
|
+
type BoardSurfaceRuntimeBoardId<Board extends BoardSurfaceBoardId> =
|
|
10118
|
+
ReturnType<typeof boardHelpers.boardIdsForBase<Board>>[number] & string;
|
|
10119
|
+
|
|
10120
|
+
type BoardSurfaceSpaceId<Board extends BoardSurfaceBoardId> =
|
|
10121
|
+
ReturnType<
|
|
10122
|
+
typeof boardHelpers.spaceIds<BoardSurfaceRuntimeBoardId<Board>>
|
|
10123
|
+
>[number] &
|
|
10124
|
+
string;
|
|
10125
|
+
|
|
10126
|
+
type BoardSurfaceTiledBoardId<Board extends BoardSurfaceBoardId> = Extract<
|
|
10127
|
+
BoardSurfaceRuntimeBoardId<Board>,
|
|
10128
|
+
TiledBoardId
|
|
10129
|
+
>;
|
|
10130
|
+
|
|
10131
|
+
type BoardSurfaceEdgeId<Board extends BoardSurfaceBoardId> =
|
|
10132
|
+
TiledEdgeState<BoardSurfaceTiledBoardId<Board>> extends { id: infer Id }
|
|
10133
|
+
? Id & string
|
|
10134
|
+
: EdgeId & string;
|
|
10135
|
+
|
|
10136
|
+
type BoardSurfaceVertexId<Board extends BoardSurfaceBoardId> =
|
|
10137
|
+
TiledVertexState<BoardSurfaceTiledBoardId<Board>> extends { id: infer Id }
|
|
10138
|
+
? Id & string
|
|
10139
|
+
: VertexId & string;
|
|
10140
|
+
|
|
10141
|
+
export type BoardSurface<Board extends BoardSurfaceBoardId = BoardSurfaceBoardId> = {
|
|
10142
|
+
readonly Root: InteractionSlotComponent;
|
|
10143
|
+
readonly Space: <Target extends BoardSurfaceSpaceId<Board>>(
|
|
10144
|
+
props: BoardSurfaceSpaceProps<Target>,
|
|
10145
|
+
) => ReactElement;
|
|
10146
|
+
readonly slot: {
|
|
10147
|
+
readonly space: BoardSurfaceInputSlot<
|
|
10148
|
+
"space",
|
|
10149
|
+
BoardSurfaceSpaceId<Board>
|
|
10150
|
+
>;
|
|
10151
|
+
readonly playerSpace: BoardSurfaceInputSlot<
|
|
10152
|
+
"space",
|
|
10153
|
+
BoardSurfaceSpaceId<Board>
|
|
10154
|
+
>;
|
|
10155
|
+
readonly edge: BoardSurfaceInputSlot<"edge", BoardSurfaceEdgeId<Board>>;
|
|
10156
|
+
readonly vertex: BoardSurfaceInputSlot<
|
|
10157
|
+
"vertex",
|
|
10158
|
+
BoardSurfaceVertexId<Board>
|
|
10159
|
+
>;
|
|
10160
|
+
readonly tile: BoardSurfaceInputSlot<"tile", BoardSurfaceSpaceId<Board>>;
|
|
10161
|
+
};
|
|
9527
10162
|
};
|
|
9528
10163
|
|
|
9529
|
-
type
|
|
9530
|
-
|
|
10164
|
+
type ZoneCardsComponent = InteractionSlotComponent<
|
|
10165
|
+
Omit<ZoneListProps, "children" | "empty"> & {
|
|
10166
|
+
empty?: ReactNode;
|
|
10167
|
+
children: (card: WorkspaceZoneCard) => ReactNode;
|
|
10168
|
+
}
|
|
10169
|
+
>;
|
|
9531
10170
|
|
|
9532
|
-
|
|
9533
|
-
|
|
9534
|
-
|
|
9535
|
-
|
|
9536
|
-
}
|
|
10171
|
+
type ZoneCardComponent = InteractionSlotComponent<
|
|
10172
|
+
Omit<ButtonHTMLAttributes<HTMLButtonElement>, "type" | "value"> & {
|
|
10173
|
+
card: WorkspaceZoneCard;
|
|
10174
|
+
swipe?: "auto" | "off";
|
|
10175
|
+
}
|
|
10176
|
+
>;
|
|
9537
10177
|
|
|
9538
|
-
type
|
|
9539
|
-
|
|
9540
|
-
|
|
9541
|
-
|
|
9542
|
-
|
|
10178
|
+
export type HandSurface<Zones extends readonly WorkspaceZoneId[] = readonly WorkspaceZoneId[]> = {
|
|
10179
|
+
readonly Hand: ZoneCardsComponent;
|
|
10180
|
+
readonly Card: ZoneCardComponent;
|
|
10181
|
+
readonly slot: {
|
|
10182
|
+
readonly card: CardSurfaceInputSlot<Zones[number] & string>;
|
|
10183
|
+
};
|
|
10184
|
+
};
|
|
10185
|
+
|
|
10186
|
+
export type PileSurface<Zones extends readonly WorkspaceZoneId[] = readonly WorkspaceZoneId[]> = {
|
|
10187
|
+
readonly Pile: ZoneCardsComponent;
|
|
10188
|
+
readonly Card: ZoneCardComponent;
|
|
10189
|
+
};
|
|
10190
|
+
|
|
10191
|
+
export type CardCollectionSurface<Zones extends readonly WorkspaceZoneId[] = readonly WorkspaceZoneId[]> = {
|
|
10192
|
+
readonly Collection: ZoneCardsComponent;
|
|
10193
|
+
readonly Card: ZoneCardComponent;
|
|
10194
|
+
readonly slot: {
|
|
10195
|
+
readonly card: CardSurfaceInputSlot<Zones[number] & string>;
|
|
10196
|
+
};
|
|
10197
|
+
};
|
|
10198
|
+
|
|
10199
|
+
export type InteractionFormInputs<Key extends InteractionKey> = {
|
|
10200
|
+
[Input in InteractionInputKeysOf<Key>]: (
|
|
10201
|
+
slot: InteractionInputSlot<Key, Input>,
|
|
10202
|
+
) => ReactNode;
|
|
10203
|
+
};
|
|
10204
|
+
|
|
10205
|
+
export type InteractionCollectSlots<Key extends InteractionKey> = {
|
|
10206
|
+
[Input in RequiredInteractionInputKeysOf<Key>]: InteractionCollectorSlot<
|
|
10207
|
+
Key,
|
|
10208
|
+
Input
|
|
10209
|
+
>;
|
|
9543
10210
|
};
|
|
9544
10211
|
|
|
10212
|
+
export type InteractionRoute<Key extends InteractionKey> = {
|
|
10213
|
+
readonly collect: InteractionCollectSlots<Key>;
|
|
10214
|
+
};
|
|
10215
|
+
|
|
10216
|
+
export type InteractionRoutes = {
|
|
10217
|
+
[Key in InteractionKey]: InteractionRoute<Key>;
|
|
10218
|
+
};
|
|
10219
|
+
|
|
10220
|
+
export type InteractionRoutesProps = {
|
|
10221
|
+
routes: InteractionRoutes;
|
|
10222
|
+
fallback?: ReactNode;
|
|
10223
|
+
includeUnavailable?: boolean | null;
|
|
10224
|
+
};
|
|
10225
|
+
|
|
10226
|
+
export type ZeroInputInteractionKey = {
|
|
10227
|
+
[K in InteractionKey]: InteractionInputKeysOf<K> extends never
|
|
10228
|
+
? K
|
|
10229
|
+
: never;
|
|
10230
|
+
}[InteractionKey];
|
|
10231
|
+
|
|
10232
|
+
export type InputInteractionKey = Exclude<
|
|
10233
|
+
InteractionKey,
|
|
10234
|
+
ZeroInputInteractionKey
|
|
10235
|
+
>;
|
|
10236
|
+
|
|
9545
10237
|
type InteractionInputKeyOf<Key extends InteractionKey> =
|
|
9546
10238
|
Key extends InteractionKey ? InteractionInputKeysOf<Key> : never;
|
|
9547
10239
|
|
|
@@ -9645,17 +10337,14 @@ export type HexBoardGridProps<
|
|
|
9645
10337
|
"board" | "interactions"
|
|
9646
10338
|
> & {
|
|
9647
10339
|
board: Id;
|
|
9648
|
-
interactions?:
|
|
9649
|
-
| "auto"
|
|
9650
|
-
| false
|
|
9651
|
-
| {
|
|
9652
|
-
edge?: readonly InteractionKey[];
|
|
9653
|
-
vertex?: readonly InteractionKey[];
|
|
9654
|
-
space?: readonly InteractionKey[];
|
|
9655
|
-
};
|
|
9656
10340
|
};
|
|
9657
10341
|
|
|
9658
|
-
type WorkspaceBoard =
|
|
10342
|
+
type WorkspaceBoard = {
|
|
10343
|
+
useSurface(name: string): BoardSurface;
|
|
10344
|
+
useSurface<const Board extends BoardSurfaceBoardId>(
|
|
10345
|
+
name: string,
|
|
10346
|
+
options: { board: Board },
|
|
10347
|
+
): BoardSurface<Board>;
|
|
9659
10348
|
HexView<
|
|
9660
10349
|
const Id extends HexBoardId,
|
|
9661
10350
|
const TSpaceView extends { id: HexBoardSpaceId<Id> },
|
|
@@ -9688,146 +10377,96 @@ type WorkspaceZoneCard = ZoneCardRenderItem<
|
|
|
9688
10377
|
: never
|
|
9689
10378
|
: never;
|
|
9690
10379
|
|
|
9691
|
-
type
|
|
9692
|
-
|
|
9693
|
-
|
|
9694
|
-
|
|
9695
|
-
|
|
9696
|
-
|
|
9697
|
-
|
|
9698
|
-
|
|
9699
|
-
|
|
9700
|
-
|
|
9701
|
-
|
|
9702
|
-
|
|
9703
|
-
|
|
9704
|
-
|
|
9705
|
-
|
|
9706
|
-
zone?: WorkspaceZoneId;
|
|
9707
|
-
children?: ReactNode | ((card: WorkspaceZoneCard) => ReactNode);
|
|
9708
|
-
},
|
|
9709
|
-
): ReactElement | null;
|
|
9710
|
-
List(
|
|
9711
|
-
props: Omit<ZoneListProps, "children"> & {
|
|
9712
|
-
children?: ReactNode | ((card: WorkspaceZoneCard) => ReactNode);
|
|
9713
|
-
},
|
|
9714
|
-
): ReactElement;
|
|
9715
|
-
PileCards(
|
|
9716
|
-
props: Omit<ZonePileCardsProps, "renderCard"> & {
|
|
9717
|
-
renderCard: (card: WorkspaceZoneCard) => ReactNode;
|
|
9718
|
-
},
|
|
9719
|
-
): ReactElement | null;
|
|
10380
|
+
type HandRole = "primary" | "auxiliary" | "task";
|
|
10381
|
+
|
|
10382
|
+
type WorkspaceZone = {
|
|
10383
|
+
useHand<const Zone extends PlayerCardZoneId>(
|
|
10384
|
+
name: string,
|
|
10385
|
+
options: { zone: Zone; role: HandRole; label: string; order?: number },
|
|
10386
|
+
): HandSurface<readonly [Zone]>;
|
|
10387
|
+
usePile<const Zone extends CardZoneId>(
|
|
10388
|
+
name: string,
|
|
10389
|
+
options: { zone: Zone },
|
|
10390
|
+
): PileSurface<readonly [Zone]>;
|
|
10391
|
+
useCardCollection<const Zones extends readonly CardZoneId[]>(
|
|
10392
|
+
name: string,
|
|
10393
|
+
options: { zones: Zones; mode?: "all" | "top-card" },
|
|
10394
|
+
): CardCollectionSurface<Zones>;
|
|
9720
10395
|
};
|
|
9721
10396
|
|
|
9722
10397
|
type WorkspaceUI = Omit<
|
|
9723
10398
|
DreamboardUI<typeof uiContract>,
|
|
9724
|
-
"Root" | "Game" | "Interaction" | "Board" | "Zone"
|
|
10399
|
+
"Root" | "Game" | "Interaction" | "Board" | "Zone" | "Prompt" | "PromptInbox"
|
|
9725
10400
|
> & {
|
|
9726
10401
|
Root(props: UIRootProps): ReactElement;
|
|
9727
10402
|
readonly Game: TypedGame<typeof uiContract, GameView, PlayerId, PhaseName>;
|
|
9728
|
-
readonly Interaction:
|
|
9729
|
-
|
|
9730
|
-
|
|
9731
|
-
> & {
|
|
9732
|
-
Switch(props: InteractionSwitchProps): ReactElement;
|
|
10403
|
+
readonly Interaction: Pick<DreamboardUI<typeof uiContract>["Interaction"], "State" | "Dialog"> & {
|
|
10404
|
+
useForm<Key extends InteractionKey>(interaction: Key): InteractionFormSurface<Key>;
|
|
10405
|
+
Routes(props: InteractionRoutesProps): ReactElement;
|
|
9733
10406
|
};
|
|
9734
10407
|
readonly Board: WorkspaceBoard;
|
|
9735
10408
|
readonly Zone: WorkspaceZone;
|
|
9736
10409
|
readonly ResourceCounter: ResourceCounterComponents<ResourceId>;
|
|
9737
10410
|
};
|
|
9738
10411
|
|
|
9739
|
-
|
|
9740
|
-
|
|
9741
|
-
const
|
|
9742
|
-
|
|
9743
|
-
>;
|
|
10412
|
+
function formInputKeysForInteraction(interaction: string): Set<string> {
|
|
10413
|
+
const [phase, id] = interaction.split(".", 2);
|
|
10414
|
+
const phaseSpec = phase ? (game.phases as Record<string, unknown>)[phase] : undefined;
|
|
10415
|
+
const phaseRecord = phaseSpec as {
|
|
10416
|
+
interactions?: Record<string, { inputs?: Record<string, { kind?: string }> }>;
|
|
10417
|
+
cardActions?: Record<string, { inputs?: Record<string, { kind?: string }> }>;
|
|
10418
|
+
submit?: { inputs?: Record<string, { kind?: string }> };
|
|
10419
|
+
} | undefined;
|
|
10420
|
+
const spec =
|
|
10421
|
+
(id ? phaseRecord?.interactions?.[id] : undefined) ??
|
|
10422
|
+
(id ? phaseRecord?.cardActions?.[id] : undefined) ??
|
|
10423
|
+
(id === "submit" ? phaseRecord?.submit : undefined);
|
|
10424
|
+
return new Set(
|
|
10425
|
+
Object.entries((spec?.inputs ?? {}) as Record<string, { kind?: string }>)
|
|
10426
|
+
.filter(
|
|
10427
|
+
([, collector]) =>
|
|
10428
|
+
collector.kind === "form" || collector.kind === "prompt",
|
|
10429
|
+
)
|
|
10430
|
+
.map(([input]) => input),
|
|
10431
|
+
);
|
|
10432
|
+
}
|
|
9744
10433
|
|
|
9745
|
-
const
|
|
9746
|
-
|
|
9747
|
-
|
|
9748
|
-
|
|
9749
|
-
|
|
9750
|
-
|
|
9751
|
-
|
|
9752
|
-
|
|
9753
|
-
|
|
9754
|
-
|
|
9755
|
-
|
|
9756
|
-
|
|
9757
|
-
|
|
9758
|
-
|
|
9759
|
-
|
|
9760
|
-
|
|
9761
|
-
|
|
9762
|
-
|
|
9763
|
-
|
|
9764
|
-
|
|
9765
|
-
board: hexStaticBoards[boardId],
|
|
9766
|
-
});
|
|
9767
|
-
},
|
|
9768
|
-
HexGrid<
|
|
9769
|
-
const Id extends HexBoardId,
|
|
9770
|
-
const TSpaceView extends { id: HexBoardSpaceId<Id> },
|
|
9771
|
-
>({ board: boardId, ...props }: HexBoardGridProps<Id, TSpaceView>) {
|
|
9772
|
-
return createElement(baseUI.Board.HexGrid<HexBoardTopology<Id>, TSpaceView>, {
|
|
9773
|
-
...props,
|
|
9774
|
-
board: hexStaticBoards[boardId],
|
|
9775
|
-
});
|
|
9776
|
-
},
|
|
9777
|
-
} as WorkspaceUI["Board"];
|
|
9778
|
-
|
|
9779
|
-
export const UI: WorkspaceUI = {
|
|
9780
|
-
...baseUI,
|
|
9781
|
-
Board,
|
|
9782
|
-
ResourceCounter: resourceCounter,
|
|
9783
|
-
};
|
|
10434
|
+
export const UI = createWorkspaceUIContract<
|
|
10435
|
+
WorkspaceUI,
|
|
10436
|
+
typeof uiContract,
|
|
10437
|
+
ResourceId,
|
|
10438
|
+
WorkspaceZoneCard,
|
|
10439
|
+
typeof hexStaticBoards
|
|
10440
|
+
>({
|
|
10441
|
+
uiContract,
|
|
10442
|
+
clientParamSchemasByPhase: createClientParamSchemasByPhase(game) as ClientParamSchemaMap,
|
|
10443
|
+
formInputKeysForInteraction,
|
|
10444
|
+
resourceIds: literals.resourceIds as readonly ResourceId[],
|
|
10445
|
+
resourcePresentationById: literals.resourcePresentationById as Partial<
|
|
10446
|
+
Record<string, { label?: string; icon?: string }>
|
|
10447
|
+
>,
|
|
10448
|
+
hexStaticBoards,
|
|
10449
|
+
cardIdFromZoneCard: (card) => card.id,
|
|
10450
|
+
zoneIdFromZoneCard: (card) => card.zone,
|
|
10451
|
+
});
|
|
10452
|
+
export const Board: WorkspaceUI["Board"] = UI.Board;
|
|
10453
|
+
export const Zone: WorkspaceUI["Zone"] = UI.Zone;
|
|
9784
10454
|
export const Game: WorkspaceUI["Game"] = UI.Game;
|
|
9785
10455
|
export const Interaction = UI.Interaction;
|
|
9786
|
-
export const Prompt = UI.Prompt;
|
|
9787
|
-
export const PromptInbox = UI.PromptInbox;
|
|
9788
10456
|
export const PlayerRoster: WorkspaceUI["PlayerRoster"] = UI.PlayerRoster;
|
|
9789
10457
|
export const Dice: WorkspaceUI["Dice"] = UI.Dice;
|
|
9790
10458
|
export const Phase = UI.Phase;
|
|
9791
|
-
export const Zone = UI.Zone;
|
|
9792
10459
|
export const ResourceCounter: WorkspaceUI["ResourceCounter"] = UI.ResourceCounter;
|
|
9793
10460
|
|
|
9794
|
-
export type InteractionFieldRenderers<Key extends InteractionKey> =
|
|
9795
|
-
InteractionFieldRenderMap<InteractionParamsShape<Key>>;
|
|
9796
|
-
|
|
9797
|
-
export type InteractionFieldProps<
|
|
9798
|
-
Key extends InteractionKey,
|
|
9799
|
-
InputKey extends keyof InteractionParamsShape<Key> & string,
|
|
9800
|
-
> = Omit<
|
|
9801
|
-
InteractionFieldPropsGeneric<InteractionParamsShape<Key>, InputKey>,
|
|
9802
|
-
"descriptor" | "handle"
|
|
9803
|
-
> & {
|
|
9804
|
-
descriptor: InteractionDescriptorFor<Key>;
|
|
9805
|
-
handle: InteractionHandle<
|
|
9806
|
-
InteractionParamsShape<Key>,
|
|
9807
|
-
InteractionHandleDefaultedKeys<Key>
|
|
9808
|
-
>;
|
|
9809
|
-
};
|
|
9810
|
-
|
|
9811
10461
|
export const clientParamSchemasByPhase = createClientParamSchemasByPhase(
|
|
9812
10462
|
game,
|
|
9813
10463
|
) as ClientParamSchemaMap;
|
|
9814
|
-
|
|
9815
|
-
export function InteractionField<
|
|
9816
|
-
Key extends InteractionKey,
|
|
9817
|
-
InputKey extends keyof InteractionParamsShape<Key> & string,
|
|
9818
|
-
>(props: InteractionFieldProps<Key, InputKey>): ReactElement | null {
|
|
9819
|
-
return createElement(
|
|
9820
|
-
InteractionFieldGeneric<InteractionParamsShape<Key>, InputKey>,
|
|
9821
|
-
props,
|
|
9822
|
-
);
|
|
9823
|
-
}
|
|
9824
10464
|
`;
|
|
9825
10465
|
}
|
|
9826
10466
|
function generateReducerSupportSeed() {
|
|
9827
10467
|
return `import {
|
|
9828
|
-
|
|
10468
|
+
createReducerEdit,
|
|
9829
10469
|
createStateQueries,
|
|
9830
|
-
pipe,
|
|
9831
10470
|
} from "@dreamboard/app-sdk/reducer";
|
|
9832
10471
|
import type { GameState } from "./game-contract";
|
|
9833
10472
|
|
|
@@ -9846,16 +10485,12 @@ import type { GameState } from "./game-contract";
|
|
|
9846
10485
|
*
|
|
9847
10486
|
* Recommended authoring pattern inside a phase reducer:
|
|
9848
10487
|
*
|
|
9849
|
-
* const
|
|
9850
|
-
*
|
|
9851
|
-
*
|
|
9852
|
-
* );
|
|
9853
|
-
* return accept(next);
|
|
10488
|
+
* const tx = edit(state);
|
|
10489
|
+
* tx.setActivePlayers([q.players.order()[0]]);
|
|
10490
|
+
* return accept(tx.state);
|
|
9854
10491
|
*/
|
|
9855
10492
|
|
|
9856
|
-
export const
|
|
9857
|
-
|
|
9858
|
-
export { pipe };
|
|
10493
|
+
export const edit = createReducerEdit<GameState>();
|
|
9859
10494
|
|
|
9860
10495
|
export function stateQueries(state: GameState) {
|
|
9861
10496
|
return createStateQueries(state);
|
|
@@ -10014,18 +10649,48 @@ function isFrameworkOwnedSetupProfilesSeed(content) {
|
|
|
10014
10649
|
}
|
|
10015
10650
|
function generateSetupPhaseSeed() {
|
|
10016
10651
|
return `import { z } from "zod";
|
|
10017
|
-
import type { GameContract } from "../game-contract";
|
|
10018
|
-
import {
|
|
10652
|
+
import type { GameContract, GameState } from "../game-contract";
|
|
10653
|
+
import {
|
|
10654
|
+
defineInteraction,
|
|
10655
|
+
definePhase,
|
|
10656
|
+
formInput,
|
|
10657
|
+
} from "@dreamboard/app-sdk/reducer";
|
|
10658
|
+
import { edit } from "../reducer-support";
|
|
10659
|
+
|
|
10660
|
+
const setupMoodChoices = [
|
|
10661
|
+
{ value: "ready", label: "Ready" },
|
|
10662
|
+
{ value: "exploring", label: "Exploring" },
|
|
10663
|
+
] as const;
|
|
10664
|
+
type SetupMood = (typeof setupMoodChoices)[number]["value"];
|
|
10665
|
+
const setupPhaseStateSchema = z.object({});
|
|
10019
10666
|
|
|
10020
10667
|
// A single phase file is fine while the phase is small. When a phase grows
|
|
10021
10668
|
// multiple action families, move it to app/phases/<phase>/index.ts and split
|
|
10022
10669
|
// interactions into neighboring concept files.
|
|
10023
10670
|
export const setup = definePhase<GameContract>()({
|
|
10024
|
-
kind: "
|
|
10025
|
-
state:
|
|
10671
|
+
kind: "player",
|
|
10672
|
+
state: setupPhaseStateSchema,
|
|
10026
10673
|
initialState: () => ({}),
|
|
10027
|
-
|
|
10028
|
-
|
|
10674
|
+
actor: ({ state }) => state.publicState.currentPlayerId,
|
|
10675
|
+
interactions: {
|
|
10676
|
+
submit: defineInteraction<GameContract, typeof setupPhaseStateSchema>()({
|
|
10677
|
+
inputs: {
|
|
10678
|
+
mood: formInput.choice<SetupMood, GameState>({
|
|
10679
|
+
choices: setupMoodChoices,
|
|
10680
|
+
defaultValue: "ready",
|
|
10681
|
+
}),
|
|
10682
|
+
},
|
|
10683
|
+
reduce({ state, input, accept }) {
|
|
10684
|
+
const tx = edit(state);
|
|
10685
|
+
tx.patchPublicState({
|
|
10686
|
+
notesByPlayerId: {
|
|
10687
|
+
...state.publicState.notesByPlayerId,
|
|
10688
|
+
[input.playerId]: input.params.mood,
|
|
10689
|
+
},
|
|
10690
|
+
});
|
|
10691
|
+
return accept(tx.state);
|
|
10692
|
+
},
|
|
10693
|
+
}),
|
|
10029
10694
|
},
|
|
10030
10695
|
});
|
|
10031
10696
|
`;
|
|
@@ -10107,55 +10772,142 @@ function generateUiFrameworkTsConfig() {
|
|
|
10107
10772
|
`;
|
|
10108
10773
|
}
|
|
10109
10774
|
function generateReducerUiAppContent() {
|
|
10110
|
-
return `import {
|
|
10775
|
+
return `import { ToastProvider } from "@dreamboard/ui-sdk";
|
|
10776
|
+
import { Game, Interaction, Phase, UI } from "@dreamboard/ui-contract";
|
|
10777
|
+
import { SetupInteractionRoutes } from "./interaction-routes";
|
|
10778
|
+
import { SetupScreen } from "./setup-screen";
|
|
10111
10779
|
|
|
10112
10780
|
function SetupPhase() {
|
|
10781
|
+
const setupForm = Interaction.useForm("setup.submit");
|
|
10782
|
+
|
|
10113
10783
|
return (
|
|
10114
|
-
|
|
10115
|
-
<
|
|
10116
|
-
|
|
10117
|
-
|
|
10118
|
-
|
|
10119
|
-
|
|
10120
|
-
|
|
10121
|
-
|
|
10122
|
-
|
|
10123
|
-
|
|
10124
|
-
|
|
10125
|
-
|
|
10126
|
-
|
|
10127
|
-
|
|
10128
|
-
|
|
10129
|
-
|
|
10130
|
-
|
|
10131
|
-
|
|
10132
|
-
</Prompt.Root>
|
|
10784
|
+
<>
|
|
10785
|
+
<SetupScreen />
|
|
10786
|
+
<SetupInteractionRoutes form={setupForm} />
|
|
10787
|
+
</>
|
|
10788
|
+
);
|
|
10789
|
+
}
|
|
10790
|
+
|
|
10791
|
+
export default function App() {
|
|
10792
|
+
return (
|
|
10793
|
+
<ToastProvider>
|
|
10794
|
+
<UI.Root>
|
|
10795
|
+
<Game.Root>
|
|
10796
|
+
{() => (
|
|
10797
|
+
<Phase.Switch
|
|
10798
|
+
routes={{
|
|
10799
|
+
setup: () => <SetupPhase />,
|
|
10800
|
+
}}
|
|
10801
|
+
/>
|
|
10133
10802
|
)}
|
|
10134
|
-
</
|
|
10135
|
-
</
|
|
10803
|
+
</Game.Root>
|
|
10804
|
+
</UI.Root>
|
|
10805
|
+
</ToastProvider>
|
|
10806
|
+
);
|
|
10807
|
+
}
|
|
10808
|
+
`;
|
|
10809
|
+
}
|
|
10810
|
+
function generateReducerUiSetupScreenContent() {
|
|
10811
|
+
return `import { PANEL_CLASS, SHELL_CLASS } from "./styles";
|
|
10812
|
+
|
|
10813
|
+
export function SetupScreen() {
|
|
10814
|
+
return (
|
|
10815
|
+
<main className={SHELL_CLASS}>
|
|
10816
|
+
<section className={PANEL_CLASS}>
|
|
10817
|
+
<p className="text-xs font-bold uppercase tracking-[0.14em] text-slate-500">
|
|
10818
|
+
Setup
|
|
10819
|
+
</p>
|
|
10820
|
+
<h1 className="text-2xl font-bold text-slate-950">Your game starts here</h1>
|
|
10821
|
+
<p className="max-w-prose text-sm leading-6 text-slate-600">
|
|
10822
|
+
Replace this screen with your board, hands, mats, and table state.
|
|
10823
|
+
Keep interaction wiring in the route file so visual components stay
|
|
10824
|
+
focused on layout and styling.
|
|
10825
|
+
</p>
|
|
10826
|
+
</section>
|
|
10136
10827
|
</main>
|
|
10137
10828
|
);
|
|
10138
10829
|
}
|
|
10830
|
+
`;
|
|
10831
|
+
}
|
|
10832
|
+
function generateReducerUiInteractionRoutesContent() {
|
|
10833
|
+
return `import {
|
|
10834
|
+
Interaction,
|
|
10835
|
+
type InteractionFormSurface,
|
|
10836
|
+
} from "@dreamboard/ui-contract";
|
|
10837
|
+
import { ACTION_BUTTON_CLASS, PANEL_CLASS } from "./styles";
|
|
10139
10838
|
|
|
10140
|
-
export
|
|
10839
|
+
export function SetupInteractionRoutes({
|
|
10840
|
+
form,
|
|
10841
|
+
}: {
|
|
10842
|
+
form: InteractionFormSurface<"setup.submit">;
|
|
10843
|
+
}) {
|
|
10141
10844
|
return (
|
|
10142
|
-
|
|
10143
|
-
|
|
10144
|
-
|
|
10145
|
-
|
|
10146
|
-
|
|
10147
|
-
|
|
10148
|
-
|
|
10149
|
-
|
|
10150
|
-
|
|
10845
|
+
<>
|
|
10846
|
+
<Interaction.Routes
|
|
10847
|
+
routes={{
|
|
10848
|
+
"setup.submit": {
|
|
10849
|
+
collect: {
|
|
10850
|
+
mood: form.slot.mood,
|
|
10851
|
+
},
|
|
10852
|
+
},
|
|
10853
|
+
}}
|
|
10854
|
+
/>
|
|
10855
|
+
<aside className={PANEL_CLASS}>
|
|
10856
|
+
<div className="grid gap-2">
|
|
10857
|
+
<p className="text-sm font-bold text-slate-950">Ready check</p>
|
|
10858
|
+
<form.slot.mood.Field />
|
|
10859
|
+
<form.Submit className={ACTION_BUTTON_CLASS}>
|
|
10860
|
+
Start building
|
|
10861
|
+
</form.Submit>
|
|
10862
|
+
</div>
|
|
10863
|
+
</aside>
|
|
10864
|
+
</>
|
|
10151
10865
|
);
|
|
10152
10866
|
}
|
|
10153
10867
|
`;
|
|
10154
10868
|
}
|
|
10869
|
+
function generateReducerUiStylesContent() {
|
|
10870
|
+
return `export const SHELL_CLASS =
|
|
10871
|
+
"min-h-screen bg-[#f8fafc] p-6 text-slate-950";
|
|
10872
|
+
|
|
10873
|
+
export const PANEL_CLASS =
|
|
10874
|
+
"mx-auto grid max-w-3xl gap-4 rounded-lg border border-slate-200 bg-white p-5 shadow-sm";
|
|
10875
|
+
|
|
10876
|
+
export const ACTION_BUTTON_CLASS =
|
|
10877
|
+
"rounded-md bg-slate-950 px-4 py-2 text-sm font-bold text-white disabled:cursor-not-allowed disabled:opacity-50";
|
|
10878
|
+
`;
|
|
10879
|
+
}
|
|
10880
|
+
function generateReducerUiContractTypingSmokeContent() {
|
|
10881
|
+
return `import { Interaction } from "@dreamboard/ui-contract";
|
|
10882
|
+
|
|
10883
|
+
export function UiContractTypingSmoke() {
|
|
10884
|
+
const form = Interaction.useForm("setup.submit");
|
|
10885
|
+
|
|
10886
|
+
return (
|
|
10887
|
+
<Interaction.Routes
|
|
10888
|
+
routes={{
|
|
10889
|
+
"setup.submit": {
|
|
10890
|
+
collect: {
|
|
10891
|
+
mood: form.slot.mood,
|
|
10892
|
+
},
|
|
10893
|
+
},
|
|
10894
|
+
}}
|
|
10895
|
+
/>
|
|
10896
|
+
);
|
|
10897
|
+
}
|
|
10898
|
+
|
|
10899
|
+
// @ts-expect-error generated contracts hide legacy interaction roots.
|
|
10900
|
+
Interaction.Root({ interaction: "setup.submit", children: null });
|
|
10901
|
+
`;
|
|
10902
|
+
}
|
|
10155
10903
|
function generateSeedFiles(manifest) {
|
|
10156
10904
|
return {
|
|
10157
10905
|
"app/README.md": generateAppReadmeSeed(),
|
|
10158
10906
|
"ui/App.tsx": generateReducerUiAppContent(),
|
|
10907
|
+
"ui/interaction-routes.tsx": generateReducerUiInteractionRoutesContent(),
|
|
10908
|
+
"ui/setup-screen.tsx": generateReducerUiSetupScreenContent(),
|
|
10909
|
+
"ui/styles.ts": generateReducerUiStylesContent(),
|
|
10910
|
+
"ui/ui-contract-typing-smoke.tsx": generateReducerUiContractTypingSmokeContent(),
|
|
10159
10911
|
"app/game-contract.ts": generateReducerGameContractSeed(),
|
|
10160
10912
|
"app/game.ts": generateReducerGameSeed(),
|
|
10161
10913
|
"app/setup-profiles.ts": generateSetupProfilesSeed(manifest),
|
|
@@ -10315,7 +11067,9 @@ function resolveRepoLocalPackageSource(specifier, options) {
|
|
|
10315
11067
|
} catch {
|
|
10316
11068
|
return null;
|
|
10317
11069
|
}
|
|
10318
|
-
const packageInfo = readPackageInfos(repoRoot).get(
|
|
11070
|
+
const packageInfo = readPackageInfos(repoRoot).get(
|
|
11071
|
+
parsedSpecifier.packageName
|
|
11072
|
+
);
|
|
10319
11073
|
if (!packageInfo) {
|
|
10320
11074
|
return null;
|
|
10321
11075
|
}
|
|
@@ -10723,8 +11477,10 @@ type InteractionKeyForId<Id extends InteractionId> = Extract<
|
|
|
10723
11477
|
InteractionKey,
|
|
10724
11478
|
\`\${string}.\${Id}\`
|
|
10725
11479
|
>;
|
|
11480
|
+
type InteractionParamsForKey<Key extends InteractionKey> =
|
|
11481
|
+
Key extends InteractionKey ? InteractionParamsOf<Key> : never;
|
|
10726
11482
|
type InteractionParamsOfId<Id extends InteractionId> =
|
|
10727
|
-
|
|
11483
|
+
InteractionParamsForKey<InteractionKeyForId<Id>>;
|
|
10728
11484
|
|
|
10729
11485
|
export interface BrowserRunnerSnapshot {
|
|
10730
11486
|
sessionId: string | null;
|
|
@@ -11573,11 +12329,29 @@ function setLatestCompileAttempt(projectConfig, attempt) {
|
|
|
11573
12329
|
function updateProjectLocalMaintainerRegistry(projectConfig, localMaintainerRegistry) {
|
|
11574
12330
|
return {
|
|
11575
12331
|
...projectConfig,
|
|
11576
|
-
localMaintainerRegistry
|
|
12332
|
+
localMaintainerRegistry: sanitizeProjectLocalMaintainerRegistry(
|
|
12333
|
+
localMaintainerRegistry
|
|
12334
|
+
)
|
|
12335
|
+
};
|
|
12336
|
+
}
|
|
12337
|
+
function sanitizeProjectLocalMaintainerRegistry(localMaintainerRegistry) {
|
|
12338
|
+
if (!localMaintainerRegistry?.packages.dreamboard) {
|
|
12339
|
+
return localMaintainerRegistry;
|
|
12340
|
+
}
|
|
12341
|
+
const { dreamboard: _dreamboard, ...packages } = localMaintainerRegistry.packages;
|
|
12342
|
+
return {
|
|
12343
|
+
...localMaintainerRegistry,
|
|
12344
|
+
packages
|
|
11577
12345
|
};
|
|
11578
12346
|
}
|
|
11579
12347
|
|
|
11580
12348
|
// src/services/project/workspace-codegen.ts
|
|
12349
|
+
var STARTER_UI_SEED_FILES = /* @__PURE__ */ new Set([
|
|
12350
|
+
"ui/interaction-routes.tsx",
|
|
12351
|
+
"ui/setup-screen.tsx",
|
|
12352
|
+
"ui/styles.ts",
|
|
12353
|
+
"ui/ui-contract-typing-smoke.tsx"
|
|
12354
|
+
]);
|
|
11581
12355
|
async function applyWorkspaceCodegen(options) {
|
|
11582
12356
|
const { projectRoot, manifest } = options;
|
|
11583
12357
|
const authoritativeFiles = generateAuthoritativeFiles(manifest);
|
|
@@ -11585,6 +12359,10 @@ async function applyWorkspaceCodegen(options) {
|
|
|
11585
12359
|
const written = [];
|
|
11586
12360
|
const skipped = [];
|
|
11587
12361
|
const merged = [];
|
|
12362
|
+
const existingUiAppBeforeSeeds = await readTextFileIfExists(
|
|
12363
|
+
`${projectRoot}/ui/App.tsx`
|
|
12364
|
+
);
|
|
12365
|
+
const shouldWriteStarterUiSeedFiles = existingUiAppBeforeSeeds === null || existingUiAppBeforeSeeds.trim().length === 0;
|
|
11588
12366
|
for (const [relativePath, content] of Object.entries(authoritativeFiles)) {
|
|
11589
12367
|
const filePath = `${projectRoot}/${relativePath}`;
|
|
11590
12368
|
const existingContent = await readTextFileIfExists(filePath);
|
|
@@ -11596,6 +12374,10 @@ async function applyWorkspaceCodegen(options) {
|
|
|
11596
12374
|
for (const [relativePath, content] of Object.entries(seedFiles)) {
|
|
11597
12375
|
const filePath = `${projectRoot}/${relativePath}`;
|
|
11598
12376
|
const existingContent = await readTextFileIfExists(filePath);
|
|
12377
|
+
if (STARTER_UI_SEED_FILES.has(relativePath) && !shouldWriteStarterUiSeedFiles && existingContent === null) {
|
|
12378
|
+
skipped.push(relativePath);
|
|
12379
|
+
continue;
|
|
12380
|
+
}
|
|
11599
12381
|
const shouldRefreshFrameworkSeed = relativePath === "app/setup-profiles.ts" && isFrameworkOwnedSetupProfilesSeed(existingContent);
|
|
11600
12382
|
if (shouldRefreshFrameworkSeed) {
|
|
11601
12383
|
await writeTextFile(filePath, content);
|
|
@@ -11845,7 +12627,7 @@ function buildRemoteAlignedSnapshotFiles(options) {
|
|
|
11845
12627
|
|
|
11846
12628
|
// src/services/project/local-maintainer-registry.ts
|
|
11847
12629
|
import { spawn } from "child_process";
|
|
11848
|
-
import { existsSync as existsSync4 } from "fs";
|
|
12630
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
|
|
11849
12631
|
import path10 from "path";
|
|
11850
12632
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
11851
12633
|
|
|
@@ -11884,16 +12666,34 @@ function getCliPackageRoot() {
|
|
|
11884
12666
|
"dreamboard-cli"
|
|
11885
12667
|
);
|
|
11886
12668
|
} catch {
|
|
11887
|
-
return
|
|
12669
|
+
return resolveInstalledCliPackageRoot(MODULE_DIR);
|
|
12670
|
+
}
|
|
12671
|
+
}
|
|
12672
|
+
function resolveInstalledCliPackageRoot(moduleDir) {
|
|
12673
|
+
let current = moduleDir;
|
|
12674
|
+
while (true) {
|
|
12675
|
+
const packageJsonPath = path10.join(current, "package.json");
|
|
12676
|
+
if (existsSync4(packageJsonPath)) {
|
|
12677
|
+
try {
|
|
12678
|
+
const packageJson = JSON.parse(
|
|
12679
|
+
readFileSync3(packageJsonPath, "utf8")
|
|
12680
|
+
);
|
|
12681
|
+
if (packageJson.name === "dreamboard" || packageJson.name === "dreamboard-cli") {
|
|
12682
|
+
return current;
|
|
12683
|
+
}
|
|
12684
|
+
} catch {
|
|
12685
|
+
}
|
|
12686
|
+
}
|
|
12687
|
+
const parent = path10.dirname(current);
|
|
12688
|
+
if (parent === current) {
|
|
12689
|
+
return moduleDir;
|
|
12690
|
+
}
|
|
12691
|
+
current = parent;
|
|
11888
12692
|
}
|
|
11889
12693
|
}
|
|
11890
12694
|
function getScriptInvocation() {
|
|
11891
12695
|
const cliPackageRoot = getCliPackageRoot();
|
|
11892
|
-
const scriptPath =
|
|
11893
|
-
cliPackageRoot,
|
|
11894
|
-
"scripts",
|
|
11895
|
-
"local-maintainer-registry.ts"
|
|
11896
|
-
);
|
|
12696
|
+
const scriptPath = getLocalMaintainerScriptPath(cliPackageRoot);
|
|
11897
12697
|
if (!existsSync4(scriptPath)) {
|
|
11898
12698
|
throw new Error(
|
|
11899
12699
|
[
|
|
@@ -11911,6 +12711,17 @@ function getScriptInvocation() {
|
|
|
11911
12711
|
cwd: cliPackageRoot
|
|
11912
12712
|
};
|
|
11913
12713
|
}
|
|
12714
|
+
function getLocalMaintainerScriptPath(cliPackageRoot) {
|
|
12715
|
+
return path10.join(cliPackageRoot, "scripts", "local-maintainer-registry.ts");
|
|
12716
|
+
}
|
|
12717
|
+
function isInstalledCliPackageRoot(cliPackageRoot) {
|
|
12718
|
+
return cliPackageRoot.split(path10.sep).includes("node_modules");
|
|
12719
|
+
}
|
|
12720
|
+
function shouldSkipLocalMaintainerHelper() {
|
|
12721
|
+
const cliPackageRoot = getCliPackageRoot();
|
|
12722
|
+
const scriptPath = getLocalMaintainerScriptPath(cliPackageRoot);
|
|
12723
|
+
return !existsSync4(scriptPath) && isInstalledCliPackageRoot(cliPackageRoot);
|
|
12724
|
+
}
|
|
11914
12725
|
function buildScriptSetupError(options) {
|
|
11915
12726
|
return new Error(
|
|
11916
12727
|
[
|
|
@@ -11922,6 +12733,15 @@ ${options.stderr.trim()}` : null
|
|
|
11922
12733
|
].filter(Boolean).join("\n")
|
|
11923
12734
|
);
|
|
11924
12735
|
}
|
|
12736
|
+
function parseJsonPayload(output) {
|
|
12737
|
+
const payload = output.trim().split(/\r?\n/).map((line) => line.trim()).reverse().find(
|
|
12738
|
+
(line) => line === "null" || line.startsWith("{") || line.startsWith("[")
|
|
12739
|
+
);
|
|
12740
|
+
if (!payload) {
|
|
12741
|
+
throw new Error("completed without returning a JSON payload");
|
|
12742
|
+
}
|
|
12743
|
+
return JSON.parse(payload);
|
|
12744
|
+
}
|
|
11925
12745
|
async function runLocalMaintainerScript(args) {
|
|
11926
12746
|
const invocation = getScriptInvocation();
|
|
11927
12747
|
return new Promise((resolve, reject) => {
|
|
@@ -11975,7 +12795,7 @@ async function runLocalMaintainerScript(args) {
|
|
|
11975
12795
|
return;
|
|
11976
12796
|
}
|
|
11977
12797
|
try {
|
|
11978
|
-
resolve(
|
|
12798
|
+
resolve(parseJsonPayload(trimmedStdout));
|
|
11979
12799
|
} catch (error) {
|
|
11980
12800
|
reject(
|
|
11981
12801
|
buildScriptSetupError({
|
|
@@ -11992,6 +12812,9 @@ async function ensureLocalMaintainerSnapshot(apiBaseUrl) {
|
|
|
11992
12812
|
if (!isLocalMaintainerRegistryEnabled(apiBaseUrl)) {
|
|
11993
12813
|
return null;
|
|
11994
12814
|
}
|
|
12815
|
+
if (shouldSkipLocalMaintainerHelper()) {
|
|
12816
|
+
return null;
|
|
12817
|
+
}
|
|
11995
12818
|
return runLocalMaintainerScript([
|
|
11996
12819
|
"ensure-snapshot",
|
|
11997
12820
|
"--api-base-url",
|
|
@@ -11999,6 +12822,9 @@ async function ensureLocalMaintainerSnapshot(apiBaseUrl) {
|
|
|
11999
12822
|
]);
|
|
12000
12823
|
}
|
|
12001
12824
|
async function readWorkspaceLocalMaintainerRegistry(projectRoot, fallbackRegistryUrl = LOCAL_REGISTRY_URL) {
|
|
12825
|
+
if (shouldSkipLocalMaintainerHelper()) {
|
|
12826
|
+
return null;
|
|
12827
|
+
}
|
|
12002
12828
|
return runLocalMaintainerScript([
|
|
12003
12829
|
"read-workspace",
|
|
12004
12830
|
"--project-root",
|
|
@@ -13008,6 +13834,11 @@ var config_default = defineCommand({
|
|
|
13008
13834
|
token: {
|
|
13009
13835
|
type: "string",
|
|
13010
13836
|
description: "Auth token (Supabase JWT)"
|
|
13837
|
+
},
|
|
13838
|
+
scope: {
|
|
13839
|
+
type: "string",
|
|
13840
|
+
description: "Config scope: global | workspace",
|
|
13841
|
+
default: "global"
|
|
13011
13842
|
}
|
|
13012
13843
|
}
|
|
13013
13844
|
},
|
|
@@ -13017,10 +13848,12 @@ var config_default = defineCommand({
|
|
|
13017
13848
|
const globalConfig = await loadGlobalConfig();
|
|
13018
13849
|
if (action === "show") {
|
|
13019
13850
|
const storedSession = await getStoredSession();
|
|
13851
|
+
const projectRoot = await findProjectRoot(process.cwd());
|
|
13852
|
+
const projectConfig = projectRoot ? await loadProjectConfig(projectRoot).catch(() => void 0) : void 0;
|
|
13020
13853
|
const config = resolveConfig(
|
|
13021
13854
|
globalConfig,
|
|
13022
13855
|
parsedArgs,
|
|
13023
|
-
|
|
13856
|
+
projectConfig,
|
|
13024
13857
|
storedSession
|
|
13025
13858
|
);
|
|
13026
13859
|
console.log(
|
|
@@ -13033,7 +13866,9 @@ var config_default = defineCommand({
|
|
|
13033
13866
|
} : {
|
|
13034
13867
|
configPath: getGlobalConfigPath(),
|
|
13035
13868
|
authPath: getGlobalAuthPath(),
|
|
13036
|
-
environment: parsedArgs.env || globalConfig.environment || "dev",
|
|
13869
|
+
environment: parsedArgs.env || projectConfig?.environment || globalConfig.environment || "dev",
|
|
13870
|
+
workspaceConfigPath: projectRoot ? `${projectRoot}/.dreamboard/project.json` : void 0,
|
|
13871
|
+
workspaceEnvironment: projectConfig?.environment,
|
|
13037
13872
|
apiBaseUrl: config.apiBaseUrl,
|
|
13038
13873
|
webBaseUrl: config.webBaseUrl,
|
|
13039
13874
|
authenticated: Boolean(config.authToken),
|
|
@@ -13051,10 +13886,24 @@ var config_default = defineCommand({
|
|
|
13051
13886
|
"The published Dreamboard CLI does not support config overrides. Use `dreamboard login` to authenticate."
|
|
13052
13887
|
);
|
|
13053
13888
|
}
|
|
13054
|
-
|
|
13055
|
-
|
|
13056
|
-
|
|
13057
|
-
|
|
13889
|
+
if (parsedArgs.scope === "workspace") {
|
|
13890
|
+
const projectRoot = await findProjectRoot(process.cwd());
|
|
13891
|
+
if (!projectRoot) {
|
|
13892
|
+
throw new Error(
|
|
13893
|
+
"Workspace-scoped config requires a Dreamboard project (.dreamboard/project.json)."
|
|
13894
|
+
);
|
|
13895
|
+
}
|
|
13896
|
+
const projectConfig = await loadProjectConfig(projectRoot);
|
|
13897
|
+
await updateProjectState(projectRoot, {
|
|
13898
|
+
...projectConfig,
|
|
13899
|
+
...parsedArgs.env ? { environment: parsedArgs.env } : {}
|
|
13900
|
+
});
|
|
13901
|
+
} else {
|
|
13902
|
+
const updated = { ...globalConfig };
|
|
13903
|
+
if (parsedArgs.env) updated.environment = parsedArgs.env;
|
|
13904
|
+
await saveGlobalConfig(updated);
|
|
13905
|
+
}
|
|
13906
|
+
const overrideToken = valueOrUndefined2(parsedArgs.token);
|
|
13058
13907
|
if (overrideToken) {
|
|
13059
13908
|
await setAccessOnlySession(overrideToken);
|
|
13060
13909
|
}
|
|
@@ -13068,7 +13917,7 @@ var config_default = defineCommand({
|
|
|
13068
13917
|
});
|
|
13069
13918
|
|
|
13070
13919
|
// src/commands/dev.ts
|
|
13071
|
-
import
|
|
13920
|
+
import path25 from "path";
|
|
13072
13921
|
import { createHash as createHash3 } from "crypto";
|
|
13073
13922
|
|
|
13074
13923
|
// ../../packages/ui-host-runtime/src/actor-principal.ts
|
|
@@ -13540,11 +14389,32 @@ async function resolveDevBearer(config) {
|
|
|
13540
14389
|
case "unchanged":
|
|
13541
14390
|
case "rotated":
|
|
13542
14391
|
return { kind: "ok", token: result.credentials.accessToken };
|
|
13543
|
-
case "transient_failure":
|
|
14392
|
+
case "transient_failure": {
|
|
14393
|
+
const expiry = getAccessTokenExpiry(config.authToken);
|
|
14394
|
+
const isExpired = expiry !== null && expiry.getTime() <= Date.now();
|
|
14395
|
+
if (isExpired) {
|
|
14396
|
+
if (shouldRepairLocalDevSession(config)) {
|
|
14397
|
+
const repaired = await repairLocalDevSession();
|
|
14398
|
+
if (repaired) {
|
|
14399
|
+
return { kind: "ok", token: repaired.accessToken };
|
|
14400
|
+
}
|
|
14401
|
+
}
|
|
14402
|
+
return {
|
|
14403
|
+
kind: "permanent_invalid",
|
|
14404
|
+
message: `Access token refresh failed: ${result.message}. Run \`dreamboard login\` to authenticate again.`
|
|
14405
|
+
};
|
|
14406
|
+
}
|
|
13544
14407
|
return { kind: "ok", token: config.authToken ?? null };
|
|
14408
|
+
}
|
|
13545
14409
|
}
|
|
13546
14410
|
} catch (err) {
|
|
13547
14411
|
if (err instanceof PermanentRefreshError) {
|
|
14412
|
+
if (shouldRepairLocalDevSession(config)) {
|
|
14413
|
+
const repaired = await repairLocalDevSession();
|
|
14414
|
+
if (repaired) {
|
|
14415
|
+
return { kind: "ok", token: repaired.accessToken };
|
|
14416
|
+
}
|
|
14417
|
+
}
|
|
13548
14418
|
return { kind: "permanent_invalid", message: err.message };
|
|
13549
14419
|
}
|
|
13550
14420
|
throw err;
|
|
@@ -14227,7 +15097,7 @@ function extractQueryParam(req, name) {
|
|
|
14227
15097
|
);
|
|
14228
15098
|
return value?.trim() || null;
|
|
14229
15099
|
}
|
|
14230
|
-
function appendQuery(
|
|
15100
|
+
function appendQuery(path29, query) {
|
|
14231
15101
|
const params = new URLSearchParams();
|
|
14232
15102
|
for (const [key, value] of Object.entries(query)) {
|
|
14233
15103
|
if (value) {
|
|
@@ -14235,7 +15105,7 @@ function appendQuery(path28, query) {
|
|
|
14235
15105
|
}
|
|
14236
15106
|
}
|
|
14237
15107
|
const serialized = params.toString();
|
|
14238
|
-
return serialized ? `${
|
|
15108
|
+
return serialized ? `${path29}?${serialized}` : path29;
|
|
14239
15109
|
}
|
|
14240
15110
|
async function loadCurrentSession(options) {
|
|
14241
15111
|
if (!await exists(options.sessionFilePath)) {
|
|
@@ -14254,12 +15124,12 @@ async function persistSessionId(sessionFilePath, sessionId) {
|
|
|
14254
15124
|
createPersistedDevSession({ sessionId })
|
|
14255
15125
|
);
|
|
14256
15126
|
}
|
|
14257
|
-
async function fetchBackendJson(config,
|
|
15127
|
+
async function fetchBackendJson(config, path29, options = {}) {
|
|
14258
15128
|
const bearer = await resolveDevBearer(config);
|
|
14259
15129
|
if (bearer.kind === "permanent_invalid") {
|
|
14260
15130
|
throw new HttpError(401, bearer.message);
|
|
14261
15131
|
}
|
|
14262
|
-
const response = await fetch(`${config.apiBaseUrl}${
|
|
15132
|
+
const response = await fetch(`${config.apiBaseUrl}${path29}`, {
|
|
14263
15133
|
method: options.method ?? "GET",
|
|
14264
15134
|
headers: {
|
|
14265
15135
|
...bearer.token ? { authorization: `Bearer ${bearer.token}` } : {},
|
|
@@ -14401,6 +15271,37 @@ function prepareFallbackStylesheet(options) {
|
|
|
14401
15271
|
return generatedPath;
|
|
14402
15272
|
}
|
|
14403
15273
|
|
|
15274
|
+
// src/dev-host/dev-hmr-guard-plugin.ts
|
|
15275
|
+
import path18 from "path";
|
|
15276
|
+
function createDevHmrGuardPlugin(options) {
|
|
15277
|
+
return {
|
|
15278
|
+
name: "dreamboard-dev-hmr-guard",
|
|
15279
|
+
handleHotUpdate(context) {
|
|
15280
|
+
if (shouldHandleProjectHotUpdate(options.projectRoot, context.file)) {
|
|
15281
|
+
return void 0;
|
|
15282
|
+
}
|
|
15283
|
+
context.server.config.logger.info(
|
|
15284
|
+
`[dreamboard] ignored HMR outside project: ${path18.relative(
|
|
15285
|
+
options.projectRoot,
|
|
15286
|
+
context.file
|
|
15287
|
+
)}`
|
|
15288
|
+
);
|
|
15289
|
+
return [];
|
|
15290
|
+
}
|
|
15291
|
+
};
|
|
15292
|
+
}
|
|
15293
|
+
function shouldHandleProjectHotUpdate(projectRoot, file) {
|
|
15294
|
+
const normalizedProjectRoot = path18.resolve(projectRoot);
|
|
15295
|
+
const normalizedFile = path18.resolve(file);
|
|
15296
|
+
const relativePath = path18.relative(normalizedProjectRoot, normalizedFile);
|
|
15297
|
+
const isInsideProject = relativePath === "" || relativePath.length > 0 && !relativePath.startsWith("..") && !path18.isAbsolute(relativePath);
|
|
15298
|
+
if (!isInsideProject) {
|
|
15299
|
+
return false;
|
|
15300
|
+
}
|
|
15301
|
+
const pathSegments = relativePath.split(path18.sep);
|
|
15302
|
+
return !pathSegments.includes(".dreamboard") && !pathSegments.includes("node_modules");
|
|
15303
|
+
}
|
|
15304
|
+
|
|
14404
15305
|
// src/dev-host/start-dev-server.ts
|
|
14405
15306
|
var require2 = createRequire2(import.meta.url);
|
|
14406
15307
|
var tailwindCssEntry = require2.resolve("tailwindcss/index.css");
|
|
@@ -14423,6 +15324,7 @@ async function startDreamboardDevServer(options) {
|
|
|
14423
15324
|
root: platform2.devHostRoot,
|
|
14424
15325
|
appType: "spa",
|
|
14425
15326
|
plugins: [
|
|
15327
|
+
createDevHmrGuardPlugin({ projectRoot }),
|
|
14426
15328
|
react(),
|
|
14427
15329
|
createVirtualDevModulesPlugin({
|
|
14428
15330
|
projectRoot,
|
|
@@ -14493,11 +15395,11 @@ function getBoundPort(server) {
|
|
|
14493
15395
|
}
|
|
14494
15396
|
|
|
14495
15397
|
// src/services/testing/reducer-native-test-harness.ts
|
|
14496
|
-
import
|
|
15398
|
+
import path22 from "path";
|
|
14497
15399
|
import {
|
|
14498
15400
|
existsSync as existsSync8,
|
|
14499
15401
|
mkdirSync as mkdirSync2,
|
|
14500
|
-
readFileSync as
|
|
15402
|
+
readFileSync as readFileSync4,
|
|
14501
15403
|
rmSync as rmSync2,
|
|
14502
15404
|
writeFileSync as writeFileSync2
|
|
14503
15405
|
} from "fs";
|
|
@@ -14606,6 +15508,9 @@ var ProjectSeatsDynamicRequestSchema = external_exports.object({ "state": Reduce
|
|
|
14606
15508
|
var BoardStaticProjectionSchema = external_exports.object({ "view": JsonValueSchema, "hash": external_exports.string().min(1), "manifestVersion": external_exports.string() }).strict();
|
|
14607
15509
|
|
|
14608
15510
|
// ../../packages/app-sdk/src/reducer/per-player.ts
|
|
15511
|
+
function asPlayerId(raw) {
|
|
15512
|
+
return raw;
|
|
15513
|
+
}
|
|
14609
15514
|
function perPlayerGet(value, id) {
|
|
14610
15515
|
for (const [candidate, v] of value.entries) {
|
|
14611
15516
|
if (candidate === id) {
|
|
@@ -14727,6 +15632,33 @@ function resolveDependentDomainChoices(choices, context) {
|
|
|
14727
15632
|
disabledReason: choice.disabledReason
|
|
14728
15633
|
}));
|
|
14729
15634
|
}
|
|
15635
|
+
function choiceValuesInclude(choices, value) {
|
|
15636
|
+
return choices.some((choice) => Object.is(choice.value, value));
|
|
15637
|
+
}
|
|
15638
|
+
function assertChoiceDefaultInChoices(inputName, choices, defaultValue) {
|
|
15639
|
+
if (choiceValuesInclude(choices, defaultValue)) return;
|
|
15640
|
+
const printable = defaultValue === null ? "null" : `'${defaultValue}'`;
|
|
15641
|
+
throw new Error(
|
|
15642
|
+
`${inputName} defaultValue ${printable} must be one of its choices. If null is a valid value, add an explicit { value: null, label: ... } choice.`
|
|
15643
|
+
);
|
|
15644
|
+
}
|
|
15645
|
+
function choiceSchema(choices) {
|
|
15646
|
+
const values = choices.map((choice) => choice.value);
|
|
15647
|
+
const stringValues = values.filter(
|
|
15648
|
+
(value) => value !== null
|
|
15649
|
+
);
|
|
15650
|
+
const hasNull = values.some((value) => value === null);
|
|
15651
|
+
if (stringValues.length === 0) {
|
|
15652
|
+
return external_exports.null();
|
|
15653
|
+
}
|
|
15654
|
+
const stringSchema = external_exports.enum(
|
|
15655
|
+
stringValues
|
|
15656
|
+
);
|
|
15657
|
+
if (hasNull) {
|
|
15658
|
+
return external_exports.union([stringSchema, external_exports.null()]);
|
|
15659
|
+
}
|
|
15660
|
+
return stringSchema;
|
|
15661
|
+
}
|
|
14730
15662
|
function resolveResourceMapChoices(choices, context) {
|
|
14731
15663
|
const resources = context.state.table.resources;
|
|
14732
15664
|
const firstResourceMap = isPerPlayer(resources) && resources.entries.length > 0 ? resources.entries[0]?.[1] : resources;
|
|
@@ -14810,38 +15742,76 @@ function choiceInput(options) {
|
|
|
14810
15742
|
if (Array.isArray(options.choices) && options.choices.length === 0) {
|
|
14811
15743
|
throw new Error("formInput.choice requires at least one choice.");
|
|
14812
15744
|
}
|
|
14813
|
-
const
|
|
14814
|
-
|
|
14815
|
-
|
|
15745
|
+
const staticChoices = Array.isArray(options.choices) ? options.choices : null;
|
|
15746
|
+
const hasStaticDefault = typeof options.defaultValue !== "function";
|
|
15747
|
+
const staticDefault = options.defaultValue;
|
|
15748
|
+
if (staticChoices && hasStaticDefault) {
|
|
15749
|
+
assertChoiceDefaultInChoices(
|
|
15750
|
+
"formInput.choice",
|
|
15751
|
+
staticChoices,
|
|
15752
|
+
staticDefault
|
|
15753
|
+
);
|
|
15754
|
+
}
|
|
15755
|
+
const schema = staticChoices ? choiceSchema(staticChoices) : external_exports.string().nullable();
|
|
15756
|
+
const dynamicDefault = typeof options.defaultValue === "function" ? options.defaultValue : void 0;
|
|
14816
15757
|
return {
|
|
14817
15758
|
kind: "form",
|
|
14818
15759
|
schema,
|
|
14819
|
-
...
|
|
15760
|
+
...hasStaticDefault ? { defaultValue: staticDefault } : {},
|
|
14820
15761
|
...dependsOn ? { dependsOn } : {},
|
|
14821
15762
|
domain: (state, playerId, q, derived, values) => {
|
|
15763
|
+
const context = {
|
|
15764
|
+
state,
|
|
15765
|
+
playerId,
|
|
15766
|
+
q,
|
|
15767
|
+
derived
|
|
15768
|
+
};
|
|
15769
|
+
const choices = dependsOn ? resolveDependentDomainChoices(
|
|
15770
|
+
options.choices,
|
|
15771
|
+
{
|
|
15772
|
+
...context,
|
|
15773
|
+
values: values ?? {}
|
|
15774
|
+
}
|
|
15775
|
+
) : resolveDomainChoices(options.choices, {
|
|
15776
|
+
...context,
|
|
15777
|
+
values: {}
|
|
15778
|
+
});
|
|
15779
|
+
if (hasStaticDefault) {
|
|
15780
|
+
assertChoiceDefaultInChoices(
|
|
15781
|
+
"formInput.choice",
|
|
15782
|
+
choices,
|
|
15783
|
+
staticDefault
|
|
15784
|
+
);
|
|
15785
|
+
}
|
|
14822
15786
|
return {
|
|
14823
15787
|
type: "choice",
|
|
14824
|
-
choices
|
|
14825
|
-
options.choices,
|
|
14826
|
-
{
|
|
14827
|
-
state,
|
|
14828
|
-
playerId,
|
|
14829
|
-
q,
|
|
14830
|
-
derived,
|
|
14831
|
-
values: values ?? {}
|
|
14832
|
-
}
|
|
14833
|
-
) : resolveDomainChoices(
|
|
14834
|
-
options.choices,
|
|
14835
|
-
{
|
|
14836
|
-
state,
|
|
14837
|
-
playerId,
|
|
14838
|
-
q,
|
|
14839
|
-
derived,
|
|
14840
|
-
values: {}
|
|
14841
|
-
}
|
|
14842
|
-
)
|
|
15788
|
+
choices
|
|
14843
15789
|
};
|
|
14844
|
-
}
|
|
15790
|
+
},
|
|
15791
|
+
...dynamicDefault ? {
|
|
15792
|
+
resolveDefaultValue: (state, playerId, q, derived, domain) => {
|
|
15793
|
+
const choices = domain.type === "choice" ? domain.choices.map((choice) => ({
|
|
15794
|
+
value: choice.value,
|
|
15795
|
+
label: choice.label,
|
|
15796
|
+
icon: choice.icon,
|
|
15797
|
+
badge: choice.badge,
|
|
15798
|
+
description: choice.description,
|
|
15799
|
+
disabled: choice.disabled,
|
|
15800
|
+
disabledReason: choice.disabledReason
|
|
15801
|
+
})) : [];
|
|
15802
|
+
const resolved = dynamicDefault({
|
|
15803
|
+
state,
|
|
15804
|
+
playerId,
|
|
15805
|
+
q,
|
|
15806
|
+
derived,
|
|
15807
|
+
values: {},
|
|
15808
|
+
choices
|
|
15809
|
+
});
|
|
15810
|
+
if (resolved === void 0) return void 0;
|
|
15811
|
+
assertChoiceDefaultInChoices("formInput.choice", choices, resolved);
|
|
15812
|
+
return resolved;
|
|
15813
|
+
}
|
|
15814
|
+
} : {}
|
|
14845
15815
|
};
|
|
14846
15816
|
}
|
|
14847
15817
|
function choiceListInput(options) {
|
|
@@ -14862,7 +15832,12 @@ function choiceListInput(options) {
|
|
|
14862
15832
|
derived,
|
|
14863
15833
|
values: {}
|
|
14864
15834
|
};
|
|
14865
|
-
const choices = resolveDomainChoices(options.choices, context)
|
|
15835
|
+
const choices = resolveDomainChoices(options.choices, context).map(
|
|
15836
|
+
(choice) => ({
|
|
15837
|
+
...choice,
|
|
15838
|
+
value: choice.value
|
|
15839
|
+
})
|
|
15840
|
+
);
|
|
14866
15841
|
return {
|
|
14867
15842
|
type: "choiceList",
|
|
14868
15843
|
choices,
|
|
@@ -14944,17 +15919,19 @@ function makeBoardCollector(kind) {
|
|
|
14944
15919
|
targetId
|
|
14945
15920
|
)),
|
|
14946
15921
|
...dependsOn ? { dependsOn } : {},
|
|
14947
|
-
domain:
|
|
14948
|
-
type: "
|
|
15922
|
+
domain: (state, playerId, q, _derived, values) => ({
|
|
15923
|
+
type: "boardTarget",
|
|
15924
|
+
projection: "resolved",
|
|
14949
15925
|
targetKind: target.targetKind,
|
|
14950
15926
|
boardId: target.boardId,
|
|
15927
|
+
valueKind: target.valueKind,
|
|
14951
15928
|
eligibleTargets: target.eligible({
|
|
14952
15929
|
state,
|
|
14953
15930
|
playerId,
|
|
14954
15931
|
q,
|
|
14955
15932
|
values
|
|
14956
15933
|
}).map(String)
|
|
14957
|
-
})
|
|
15934
|
+
}),
|
|
14958
15935
|
meta: {
|
|
14959
15936
|
targetKind: target.targetKind,
|
|
14960
15937
|
boardId: target.boardId,
|
|
@@ -15129,8 +16106,8 @@ function createCardTargetBuilder(zoneIds) {
|
|
|
15129
16106
|
}
|
|
15130
16107
|
}
|
|
15131
16108
|
),
|
|
15132
|
-
zoneIds
|
|
15133
|
-
zoneId: zoneIds[0]
|
|
16109
|
+
zoneIds,
|
|
16110
|
+
zoneId: zoneIds[0],
|
|
15134
16111
|
targetKind: "card"
|
|
15135
16112
|
})
|
|
15136
16113
|
);
|
|
@@ -15164,10 +16141,10 @@ function cardInput(options) {
|
|
|
15164
16141
|
targetId
|
|
15165
16142
|
)),
|
|
15166
16143
|
...dependsOn ? { dependsOn } : {},
|
|
15167
|
-
domain:
|
|
15168
|
-
type: "
|
|
16144
|
+
domain: (state, playerId, q, _derived, values) => ({
|
|
16145
|
+
type: "cardTarget",
|
|
16146
|
+
projection: "resolved",
|
|
15169
16147
|
targetKind: target.targetKind,
|
|
15170
|
-
zoneId: target.zoneId,
|
|
15171
16148
|
zoneIds: target.zoneIds,
|
|
15172
16149
|
eligibleTargets: target.eligible({
|
|
15173
16150
|
state,
|
|
@@ -15175,7 +16152,7 @@ function cardInput(options) {
|
|
|
15175
16152
|
q,
|
|
15176
16153
|
values
|
|
15177
16154
|
}).map(String)
|
|
15178
|
-
})
|
|
16155
|
+
}),
|
|
15179
16156
|
meta: {
|
|
15180
16157
|
zoneId: target.zoneId,
|
|
15181
16158
|
zoneIds: target.zoneIds,
|
|
@@ -17344,6 +18321,126 @@ function createReducerFx(_state) {
|
|
|
17344
18321
|
function updateTable(state, nextTable) {
|
|
17345
18322
|
return { ...state, table: nextTable };
|
|
17346
18323
|
}
|
|
18324
|
+
function computePlayerZoneVisibility(table, zoneId, playerId) {
|
|
18325
|
+
const mode = table.handVisibility[zoneId];
|
|
18326
|
+
if (mode === "all" || mode === "public") {
|
|
18327
|
+
return { faceUp: true };
|
|
18328
|
+
}
|
|
18329
|
+
return { faceUp: false, visibleTo: [playerId] };
|
|
18330
|
+
}
|
|
18331
|
+
function readPlayerZoneCards(table, zoneId, playerId) {
|
|
18332
|
+
const zone = table.zones.perPlayer[zoneId] ?? table.hands[zoneId];
|
|
18333
|
+
if (!zone) {
|
|
18334
|
+
throw new Error(`Player zone '${zoneId}' does not exist.`);
|
|
18335
|
+
}
|
|
18336
|
+
return perPlayerGet(zone, asPlayerId(playerId)) ?? [];
|
|
18337
|
+
}
|
|
18338
|
+
function writePlayerZoneCards(table, zoneId, playerId, cards) {
|
|
18339
|
+
const currentZone = table.zones.perPlayer[zoneId];
|
|
18340
|
+
const currentHand = table.hands[zoneId];
|
|
18341
|
+
const player = asPlayerId(playerId);
|
|
18342
|
+
if (currentZone) {
|
|
18343
|
+
table.zones.perPlayer[zoneId] = perPlayerSet(
|
|
18344
|
+
currentZone,
|
|
18345
|
+
player,
|
|
18346
|
+
[...cards]
|
|
18347
|
+
);
|
|
18348
|
+
}
|
|
18349
|
+
if (currentHand) {
|
|
18350
|
+
table.hands[zoneId] = perPlayerSet(
|
|
18351
|
+
currentHand,
|
|
18352
|
+
player,
|
|
18353
|
+
[...cards]
|
|
18354
|
+
);
|
|
18355
|
+
}
|
|
18356
|
+
}
|
|
18357
|
+
function assertCardAllowedInPlayerZone(table, zoneId, cardId) {
|
|
18358
|
+
const allowedCardSetIds = table.zones.cardSetIdsByZoneId?.[zoneId];
|
|
18359
|
+
if (!allowedCardSetIds || allowedCardSetIds.length === 0) {
|
|
18360
|
+
return;
|
|
18361
|
+
}
|
|
18362
|
+
const card = table.cards[cardId];
|
|
18363
|
+
if (!card) {
|
|
18364
|
+
throw new Error(`Card '${cardId}' does not exist.`);
|
|
18365
|
+
}
|
|
18366
|
+
if (!allowedCardSetIds.includes(card.cardSetId)) {
|
|
18367
|
+
throw new Error(
|
|
18368
|
+
`Card '${cardId}' from set '${card.cardSetId}' is not allowed in player zone '${zoneId}'.`
|
|
18369
|
+
);
|
|
18370
|
+
}
|
|
18371
|
+
}
|
|
18372
|
+
function rotatePlayerZoneTable(options) {
|
|
18373
|
+
const nextTable = cloneRuntimeTable(options.table);
|
|
18374
|
+
const zoneId = options.zoneId;
|
|
18375
|
+
if (!nextTable.zones.perPlayer[zoneId] && !nextTable.hands[zoneId]) {
|
|
18376
|
+
throw new Error(`Player zone '${zoneId}' does not exist.`);
|
|
18377
|
+
}
|
|
18378
|
+
const players = [...options.players ?? nextTable.playerOrder];
|
|
18379
|
+
if (players.length === 0) {
|
|
18380
|
+
return nextTable;
|
|
18381
|
+
}
|
|
18382
|
+
const playerSet = new Set(nextTable.playerOrder);
|
|
18383
|
+
for (const playerId of players) {
|
|
18384
|
+
if (!playerSet.has(playerId)) {
|
|
18385
|
+
throw new Error(
|
|
18386
|
+
`Cannot rotate player zone '${zoneId}': player '${playerId}' is not in player order.`
|
|
18387
|
+
);
|
|
18388
|
+
}
|
|
18389
|
+
}
|
|
18390
|
+
const selectedByPlayer = /* @__PURE__ */ new Map();
|
|
18391
|
+
for (const playerId of players) {
|
|
18392
|
+
const sourceCards = readPlayerZoneCards(nextTable, zoneId, playerId);
|
|
18393
|
+
const selected = options.cardIdsByPlayer?.[playerId] ?? sourceCards;
|
|
18394
|
+
for (const cardId of selected) {
|
|
18395
|
+
if (!sourceCards.includes(cardId)) {
|
|
18396
|
+
throw new Error(
|
|
18397
|
+
`Cannot rotate player zone '${zoneId}': card '${cardId}' is not in zone for player '${playerId}'.`
|
|
18398
|
+
);
|
|
18399
|
+
}
|
|
18400
|
+
assertCardAllowedInPlayerZone(nextTable, zoneId, cardId);
|
|
18401
|
+
}
|
|
18402
|
+
selectedByPlayer.set(playerId, [...selected]);
|
|
18403
|
+
}
|
|
18404
|
+
const removeByPlayer = /* @__PURE__ */ new Map();
|
|
18405
|
+
for (const playerId of players) {
|
|
18406
|
+
const selected = new Set(selectedByPlayer.get(playerId) ?? []);
|
|
18407
|
+
removeByPlayer.set(
|
|
18408
|
+
playerId,
|
|
18409
|
+
readPlayerZoneCards(nextTable, zoneId, playerId).filter(
|
|
18410
|
+
(cardId) => !selected.has(cardId)
|
|
18411
|
+
)
|
|
18412
|
+
);
|
|
18413
|
+
}
|
|
18414
|
+
const additionsByPlayer = new Map(
|
|
18415
|
+
players.map((playerId) => [playerId, []])
|
|
18416
|
+
);
|
|
18417
|
+
for (const [index, fromPlayerId] of players.entries()) {
|
|
18418
|
+
const offset = options.direction === "left" ? 1 : -1;
|
|
18419
|
+
const recipient = players[(index + offset + players.length) % players.length];
|
|
18420
|
+
additionsByPlayer.get(recipient).push(...selectedByPlayer.get(fromPlayerId) ?? []);
|
|
18421
|
+
}
|
|
18422
|
+
for (const playerId of players) {
|
|
18423
|
+
const remaining = removeByPlayer.get(playerId) ?? [];
|
|
18424
|
+
const additions = additionsByPlayer.get(playerId) ?? [];
|
|
18425
|
+
const nextCards = options.position === "top" ? [...additions, ...remaining] : [...remaining, ...additions];
|
|
18426
|
+
writePlayerZoneCards(nextTable, zoneId, playerId, nextCards);
|
|
18427
|
+
for (const [position, cardId] of nextCards.entries()) {
|
|
18428
|
+
nextTable.componentLocations[cardId] = {
|
|
18429
|
+
type: "InHand",
|
|
18430
|
+
handId: zoneId,
|
|
18431
|
+
playerId,
|
|
18432
|
+
position
|
|
18433
|
+
};
|
|
18434
|
+
nextTable.ownerOfCard[cardId] = playerId;
|
|
18435
|
+
nextTable.visibility[cardId] = computePlayerZoneVisibility(
|
|
18436
|
+
nextTable,
|
|
18437
|
+
zoneId,
|
|
18438
|
+
playerId
|
|
18439
|
+
);
|
|
18440
|
+
}
|
|
18441
|
+
}
|
|
18442
|
+
return nextTable;
|
|
18443
|
+
}
|
|
17347
18444
|
var moveComponentToEdgeInternal = moveComponentToEdge;
|
|
17348
18445
|
var moveComponentToVertexInternal = moveComponentToVertex;
|
|
17349
18446
|
var dealCardsFromDeckToHandInternal = dealCardsFromDeckToHand;
|
|
@@ -17527,6 +18624,19 @@ function createReducerOps() {
|
|
|
17527
18624
|
return updateTable(state, nextTable);
|
|
17528
18625
|
};
|
|
17529
18626
|
},
|
|
18627
|
+
rotatePlayerZone(args) {
|
|
18628
|
+
return (state) => {
|
|
18629
|
+
const nextTable = rotatePlayerZoneTable({
|
|
18630
|
+
table: state.table,
|
|
18631
|
+
zoneId: args.zoneId,
|
|
18632
|
+
direction: args.direction,
|
|
18633
|
+
players: args.players,
|
|
18634
|
+
cardIdsByPlayer: args.cardIdsByPlayer,
|
|
18635
|
+
position: args.position ?? "bottom"
|
|
18636
|
+
});
|
|
18637
|
+
return updateTable(state, nextTable);
|
|
18638
|
+
};
|
|
18639
|
+
},
|
|
17530
18640
|
moveComponentToSpace(args) {
|
|
17531
18641
|
return (state) => {
|
|
17532
18642
|
const nextTable = moveComponentToSpace(
|
|
@@ -17626,6 +18736,47 @@ function createReducerOps() {
|
|
|
17626
18736
|
return impl;
|
|
17627
18737
|
}
|
|
17628
18738
|
|
|
18739
|
+
// ../../packages/app-sdk/src/reducer/transaction.ts
|
|
18740
|
+
function createReducerTransaction(initialState, ops = createReducerOps()) {
|
|
18741
|
+
let currentState = initialState;
|
|
18742
|
+
let currentQueries = createStateQueries(currentState);
|
|
18743
|
+
const refresh = (nextState) => {
|
|
18744
|
+
currentState = nextState;
|
|
18745
|
+
currentQueries = createStateQueries(currentState);
|
|
18746
|
+
return currentState;
|
|
18747
|
+
};
|
|
18748
|
+
const apply = (op) => refresh(op(currentState));
|
|
18749
|
+
const base = {
|
|
18750
|
+
get state() {
|
|
18751
|
+
return currentState;
|
|
18752
|
+
},
|
|
18753
|
+
get q() {
|
|
18754
|
+
return currentQueries;
|
|
18755
|
+
},
|
|
18756
|
+
apply
|
|
18757
|
+
};
|
|
18758
|
+
return new Proxy(base, {
|
|
18759
|
+
get(target, property, receiver) {
|
|
18760
|
+
if (property in target) {
|
|
18761
|
+
return Reflect.get(target, property, receiver);
|
|
18762
|
+
}
|
|
18763
|
+
const opFactory = ops[property];
|
|
18764
|
+
if (typeof opFactory !== "function") {
|
|
18765
|
+
return void 0;
|
|
18766
|
+
}
|
|
18767
|
+
return (...args) => {
|
|
18768
|
+
const op = opFactory(
|
|
18769
|
+
...args
|
|
18770
|
+
);
|
|
18771
|
+
return apply(op);
|
|
18772
|
+
};
|
|
18773
|
+
}
|
|
18774
|
+
});
|
|
18775
|
+
}
|
|
18776
|
+
function createReducerEdit(ops = createReducerOps()) {
|
|
18777
|
+
return (state) => createReducerTransaction(state, ops);
|
|
18778
|
+
}
|
|
18779
|
+
|
|
17629
18780
|
// ../../packages/app-sdk/src/reducer/definition-index.ts
|
|
17630
18781
|
function phaseEntriesOf(definition) {
|
|
17631
18782
|
return Object.entries(definition.phases);
|
|
@@ -17927,7 +19078,8 @@ function createTrustedRuntimeScope(definition) {
|
|
|
17927
19078
|
}
|
|
17928
19079
|
const helpers = {
|
|
17929
19080
|
...runtimeResultHelpers,
|
|
17930
|
-
ops: createReducerOps()
|
|
19081
|
+
ops: createReducerOps(),
|
|
19082
|
+
edit: createReducerEdit()
|
|
17931
19083
|
};
|
|
17932
19084
|
function fxForState2(state) {
|
|
17933
19085
|
return fxForState(state);
|
|
@@ -18264,10 +19416,10 @@ function createTrustedInstructionRunner(scope, interactions, lifecycle) {
|
|
|
18264
19416
|
|
|
18265
19417
|
// ../../packages/app-sdk/src/reducer/parse-utils.ts
|
|
18266
19418
|
function formatIssue(label, issue) {
|
|
18267
|
-
const
|
|
19419
|
+
const path29 = issue.path.map(
|
|
18268
19420
|
(segment) => typeof segment === "symbol" ? segment.toString() : String(segment)
|
|
18269
19421
|
).join(".");
|
|
18270
|
-
return `${
|
|
19422
|
+
return `${path29 || label}: ${issue.message}`;
|
|
18271
19423
|
}
|
|
18272
19424
|
function safeParseOrThrow(schema, value, label) {
|
|
18273
19425
|
const parsed = schema.safeParse(value);
|
|
@@ -18288,6 +19440,7 @@ function makeValidationError(errorCode, message) {
|
|
|
18288
19440
|
}
|
|
18289
19441
|
|
|
18290
19442
|
// ../../packages/app-sdk/src/reducer/bundle/trusted/interaction-collectors.ts
|
|
19443
|
+
var MAX_EAGER_DEPENDENT_DOMAIN_CASES = 64;
|
|
18291
19444
|
function collectTargetDomainMetadata(collector) {
|
|
18292
19445
|
switch (collector.kind) {
|
|
18293
19446
|
case "card": {
|
|
@@ -18305,28 +19458,63 @@ function collectTargetDomainMetadata(collector) {
|
|
|
18305
19458
|
const meta = collector.meta ?? {};
|
|
18306
19459
|
return {
|
|
18307
19460
|
targetKind: meta.targetKind ?? collector.kind.replace("board-", ""),
|
|
18308
|
-
boardId: meta.boardId
|
|
19461
|
+
boardId: meta.boardId,
|
|
19462
|
+
valueKind: meta.valueKind
|
|
18309
19463
|
};
|
|
18310
19464
|
}
|
|
18311
19465
|
default:
|
|
18312
19466
|
return {};
|
|
18313
19467
|
}
|
|
18314
19468
|
}
|
|
18315
|
-
function isTargetCollector(collector) {
|
|
18316
|
-
return collector.kind === "card" || collector.kind === "board-edge" || collector.kind === "board-space" || collector.kind === "board-tile" || collector.kind === "board-vertex";
|
|
18317
|
-
}
|
|
18318
19469
|
function withSelection(domain, collector) {
|
|
18319
19470
|
if (!collector.selection) return domain;
|
|
18320
19471
|
return { ...domain, selection: collector.selection };
|
|
18321
19472
|
}
|
|
19473
|
+
function lazyTargetDomainFromCollectorMetadata(key, collector, dependencies) {
|
|
19474
|
+
const metadata = collectTargetDomainMetadata(collector);
|
|
19475
|
+
if (collector.kind === "card") {
|
|
19476
|
+
return withSelection(
|
|
19477
|
+
{
|
|
19478
|
+
type: "cardTarget",
|
|
19479
|
+
projection: "lazy",
|
|
19480
|
+
targetKind: "card",
|
|
19481
|
+
zoneIds: metadata.zoneIds ?? (metadata.zoneId === void 0 ? [] : [metadata.zoneId]),
|
|
19482
|
+
dependencies: {
|
|
19483
|
+
mode: "lazy",
|
|
19484
|
+
dependsOn: dependencies,
|
|
19485
|
+
resolver: { inputKey: key }
|
|
19486
|
+
}
|
|
19487
|
+
},
|
|
19488
|
+
collector
|
|
19489
|
+
);
|
|
19490
|
+
}
|
|
19491
|
+
if (collector.kind === "board-edge" || collector.kind === "board-space" || collector.kind === "board-tile" || collector.kind === "board-vertex") {
|
|
19492
|
+
return withSelection(
|
|
19493
|
+
{
|
|
19494
|
+
type: "boardTarget",
|
|
19495
|
+
projection: "lazy",
|
|
19496
|
+
targetKind: metadata.targetKind ?? collector.kind.replace("board-", ""),
|
|
19497
|
+
boardId: metadata.boardId ?? "",
|
|
19498
|
+
...metadata.valueKind ? { valueKind: metadata.valueKind } : {},
|
|
19499
|
+
dependencies: {
|
|
19500
|
+
mode: "lazy",
|
|
19501
|
+
dependsOn: dependencies,
|
|
19502
|
+
resolver: { inputKey: key }
|
|
19503
|
+
}
|
|
19504
|
+
},
|
|
19505
|
+
collector
|
|
19506
|
+
);
|
|
19507
|
+
}
|
|
19508
|
+
return null;
|
|
19509
|
+
}
|
|
18322
19510
|
function finiteValuesForDependency(key, domain) {
|
|
18323
19511
|
if (!domain) {
|
|
18324
19512
|
throw new Error(
|
|
18325
19513
|
`Interaction input '${key}' is declared as a dependency before it has a projected domain.`
|
|
18326
19514
|
);
|
|
18327
19515
|
}
|
|
18328
|
-
if (domain.type === "
|
|
18329
|
-
if (
|
|
19516
|
+
if (domain.type === "cardTarget" || domain.type === "boardTarget") {
|
|
19517
|
+
if (domain.projection !== "resolved") {
|
|
18330
19518
|
throw new Error(
|
|
18331
19519
|
`Interaction input '${key}' cannot be used as a dependency because its target domain is not finite.`
|
|
18332
19520
|
);
|
|
@@ -18334,7 +19522,9 @@ function finiteValuesForDependency(key, domain) {
|
|
|
18334
19522
|
return [...domain.eligibleTargets];
|
|
18335
19523
|
}
|
|
18336
19524
|
if (domain.type === "choice") {
|
|
18337
|
-
return domain.choices.
|
|
19525
|
+
return domain.choices.flatMap(
|
|
19526
|
+
(choice) => choice.value === null ? [] : [choice.value]
|
|
19527
|
+
);
|
|
18338
19528
|
}
|
|
18339
19529
|
throw new Error(
|
|
18340
19530
|
`Interaction input '${key}' cannot be used as a dependency. V1 supports finite target and choice dependencies only.`
|
|
@@ -18352,13 +19542,44 @@ function cartesianDependencyTuples(dependencies, domainsByKey) {
|
|
|
18352
19542
|
);
|
|
18353
19543
|
}
|
|
18354
19544
|
function withoutDependentProjection(domain) {
|
|
18355
|
-
const {
|
|
18356
|
-
dependsOn: _dependsOn,
|
|
18357
|
-
dependentCases: _dependentCases,
|
|
18358
|
-
...rest
|
|
18359
|
-
} = domain;
|
|
19545
|
+
const { dependencies: _dependencies, ...rest } = domain;
|
|
18360
19546
|
return rest;
|
|
18361
19547
|
}
|
|
19548
|
+
function toLazyTargetDomain(key, domain, dependencies) {
|
|
19549
|
+
if (domain.type === "cardTarget") {
|
|
19550
|
+
return {
|
|
19551
|
+
type: "cardTarget",
|
|
19552
|
+
projection: "lazy",
|
|
19553
|
+
targetKind: "card",
|
|
19554
|
+
zoneIds: domain.zoneIds,
|
|
19555
|
+
...domain.selection ? { selection: domain.selection } : {},
|
|
19556
|
+
dependencies: {
|
|
19557
|
+
mode: "lazy",
|
|
19558
|
+
dependsOn: dependencies,
|
|
19559
|
+
resolver: { inputKey: key }
|
|
19560
|
+
}
|
|
19561
|
+
};
|
|
19562
|
+
}
|
|
19563
|
+
if (domain.type === "boardTarget") {
|
|
19564
|
+
return {
|
|
19565
|
+
type: "boardTarget",
|
|
19566
|
+
projection: "lazy",
|
|
19567
|
+
targetKind: domain.targetKind,
|
|
19568
|
+
boardId: domain.boardId,
|
|
19569
|
+
...domain.valueKind ? { valueKind: domain.valueKind } : {},
|
|
19570
|
+
...domain.selection ? { selection: domain.selection } : {},
|
|
19571
|
+
dependencies: {
|
|
19572
|
+
mode: "lazy",
|
|
19573
|
+
dependsOn: dependencies,
|
|
19574
|
+
resolver: { inputKey: key }
|
|
19575
|
+
}
|
|
19576
|
+
};
|
|
19577
|
+
}
|
|
19578
|
+
return null;
|
|
19579
|
+
}
|
|
19580
|
+
function dependencyCaseCount(dependencies, domainsByKey) {
|
|
19581
|
+
return dependencies.map((key) => finiteValuesForDependency(key, domainsByKey[key]).length).reduce((total, count) => total * count, 1);
|
|
19582
|
+
}
|
|
18362
19583
|
function unsupportedDefaultInputError(key, collector) {
|
|
18363
19584
|
return new Error(
|
|
18364
19585
|
`Interaction input '${key}' uses a '${collector.kind}' collector without a default-renderable domain or target metadata. Use formInput.choice(...), formInput.choiceList(...), formInput.number(...), formInput.resourceMap(...), cardInput(...), or boardInput(...). For custom payloads, use a custom interaction surface with paramsSchema instead of the default InteractionForm.`
|
|
@@ -18437,9 +19658,21 @@ function collectInputDomains(interaction, domainState, playerId, eligibleTargets
|
|
|
18437
19658
|
continue;
|
|
18438
19659
|
}
|
|
18439
19660
|
if (collector.domain) {
|
|
19661
|
+
const domainProjector = collector.domain;
|
|
18440
19662
|
const dependencies = collector.dependsOn ?? [];
|
|
19663
|
+
if (options.includeEligibleTargets === false && !Object.prototype.hasOwnProperty.call(eligibleTargets, key)) {
|
|
19664
|
+
const lazyDomain2 = lazyTargetDomainFromCollectorMetadata(
|
|
19665
|
+
key,
|
|
19666
|
+
collector,
|
|
19667
|
+
dependencies
|
|
19668
|
+
);
|
|
19669
|
+
if (lazyDomain2) {
|
|
19670
|
+
result[key] = lazyDomain2;
|
|
19671
|
+
continue;
|
|
19672
|
+
}
|
|
19673
|
+
}
|
|
18441
19674
|
const baseDomain = withSelection(
|
|
18442
|
-
|
|
19675
|
+
domainProjector(
|
|
18443
19676
|
domainState,
|
|
18444
19677
|
playerId,
|
|
18445
19678
|
queries(),
|
|
@@ -18452,6 +19685,12 @@ function collectInputDomains(interaction, domainState, playerId, eligibleTargets
|
|
|
18452
19685
|
result[key] = baseDomain;
|
|
18453
19686
|
continue;
|
|
18454
19687
|
}
|
|
19688
|
+
const caseCount = dependencyCaseCount(dependencies, result);
|
|
19689
|
+
const lazyDomain = caseCount > MAX_EAGER_DEPENDENT_DOMAIN_CASES ? toLazyTargetDomain(key, baseDomain, dependencies) : null;
|
|
19690
|
+
if (lazyDomain) {
|
|
19691
|
+
result[key] = lazyDomain;
|
|
19692
|
+
continue;
|
|
19693
|
+
}
|
|
18455
19694
|
const dependentCases = cartesianDependencyTuples(
|
|
18456
19695
|
dependencies,
|
|
18457
19696
|
result
|
|
@@ -18459,7 +19698,7 @@ function collectInputDomains(interaction, domainState, playerId, eligibleTargets
|
|
|
18459
19698
|
when: values,
|
|
18460
19699
|
domain: withoutDependentProjection(
|
|
18461
19700
|
withSelection(
|
|
18462
|
-
|
|
19701
|
+
domainProjector(
|
|
18463
19702
|
domainState,
|
|
18464
19703
|
playerId,
|
|
18465
19704
|
queries(),
|
|
@@ -18472,24 +19711,13 @@ function collectInputDomains(interaction, domainState, playerId, eligibleTargets
|
|
|
18472
19711
|
}));
|
|
18473
19712
|
result[key] = {
|
|
18474
19713
|
...baseDomain,
|
|
18475
|
-
|
|
18476
|
-
|
|
19714
|
+
dependencies: {
|
|
19715
|
+
mode: "eager",
|
|
19716
|
+
dependentCases
|
|
19717
|
+
}
|
|
18477
19718
|
};
|
|
18478
19719
|
continue;
|
|
18479
19720
|
}
|
|
18480
|
-
const targets = eligibleTargets[key];
|
|
18481
|
-
const targetMetadata = collectTargetDomainMetadata(collector);
|
|
18482
|
-
if (isTargetCollector(collector) || Boolean(collector.eligibleTargets) || Boolean(collector.validateTarget) || targets || Object.keys(targetMetadata).length > 0) {
|
|
18483
|
-
result[key] = withSelection(
|
|
18484
|
-
{
|
|
18485
|
-
type: "target",
|
|
18486
|
-
...targetMetadata,
|
|
18487
|
-
...targets ? { eligibleTargets: targets } : {}
|
|
18488
|
-
},
|
|
18489
|
-
collector
|
|
18490
|
-
);
|
|
18491
|
-
continue;
|
|
18492
|
-
}
|
|
18493
19721
|
throw unsupportedDefaultInputError(key, collector);
|
|
18494
19722
|
}
|
|
18495
19723
|
return result;
|
|
@@ -18538,16 +19766,50 @@ function collectInteractionInputs(interaction, domainState, playerId, options =
|
|
|
18538
19766
|
derived(),
|
|
18539
19767
|
domain
|
|
18540
19768
|
);
|
|
19769
|
+
const defaultValue = "defaultValue" in collector ? collector.defaultValue : dynamicDefault;
|
|
19770
|
+
warnConcreteDependentChoiceDefault({
|
|
19771
|
+
inputKey: key,
|
|
19772
|
+
collector,
|
|
19773
|
+
domain,
|
|
19774
|
+
defaultValue,
|
|
19775
|
+
dependencyKeys
|
|
19776
|
+
});
|
|
18541
19777
|
return [
|
|
18542
19778
|
{
|
|
18543
19779
|
key,
|
|
18544
19780
|
kind: collector.kind,
|
|
18545
19781
|
domain,
|
|
18546
|
-
...
|
|
19782
|
+
...defaultValue !== void 0 ? { defaultValue } : {}
|
|
18547
19783
|
}
|
|
18548
19784
|
];
|
|
18549
19785
|
});
|
|
18550
19786
|
}
|
|
19787
|
+
var concreteDependentChoiceDefaultWarnings = /* @__PURE__ */ new Set();
|
|
19788
|
+
function shouldEmitAuthoringWarning() {
|
|
19789
|
+
const env2 = globalThis.process?.env;
|
|
19790
|
+
return env2?.NODE_ENV !== "production" && env2?.DREAMBOARD_SUPPRESS_AUTHORING_WARNINGS !== "1";
|
|
19791
|
+
}
|
|
19792
|
+
function warnConcreteDependentChoiceDefault({
|
|
19793
|
+
inputKey,
|
|
19794
|
+
collector,
|
|
19795
|
+
domain,
|
|
19796
|
+
defaultValue,
|
|
19797
|
+
dependencyKeys
|
|
19798
|
+
}) {
|
|
19799
|
+
if (!shouldEmitAuthoringWarning() || !dependencyKeys.has(inputKey) || collector.kind !== "form" || domain.type !== "choice" || defaultValue === void 0 || defaultValue === null) {
|
|
19800
|
+
return;
|
|
19801
|
+
}
|
|
19802
|
+
const warningKey = `${inputKey}:${String(defaultValue)}`;
|
|
19803
|
+
if (concreteDependentChoiceDefaultWarnings.has(warningKey)) {
|
|
19804
|
+
return;
|
|
19805
|
+
}
|
|
19806
|
+
concreteDependentChoiceDefaultWarnings.add(warningKey);
|
|
19807
|
+
console.warn(
|
|
19808
|
+
`[dreamboard] Form choice input "${inputKey}" feeds another collector and defaulted to "${String(
|
|
19809
|
+
defaultValue
|
|
19810
|
+
)}". Dependent choices that select the object an action applies to should usually use defaultValue: () => undefined so collection stays explicit.`
|
|
19811
|
+
);
|
|
19812
|
+
}
|
|
18551
19813
|
function collectFirstCardZoneId(interaction) {
|
|
18552
19814
|
const collectors = interactionInputsOf(interaction);
|
|
18553
19815
|
for (const collector of Object.values(collectors)) {
|
|
@@ -18661,13 +19923,18 @@ function validateCollectorTargets(interaction, domainState, playerId, params) {
|
|
|
18661
19923
|
if (!collector.validateTarget) continue;
|
|
18662
19924
|
const rawTarget = params[key];
|
|
18663
19925
|
if (rawTarget === null || rawTarget === void 0) continue;
|
|
18664
|
-
const
|
|
18665
|
-
|
|
19926
|
+
const dependencyValues = dependencyValuesForCollector(collector, params);
|
|
19927
|
+
const targetValues = valuesForCollectorValidation(
|
|
19928
|
+
collector.selection,
|
|
19929
|
+
rawTarget
|
|
19930
|
+
);
|
|
19931
|
+
for (const value of targetValues) {
|
|
18666
19932
|
const issue = collector.validateTarget(
|
|
18667
19933
|
domainState,
|
|
18668
19934
|
playerId,
|
|
18669
19935
|
queries(),
|
|
18670
|
-
value
|
|
19936
|
+
value,
|
|
19937
|
+
dependencyValues
|
|
18671
19938
|
);
|
|
18672
19939
|
if (issue) {
|
|
18673
19940
|
return makeValidationError(issue.errorCode, issue.message);
|
|
@@ -18676,6 +19943,13 @@ function validateCollectorTargets(interaction, domainState, playerId, params) {
|
|
|
18676
19943
|
}
|
|
18677
19944
|
return { valid: true };
|
|
18678
19945
|
}
|
|
19946
|
+
function dependencyValuesForCollector(collector, params) {
|
|
19947
|
+
const dependencies = collector.dependsOn ?? [];
|
|
19948
|
+
if (dependencies.length === 0) return void 0;
|
|
19949
|
+
return Object.fromEntries(
|
|
19950
|
+
dependencies.map((dependencyKey) => [dependencyKey, params[dependencyKey]])
|
|
19951
|
+
);
|
|
19952
|
+
}
|
|
18679
19953
|
function valuesForCollectorValidation(selection, value) {
|
|
18680
19954
|
if (selection?.mode === "many") {
|
|
18681
19955
|
return Array.isArray(value) ? value : [];
|
|
@@ -18847,7 +20121,7 @@ function deriveInteractionKind(inputs) {
|
|
|
18847
20121
|
}
|
|
18848
20122
|
return "action";
|
|
18849
20123
|
}
|
|
18850
|
-
function
|
|
20124
|
+
function isTargetCollector(collector) {
|
|
18851
20125
|
switch (collector.kind) {
|
|
18852
20126
|
case "card":
|
|
18853
20127
|
case "board-edge":
|
|
@@ -18862,8 +20136,19 @@ function isTargetCollector2(collector) {
|
|
|
18862
20136
|
function isManyCollector(collector) {
|
|
18863
20137
|
return collector.selection?.mode === "many";
|
|
18864
20138
|
}
|
|
18865
|
-
function
|
|
18866
|
-
|
|
20139
|
+
function terminalCollectorsForInputs(inputs) {
|
|
20140
|
+
const terminalKeys = new Set(Object.keys(inputs));
|
|
20141
|
+
for (const collector of Object.values(inputs)) {
|
|
20142
|
+
for (const dependencyKey of collector.dependsOn ?? []) {
|
|
20143
|
+
terminalKeys.delete(dependencyKey);
|
|
20144
|
+
}
|
|
20145
|
+
}
|
|
20146
|
+
const collectors = [];
|
|
20147
|
+
for (const key of terminalKeys) {
|
|
20148
|
+
const collector = inputs[key];
|
|
20149
|
+
if (collector) collectors.push(collector);
|
|
20150
|
+
}
|
|
20151
|
+
return collectors;
|
|
18867
20152
|
}
|
|
18868
20153
|
function deriveCommitPolicy(inputs, explicit) {
|
|
18869
20154
|
const collectors = Object.values(inputs);
|
|
@@ -18879,15 +20164,16 @@ function deriveCommitPolicy(inputs, explicit) {
|
|
|
18879
20164
|
if (hasManyCollector) {
|
|
18880
20165
|
return { mode: "manual" };
|
|
18881
20166
|
}
|
|
18882
|
-
if (collectors.some(
|
|
20167
|
+
if (collectors.length === 0 || !collectors.some(isTargetCollector)) {
|
|
18883
20168
|
return { mode: "manual" };
|
|
18884
20169
|
}
|
|
18885
|
-
|
|
20170
|
+
const terminalCollectors = terminalCollectorsForInputs(inputs);
|
|
20171
|
+
if (terminalCollectors.length === 0) {
|
|
18886
20172
|
return { mode: "manual" };
|
|
18887
20173
|
}
|
|
18888
|
-
return
|
|
18889
|
-
(collector) =>
|
|
18890
|
-
) ? { mode: "autoWhenReady" } : { mode: "manual" };
|
|
20174
|
+
return terminalCollectors.every(
|
|
20175
|
+
(collector) => isTargetCollector(collector) || collector.kind === "rng"
|
|
20176
|
+
) && terminalCollectors.some(isTargetCollector) ? { mode: "autoWhenReady" } : { mode: "manual" };
|
|
18891
20177
|
}
|
|
18892
20178
|
function projectInteractionMetadata(interaction) {
|
|
18893
20179
|
return {
|
|
@@ -18902,7 +20188,7 @@ function enrichResourceInputPresentation(inputs, manifest) {
|
|
|
18902
20188
|
}
|
|
18903
20189
|
const resources = presentationById;
|
|
18904
20190
|
const enrichChoice = (choice) => {
|
|
18905
|
-
const presentation = resources[choice.value];
|
|
20191
|
+
const presentation = choice.value === null ? void 0 : resources[choice.value];
|
|
18906
20192
|
return {
|
|
18907
20193
|
...choice,
|
|
18908
20194
|
label: typeof presentation?.label === "string" && (!choice.label || choice.label === choice.value) ? presentation.label : choice.label || (typeof presentation?.label === "string" ? presentation.label : ""),
|
|
@@ -18910,7 +20196,16 @@ function enrichResourceInputPresentation(inputs, manifest) {
|
|
|
18910
20196
|
};
|
|
18911
20197
|
};
|
|
18912
20198
|
return inputs.map((input) => {
|
|
18913
|
-
if (input.domain.type === "choice"
|
|
20199
|
+
if (input.domain.type === "choice") {
|
|
20200
|
+
return {
|
|
20201
|
+
...input,
|
|
20202
|
+
domain: {
|
|
20203
|
+
...input.domain,
|
|
20204
|
+
choices: input.domain.choices.map(enrichChoice)
|
|
20205
|
+
}
|
|
20206
|
+
};
|
|
20207
|
+
}
|
|
20208
|
+
if (input.domain.type === "choiceList") {
|
|
18914
20209
|
return {
|
|
18915
20210
|
...input,
|
|
18916
20211
|
domain: {
|
|
@@ -18936,6 +20231,23 @@ function enrichResourceInputPresentation(inputs, manifest) {
|
|
|
18936
20231
|
};
|
|
18937
20232
|
});
|
|
18938
20233
|
}
|
|
20234
|
+
function interactionAvailabilityFromDecision(decision) {
|
|
20235
|
+
if (decision.available) return { status: "available" };
|
|
20236
|
+
if (decision.unavailableReason === "Not your turn") {
|
|
20237
|
+
return { status: "notYourTurn", reason: decision.unavailableReason };
|
|
20238
|
+
}
|
|
20239
|
+
if (decision.unavailableReason === "INSUFFICIENT_RESOURCES") {
|
|
20240
|
+
return {
|
|
20241
|
+
status: "insufficientResources",
|
|
20242
|
+
reason: decision.unavailableReason,
|
|
20243
|
+
missingResources: { ...decision.missingResources ?? {} }
|
|
20244
|
+
};
|
|
20245
|
+
}
|
|
20246
|
+
return {
|
|
20247
|
+
status: "blocked",
|
|
20248
|
+
reason: decision.unavailableReason ?? "Interaction unavailable"
|
|
20249
|
+
};
|
|
20250
|
+
}
|
|
18939
20251
|
function createInteractionDecisionResolver(scope, stages, authorization) {
|
|
18940
20252
|
function evaluateInteractionCost(state, interaction, playerId, params, projection) {
|
|
18941
20253
|
if (!interaction.cost) {
|
|
@@ -18969,15 +20281,15 @@ function createInteractionDecisionResolver(scope, stages, authorization) {
|
|
|
18969
20281
|
const queries = options.projection?.q ?? createStateQueries(domainState);
|
|
18970
20282
|
const derived = options.projection?.derived;
|
|
18971
20283
|
const shouldMaterializeInputDomains = decision.available || decision.unavailableReason !== "Not your turn";
|
|
18972
|
-
const promptContext = metadata.kind === "prompt"
|
|
20284
|
+
const promptContext = metadata.kind === "prompt" ? {
|
|
18973
20285
|
to: playerId,
|
|
18974
20286
|
title: humanizeInteractionId(interactionId),
|
|
18975
|
-
options: collectPromptOptions(
|
|
20287
|
+
options: shouldMaterializeInputDomains ? collectPromptOptions(
|
|
18976
20288
|
{ inputs: interactionInputs },
|
|
18977
20289
|
domainState,
|
|
18978
20290
|
playerId,
|
|
18979
20291
|
queries
|
|
18980
|
-
)
|
|
20292
|
+
) : void 0
|
|
18981
20293
|
} : void 0;
|
|
18982
20294
|
const inputs = shouldMaterializeInputDomains ? enrichResourceInputPresentation(
|
|
18983
20295
|
collectInteractionInputs(interaction, domainState, playerId, {
|
|
@@ -18991,11 +20303,11 @@ function createInteractionDecisionResolver(scope, stages, authorization) {
|
|
|
18991
20303
|
}),
|
|
18992
20304
|
scope.definition.contract.manifest
|
|
18993
20305
|
) : [];
|
|
18994
|
-
|
|
20306
|
+
const baseDescriptor = {
|
|
18995
20307
|
phaseName,
|
|
18996
20308
|
interactionKey: `${phaseName}.${interactionId}`,
|
|
18997
20309
|
interactionId,
|
|
18998
|
-
|
|
20310
|
+
commit: metadata.commit,
|
|
18999
20311
|
zoneId: collectFirstCardZoneId(interaction),
|
|
19000
20312
|
zoneIds: collectCardZoneIds(interaction),
|
|
19001
20313
|
inputs,
|
|
@@ -19003,10 +20315,21 @@ function createInteractionDecisionResolver(scope, stages, authorization) {
|
|
|
19003
20315
|
currentResources: decision.cost ? {
|
|
19004
20316
|
...queries.player.resources(playerId)
|
|
19005
20317
|
} : void 0,
|
|
19006
|
-
|
|
19007
|
-
|
|
19008
|
-
|
|
19009
|
-
|
|
20318
|
+
availability: interactionAvailabilityFromDecision(decision)
|
|
20319
|
+
};
|
|
20320
|
+
if (metadata.kind === "prompt") {
|
|
20321
|
+
return {
|
|
20322
|
+
...baseDescriptor,
|
|
20323
|
+
kind: "prompt",
|
|
20324
|
+
context: promptContext ?? {
|
|
20325
|
+
to: playerId,
|
|
20326
|
+
title: humanizeInteractionId(interactionId)
|
|
20327
|
+
}
|
|
20328
|
+
};
|
|
20329
|
+
}
|
|
20330
|
+
return {
|
|
20331
|
+
...baseDescriptor,
|
|
20332
|
+
kind: "action"
|
|
19010
20333
|
};
|
|
19011
20334
|
}
|
|
19012
20335
|
function resolveInteractionDecision({
|
|
@@ -19422,16 +20745,15 @@ function resolveContainerRef(table, ref) {
|
|
|
19422
20745
|
throw new Error(`Unknown board '${ref.boardId}'.`);
|
|
19423
20746
|
}
|
|
19424
20747
|
const space2 = board2?.spaces[ref.spaceId];
|
|
19425
|
-
if (!space2
|
|
20748
|
+
if (!space2) {
|
|
19426
20749
|
throw new Error(
|
|
19427
|
-
`
|
|
20750
|
+
`Unknown board space '${ref.spaceId}' on board '${ref.boardId}'.`
|
|
19428
20751
|
);
|
|
19429
20752
|
}
|
|
19430
20753
|
return {
|
|
19431
20754
|
kind: "space",
|
|
19432
20755
|
boardId: board2.id,
|
|
19433
|
-
spaceId: ref.spaceId
|
|
19434
|
-
zoneId: space2.zoneId
|
|
20756
|
+
spaceId: ref.spaceId
|
|
19435
20757
|
};
|
|
19436
20758
|
}
|
|
19437
20759
|
const board = table.boards.byId[resolveRuntimeBoardId(table, ref.boardId, ref.playerId)];
|
|
@@ -19441,16 +20763,15 @@ function resolveContainerRef(table, ref) {
|
|
|
19441
20763
|
);
|
|
19442
20764
|
}
|
|
19443
20765
|
const space = board?.spaces[ref.spaceId];
|
|
19444
|
-
if (!space
|
|
20766
|
+
if (!space) {
|
|
19445
20767
|
throw new Error(
|
|
19446
|
-
`
|
|
20768
|
+
`Unknown board space '${ref.spaceId}' on board '${ref.boardId}' for '${ref.playerId}'.`
|
|
19447
20769
|
);
|
|
19448
20770
|
}
|
|
19449
20771
|
return {
|
|
19450
20772
|
kind: "space",
|
|
19451
20773
|
boardId: board.id,
|
|
19452
|
-
spaceId: ref.spaceId
|
|
19453
|
-
zoneId: space.zoneId
|
|
20774
|
+
spaceId: ref.spaceId
|
|
19454
20775
|
};
|
|
19455
20776
|
}
|
|
19456
20777
|
function readContainerComponents(table, ref) {
|
|
@@ -20072,7 +21393,7 @@ function createProjectionBuilder(scope, interactions) {
|
|
|
20072
21393
|
});
|
|
20073
21394
|
if (!decision.found || !decision.visible) continue;
|
|
20074
21395
|
const cardDomain = cardKey ? decision.descriptor.inputs.find((input) => input.key === cardKey)?.domain : void 0;
|
|
20075
|
-
const cardTargets = cardDomain?.type === "
|
|
21396
|
+
const cardTargets = cardDomain?.type === "cardTarget" && cardDomain.projection === "resolved" ? cardDomain.eligibleTargets : void 0;
|
|
20076
21397
|
if (cardKey && !cardTargets?.includes(cardId)) {
|
|
20077
21398
|
continue;
|
|
20078
21399
|
}
|
|
@@ -20881,6 +22202,9 @@ function toWireDispatchResult(result, serializeState) {
|
|
|
20881
22202
|
trace
|
|
20882
22203
|
};
|
|
20883
22204
|
}
|
|
22205
|
+
function toWireDispatchTrace(result) {
|
|
22206
|
+
return toWireDispatchResult(result, (state) => state).trace;
|
|
22207
|
+
}
|
|
20884
22208
|
function createReducerBundle(definition) {
|
|
20885
22209
|
const trustedBundle = createTrustedReducerBundle(definition);
|
|
20886
22210
|
const codec = createIngressRuntimeCodec(definition);
|
|
@@ -21043,7 +22367,11 @@ function createReducerBundle(definition) {
|
|
|
21043
22367
|
};
|
|
21044
22368
|
}
|
|
21045
22369
|
state = result.state;
|
|
21046
|
-
return {
|
|
22370
|
+
return {
|
|
22371
|
+
kind: "accept",
|
|
22372
|
+
state: codec.serializeState(state),
|
|
22373
|
+
trace: toWireDispatchTrace(result)
|
|
22374
|
+
};
|
|
21047
22375
|
},
|
|
21048
22376
|
projectSeatViewDynamic({ playerId, viewId = "player" }) {
|
|
21049
22377
|
return trustedBundle.projectSeatViewDynamic({
|
|
@@ -21077,7 +22405,7 @@ function createReducerBundle(definition) {
|
|
|
21077
22405
|
// src/utils/ts-module-loader.ts
|
|
21078
22406
|
import { mkdtemp as mkdtemp2, rm as rm4, writeFile as writeFile3 } from "fs/promises";
|
|
21079
22407
|
import { tmpdir as tmpdir2 } from "os";
|
|
21080
|
-
import
|
|
22408
|
+
import path19 from "path";
|
|
21081
22409
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
21082
22410
|
import { build as build2 } from "esbuild";
|
|
21083
22411
|
var ESBUILD_EXTERNALS = [
|
|
@@ -21091,14 +22419,14 @@ function resolveSourceCheckoutBuildContext() {
|
|
|
21091
22419
|
const repoRoot = resolveCliRepoRoot(import.meta.url);
|
|
21092
22420
|
return {
|
|
21093
22421
|
nodePaths: [
|
|
21094
|
-
|
|
21095
|
-
|
|
22422
|
+
path19.join(repoRoot, "apps", "dreamboard-cli", "node_modules"),
|
|
22423
|
+
path19.join(repoRoot, "node_modules")
|
|
21096
22424
|
],
|
|
21097
22425
|
plugins: [createRepoLocalPackageResolutionPlugin({ repoRoot })]
|
|
21098
22426
|
};
|
|
21099
22427
|
} catch {
|
|
21100
22428
|
return {
|
|
21101
|
-
nodePaths: [
|
|
22429
|
+
nodePaths: [path19.join(process.cwd(), "node_modules")],
|
|
21102
22430
|
plugins: []
|
|
21103
22431
|
};
|
|
21104
22432
|
}
|
|
@@ -21124,10 +22452,10 @@ async function bundleTypeScriptModuleText(entryPath, options = {}) {
|
|
|
21124
22452
|
return output.text;
|
|
21125
22453
|
}
|
|
21126
22454
|
async function importTypeScriptModule(entryPath) {
|
|
21127
|
-
const tempDir = await mkdtemp2(
|
|
21128
|
-
const outfile =
|
|
22455
|
+
const tempDir = await mkdtemp2(path19.join(tmpdir2(), "dreamboard-ts-module-"));
|
|
22456
|
+
const outfile = path19.join(
|
|
21129
22457
|
tempDir,
|
|
21130
|
-
`${
|
|
22458
|
+
`${path19.basename(entryPath).replace(/\.[^.]+$/u, "")}.mjs`
|
|
21131
22459
|
);
|
|
21132
22460
|
try {
|
|
21133
22461
|
const bundledText = await bundleTypeScriptModuleText(entryPath);
|
|
@@ -21152,7 +22480,7 @@ import {
|
|
|
21152
22480
|
symlink
|
|
21153
22481
|
} from "fs/promises";
|
|
21154
22482
|
import { tmpdir as tmpdir3 } from "os";
|
|
21155
|
-
import
|
|
22483
|
+
import path20 from "path";
|
|
21156
22484
|
import { createInterface } from "readline";
|
|
21157
22485
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
21158
22486
|
var READY_PREFIX = "HARNESS_READY ";
|
|
@@ -21160,15 +22488,15 @@ var HARNESS_START_IDLE_TIMEOUT_MS = 18e4;
|
|
|
21160
22488
|
var HARNESS_START_MAX_TIMEOUT_MS = 6e5;
|
|
21161
22489
|
var HARNESS_STOP_TIMEOUT_MS = 1e4;
|
|
21162
22490
|
var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
21163
|
-
var MODULE_DIR4 =
|
|
21164
|
-
var REPO_ROOT3 =
|
|
21165
|
-
var PROJECT_DEPENDENCY_NODE_MODULES =
|
|
22491
|
+
var MODULE_DIR4 = path20.dirname(fileURLToPath7(import.meta.url));
|
|
22492
|
+
var REPO_ROOT3 = path20.resolve(MODULE_DIR4, "../../../../..");
|
|
22493
|
+
var PROJECT_DEPENDENCY_NODE_MODULES = path20.join(
|
|
21166
22494
|
REPO_ROOT3,
|
|
21167
22495
|
"apps",
|
|
21168
22496
|
"dreamboard-cli",
|
|
21169
22497
|
"node_modules"
|
|
21170
22498
|
);
|
|
21171
|
-
var UI_SDK_NODE_MODULES =
|
|
22499
|
+
var UI_SDK_NODE_MODULES = path20.join(
|
|
21172
22500
|
REPO_ROOT3,
|
|
21173
22501
|
"packages",
|
|
21174
22502
|
"ui-sdk",
|
|
@@ -21178,8 +22506,8 @@ async function startEmbeddedHarnessSession(options) {
|
|
|
21178
22506
|
const repoRoot = await resolveRepoRoot2(options.projectRoot);
|
|
21179
22507
|
const gradlew = await resolveGradleLauncher(repoRoot);
|
|
21180
22508
|
const fixture = await prepareLocalHarnessFixture(options);
|
|
21181
|
-
const logDir =
|
|
21182
|
-
const logFilePath =
|
|
22509
|
+
const logDir = path20.join(options.projectRoot, "test", "generated");
|
|
22510
|
+
const logFilePath = path20.join(logDir, "embedded-harness.log");
|
|
21183
22511
|
await mkdir2(logDir, { recursive: true });
|
|
21184
22512
|
const previousClientConfig = client.getConfig();
|
|
21185
22513
|
const child = spawn5(
|
|
@@ -21188,7 +22516,7 @@ async function startEmbeddedHarnessSession(options) {
|
|
|
21188
22516
|
...gradlew.args,
|
|
21189
22517
|
"--console=plain",
|
|
21190
22518
|
":apps:backend:runEmbeddedHarness",
|
|
21191
|
-
`-PharnessManifestPath=${
|
|
22519
|
+
`-PharnessManifestPath=${path20.join(options.projectRoot, MATERIALIZED_MANIFEST_FILE)}`,
|
|
21192
22520
|
`-PharnessBundlePath=${fixture.bundleRoot}`,
|
|
21193
22521
|
`-PharnessGameId=${fixture.gameId}`,
|
|
21194
22522
|
`-PharnessManifestId=${fixture.manifestId}`,
|
|
@@ -21255,7 +22583,7 @@ async function ensureSymlink(targetPath, linkPath) {
|
|
|
21255
22583
|
if (await pathExists3(linkPath)) {
|
|
21256
22584
|
return;
|
|
21257
22585
|
}
|
|
21258
|
-
await mkdir2(
|
|
22586
|
+
await mkdir2(path20.dirname(linkPath), { recursive: true });
|
|
21259
22587
|
await symlink(
|
|
21260
22588
|
targetPath,
|
|
21261
22589
|
linkPath,
|
|
@@ -21266,13 +22594,13 @@ async function ensureEmbeddedHarnessDependencies(projectRoot) {
|
|
|
21266
22594
|
if (await pathExists3(PROJECT_DEPENDENCY_NODE_MODULES)) {
|
|
21267
22595
|
await ensureSymlink(
|
|
21268
22596
|
PROJECT_DEPENDENCY_NODE_MODULES,
|
|
21269
|
-
|
|
22597
|
+
path20.join(projectRoot, "node_modules")
|
|
21270
22598
|
);
|
|
21271
22599
|
}
|
|
21272
22600
|
if (await pathExists3(UI_SDK_NODE_MODULES)) {
|
|
21273
22601
|
await ensureSymlink(
|
|
21274
22602
|
UI_SDK_NODE_MODULES,
|
|
21275
|
-
|
|
22603
|
+
path20.join(projectRoot, "ui", "node_modules")
|
|
21276
22604
|
);
|
|
21277
22605
|
}
|
|
21278
22606
|
}
|
|
@@ -21282,15 +22610,15 @@ async function prepareLocalHarnessFixture(options) {
|
|
|
21282
22610
|
const manifestContent = await readMaterializedManifestText(
|
|
21283
22611
|
options.projectRoot
|
|
21284
22612
|
);
|
|
21285
|
-
const appEntryPath =
|
|
22613
|
+
const appEntryPath = path20.join(options.projectRoot, "app", "index.ts");
|
|
21286
22614
|
if (!await exists(appEntryPath)) {
|
|
21287
22615
|
throw new Error(
|
|
21288
|
-
`Embedded harness requires ${
|
|
22616
|
+
`Embedded harness requires ${path20.relative(options.projectRoot, appEntryPath)}.`
|
|
21289
22617
|
);
|
|
21290
22618
|
}
|
|
21291
|
-
const bundleRoot = await mkdtemp3(
|
|
21292
|
-
const bundleEntryPath =
|
|
21293
|
-
await mkdir2(
|
|
22619
|
+
const bundleRoot = await mkdtemp3(path20.join(tmpdir3(), "dreamboard-harness-"));
|
|
22620
|
+
const bundleEntryPath = path20.join(bundleRoot, "src", "app", "index.js");
|
|
22621
|
+
await mkdir2(path20.dirname(bundleEntryPath), { recursive: true });
|
|
21294
22622
|
const bunExecutable = await resolveBunExecutable();
|
|
21295
22623
|
if (!bunExecutable) {
|
|
21296
22624
|
await rm5(bundleRoot, { recursive: true, force: true });
|
|
@@ -21327,7 +22655,7 @@ async function prepareLocalHarnessFixture(options) {
|
|
|
21327
22655
|
const bundleContent = await readFile3(bundleEntryPath, "utf8");
|
|
21328
22656
|
const manifestHash = hashContent(manifestContent);
|
|
21329
22657
|
const bundleHash = hashContent(bundleContent);
|
|
21330
|
-
const gameSlug = options.projectConfig.slug ||
|
|
22658
|
+
const gameSlug = options.projectConfig.slug || path20.basename(options.projectRoot);
|
|
21331
22659
|
const authoring = getProjectAuthoringState(options.projectConfig);
|
|
21332
22660
|
return {
|
|
21333
22661
|
bundleRoot,
|
|
@@ -21347,14 +22675,14 @@ async function prepareLocalHarnessFixture(options) {
|
|
|
21347
22675
|
};
|
|
21348
22676
|
}
|
|
21349
22677
|
async function resolveBunExecutable() {
|
|
21350
|
-
const currentExecutable =
|
|
22678
|
+
const currentExecutable = path20.basename(process.execPath).toLowerCase();
|
|
21351
22679
|
if (currentExecutable === "bun" || currentExecutable === "bun.exe") {
|
|
21352
22680
|
return process.execPath;
|
|
21353
22681
|
}
|
|
21354
22682
|
const candidatePaths = [
|
|
21355
|
-
...(process.env.PATH ?? "").split(
|
|
21356
|
-
...process.env.BUN_INSTALL ? executableCandidates(
|
|
21357
|
-
...process.env.HOME ? executableCandidates(
|
|
22683
|
+
...(process.env.PATH ?? "").split(path20.delimiter).filter((directory) => directory.length > 0).flatMap((directory) => executableCandidates(directory, "bun")),
|
|
22684
|
+
...process.env.BUN_INSTALL ? executableCandidates(path20.join(process.env.BUN_INSTALL, "bin"), "bun") : [],
|
|
22685
|
+
...process.env.HOME ? executableCandidates(path20.join(process.env.HOME, ".bun", "bin"), "bun") : []
|
|
21358
22686
|
];
|
|
21359
22687
|
for (const candidate of candidatePaths) {
|
|
21360
22688
|
try {
|
|
@@ -21370,11 +22698,11 @@ function executableCandidates(directory, executableName) {
|
|
|
21370
22698
|
return [];
|
|
21371
22699
|
}
|
|
21372
22700
|
if (process.platform !== "win32") {
|
|
21373
|
-
return [
|
|
22701
|
+
return [path20.join(directory, executableName)];
|
|
21374
22702
|
}
|
|
21375
22703
|
const extensions = (process.env.PATHEXT ?? ".EXE;.CMD;.BAT;.COM").split(";").filter((extension) => extension.length > 0);
|
|
21376
22704
|
return extensions.map(
|
|
21377
|
-
(extension) =>
|
|
22705
|
+
(extension) => path20.join(directory, `${executableName}${extension.toLowerCase()}`)
|
|
21378
22706
|
);
|
|
21379
22707
|
}
|
|
21380
22708
|
async function waitForExitCode(child) {
|
|
@@ -21532,13 +22860,13 @@ async function waitForExit(child, timeoutMs) {
|
|
|
21532
22860
|
}
|
|
21533
22861
|
async function resolveGradleLauncher(repoRoot) {
|
|
21534
22862
|
if (process.platform === "win32") {
|
|
21535
|
-
const gradleBat =
|
|
22863
|
+
const gradleBat = path20.join(repoRoot, "gradlew.bat");
|
|
21536
22864
|
if (!await exists(gradleBat)) {
|
|
21537
22865
|
throw new Error(`Missing Gradle launcher at ${gradleBat}`);
|
|
21538
22866
|
}
|
|
21539
22867
|
return { command: gradleBat, args: [] };
|
|
21540
22868
|
}
|
|
21541
|
-
const gradleShell =
|
|
22869
|
+
const gradleShell = path20.join(repoRoot, "gradlew");
|
|
21542
22870
|
if (!await exists(gradleShell)) {
|
|
21543
22871
|
throw new Error(`Missing Gradle launcher at ${gradleShell}`);
|
|
21544
22872
|
}
|
|
@@ -21546,7 +22874,7 @@ async function resolveGradleLauncher(repoRoot) {
|
|
|
21546
22874
|
}
|
|
21547
22875
|
async function resolveRepoRoot2(projectRoot) {
|
|
21548
22876
|
const currentFile = fileURLToPath7(import.meta.url);
|
|
21549
|
-
const searchRoots = [
|
|
22877
|
+
const searchRoots = [path20.dirname(currentFile), projectRoot, process.cwd()];
|
|
21550
22878
|
for (const root of searchRoots) {
|
|
21551
22879
|
const repoRoot = await findSourceCheckoutRepoRoot(root);
|
|
21552
22880
|
if (repoRoot) {
|
|
@@ -21558,12 +22886,12 @@ async function resolveRepoRoot2(projectRoot) {
|
|
|
21558
22886
|
);
|
|
21559
22887
|
}
|
|
21560
22888
|
async function findSourceCheckoutRepoRoot(startDir) {
|
|
21561
|
-
let currentDir =
|
|
22889
|
+
let currentDir = path20.resolve(startDir);
|
|
21562
22890
|
while (true) {
|
|
21563
22891
|
if (await isSourceCheckoutRepoRoot(currentDir)) {
|
|
21564
22892
|
return currentDir;
|
|
21565
22893
|
}
|
|
21566
|
-
const parentDir =
|
|
22894
|
+
const parentDir = path20.dirname(currentDir);
|
|
21567
22895
|
if (parentDir === currentDir) {
|
|
21568
22896
|
return null;
|
|
21569
22897
|
}
|
|
@@ -21571,7 +22899,7 @@ async function findSourceCheckoutRepoRoot(startDir) {
|
|
|
21571
22899
|
}
|
|
21572
22900
|
}
|
|
21573
22901
|
async function isSourceCheckoutRepoRoot(rootDir) {
|
|
21574
|
-
return await exists(
|
|
22902
|
+
return await exists(path20.join(rootDir, "gradlew")) && await exists(path20.join(rootDir, "apps", "backend", "build.gradle.kts"));
|
|
21575
22903
|
}
|
|
21576
22904
|
function normalizeUuid(candidate, fallbackSeed) {
|
|
21577
22905
|
if (candidate && UUID_PATTERN.test(candidate)) {
|
|
@@ -21623,7 +22951,7 @@ async function subscribeToCliSessionEvents(options) {
|
|
|
21623
22951
|
|
|
21624
22952
|
// src/ui/playwright-runner.ts
|
|
21625
22953
|
import os2 from "os";
|
|
21626
|
-
import
|
|
22954
|
+
import path21 from "path";
|
|
21627
22955
|
function configurePlaywrightBrowsersPath() {
|
|
21628
22956
|
if (process.env.PLAYWRIGHT_BROWSERS_PATH) {
|
|
21629
22957
|
return;
|
|
@@ -21635,10 +22963,10 @@ function configurePlaywrightBrowsersPath() {
|
|
|
21635
22963
|
} catch {
|
|
21636
22964
|
return;
|
|
21637
22965
|
}
|
|
21638
|
-
if (!runtimeHome ||
|
|
22966
|
+
if (!runtimeHome || path21.resolve(runtimeHome) === path21.resolve(realHome)) {
|
|
21639
22967
|
return;
|
|
21640
22968
|
}
|
|
21641
|
-
const browserCachePath = process.platform === "darwin" ?
|
|
22969
|
+
const browserCachePath = process.platform === "darwin" ? path21.join(realHome, "Library", "Caches", "ms-playwright") : process.platform === "win32" ? path21.join(realHome, "AppData", "Local", "ms-playwright") : path21.join(realHome, ".cache", "ms-playwright");
|
|
21642
22970
|
process.env.PLAYWRIGHT_BROWSERS_PATH = browserCachePath;
|
|
21643
22971
|
}
|
|
21644
22972
|
async function buildBrowserAuthInitScript(config) {
|
|
@@ -21647,7 +22975,7 @@ async function buildBrowserAuthInitScript(config) {
|
|
|
21647
22975
|
return `(function(){localStorage.setItem('supabase_token',${JSON.stringify(config.authToken)});})();`;
|
|
21648
22976
|
}
|
|
21649
22977
|
try {
|
|
21650
|
-
const { createClient: createClient2 } = await import("./dist-
|
|
22978
|
+
const { createClient: createClient2 } = await import("./dist-JNA2CLKS.js");
|
|
21651
22979
|
const supabase = createClient2(config.supabaseUrl, config.supabaseAnonKey);
|
|
21652
22980
|
let sessionData = null;
|
|
21653
22981
|
if (!sessionData) {
|
|
@@ -21741,9 +23069,42 @@ var TESTING_TYPES_STUB2 = "export function defineScenario(scenario) { return sce
|
|
|
21741
23069
|
var DEFAULT_TIMEOUT_MS = 1e4;
|
|
21742
23070
|
var BASE_SUFFIX = ".base.ts";
|
|
21743
23071
|
var SCENARIO_SUFFIX = ".scenario.ts";
|
|
23072
|
+
function formatScenarioErrorForDisplay(options) {
|
|
23073
|
+
const message = options.error.message || "Scenario failed.";
|
|
23074
|
+
const scenarioFrame = findScenarioStackFrame({
|
|
23075
|
+
stack: options.error.stack,
|
|
23076
|
+
projectRoot: options.projectRoot,
|
|
23077
|
+
scenarioFilePath: options.scenarioFilePath
|
|
23078
|
+
});
|
|
23079
|
+
return scenarioFrame ? `${message}
|
|
23080
|
+
${scenarioFrame}` : message;
|
|
23081
|
+
}
|
|
23082
|
+
function findScenarioStackFrame(options) {
|
|
23083
|
+
if (!options.stack) {
|
|
23084
|
+
return null;
|
|
23085
|
+
}
|
|
23086
|
+
const absolutePath = path22.resolve(options.scenarioFilePath);
|
|
23087
|
+
const relativePath = path22.relative(options.projectRoot, absolutePath);
|
|
23088
|
+
const normalizedRelativePath = relativePath.split(path22.sep).join("/");
|
|
23089
|
+
const escapedAbsolutePath = escapeRegExp(absolutePath);
|
|
23090
|
+
const escapedRelativePath = escapeRegExp(normalizedRelativePath);
|
|
23091
|
+
const absoluteFrame = new RegExp(`${escapedAbsolutePath}:(\\d+):(\\d+)`);
|
|
23092
|
+
const relativeFrame = new RegExp(`${escapedRelativePath}:(\\d+):(\\d+)`);
|
|
23093
|
+
for (const line of options.stack.split("\n")) {
|
|
23094
|
+
const normalizedLine = line.split(path22.sep).join("/");
|
|
23095
|
+
const match = normalizedLine.match(absoluteFrame) ?? normalizedLine.match(relativeFrame);
|
|
23096
|
+
if (match?.[1] && match?.[2]) {
|
|
23097
|
+
return `at ${normalizedRelativePath}:${match[1]}:${match[2]}`;
|
|
23098
|
+
}
|
|
23099
|
+
}
|
|
23100
|
+
return null;
|
|
23101
|
+
}
|
|
23102
|
+
function escapeRegExp(value) {
|
|
23103
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
23104
|
+
}
|
|
21744
23105
|
var testingExpectApiFactoryPromise;
|
|
21745
23106
|
async function loadTestingExpectApiFactory() {
|
|
21746
|
-
testingExpectApiFactoryPromise ??= import("./dist-
|
|
23107
|
+
testingExpectApiFactoryPromise ??= import("./dist-JO2OGKJD.js").then(
|
|
21747
23108
|
(module) => module.createExpectApi
|
|
21748
23109
|
);
|
|
21749
23110
|
return testingExpectApiFactoryPromise;
|
|
@@ -21783,7 +23144,7 @@ async function discoverFiles(root, suffix) {
|
|
|
21783
23144
|
const entries = await readdir3(root, { withFileTypes: true });
|
|
21784
23145
|
const files = [];
|
|
21785
23146
|
for (const entry of entries) {
|
|
21786
|
-
const entryPath =
|
|
23147
|
+
const entryPath = path22.join(root, entry.name);
|
|
21787
23148
|
if (entry.isDirectory()) {
|
|
21788
23149
|
files.push(...await discoverFiles(entryPath, suffix));
|
|
21789
23150
|
continue;
|
|
@@ -21832,38 +23193,38 @@ function parseTypedScenarioDefinition(value) {
|
|
|
21832
23193
|
};
|
|
21833
23194
|
}
|
|
21834
23195
|
async function isReducerNativeTestingWorkspace(projectRoot) {
|
|
21835
|
-
return await exists(
|
|
21836
|
-
|
|
23196
|
+
return await exists(path22.join(projectRoot, "app", "game.ts")) && await exists(
|
|
23197
|
+
path22.join(projectRoot, "shared", "generated", "ui-contract.ts")
|
|
21837
23198
|
);
|
|
21838
23199
|
}
|
|
21839
23200
|
async function ensureReducerNativeTestingFiles(projectRoot) {
|
|
21840
|
-
const testingTypesPath =
|
|
21841
|
-
const testingContractPath =
|
|
23201
|
+
const testingTypesPath = path22.join(projectRoot, "test", "testing-types.ts");
|
|
23202
|
+
const testingContractPath = path22.join(
|
|
21842
23203
|
projectRoot,
|
|
21843
23204
|
"test",
|
|
21844
23205
|
"generated",
|
|
21845
23206
|
"testing-contract.ts"
|
|
21846
23207
|
);
|
|
21847
|
-
const baseStatesPath =
|
|
23208
|
+
const baseStatesPath = path22.join(
|
|
21848
23209
|
projectRoot,
|
|
21849
23210
|
"test",
|
|
21850
23211
|
"generated",
|
|
21851
23212
|
"base-states.generated.ts"
|
|
21852
23213
|
);
|
|
21853
|
-
const baseStatesDtsPath =
|
|
23214
|
+
const baseStatesDtsPath = path22.join(
|
|
21854
23215
|
projectRoot,
|
|
21855
23216
|
"test",
|
|
21856
23217
|
"generated",
|
|
21857
23218
|
"base-states.generated.d.ts"
|
|
21858
23219
|
);
|
|
21859
|
-
const scenarioManifestPath =
|
|
23220
|
+
const scenarioManifestPath = path22.join(
|
|
21860
23221
|
projectRoot,
|
|
21861
23222
|
"test",
|
|
21862
23223
|
"generated",
|
|
21863
23224
|
"scenario-manifest.generated.ts"
|
|
21864
23225
|
);
|
|
21865
|
-
await ensureDir(
|
|
21866
|
-
await ensureDir(
|
|
23226
|
+
await ensureDir(path22.dirname(testingTypesPath));
|
|
23227
|
+
await ensureDir(path22.dirname(testingContractPath));
|
|
21867
23228
|
const existingTestingTypes = await readTextFileIfExists(testingTypesPath);
|
|
21868
23229
|
if (shouldRefreshReducerTestingTypes(existingTestingTypes)) {
|
|
21869
23230
|
await writeTextFile(
|
|
@@ -21907,7 +23268,7 @@ var DEFAULT_REJECTION_CODES2 = [
|
|
|
21907
23268
|
];
|
|
21908
23269
|
async function collectKnownRejectionCodes(projectRoot) {
|
|
21909
23270
|
const knownCodes = new Set(DEFAULT_REJECTION_CODES2);
|
|
21910
|
-
const gamePath =
|
|
23271
|
+
const gamePath = path22.join(projectRoot, "app", "game.ts");
|
|
21911
23272
|
if (!await exists(gamePath)) {
|
|
21912
23273
|
return Array.from(knownCodes).sort(
|
|
21913
23274
|
(left, right) => left.localeCompare(right)
|
|
@@ -21934,7 +23295,7 @@ async function collectKnownRejectionCodes(projectRoot) {
|
|
|
21934
23295
|
}
|
|
21935
23296
|
async function loadTypedBases(projectRoot) {
|
|
21936
23297
|
const baseFiles = await discoverFiles(
|
|
21937
|
-
|
|
23298
|
+
path22.join(projectRoot, "test", "bases"),
|
|
21938
23299
|
BASE_SUFFIX
|
|
21939
23300
|
);
|
|
21940
23301
|
const loaded = [];
|
|
@@ -21953,8 +23314,8 @@ async function loadTypedBases(projectRoot) {
|
|
|
21953
23314
|
return loaded;
|
|
21954
23315
|
}
|
|
21955
23316
|
async function loadTypedScenarios(projectRoot, options) {
|
|
21956
|
-
const scenarioFiles = options.scenarioPath ? [
|
|
21957
|
-
|
|
23317
|
+
const scenarioFiles = options.scenarioPath ? [path22.resolve(projectRoot, options.scenarioPath)] : await discoverFiles(
|
|
23318
|
+
path22.join(projectRoot, "test", "scenarios"),
|
|
21958
23319
|
SCENARIO_SUFFIX
|
|
21959
23320
|
);
|
|
21960
23321
|
const loaded = [];
|
|
@@ -21973,8 +23334,8 @@ async function loadTypedScenarios(projectRoot, options) {
|
|
|
21973
23334
|
return loaded;
|
|
21974
23335
|
}
|
|
21975
23336
|
function reducerNativeTestHelperExternals(projectRoot, filePath) {
|
|
21976
|
-
const testingTypesPath =
|
|
21977
|
-
const relative =
|
|
23337
|
+
const testingTypesPath = path22.join(projectRoot, "test", "testing-types");
|
|
23338
|
+
const relative = path22.relative(path22.dirname(filePath), testingTypesPath).replaceAll("\\", "/");
|
|
21978
23339
|
const specifier = relative.startsWith(".") ? relative : `./${relative}`;
|
|
21979
23340
|
return [specifier, `${specifier}.ts`];
|
|
21980
23341
|
}
|
|
@@ -22479,7 +23840,7 @@ async function assertLiveMatchesShadow(runner, shadow, live) {
|
|
|
22479
23840
|
}
|
|
22480
23841
|
}
|
|
22481
23842
|
async function loadBrowserDriver(projectRoot) {
|
|
22482
|
-
const filePath =
|
|
23843
|
+
const filePath = path22.join(projectRoot, "test", "browser-driver.ts");
|
|
22483
23844
|
if (!await exists(filePath)) {
|
|
22484
23845
|
return null;
|
|
22485
23846
|
}
|
|
@@ -22507,7 +23868,7 @@ function sanitizeSnapshotSegment(value) {
|
|
|
22507
23868
|
function createScenarioSnapshotMatcher(options) {
|
|
22508
23869
|
return (filename, actual) => {
|
|
22509
23870
|
const suffix = filename ? `.${sanitizeSnapshotSegment(filename)}` : "";
|
|
22510
|
-
const snapshotPath =
|
|
23871
|
+
const snapshotPath = path22.join(
|
|
22511
23872
|
options.projectRoot,
|
|
22512
23873
|
"test",
|
|
22513
23874
|
"generated",
|
|
@@ -22519,15 +23880,15 @@ function createScenarioSnapshotMatcher(options) {
|
|
|
22519
23880
|
};
|
|
22520
23881
|
const serialized = `${JSON.stringify(wrappedValue, null, 2)}
|
|
22521
23882
|
`;
|
|
22522
|
-
mkdirSync2(
|
|
23883
|
+
mkdirSync2(path22.dirname(snapshotPath), { recursive: true });
|
|
22523
23884
|
if (!existsSync8(snapshotPath) || options.updateSnapshots) {
|
|
22524
23885
|
writeFileSync2(snapshotPath, serialized, "utf8");
|
|
22525
23886
|
return;
|
|
22526
23887
|
}
|
|
22527
|
-
const previous = JSON.parse(
|
|
23888
|
+
const previous = JSON.parse(readFileSync4(snapshotPath, "utf8"));
|
|
22528
23889
|
if (!deepEqual(previous.value, actual)) {
|
|
22529
23890
|
throw new Error(
|
|
22530
|
-
`Snapshot mismatch for scenario '${options.scenarioId}'. Re-run with --update-snapshots to refresh ${
|
|
23891
|
+
`Snapshot mismatch for scenario '${options.scenarioId}'. Re-run with --update-snapshots to refresh ${path22.relative(options.projectRoot, snapshotPath)}.`
|
|
22531
23892
|
);
|
|
22532
23893
|
}
|
|
22533
23894
|
};
|
|
@@ -22788,7 +24149,7 @@ async function createSessionFromScenario(options) {
|
|
|
22788
24149
|
}
|
|
22789
24150
|
var MATERIALIZED_SCENARIO_CACHE_VERSION = 1;
|
|
22790
24151
|
function materializedScenarioCachePath(options) {
|
|
22791
|
-
return
|
|
24152
|
+
return path22.join(
|
|
22792
24153
|
options.projectRoot,
|
|
22793
24154
|
PROJECT_DIR_NAME,
|
|
22794
24155
|
"dev",
|
|
@@ -22816,7 +24177,7 @@ async function readMaterializedScenarioCache(options) {
|
|
|
22816
24177
|
}
|
|
22817
24178
|
async function writeMaterializedScenarioCache(options) {
|
|
22818
24179
|
const cachePath = materializedScenarioCachePath(options);
|
|
22819
|
-
await ensureDir(
|
|
24180
|
+
await ensureDir(path22.dirname(cachePath));
|
|
22820
24181
|
await writeJsonFile(cachePath, {
|
|
22821
24182
|
cacheVersion: MATERIALIZED_SCENARIO_CACHE_VERSION,
|
|
22822
24183
|
fingerprintHash: options.fingerprintHash,
|
|
@@ -22913,10 +24274,10 @@ async function materializeScenarioReducerState(options) {
|
|
|
22913
24274
|
}
|
|
22914
24275
|
const [gameModule, manifestContractModule] = await Promise.all([
|
|
22915
24276
|
importTypeScriptModule(
|
|
22916
|
-
|
|
24277
|
+
path22.join(options.projectRoot, "app", "game.ts")
|
|
22917
24278
|
),
|
|
22918
24279
|
importTypeScriptModule(
|
|
22919
|
-
|
|
24280
|
+
path22.join(options.projectRoot, "shared", "manifest-contract.ts")
|
|
22920
24281
|
)
|
|
22921
24282
|
]);
|
|
22922
24283
|
const createInitialTable = typeof manifestContractModule.createInitialTable === "function" ? manifestContractModule.createInitialTable : null;
|
|
@@ -22998,10 +24359,10 @@ async function createScenarioActionPlan(options) {
|
|
|
22998
24359
|
loadGeneratedBaseStates(options.projectRoot),
|
|
22999
24360
|
loadManifest(options.projectRoot),
|
|
23000
24361
|
importTypeScriptModule(
|
|
23001
|
-
|
|
24362
|
+
path22.join(options.projectRoot, "app", "game.ts")
|
|
23002
24363
|
),
|
|
23003
24364
|
importTypeScriptModule(
|
|
23004
|
-
|
|
24365
|
+
path22.join(options.projectRoot, "shared", "manifest-contract.ts")
|
|
23005
24366
|
)
|
|
23006
24367
|
]);
|
|
23007
24368
|
const matchingScenarios = scenarios.filter(
|
|
@@ -23268,7 +24629,7 @@ function sortBasesForArtifacts(bases, basesById) {
|
|
|
23268
24629
|
return ordered;
|
|
23269
24630
|
}
|
|
23270
24631
|
function writeProjectionSnapshots(options) {
|
|
23271
|
-
const projectionDir =
|
|
24632
|
+
const projectionDir = path22.join(
|
|
23272
24633
|
options.projectRoot,
|
|
23273
24634
|
"test",
|
|
23274
24635
|
"generated",
|
|
@@ -23279,7 +24640,7 @@ function writeProjectionSnapshots(options) {
|
|
|
23279
24640
|
mkdirSync2(projectionDir, { recursive: true });
|
|
23280
24641
|
const projection = options.shadow.projectAllSeats();
|
|
23281
24642
|
for (const [playerId, seatProjection] of Object.entries(projection.seats)) {
|
|
23282
|
-
const outputPath =
|
|
24643
|
+
const outputPath = path22.join(projectionDir, `${playerId}.projection.json`);
|
|
23283
24644
|
writeFileSync2(
|
|
23284
24645
|
outputPath,
|
|
23285
24646
|
`${JSON.stringify(
|
|
@@ -23299,7 +24660,7 @@ function writeProjectionSnapshots(options) {
|
|
|
23299
24660
|
function validateTypedScenarioBases(scenarios, basesById) {
|
|
23300
24661
|
const available = new Set(basesById.keys());
|
|
23301
24662
|
const invalid = scenarios.filter((scenario) => !available.has(scenario.definition.from)).map(
|
|
23302
|
-
(scenario) =>
|
|
24663
|
+
(scenario) => path22.relative(process.cwd(), scenario.filePath) + ` -> '${scenario.definition.from}'`
|
|
23303
24664
|
);
|
|
23304
24665
|
if (invalid.length > 0) {
|
|
23305
24666
|
throw new Error(
|
|
@@ -23313,23 +24674,23 @@ async function writeReducerNativeGeneratedFiles(options) {
|
|
|
23313
24674
|
const manifestHash = hashContent(JSON.stringify(manifest));
|
|
23314
24675
|
const appBundleHash = hashContent(
|
|
23315
24676
|
await bundleTypeScriptModuleText(
|
|
23316
|
-
|
|
24677
|
+
path22.join(options.projectRoot, "app", "game.ts")
|
|
23317
24678
|
)
|
|
23318
24679
|
);
|
|
23319
24680
|
const uiContractHash = hashContent(
|
|
23320
24681
|
await bundleTypeScriptModuleText(
|
|
23321
|
-
|
|
24682
|
+
path22.join(options.projectRoot, "shared", "generated", "ui-contract.ts")
|
|
23322
24683
|
)
|
|
23323
24684
|
);
|
|
23324
|
-
const generatedDir =
|
|
24685
|
+
const generatedDir = path22.join(options.projectRoot, "test", "generated");
|
|
23325
24686
|
await ensureDir(generatedDir);
|
|
23326
24687
|
const baseStates = {};
|
|
23327
24688
|
const [gameModule, manifestContractModule] = await Promise.all([
|
|
23328
24689
|
importTypeScriptModule(
|
|
23329
|
-
|
|
24690
|
+
path22.join(options.projectRoot, "app", "game.ts")
|
|
23330
24691
|
),
|
|
23331
24692
|
importTypeScriptModule(
|
|
23332
|
-
|
|
24693
|
+
path22.join(options.projectRoot, "shared", "manifest-contract.ts")
|
|
23333
24694
|
)
|
|
23334
24695
|
]);
|
|
23335
24696
|
const createInitialTable = typeof manifestContractModule.createInitialTable === "function" ? manifestContractModule.createInitialTable : null;
|
|
@@ -23417,21 +24778,21 @@ async function writeReducerNativeGeneratedFiles(options) {
|
|
|
23417
24778
|
}
|
|
23418
24779
|
const header = "// Generated by dreamboard test generate. Do not edit by hand.\n";
|
|
23419
24780
|
await writeTextFile(
|
|
23420
|
-
|
|
24781
|
+
path22.join(generatedDir, "base-states.generated.ts"),
|
|
23421
24782
|
`${header}export const BASE_STATES = ${JSON.stringify(baseStates, null, 2)} as const;
|
|
23422
24783
|
`
|
|
23423
24784
|
);
|
|
23424
24785
|
await writeTextFile(
|
|
23425
|
-
|
|
24786
|
+
path22.join(generatedDir, "base-states.generated.d.ts"),
|
|
23426
24787
|
`${header}export declare const BASE_STATES: Record<string, unknown>;
|
|
23427
24788
|
`
|
|
23428
24789
|
);
|
|
23429
24790
|
await writeTextFile(
|
|
23430
|
-
|
|
24791
|
+
path22.join(generatedDir, "scenario-manifest.generated.ts"),
|
|
23431
24792
|
`${header}export const SCENARIO_MANIFEST = ${JSON.stringify(
|
|
23432
24793
|
options.scenarios.map((scenario) => ({
|
|
23433
24794
|
id: scenario.definition.id,
|
|
23434
|
-
filePath:
|
|
24795
|
+
filePath: path22.relative(generatedDir, scenario.filePath),
|
|
23435
24796
|
base: scenario.definition.from,
|
|
23436
24797
|
runners: normalizeScenarioRunners(scenario.definition.runners)
|
|
23437
24798
|
})),
|
|
@@ -23440,14 +24801,14 @@ async function writeReducerNativeGeneratedFiles(options) {
|
|
|
23440
24801
|
)} as const;
|
|
23441
24802
|
`
|
|
23442
24803
|
);
|
|
23443
|
-
await writeJsonFile(
|
|
24804
|
+
await writeJsonFile(path22.join(generatedDir, ".generation-meta.json"), {
|
|
23444
24805
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
23445
24806
|
scenarioCount: options.scenarios.length,
|
|
23446
24807
|
baseStateCount: options.bases.length
|
|
23447
24808
|
});
|
|
23448
24809
|
}
|
|
23449
24810
|
async function loadGeneratedBaseStates(projectRoot) {
|
|
23450
|
-
const filePath =
|
|
24811
|
+
const filePath = path22.join(
|
|
23451
24812
|
projectRoot,
|
|
23452
24813
|
"test",
|
|
23453
24814
|
"generated",
|
|
@@ -23460,7 +24821,7 @@ async function loadGeneratedBaseStates(projectRoot) {
|
|
|
23460
24821
|
return module.BASE_STATES ?? null;
|
|
23461
24822
|
}
|
|
23462
24823
|
async function loadGeneratedScenarioManifest(projectRoot) {
|
|
23463
|
-
const filePath =
|
|
24824
|
+
const filePath = path22.join(
|
|
23464
24825
|
projectRoot,
|
|
23465
24826
|
"test",
|
|
23466
24827
|
"generated",
|
|
@@ -23550,12 +24911,12 @@ async function currentFingerprint(options) {
|
|
|
23550
24911
|
manifestHash: hashContent(JSON.stringify(manifest)),
|
|
23551
24912
|
appBundleHash: hashContent(
|
|
23552
24913
|
await bundleTypeScriptModuleText(
|
|
23553
|
-
|
|
24914
|
+
path22.join(options.projectRoot, "app", "game.ts")
|
|
23554
24915
|
)
|
|
23555
24916
|
),
|
|
23556
24917
|
uiContractHash: hashContent(
|
|
23557
24918
|
await bundleTypeScriptModuleText(
|
|
23558
|
-
|
|
24919
|
+
path22.join(options.projectRoot, "shared", "generated", "ui-contract.ts")
|
|
23559
24920
|
)
|
|
23560
24921
|
),
|
|
23561
24922
|
setupProfileId: effectiveSetup.setupProfileId,
|
|
@@ -23602,10 +24963,10 @@ async function runReducerNativeScenarios(options) {
|
|
|
23602
24963
|
loadGeneratedBaseStates(options.projectRoot),
|
|
23603
24964
|
loadManifest(options.projectRoot),
|
|
23604
24965
|
importTypeScriptModule(
|
|
23605
|
-
|
|
24966
|
+
path22.join(options.projectRoot, "app", "game.ts")
|
|
23606
24967
|
),
|
|
23607
24968
|
importTypeScriptModule(
|
|
23608
|
-
|
|
24969
|
+
path22.join(options.projectRoot, "shared", "manifest-contract.ts")
|
|
23609
24970
|
)
|
|
23610
24971
|
]);
|
|
23611
24972
|
let generatedBaseStates = initialGeneratedBaseStates;
|
|
@@ -23823,7 +25184,11 @@ async function runReducerNativeScenarios(options) {
|
|
|
23823
25184
|
results.push({
|
|
23824
25185
|
id: scenario.definition.id,
|
|
23825
25186
|
success: false,
|
|
23826
|
-
error: error instanceof Error ?
|
|
25187
|
+
error: error instanceof Error ? formatScenarioErrorForDisplay({
|
|
25188
|
+
error,
|
|
25189
|
+
projectRoot: options.projectRoot,
|
|
25190
|
+
scenarioFilePath: scenario.filePath
|
|
25191
|
+
}) : `Scenario '${scenario.definition.id}' failed.`
|
|
23827
25192
|
});
|
|
23828
25193
|
}
|
|
23829
25194
|
}
|
|
@@ -23839,8 +25204,8 @@ async function runReducerNativeScenarios(options) {
|
|
|
23839
25204
|
}
|
|
23840
25205
|
|
|
23841
25206
|
// src/services/project/reducer-contract-preflight.ts
|
|
23842
|
-
import
|
|
23843
|
-
var GAME_CONTRACT_ENTRY_PATH =
|
|
25207
|
+
import path23 from "path";
|
|
25208
|
+
var GAME_CONTRACT_ENTRY_PATH = path23.join("app", "game-contract.ts");
|
|
23844
25209
|
function normalizeErrorMessage(error) {
|
|
23845
25210
|
const rawMessage = error instanceof Error ? error.message : String(error ?? "Unknown error");
|
|
23846
25211
|
return rawMessage.split("\n").map((line) => line.trim()).find(Boolean)?.replace(/^Error:\s*/u, "") ?? "Unknown error";
|
|
@@ -23849,7 +25214,7 @@ function isManifestScopedIdBrandingError(message) {
|
|
|
23849
25214
|
return message.includes("defineGameContract:") && message.includes("manifest-scoped") && (message.includes("uses a raw z.string()") || message.includes("uses z.array(z.string())"));
|
|
23850
25215
|
}
|
|
23851
25216
|
async function assertReducerContractPreflight(projectRoot) {
|
|
23852
|
-
const entryPath =
|
|
25217
|
+
const entryPath = path23.join(projectRoot, GAME_CONTRACT_ENTRY_PATH);
|
|
23853
25218
|
try {
|
|
23854
25219
|
await importTypeScriptModule(entryPath);
|
|
23855
25220
|
} catch (error) {
|
|
@@ -23875,8 +25240,8 @@ async function assertReducerContractPreflight(projectRoot) {
|
|
|
23875
25240
|
}
|
|
23876
25241
|
|
|
23877
25242
|
// src/services/project/reducer-bundle-preflight.ts
|
|
23878
|
-
import
|
|
23879
|
-
var REDUCER_BUNDLE_ENTRY_PATH =
|
|
25243
|
+
import path24 from "path";
|
|
25244
|
+
var REDUCER_BUNDLE_ENTRY_PATH = path24.join("app", "index.ts");
|
|
23880
25245
|
var PREFLIGHT_RNG_SEED = 1337;
|
|
23881
25246
|
function buildPlayerIds(playerCount) {
|
|
23882
25247
|
const ids = [];
|
|
@@ -24064,7 +25429,7 @@ async function runReducerBundleSmoke(options) {
|
|
|
24064
25429
|
if (scenarios.length === 0) {
|
|
24065
25430
|
return [];
|
|
24066
25431
|
}
|
|
24067
|
-
const entryPath =
|
|
25432
|
+
const entryPath = path24.join(projectRoot, REDUCER_BUNDLE_ENTRY_PATH);
|
|
24068
25433
|
let module;
|
|
24069
25434
|
try {
|
|
24070
25435
|
module = await importTypeScriptModule(
|
|
@@ -24249,9 +25614,9 @@ var dev_default = defineCommand({
|
|
|
24249
25614
|
env: parsedArgs.env ?? "dev",
|
|
24250
25615
|
debug: parsedArgs.debug
|
|
24251
25616
|
});
|
|
24252
|
-
const devDir =
|
|
25617
|
+
const devDir = path25.join(projectRoot, PROJECT_DIR_NAME, "dev");
|
|
24253
25618
|
await ensureDir(devDir);
|
|
24254
|
-
const sessionFilePath =
|
|
25619
|
+
const sessionFilePath = path25.join(devDir, "session.json");
|
|
24255
25620
|
const requestedResumeSessionId = parsedArgs.resume?.trim() || null;
|
|
24256
25621
|
const requestedScenarioId = parsedArgs["from-scenario"]?.trim() || null;
|
|
24257
25622
|
if (requestedResumeSessionId && parsedArgs["new-session"]) {
|
|
@@ -24431,26 +25796,32 @@ async function ensureDevCompiledResult(options) {
|
|
|
24431
25796
|
const localMaintainerEnabled = isLocalMaintainerRegistryEnabled(
|
|
24432
25797
|
options.config.apiBaseUrl
|
|
24433
25798
|
);
|
|
24434
|
-
const
|
|
25799
|
+
const existingLocalMaintainerRegistry = getProjectLocalMaintainerRegistry(
|
|
25800
|
+
options.projectConfig
|
|
25801
|
+
);
|
|
25802
|
+
const refreshedLocalMaintainerRegistry = localMaintainerEnabled ? await runLoggedStep(
|
|
24435
25803
|
"Checking local SDK snapshot...",
|
|
24436
25804
|
() => ensureLocalMaintainerSnapshot(options.config.apiBaseUrl)
|
|
24437
25805
|
) : await ensureLocalMaintainerSnapshot(options.config.apiBaseUrl);
|
|
24438
|
-
|
|
25806
|
+
const localMaintainerRegistry = refreshedLocalMaintainerRegistry ?? (localMaintainerEnabled ? existingLocalMaintainerRegistry ?? null : null);
|
|
25807
|
+
if (refreshedLocalMaintainerRegistry) {
|
|
24439
25808
|
if (didLocalMaintainerSnapshotChange(
|
|
24440
|
-
|
|
24441
|
-
|
|
25809
|
+
existingLocalMaintainerRegistry,
|
|
25810
|
+
refreshedLocalMaintainerRegistry
|
|
24442
25811
|
)) {
|
|
24443
25812
|
await updateProjectState(
|
|
24444
25813
|
options.projectRoot,
|
|
24445
25814
|
updateProjectLocalMaintainerRegistry(
|
|
24446
25815
|
options.projectConfig,
|
|
24447
|
-
|
|
25816
|
+
refreshedLocalMaintainerRegistry
|
|
24448
25817
|
)
|
|
24449
25818
|
);
|
|
24450
25819
|
consola.info("Local SDK snapshot refreshed.");
|
|
24451
25820
|
} else {
|
|
24452
25821
|
consola.info("Using existing local SDK snapshot.");
|
|
24453
25822
|
}
|
|
25823
|
+
} else if (localMaintainerRegistry) {
|
|
25824
|
+
consola.info("Using workspace-pinned local SDK snapshot.");
|
|
24454
25825
|
}
|
|
24455
25826
|
await runLoggedStep(
|
|
24456
25827
|
"Refreshing static scaffold...",
|
|
@@ -24586,7 +25957,7 @@ async function resolveBackendVersionMetadata() {
|
|
|
24586
25957
|
}
|
|
24587
25958
|
async function readWorkspacePackageJson(projectRoot) {
|
|
24588
25959
|
try {
|
|
24589
|
-
const raw = await readTextFile(
|
|
25960
|
+
const raw = await readTextFile(path25.join(projectRoot, "package.json"));
|
|
24590
25961
|
const parsed = JSON.parse(raw);
|
|
24591
25962
|
return {
|
|
24592
25963
|
dependencies: Object.fromEntries(
|
|
@@ -24724,7 +26095,7 @@ function extractUserIdFromJwt(token) {
|
|
|
24724
26095
|
}
|
|
24725
26096
|
|
|
24726
26097
|
// src/commands/join.ts
|
|
24727
|
-
import
|
|
26098
|
+
import path26 from "path";
|
|
24728
26099
|
|
|
24729
26100
|
// src/services/join/jsonl-bot-session.ts
|
|
24730
26101
|
import { createInterface as createInterface2 } from "readline";
|
|
@@ -25104,17 +26475,20 @@ function actionCacheFromGameplay(gameplay) {
|
|
|
25104
26475
|
};
|
|
25105
26476
|
}
|
|
25106
26477
|
function compactActionFromDescriptor(descriptor) {
|
|
26478
|
+
const availability = descriptor.availability;
|
|
26479
|
+
const unavailableReason = availability.status === "available" ? void 0 : availability.reason;
|
|
26480
|
+
const missingResources = availability.status === "insufficientResources" ? availability.missingResources : void 0;
|
|
25107
26481
|
return compactObject({
|
|
25108
26482
|
interactionId: descriptor.interactionId,
|
|
25109
26483
|
interactionKey: descriptor.interactionKey,
|
|
25110
26484
|
kind: descriptor.kind,
|
|
25111
|
-
available:
|
|
25112
|
-
unavailableReason
|
|
26485
|
+
available: availability.status === "available",
|
|
26486
|
+
unavailableReason,
|
|
25113
26487
|
inputs: normalizeUnknownJson(descriptor.inputs),
|
|
25114
26488
|
cost: normalizeUnknownJson(descriptor.cost),
|
|
25115
26489
|
currentResources: normalizeUnknownJson(descriptor.currentResources),
|
|
25116
|
-
missingResources
|
|
25117
|
-
context: normalizeUnknownJson(descriptor.context)
|
|
26490
|
+
missingResources,
|
|
26491
|
+
context: descriptor.kind === "prompt" ? normalizeUnknownJson(descriptor.context) : void 0
|
|
25118
26492
|
});
|
|
25119
26493
|
}
|
|
25120
26494
|
function compactGameplayEvent(options) {
|
|
@@ -25646,7 +27020,7 @@ async function resolveDefaultSessionId(projectRoot) {
|
|
|
25646
27020
|
"No session id provided and this directory is not a Dreamboard project. Pass --session or run from a workspace with .dreamboard/dev/session.json."
|
|
25647
27021
|
);
|
|
25648
27022
|
}
|
|
25649
|
-
const sessionFilePath =
|
|
27023
|
+
const sessionFilePath = path26.join(
|
|
25650
27024
|
projectRoot,
|
|
25651
27025
|
PROJECT_DIR_NAME,
|
|
25652
27026
|
"dev",
|
|
@@ -25758,7 +27132,7 @@ var logout_default = defineCommand({
|
|
|
25758
27132
|
});
|
|
25759
27133
|
|
|
25760
27134
|
// src/commands/new.ts
|
|
25761
|
-
import
|
|
27135
|
+
import path27 from "path";
|
|
25762
27136
|
var new_default = defineCommand({
|
|
25763
27137
|
meta: {
|
|
25764
27138
|
name: "new",
|
|
@@ -25879,7 +27253,7 @@ var new_default = defineCommand({
|
|
|
25879
27253
|
ruleId
|
|
25880
27254
|
);
|
|
25881
27255
|
consola.start("Scaffolding local workspace...");
|
|
25882
|
-
const targetDir =
|
|
27256
|
+
const targetDir = path27.resolve(process.cwd(), normalizedSlug);
|
|
25883
27257
|
await ensureDir(targetDir);
|
|
25884
27258
|
await writeManifest(targetDir, blankManifest);
|
|
25885
27259
|
await writeRule(targetDir, "");
|
|
@@ -26104,7 +27478,8 @@ var status_default = defineCommand({
|
|
|
26104
27478
|
let remoteHeadId = null;
|
|
26105
27479
|
let authoredRelation = "unknown";
|
|
26106
27480
|
let compileRelation = "never_compiled";
|
|
26107
|
-
let
|
|
27481
|
+
let verified = null;
|
|
27482
|
+
let verifiedAt = null;
|
|
26108
27483
|
if (config.authToken) {
|
|
26109
27484
|
await configureClient(config);
|
|
26110
27485
|
const remoteHead = await getAuthoringHeadSdk(projectConfig.gameId);
|
|
@@ -26113,7 +27488,8 @@ var status_default = defineCommand({
|
|
|
26113
27488
|
path: { gameId: projectConfig.gameId }
|
|
26114
27489
|
});
|
|
26115
27490
|
if (game) {
|
|
26116
|
-
|
|
27491
|
+
verified = game.verified;
|
|
27492
|
+
verifiedAt = game.verifiedAt ?? null;
|
|
26117
27493
|
}
|
|
26118
27494
|
const hasLocalDiff = diff.modified.length > 0 || diff.added.length > 0 || diff.deleted.length > 0;
|
|
26119
27495
|
if (pendingSync) {
|
|
@@ -26168,7 +27544,10 @@ var status_default = defineCommand({
|
|
|
26168
27544
|
deleted: diff.deleted.length
|
|
26169
27545
|
},
|
|
26170
27546
|
localDiffPaths: diff,
|
|
26171
|
-
|
|
27547
|
+
verification: {
|
|
27548
|
+
verified,
|
|
27549
|
+
verifiedAt
|
|
27550
|
+
}
|
|
26172
27551
|
},
|
|
26173
27552
|
null,
|
|
26174
27553
|
2
|
|
@@ -26184,14 +27563,10 @@ var status_default = defineCommand({
|
|
|
26184
27563
|
if (diff.added.length > 0) consola.log(`Added: ${diff.added.join(", ")}`);
|
|
26185
27564
|
if (diff.deleted.length > 0)
|
|
26186
27565
|
consola.log(`Deleted: ${diff.deleted.join(", ")}`);
|
|
26187
|
-
if (
|
|
26188
|
-
|
|
26189
|
-
`
|
|
26190
|
-
|
|
26191
|
-
`phases:${completionLights.phases}`,
|
|
26192
|
-
`ui:${completionLights.ui}`
|
|
26193
|
-
].join(" ");
|
|
26194
|
-
consola.info(`Completion lights: ${lightSummary}`);
|
|
27566
|
+
if (verified !== null) {
|
|
27567
|
+
consola.info(
|
|
27568
|
+
`Verification: ${verified ? "verified" : "unverified"}${verifiedAt ? ` at ${verifiedAt}` : ""}`
|
|
27569
|
+
);
|
|
26195
27570
|
}
|
|
26196
27571
|
if (!config.authToken) {
|
|
26197
27572
|
consola.warn("Remote status unavailable (no auth token).");
|
|
@@ -26235,9 +27610,9 @@ function buildSourceChanges(options) {
|
|
|
26235
27610
|
if (mode === "replace") {
|
|
26236
27611
|
return Object.entries(localFiles).filter(
|
|
26237
27612
|
([filePath]) => isSourceRevisionPath(filePath) || shouldAlwaysUpsertSourcePath(filePath)
|
|
26238
|
-
).sort(([left], [right]) => left.localeCompare(right)).map(([
|
|
27613
|
+
).sort(([left], [right]) => left.localeCompare(right)).map(([path29, content]) => ({
|
|
26239
27614
|
kind: "upsert",
|
|
26240
|
-
path:
|
|
27615
|
+
path: path29,
|
|
26241
27616
|
content
|
|
26242
27617
|
}));
|
|
26243
27618
|
}
|
|
@@ -26404,22 +27779,26 @@ var sync_default = defineCommand({
|
|
|
26404
27779
|
const localMaintainerEnabled = isLocalMaintainerRegistryEnabled(
|
|
26405
27780
|
config.apiBaseUrl
|
|
26406
27781
|
);
|
|
26407
|
-
const
|
|
27782
|
+
const existingLocalMaintainerRegistry = getProjectLocalMaintainerRegistry(projectConfig);
|
|
27783
|
+
const refreshedLocalMaintainerRegistry = localMaintainerEnabled ? await runLoggedStep2(
|
|
26408
27784
|
"Checking local SDK snapshot...",
|
|
26409
27785
|
() => ensureLocalMaintainerSnapshot(config.apiBaseUrl)
|
|
26410
27786
|
) : await ensureLocalMaintainerSnapshot(config.apiBaseUrl);
|
|
27787
|
+
const localMaintainerRegistry = refreshedLocalMaintainerRegistry ?? (localMaintainerEnabled ? existingLocalMaintainerRegistry ?? null : null);
|
|
26411
27788
|
const localMaintainerSnapshotChanged = didLocalMaintainerSnapshotChange(
|
|
26412
|
-
|
|
26413
|
-
|
|
27789
|
+
existingLocalMaintainerRegistry,
|
|
27790
|
+
refreshedLocalMaintainerRegistry
|
|
26414
27791
|
);
|
|
26415
|
-
if (
|
|
27792
|
+
if (refreshedLocalMaintainerRegistry) {
|
|
26416
27793
|
nextProjectConfig = updateProjectLocalMaintainerRegistry(
|
|
26417
27794
|
nextProjectConfig,
|
|
26418
|
-
|
|
27795
|
+
refreshedLocalMaintainerRegistry
|
|
26419
27796
|
);
|
|
26420
27797
|
consola.info(
|
|
26421
27798
|
localMaintainerSnapshotChanged ? "Local SDK snapshot refreshed." : "Using existing local SDK snapshot."
|
|
26422
27799
|
);
|
|
27800
|
+
} else if (localMaintainerRegistry) {
|
|
27801
|
+
consola.info("Using workspace-pinned local SDK snapshot.");
|
|
26423
27802
|
}
|
|
26424
27803
|
await runLoggedStep2(
|
|
26425
27804
|
"Refreshing static scaffold...",
|
|
@@ -26791,7 +28170,7 @@ var sync_default = defineCommand({
|
|
|
26791
28170
|
|
|
26792
28171
|
// src/commands/test.ts
|
|
26793
28172
|
import { readFile as readFile4 } from "fs/promises";
|
|
26794
|
-
import
|
|
28173
|
+
import path28 from "path";
|
|
26795
28174
|
|
|
26796
28175
|
// src/services/testing/runtime-mode.ts
|
|
26797
28176
|
function isRemoteTestEnvironment(environment) {
|
|
@@ -26855,7 +28234,7 @@ async function uploadGeneratedPreviewProjection(options) {
|
|
|
26855
28234
|
if (!previewBase) {
|
|
26856
28235
|
return;
|
|
26857
28236
|
}
|
|
26858
|
-
const projectionPath =
|
|
28237
|
+
const projectionPath = path28.join(
|
|
26859
28238
|
options.projectRoot,
|
|
26860
28239
|
"test",
|
|
26861
28240
|
"generated",
|
|
@@ -27115,7 +28494,7 @@ function runDreamboardCli(internalSubCommands = {}) {
|
|
|
27115
28494
|
const main = defineCommand({
|
|
27116
28495
|
meta: {
|
|
27117
28496
|
name: "dreamboard",
|
|
27118
|
-
version: "0.1.
|
|
28497
|
+
version: "0.1.26",
|
|
27119
28498
|
description: "Dreamboard CLI \u2014 game development platform"
|
|
27120
28499
|
},
|
|
27121
28500
|
subCommands
|
|
@@ -27171,4 +28550,4 @@ export {
|
|
|
27171
28550
|
test_default,
|
|
27172
28551
|
runDreamboardCli
|
|
27173
28552
|
};
|
|
27174
|
-
//# sourceMappingURL=chunk-
|
|
28553
|
+
//# sourceMappingURL=chunk-VRJ4FOH2.js.map
|