Hermes 284313f908
Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Initial import of AlgaPSA codebase from PSA server
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz

Source: /opt/alga-psa on psa.joliet.tech
2026-06-22 16:12:17 -05:00

227 lines
6.3 KiB
JavaScript

import { get as secretGet, listKeys as secretListKeys } from 'alga:extension/secrets';
import { callRoute as uiProxyCallRoute } from 'alga:extension/ui-proxy';
if (typeof globalThis.TextEncoder === 'undefined') {
globalThis.TextEncoder = class {
encode(value) {
const text = String(value);
const bytes = new Uint8Array(text.length);
for (let i = 0; i < text.length; i += 1) {
bytes[i] = text.charCodeAt(i) & 0xff;
}
return bytes;
}
encodeInto(source, destination) {
const text = String(source);
const len = Math.min(text.length, destination.length);
for (let i = 0; i < len; i += 1) {
destination[i] = text.charCodeAt(i) & 0xff;
}
return { read: len, written: len };
}
};
}
if (typeof globalThis.TextDecoder === 'undefined') {
globalThis.TextDecoder = class {
decode(view) {
if (!view || typeof view.length !== 'number') {
return '';
}
let result = '';
for (let i = 0; i < view.length; i += 1) {
result += String.fromCharCode(view[i]);
}
return result;
}
};
}
if (typeof globalThis.process === 'undefined') {
globalThis.process = { env: {} };
}
if (globalThis.process && globalThis.process.env && !globalThis.process.env.JCO_DEBUG) {
globalThis.process.env.JCO_DEBUG = '1';
}
const __logBuffer = [];
if (typeof globalThis.console === 'undefined') {
globalThis.console = {};
}
const noop = () => {};
const appendLog = (level, args) => {
try {
const msg = `[${level}] ${args.map((value) => String(value)).join(' ')}`;
__logBuffer.push(msg);
} catch (_) {
__logBuffer.push(`[${level}] <unprintable>`);
}
};
globalThis.console.log = (...args) => appendLog('log', args);
globalThis.console.info = (...args) => appendLog('info', args);
globalThis.console.warn = (...args) => appendLog('warn', args);
globalThis.console.error = (...args) => appendLog('error', args);
let __nextTimeoutId = 1;
const __scheduledTimeouts = new Map();
if (typeof globalThis.setTimeout === 'undefined') {
globalThis.setTimeout = (fn) => {
if (typeof fn !== 'function') {
return 0;
}
const id = __nextTimeoutId++;
const run = () => {
if (!__scheduledTimeouts.has(id)) {
return;
}
__scheduledTimeouts.delete(id);
try {
fn();
} catch (err) {
console.error('setTimeout callback failed', err);
}
};
__scheduledTimeouts.set(id, run);
Promise.resolve().then(run);
return id;
};
}
if (typeof globalThis.clearTimeout === 'undefined') {
globalThis.clearTimeout = (id) => {
__scheduledTimeouts.delete(id);
};
}
const encoder = new TextEncoder();
function encodeJson(value) {
return encoder.encode(JSON.stringify(value));
}
export async function handler(request, host) {
const logInfo =
host && host.logging && typeof host.logging.info === 'function'
? (msg) => {
try {
return host.logging.info(String(msg));
} catch (_) {
return Promise.resolve();
}
}
: () => Promise.resolve();
const flushLogs = async () => {
while (__logBuffer.length > 0) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const entry = __logBuffer.shift();
await logInfo(entry);
}
};
try {
console.log('js component handler invoked');
await flushLogs();
const ctx = request.context;
const httpUrl = request?.http?.url || request?.http?.path || '';
if (httpUrl.startsWith('/dynamic/secrets')) {
let secretValue = null;
let keys = [];
let secretError = null;
try {
keys = (await secretListKeys()) ?? [];
} catch (err) {
secretError = err instanceof Error ? err.message : String(err);
}
if (!secretError) {
try {
secretValue = await secretGet('ALGA_API_KEY');
} catch (err) {
secretError = err instanceof Error ? err.message : String(err);
}
}
return {
status: 200,
headers: [
{ name: 'content-type', value: 'application/json' },
{ name: 'x-generated-by', value: 'js-component' }
],
body: encodeJson({
ok: secretError === null,
method: request.http.method,
path: request.http.url,
tenantId: ctx?.tenantId ?? null,
extensionId: ctx?.extensionId ?? null,
secrets: {
value: secretValue,
keys,
error: secretError
}
})
};
}
if (httpUrl.startsWith('/dynamic/ui-proxy')) {
let proxyResponse = null;
let proxyError = null;
try {
const payload = request.http.body ? new Uint8Array(request.http.body) : new Uint8Array();
const bytes = await uiProxyCallRoute('/proxy/ping', payload.length ? payload : null);
proxyResponse = bytes ? Array.from(bytes) : null;
} catch (err) {
proxyError = err instanceof Error ? err.message : String(err);
}
return {
status: 200,
headers: [
{ name: 'content-type', value: 'application/json' },
{ name: 'x-generated-by', value: 'js-component' }
],
body: encodeJson({
ok: proxyError === null,
method: request.http.method,
path: request.http.url,
tenantId: ctx?.tenantId ?? null,
extensionId: ctx?.extensionId ?? null,
proxy: {
response: proxyResponse,
error: proxyError
}
})
};
}
return {
status: 200,
headers: [
{ name: 'content-type', value: 'application/json' },
{ name: 'x-generated-by', value: 'js-component' }
],
body: encodeJson({
ok: true,
method: request.http.method,
path: request.http.url,
tenantId: ctx?.tenantId ?? null,
extensionId: ctx?.extensionId ?? null,
echo: request.http.body ? Array.from(request.http.body) : null
})
};
} catch (err) {
console.error('js component error', err);
await flushLogs();
const message = err instanceof Error ? err.message : String(err);
return {
status: 500,
headers: [{ name: 'content-type', value: 'application/json' }],
body: encodeJson({ ok: false, error: message })
};
}
}