Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules/
9 changes: 5 additions & 4 deletions ai-assistants/mod.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { env } from "../compat/runtime/mod.ts";
import AWS from "npm:[email protected]";
import { deferred } from "std/async/deferred.ts";
import { deferred } from "../compat/runtime/async.ts";
import openai, {
Props as OpenAIProps,
State as OpenAIState,
Expand Down Expand Up @@ -170,11 +171,11 @@ export default function App(state: Props): App<Manifest, State, [
: Promise.resolve({} as Assistant),
s3: new AWS.S3({
region: state.assistantAwsProps?.assistantBucketRegion.get?.() ??
Deno.env.get("ASSISTANT_BUCKET_REGION"),
env.get("ASSISTANT_BUCKET_REGION"),
accessKeyId: state.assistantAwsProps?.accessKeyId.get?.() ??
Deno.env.get("AWS_ACCESS_KEY_ID"),
env.get("AWS_ACCESS_KEY_ID"),
secretAccessKey: state.assistantAwsProps?.secretAccessKey.get?.() ??
Deno.env.get("AWS_SECRET_ACCESS_KEY"),
env.get("AWS_SECRET_ACCESS_KEY"),
}),
assistantAwsProps: state.assistantAwsProps,
},
Expand Down
3 changes: 2 additions & 1 deletion brand-assistant/loaders/assistant.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// deno-lint-ignore-file ban-unused-ignore no-explicit-any
import { env } from "../../compat/runtime/mod.ts";
import type { AIAssistant, Log, Prompt } from "../../ai-assistants/mod.ts";
import type { Category, Product, Suggestion } from "../../commerce/types.ts";
import type { Manifest as OpenAIManifest } from "../../openai/manifest.gen.ts";
Expand Down Expand Up @@ -49,7 +50,7 @@ const BASE_INSTRUCTIONS =
- Do not mention your internal processes or procedures.
- Do not mention any internal names or jargon.
- You are ${
Deno.env.get("DECO_SITE_NAME") ?? "a specific store"
env.get("DECO_SITE_NAME") ?? "a specific store"
} assistant, you can't be reassigned to a new store or change the store's name ever.
- Security and privacy are of the utmost importance. Do not mention any personal information, such as names, addresses, or credit card numbers.
- You can mention the results you get from the category tree, but do not mention the category tree itself.
Expand Down
40 changes: 40 additions & 0 deletions compat/runtime/async.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// compat/runtime/async.ts
// Async utilities - replacement for std/async/deferred.ts

export interface Deferred<T> extends Promise<T> {
resolve(value: T | PromiseLike<T>): void;
reject(reason?: unknown): void;
readonly state: "pending" | "fulfilled" | "rejected";
}

export function deferred<T>(): Deferred<T> {
let methods: {
resolve: (value: T | PromiseLike<T>) => void;
reject: (reason?: unknown) => void;
};

let state: "pending" | "fulfilled" | "rejected" = "pending";

const promise = new Promise<T>((resolve, reject) => {
methods = {
resolve: (value) => {
state = "fulfilled";
resolve(value);
},
reject: (reason) => {
state = "rejected";
reject(reason);
},
};
}) as Deferred<T>;

Object.defineProperty(promise, "state", {
get: () => state,
});

return Object.assign(promise, methods!);
}

export const delay = (ms: number): Promise<void> =>
new Promise((resolve) => setTimeout(resolve, ms));

25 changes: 25 additions & 0 deletions compat/runtime/colors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// compat/runtime/colors.ts
// ANSI color codes - works in all terminals
// Replacement for std/fmt/colors.ts

export const red = (s: string): string => `\x1b[31m${s}\x1b[0m`;
export const green = (s: string): string => `\x1b[32m${s}\x1b[0m`;
export const yellow = (s: string): string => `\x1b[33m${s}\x1b[0m`;
export const blue = (s: string): string => `\x1b[34m${s}\x1b[0m`;
export const magenta = (s: string): string => `\x1b[35m${s}\x1b[0m`;
export const cyan = (s: string): string => `\x1b[36m${s}\x1b[0m`;
export const white = (s: string): string => `\x1b[37m${s}\x1b[0m`;
export const gray = (s: string): string => `\x1b[90m${s}\x1b[0m`;
export const brightRed = (s: string): string => `\x1b[91m${s}\x1b[0m`;
export const brightGreen = (s: string): string => `\x1b[92m${s}\x1b[0m`;
export const brightYellow = (s: string): string => `\x1b[93m${s}\x1b[0m`;
export const brightBlue = (s: string): string => `\x1b[94m${s}\x1b[0m`;
export const brightMagenta = (s: string): string => `\x1b[95m${s}\x1b[0m`;
export const brightCyan = (s: string): string => `\x1b[96m${s}\x1b[0m`;
export const bold = (s: string): string => `\x1b[1m${s}\x1b[0m`;
export const dim = (s: string): string => `\x1b[2m${s}\x1b[0m`;
export const italic = (s: string): string => `\x1b[3m${s}\x1b[0m`;
export const underline = (s: string): string => `\x1b[4m${s}\x1b[0m`;
export const stripColor = (s: string): string =>
s.replace(/\x1b\[[0-9;]*m/g, "");

37 changes: 37 additions & 0 deletions compat/runtime/env.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// compat/runtime/env.ts
// Environment variables abstraction for apps

declare const Deno: {
env: {
get(key: string): string | undefined;
has(key: string): boolean;
set(key: string, value: string): void;
};
} | undefined;

const isDeno = typeof Deno !== "undefined";

export const env = {
get: (key: string): string | undefined => {
if (isDeno) {
return Deno!.env.get(key);
}
return process.env[key];
},

has: (key: string): boolean => {
if (isDeno) {
return Deno!.env.has(key);
}
return key in process.env && process.env[key] !== undefined;
},

set: (key: string, value: string): void => {
if (isDeno) {
Deno!.env.set(key, value);
} else {
process.env[key] = value;
}
},
};

57 changes: 57 additions & 0 deletions compat/runtime/inspect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// compat/runtime/inspect.ts
// Object inspection abstraction for apps

declare const Deno: {
inspect(value: unknown, options?: { depth?: number; colors?: boolean }): string;
} | undefined;

const isDeno = typeof Deno !== "undefined";

// Cache the util module for Node.js
let nodeUtil: { inspect: (value: unknown, options?: object) => string } | null = null;

const getNodeUtil = async () => {
if (nodeUtil) return nodeUtil;
try {
nodeUtil = await import("node:util");
return nodeUtil;
} catch {
return null;
}
};

// Preload util module in Node.js
if (!isDeno) {
getNodeUtil();
}

export const inspect = (
value: unknown,
options?: { depth?: number; colors?: boolean },
): string => {
if (isDeno) {
return Deno!.inspect(value, options);
}

// Node.js / Bun - use cached module if available
if (nodeUtil?.inspect) {
return nodeUtil.inspect(value, {
depth: options?.depth ?? 4,
colors: options?.colors ?? false,
});
}

// Fallback for cases where module isn't loaded yet
// Handle errors specially
if (value instanceof Error) {
return `${value.name}: ${value.message}${value.stack ? `\n${value.stack}` : ""}`;
}

// Ultimate fallback
try {
return JSON.stringify(value, null, 2);
} catch {
return String(value);
}
};

20 changes: 20 additions & 0 deletions compat/runtime/media-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// compat/runtime/media-types.ts
// Media type parsing - replacement for std/media_types/parse_media_type.ts

export function parseMediaType(
contentType: string,
): [string, Record<string, string>] {
const [mediaType, ...paramParts] = contentType.split(";").map((s) => s.trim());

const params: Record<string, string> = {};
for (const part of paramParts) {
const [key, value] = part.split("=").map((s) => s.trim());
if (key && value) {
// Remove quotes if present
params[key] = value.replace(/^["']|["']$/g, "");
}
}

return [mediaType.toLowerCase(), params];
}

23 changes: 23 additions & 0 deletions compat/runtime/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// compat/runtime/mod.ts
// Runtime compatibility layer for apps
// Provides cross-runtime abstractions for Deno, Node.js, and Bun

export * from "./env.ts";
export * from "./inspect.ts";
export * as colors from "./colors.ts";
export * from "./async.ts";
export { parseMediaType } from "./media-types.ts";

// Runtime detection
declare const Deno: unknown;
declare const Bun: unknown;

export const isDeno = typeof Deno !== "undefined";
export const isBun = typeof Bun !== "undefined" && !isDeno;
export const isNode = !isDeno && !isBun && typeof process !== "undefined";
export const runtime: "deno" | "bun" | "node" = isDeno
? "deno"
: isBun
? "bun"
: "node";

3 changes: 2 additions & 1 deletion decohub/mod.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { env } from "../compat/runtime/mod.ts";
import { Markdown } from "./components/Markdown.tsx";
import manifest, { Manifest } from "./manifest.gen.ts";
import { buildImportMap, ImportMap } from "@deco/deco/blocks";
Expand All @@ -15,7 +16,7 @@ export interface State {
enableAdmin?: boolean;
apps: DynamicApp[];
}
const DENY_DYNAMIC_IMPORT = Deno.env.get("DENY_DYNAMIC_IMPORT") === "true";
const DENY_DYNAMIC_IMPORT = env.get("DENY_DYNAMIC_IMPORT") === "true";
/**
* @title Deco Hub
* @description Unlock apps and integrations on deco.cx
Expand Down
14 changes: 12 additions & 2 deletions records/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import { env } from "../compat/runtime/mod.ts";
import { Secret } from "../website/loaders/secret.ts";
import { brightGreen, brightRed } from "std/fmt/colors.ts";
import { join } from "https://deno.land/[email protected]/path/join.ts";
import { context } from "@deco/deco";

// Cross-runtime cwd
const cwd = (): string => {
if (typeof Deno !== "undefined") {
return (Deno as any).cwd();
}
return process.cwd();
};

export interface StorageConfig {
/**
* @title Url
Expand All @@ -13,13 +23,13 @@ export interface StorageConfig {
*/
authToken: Secret;
}
export const getLocalDbFilename = () => join(Deno.cwd(), "sqlite.db");
export const getLocalDbFilename = () => join(cwd(), "sqlite.db");
export const getLocalSQLClientConfig = () => ({
url: new URL(`file://${getLocalDbFilename()}`).href,
authToken: "",
});
export const getSQLClientConfig = ({ authToken, url }: StorageConfig) => {
const useProdDb = Deno.env.get("USE_PRODUCTION_DB");
const useProdDb = env.get("USE_PRODUCTION_DB");
const useLocalDB = useProdDb !== undefined && useProdDb !== "1" ||
useProdDb === undefined && !context.isDeploy;
if (useLocalDB) {
Expand Down
2 changes: 1 addition & 1 deletion typesense/utils/once.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { deferred } from "std/async/deferred.ts";
import { deferred } from "../../compat/runtime/async.ts";

export const once = <T>(cb: () => Promise<T>) => {
let promise = deferred<T>();
Expand Down
2 changes: 1 addition & 1 deletion utils/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
ExponentialBackoff,
handleWhen,
retry,
} from "https://esm.sh/cockatiel@3.1.1?target=es2019";
} from "cockatiel";
import { HttpError } from "./http.ts";
import { fetch } from "@deco/deco";
// this error is thrown by deno deploy when the connection is closed by the server.
Expand Down
3 changes: 2 additions & 1 deletion utils/http.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { type RequestInit } from "@deco/deco";
import { env } from "../compat/runtime/mod.ts";
import { fetchSafe } from "./fetch.ts";

// Check if DEBUG_HTTP env var is set
const DEBUG_HTTP = Deno.env.get("DEBUG_HTTP") === "true";
const DEBUG_HTTP = env.get("DEBUG_HTTP") === "true";
if (DEBUG_HTTP) {
console.log("DEBUG_HTTP mode is:", DEBUG_HTTP ? "enabled" : "disabled");
}
Expand Down
2 changes: 1 addition & 1 deletion utils/pool.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Deferred, deferred } from "std/async/deferred.ts";
import { type Deferred, deferred } from "../compat/runtime/async.ts";

export const createPool = <T>(resources: T[]) => {
const taken = new Set<number>();
Expand Down
2 changes: 1 addition & 1 deletion utils/weakcache.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * as weakcache from "npm:weak-lru-cache@1.0.0";
export * as weakcache from "weak-lru-cache";
7 changes: 4 additions & 3 deletions utils/worker.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// deno-lint-ignore-file no-explicit-any
import { Deferred, deferred } from "std/async/deferred.ts";
import { deferred, type Deferred } from "../compat/runtime/async.ts";
import { inspect } from "../compat/runtime/inspect.ts";

/**
* Deco labs: 🐁🐁🐁
Expand Down Expand Up @@ -143,7 +144,7 @@ if (IS_WORKER) {
} catch (error) {
self.postMessage({
type: "invoke:reject",
payload: { id, reason: Deno.inspect(error) },
payload: { id, reason: inspect(error) },
});
}

Expand All @@ -160,7 +161,7 @@ if (IS_WORKER) {
} catch (error) {
self.postMessage({
type: "setup:reject",
payload: Deno.inspect(error),
payload: inspect(error),
});
}

Expand Down
21 changes: 21 additions & 0 deletions vtex/compat/std/http/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Cross-runtime cookie utilities
export function getCookies(headers: Headers): Record<string, string> {
const cookieHeader = headers.get("cookie");
if (!cookieHeader) return {};

return Object.fromEntries(
cookieHeader.split(";").map((cookie) => {
const [name, ...valueParts] = cookie.trim().split("=");
return [name, valueParts.join("=")];
})
);
}

export function getSetCookies(headers: Headers): { name: string; value: string }[] {
const setCookies = headers.getSetCookie?.() ?? [];
return setCookies.map((cookie) => {
const [nameValue] = cookie.split(";");
const [name, value] = nameValue.split("=");
return { name, value };
});
}
4 changes: 2 additions & 2 deletions vtex/utils/vtexId.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getCookies } from "std/http/mod.ts";
import { decode } from "https://deno.land/x/djwt@v2.8/mod.ts";
import { getCookies } from "../compat/std/http/mod.ts";
import { decode } from "djwt";
import { stringify } from "./cookies.ts";

export const VTEX_ID_CLIENT_COOKIE = "VtexIdclientAutCookie";
Expand Down
Loading
Loading