422 lines
16 KiB
JavaScript
422 lines
16 KiB
JavaScript
(function attachBackgroundGrokState(root, factory) {
|
|
root.MultiPageBackgroundGrokState = factory();
|
|
})(typeof self !== 'undefined' ? self : globalThis, function createBackgroundGrokStateModule() {
|
|
function isPlainObject(value) {
|
|
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
}
|
|
|
|
function cloneValue(value) {
|
|
if (Array.isArray(value)) {
|
|
return value.map((entry) => cloneValue(entry));
|
|
}
|
|
if (isPlainObject(value)) {
|
|
return Object.fromEntries(
|
|
Object.entries(value).map(([key, entryValue]) => [key, cloneValue(entryValue)])
|
|
);
|
|
}
|
|
return value;
|
|
}
|
|
|
|
function deepMerge(baseValue, patchValue) {
|
|
if (Array.isArray(patchValue)) {
|
|
return patchValue.map((entry) => cloneValue(entry));
|
|
}
|
|
if (!isPlainObject(patchValue)) {
|
|
return patchValue === undefined ? cloneValue(baseValue) : patchValue;
|
|
}
|
|
|
|
const baseObject = isPlainObject(baseValue) ? baseValue : {};
|
|
const next = {
|
|
...cloneValue(baseObject),
|
|
};
|
|
Object.entries(patchValue).forEach(([key, value]) => {
|
|
next[key] = deepMerge(baseObject[key], value);
|
|
});
|
|
return next;
|
|
}
|
|
|
|
function cleanString(value = '') {
|
|
return String(value ?? '').trim();
|
|
}
|
|
|
|
function assignCleanString(target = {}, key = '', value = '') {
|
|
const normalized = cleanString(value);
|
|
if (normalized) {
|
|
target[key] = normalized;
|
|
}
|
|
}
|
|
|
|
function assignPositiveInteger(target = {}, key = '', value) {
|
|
const numeric = Math.floor(Number(value));
|
|
if (Number.isInteger(numeric) && numeric > 0) {
|
|
target[key] = numeric;
|
|
}
|
|
}
|
|
|
|
function assignNonEmptyArray(target = {}, key = '', value) {
|
|
if (Array.isArray(value) && value.length) {
|
|
target[key] = value;
|
|
}
|
|
}
|
|
|
|
function normalizeInteger(value, fallback = 0) {
|
|
const numeric = Math.floor(Number(value));
|
|
return Number.isInteger(numeric) ? numeric : fallback;
|
|
}
|
|
|
|
function normalizeNullableInteger(value, fallback = null) {
|
|
if (value === null || value === undefined || value === '') {
|
|
return fallback;
|
|
}
|
|
const numeric = Math.floor(Number(value));
|
|
return Number.isInteger(numeric) ? numeric : fallback;
|
|
}
|
|
|
|
function normalizeSsoCookies(values = []) {
|
|
if (!Array.isArray(values)) {
|
|
return [];
|
|
}
|
|
return Array.from(new Set(
|
|
values
|
|
.map((entry) => cleanString(entry))
|
|
.filter(Boolean)
|
|
));
|
|
}
|
|
|
|
function buildDefaultRuntimeState() {
|
|
return {
|
|
session: {
|
|
registerTabId: null,
|
|
startedAt: 0,
|
|
pageState: '',
|
|
pageUrl: '',
|
|
lastError: '',
|
|
},
|
|
register: {
|
|
email: '',
|
|
firstName: '',
|
|
lastName: '',
|
|
password: '',
|
|
verificationRequestedAt: 0,
|
|
verificationCode: '',
|
|
status: '',
|
|
completedAt: 0,
|
|
},
|
|
sso: {
|
|
currentCookie: '',
|
|
cookies: [],
|
|
extractedAt: 0,
|
|
},
|
|
upload: {
|
|
status: '',
|
|
uploadedAt: 0,
|
|
message: '',
|
|
targetUrl: '',
|
|
},
|
|
};
|
|
}
|
|
|
|
function normalizeRuntimeState(runtimeState = {}) {
|
|
const merged = deepMerge(buildDefaultRuntimeState(), runtimeState);
|
|
return {
|
|
session: {
|
|
registerTabId: normalizeNullableInteger(merged.session?.registerTabId),
|
|
startedAt: Math.max(0, normalizeInteger(merged.session?.startedAt)),
|
|
pageState: cleanString(merged.session?.pageState),
|
|
pageUrl: cleanString(merged.session?.pageUrl),
|
|
lastError: cleanString(merged.session?.lastError),
|
|
},
|
|
register: {
|
|
email: cleanString(merged.register?.email).toLowerCase(),
|
|
firstName: cleanString(merged.register?.firstName),
|
|
lastName: cleanString(merged.register?.lastName),
|
|
password: cleanString(merged.register?.password),
|
|
verificationRequestedAt: Math.max(0, normalizeInteger(merged.register?.verificationRequestedAt)),
|
|
verificationCode: cleanString(merged.register?.verificationCode),
|
|
status: cleanString(merged.register?.status),
|
|
completedAt: Math.max(0, normalizeInteger(merged.register?.completedAt)),
|
|
},
|
|
sso: {
|
|
currentCookie: cleanString(merged.sso?.currentCookie || merged.ssoCookie),
|
|
cookies: normalizeSsoCookies(merged.sso?.cookies || merged.ssoCookies),
|
|
extractedAt: Math.max(0, normalizeInteger(merged.sso?.extractedAt)),
|
|
},
|
|
upload: {
|
|
status: cleanString(merged.upload?.status),
|
|
uploadedAt: Math.max(0, normalizeInteger(merged.upload?.uploadedAt)),
|
|
message: cleanString(merged.upload?.message),
|
|
targetUrl: cleanString(merged.upload?.targetUrl),
|
|
},
|
|
};
|
|
}
|
|
|
|
function buildCanonicalRuntimeStatePatch(state = {}, runtimeState = {}) {
|
|
const normalizedRuntimeState = normalizeRuntimeState(runtimeState);
|
|
const baseRuntimeState = isPlainObject(state?.runtimeState)
|
|
? cloneValue(state.runtimeState)
|
|
: {};
|
|
const baseFlowState = isPlainObject(baseRuntimeState.flowState)
|
|
? cloneValue(baseRuntimeState.flowState)
|
|
: {};
|
|
return {
|
|
...baseRuntimeState,
|
|
flowState: {
|
|
...baseFlowState,
|
|
grok: normalizedRuntimeState,
|
|
},
|
|
};
|
|
}
|
|
|
|
function projectRuntimeFields(runtimeState = {}) {
|
|
const normalizedRuntimeState = normalizeRuntimeState(runtimeState);
|
|
return {
|
|
grokRegisterTabId: normalizedRuntimeState.session.registerTabId,
|
|
grokPageState: normalizedRuntimeState.session.pageState,
|
|
grokPageUrl: normalizedRuntimeState.session.pageUrl,
|
|
grokEmail: normalizedRuntimeState.register.email,
|
|
grokFirstName: normalizedRuntimeState.register.firstName,
|
|
grokLastName: normalizedRuntimeState.register.lastName,
|
|
grokPassword: normalizedRuntimeState.register.password,
|
|
grokVerificationRequestedAt: normalizedRuntimeState.register.verificationRequestedAt,
|
|
grokVerificationCode: normalizedRuntimeState.register.verificationCode,
|
|
grokRegisterStatus: normalizedRuntimeState.register.status,
|
|
grokCompletedAt: normalizedRuntimeState.register.completedAt,
|
|
grokSsoCookie: normalizedRuntimeState.sso.currentCookie,
|
|
grokSsoCookies: normalizedRuntimeState.sso.cookies,
|
|
grokSsoExtractedAt: normalizedRuntimeState.sso.extractedAt,
|
|
grokWebchat2ApiUploadStatus: normalizedRuntimeState.upload.status,
|
|
grokWebchat2ApiUploadedAt: normalizedRuntimeState.upload.uploadedAt,
|
|
grokWebchat2ApiUploadMessage: normalizedRuntimeState.upload.message,
|
|
grokWebchat2ApiTargetUrl: normalizedRuntimeState.upload.targetUrl,
|
|
};
|
|
}
|
|
|
|
function ensureRuntimeState(state = {}) {
|
|
const runtimeFlowState = isPlainObject(state?.runtimeState?.flowState)
|
|
? state.runtimeState.flowState
|
|
: {};
|
|
const legacyFlowState = isPlainObject(state?.flowState?.grok)
|
|
? state.flowState.grok
|
|
: {};
|
|
const flatRuntime = {
|
|
session: {},
|
|
register: {},
|
|
sso: {},
|
|
upload: {},
|
|
};
|
|
assignPositiveInteger(flatRuntime.session, 'registerTabId', state.grokRegisterTabId);
|
|
assignCleanString(flatRuntime.session, 'pageState', state.grokPageState);
|
|
assignCleanString(flatRuntime.session, 'pageUrl', state.grokPageUrl || state.grokPostVerificationUrl);
|
|
assignCleanString(flatRuntime.register, 'email', state.grokEmail || state.email);
|
|
assignCleanString(flatRuntime.register, 'firstName', state.grokFirstName);
|
|
assignCleanString(flatRuntime.register, 'lastName', state.grokLastName);
|
|
assignCleanString(flatRuntime.register, 'password', state.grokPassword);
|
|
assignPositiveInteger(flatRuntime.register, 'verificationRequestedAt', state.grokVerificationRequestedAt);
|
|
assignCleanString(flatRuntime.register, 'verificationCode', state.grokVerificationCode);
|
|
assignCleanString(flatRuntime.register, 'status', state.grokRegisterStatus);
|
|
assignPositiveInteger(flatRuntime.register, 'completedAt', state.grokCompletedAt);
|
|
assignCleanString(flatRuntime.sso, 'currentCookie', state.grokSsoCookie);
|
|
assignNonEmptyArray(flatRuntime.sso, 'cookies', state.grokSsoCookies);
|
|
assignPositiveInteger(flatRuntime.sso, 'extractedAt', state.grokSsoExtractedAt || state.grokCompletedAt);
|
|
assignCleanString(flatRuntime.upload, 'status', state.grokWebchat2ApiUploadStatus);
|
|
assignPositiveInteger(flatRuntime.upload, 'uploadedAt', state.grokWebchat2ApiUploadedAt);
|
|
assignCleanString(flatRuntime.upload, 'message', state.grokWebchat2ApiUploadMessage);
|
|
assignCleanString(flatRuntime.upload, 'targetUrl', state.grokWebchat2ApiTargetUrl);
|
|
return normalizeRuntimeState(deepMerge(deepMerge(runtimeFlowState.grok || {}, legacyFlowState), flatRuntime));
|
|
}
|
|
|
|
function buildStateView(state = {}) {
|
|
const runtimeState = ensureRuntimeState(state);
|
|
const canonicalRuntimeState = buildCanonicalRuntimeStatePatch(state, runtimeState);
|
|
return {
|
|
...state,
|
|
...projectRuntimeFields(runtimeState),
|
|
runtimeState: canonicalRuntimeState,
|
|
flowState: {
|
|
...(isPlainObject(state?.flowState) ? state.flowState : {}),
|
|
grok: runtimeState,
|
|
},
|
|
flows: {
|
|
...(isPlainObject(state?.flows) ? state.flows : {}),
|
|
grok: runtimeState,
|
|
},
|
|
};
|
|
}
|
|
|
|
function buildRuntimeStatePatch(currentState = {}, patch = {}) {
|
|
if (!isPlainObject(patch)) {
|
|
return {};
|
|
}
|
|
const nextRuntimeState = normalizeRuntimeState(
|
|
deepMerge(ensureRuntimeState(currentState), patch)
|
|
);
|
|
return {
|
|
...projectRuntimeFields(nextRuntimeState),
|
|
runtimeState: buildCanonicalRuntimeStatePatch(currentState, nextRuntimeState),
|
|
};
|
|
}
|
|
|
|
function buildSessionStatePatch(currentState = {}, updates = {}) {
|
|
const runtimePatch = isPlainObject(updates?.runtimeState?.flowState?.grok)
|
|
? updates.runtimeState.flowState.grok
|
|
: (isPlainObject(updates?.flowState?.grok) ? updates.flowState.grok : null);
|
|
if (!runtimePatch) {
|
|
return {};
|
|
}
|
|
return buildRuntimeStatePatch(currentState, runtimePatch);
|
|
}
|
|
|
|
function buildRuntimeResetPatch(currentState = {}, patch = {}) {
|
|
return buildRuntimeStatePatch(currentState, patch);
|
|
}
|
|
|
|
function buildStartRegisterResetPatch(currentState = {}) {
|
|
return buildRuntimeStatePatch(currentState, buildDefaultRuntimeState());
|
|
}
|
|
|
|
function buildRegisterOnlyResetPatch(currentState = {}, registerPatch = {}) {
|
|
const currentRuntimeState = ensureRuntimeState(currentState);
|
|
return buildRuntimeStatePatch(currentState, {
|
|
...currentRuntimeState,
|
|
session: {
|
|
...currentRuntimeState.session,
|
|
pageState: '',
|
|
pageUrl: '',
|
|
lastError: '',
|
|
},
|
|
register: {
|
|
...buildDefaultRuntimeState().register,
|
|
email: currentRuntimeState.register?.email || '',
|
|
...registerPatch,
|
|
},
|
|
});
|
|
}
|
|
|
|
function buildSsoResetPatch(currentState = {}) {
|
|
const currentRuntimeState = ensureRuntimeState(currentState);
|
|
return buildRuntimeStatePatch(currentState, {
|
|
...currentRuntimeState,
|
|
sso: buildDefaultRuntimeState().sso,
|
|
});
|
|
}
|
|
|
|
function buildDownstreamResetPatch(stepKey = '', currentState = {}) {
|
|
switch (cleanString(stepKey)) {
|
|
case 'grok-open-signup-page':
|
|
return {
|
|
flowStartTime: null,
|
|
...buildStartRegisterResetPatch(currentState),
|
|
};
|
|
case 'grok-submit-email':
|
|
return buildRegisterOnlyResetPatch(currentState, {
|
|
email: '',
|
|
});
|
|
case 'grok-submit-verification-code':
|
|
return buildRegisterOnlyResetPatch(currentState, {});
|
|
case 'grok-submit-profile':
|
|
case 'grok-extract-sso-cookie':
|
|
return buildSsoResetPatch(currentState);
|
|
default:
|
|
return {};
|
|
}
|
|
}
|
|
|
|
function applyNodeCompletionPayload(currentState = {}, payload = {}) {
|
|
const runtimePatch = isPlainObject(payload?.runtimeState?.flowState?.grok)
|
|
? payload.runtimeState.flowState.grok
|
|
: (isPlainObject(payload?.flowState?.grok) ? payload.flowState.grok : null);
|
|
if (runtimePatch) {
|
|
return buildRuntimeStatePatch(currentState, runtimePatch);
|
|
}
|
|
|
|
const patch = {};
|
|
if (Object.prototype.hasOwnProperty.call(payload, 'grokRegisterTabId')) {
|
|
patch.session = { ...(patch.session || {}), registerTabId: payload.grokRegisterTabId };
|
|
}
|
|
if (Object.prototype.hasOwnProperty.call(payload, 'grokPageState')) {
|
|
patch.session = { ...(patch.session || {}), pageState: payload.grokPageState };
|
|
}
|
|
if (Object.prototype.hasOwnProperty.call(payload, 'grokPageUrl') || Object.prototype.hasOwnProperty.call(payload, 'grokSignupUrl') || Object.prototype.hasOwnProperty.call(payload, 'grokPostVerificationUrl')) {
|
|
patch.session = {
|
|
...(patch.session || {}),
|
|
pageUrl: payload.grokPageUrl || payload.grokPostVerificationUrl || payload.grokSignupUrl || '',
|
|
};
|
|
}
|
|
if (Object.prototype.hasOwnProperty.call(payload, 'grokEmail') || Object.prototype.hasOwnProperty.call(payload, 'email')) {
|
|
patch.register = {
|
|
...(patch.register || {}),
|
|
email: payload.grokEmail || payload.email || '',
|
|
};
|
|
}
|
|
if (Object.prototype.hasOwnProperty.call(payload, 'grokFirstName')) {
|
|
patch.register = { ...(patch.register || {}), firstName: payload.grokFirstName };
|
|
}
|
|
if (Object.prototype.hasOwnProperty.call(payload, 'grokLastName')) {
|
|
patch.register = { ...(patch.register || {}), lastName: payload.grokLastName };
|
|
}
|
|
if (Object.prototype.hasOwnProperty.call(payload, 'grokPassword')) {
|
|
patch.register = { ...(patch.register || {}), password: payload.grokPassword };
|
|
}
|
|
if (Object.prototype.hasOwnProperty.call(payload, 'grokVerificationRequestedAt')) {
|
|
patch.register = {
|
|
...(patch.register || {}),
|
|
verificationRequestedAt: payload.grokVerificationRequestedAt,
|
|
};
|
|
}
|
|
if (Object.prototype.hasOwnProperty.call(payload, 'grokVerificationCode')) {
|
|
patch.register = { ...(patch.register || {}), verificationCode: payload.grokVerificationCode };
|
|
}
|
|
if (Object.prototype.hasOwnProperty.call(payload, 'grokRegisterStatus')) {
|
|
patch.register = { ...(patch.register || {}), status: payload.grokRegisterStatus };
|
|
}
|
|
if (Object.prototype.hasOwnProperty.call(payload, 'grokCompletedAt')) {
|
|
patch.register = { ...(patch.register || {}), completedAt: payload.grokCompletedAt };
|
|
}
|
|
if (Object.prototype.hasOwnProperty.call(payload, 'grokSsoCookie')) {
|
|
patch.sso = { ...(patch.sso || {}), currentCookie: payload.grokSsoCookie };
|
|
}
|
|
if (Object.prototype.hasOwnProperty.call(payload, 'grokSsoCookies')) {
|
|
patch.sso = { ...(patch.sso || {}), cookies: payload.grokSsoCookies };
|
|
}
|
|
if (Object.prototype.hasOwnProperty.call(payload, 'grokSsoExtractedAt') || Object.prototype.hasOwnProperty.call(payload, 'grokCompletedAt')) {
|
|
patch.sso = {
|
|
...(patch.sso || {}),
|
|
extractedAt: payload.grokSsoExtractedAt || payload.grokCompletedAt || 0,
|
|
};
|
|
}
|
|
if (Object.prototype.hasOwnProperty.call(payload, 'grokWebchat2ApiUploadStatus')) {
|
|
patch.upload = { ...(patch.upload || {}), status: payload.grokWebchat2ApiUploadStatus };
|
|
}
|
|
if (Object.prototype.hasOwnProperty.call(payload, 'grokWebchat2ApiUploadedAt')) {
|
|
patch.upload = { ...(patch.upload || {}), uploadedAt: payload.grokWebchat2ApiUploadedAt };
|
|
}
|
|
if (Object.prototype.hasOwnProperty.call(payload, 'grokWebchat2ApiUploadMessage')) {
|
|
patch.upload = { ...(patch.upload || {}), message: payload.grokWebchat2ApiUploadMessage };
|
|
}
|
|
if (Object.prototype.hasOwnProperty.call(payload, 'grokWebchat2ApiTargetUrl')) {
|
|
patch.upload = { ...(patch.upload || {}), targetUrl: payload.grokWebchat2ApiTargetUrl };
|
|
}
|
|
if (!Object.keys(patch).length) {
|
|
return {};
|
|
}
|
|
return buildRuntimeStatePatch(currentState, patch);
|
|
}
|
|
|
|
function buildFreshKeepState(currentState = {}) {
|
|
return buildRuntimeStatePatch(currentState, buildDefaultRuntimeState());
|
|
}
|
|
|
|
return {
|
|
applyNodeCompletionPayload,
|
|
buildDefaultRuntimeState,
|
|
buildDownstreamResetPatch,
|
|
buildFreshKeepState,
|
|
buildRuntimeStatePatch,
|
|
buildSessionStatePatch,
|
|
buildStateView,
|
|
ensureRuntimeState,
|
|
normalizeSsoCookies,
|
|
projectRuntimeFields,
|
|
};
|
|
});
|