Skip to content
Open
Show file tree
Hide file tree
Changes from 10 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
4 changes: 2 additions & 2 deletions examples/common/apps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const BASE_NEXT_PORT = 3100;
/**
* Returns a distinct port for each application so they can run in parallel.
*/
export function getAppPort(app: AppName, { isWorker = true } = {}) {
export function getAppPort(app: AppName, { isWorker = true } = {}): number {
const index = apps.indexOf(app);
if (index === -1) {
throw new Error(`Unknown app: ${app}`);
Expand All @@ -46,7 +46,7 @@ export function getAppPort(app: AppName, { isWorker = true } = {}) {
/**
* Returns a distinct port for each application so they can run in parallel.
*/
export function getInspectorPort(app: AppName) {
export function getInspectorPort(app: AppName): number {
const index = apps.indexOf(app);
if (index === -1) {
throw new Error(`Unknown app: ${app}`);
Expand Down
8 changes: 3 additions & 5 deletions examples/common/config-e2e.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { defineConfig, devices } from "@playwright/test";
import { defineConfig, devices, type PlaywrightTestConfig } from "@playwright/test";
import { getAppPort, getInspectorPort, type AppName } from "./apps";

declare const process: typeof nodeProcess;

export function configurePlaywright(
app: AppName,
{
// Do we run on CI?
isCI = Boolean(process.env.CI),
isCI = !!process.env.CI,
Comment thread
314systems marked this conversation as resolved.
Outdated
// Do we run on workers (`wrangler dev`) or on Node (`next dev`)
isWorker = true,
// Tests with multiple browsers
Expand All @@ -17,7 +15,7 @@ export function configurePlaywright(
// Use the turbopack runtime
useTurbopack = false,
} = {}
) {
): PlaywrightTestConfig {
const port = getAppPort(app, { isWorker });
const inspectorPort = getInspectorPort(app);
const baseURL = `http://localhost:${port}`;
Expand Down
6 changes: 5 additions & 1 deletion examples/common/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
{
"name": "common",
"private": true,
"type": "module"
"type": "module",
"devDependencies": {
"typescript": "catalog:",
"@types/node": "catalog:"
}
}
6 changes: 3 additions & 3 deletions examples/common/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{
"compilerOptions": {
"lib": ["esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"strict": true,
"noEmit": true,
"incremental": true,
"module": "esnext",
"esModuleInterop": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true
"isolatedModules": true,
"types": ["node"]
}
}
2 changes: 1 addition & 1 deletion packages/cloudflare/src/api/cloudflare-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ async function getCloudflareContextAsync<
* Note: this function should only be called inside the Next.js config file, and although async it doesn't need to be `await`ed
* @param options options on how the function should operate and if/where to persist the platform data
*/
export async function initOpenNextCloudflareForDev(options?: GetPlatformProxyOptions) {
export async function initOpenNextCloudflareForDev(options?: GetPlatformProxyOptions): Promise<void> {
const shouldInitializationRun = shouldContextInitializationRun();
if (!shouldInitializationRun) return;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export class BucketCachePurge extends DurableObject<CloudflareEnv> {
});
}

async purgeCacheByTags(tags: string[]) {
async purgeCacheByTags(tags: string[]): Promise<void> {
for (const tag of tags) {
// Insert the tag into the sql table
this.ctx.storage.sql.exec(
Expand All @@ -43,7 +43,7 @@ export class BucketCachePurge extends DurableObject<CloudflareEnv> {
}
}

override async alarm() {
override async alarm(): Promise<void> {
let tags = this.ctx.storage.sql
.exec<{ tag: string }>(
`
Expand Down
14 changes: 7 additions & 7 deletions packages/cloudflare/src/api/durable-objects/queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export class DOQueueHandler extends DurableObject<CloudflareEnv> {
debug(`Durable object initialized`);
}

async revalidate(msg: QueueMessage) {
async revalidate(msg: QueueMessage): Promise<void> {
if (this.ongoingRevalidations.size > 2 * this.maxRevalidations) {
warn(
`Your durable object has 2 times the maximum number of revalidations (${this.maxRevalidations}) in progress. If this happens often, you should consider increasing the NEXT_CACHE_DO_QUEUE_MAX_REVALIDATION or the number of durable objects with the MAX_REVALIDATE_CONCURRENCY env var.`
Expand Down Expand Up @@ -110,7 +110,7 @@ export class DOQueueHandler extends DurableObject<CloudflareEnv> {
this.ctx.waitUntil(revalidationPromise);
}

async executeRevalidation(msg: QueueMessage) {
async executeRevalidation(msg: QueueMessage): Promise<void> {
let response: Response | undefined;
try {
debug(`Revalidating ${msg.MessageBody.host}${msg.MessageBody.url}`);
Expand Down Expand Up @@ -187,7 +187,7 @@ export class DOQueueHandler extends DurableObject<CloudflareEnv> {
}
}

override async alarm() {
override async alarm(): Promise<void> {
const currentDateTime = Date.now();
// We fetch the first event that needs to be retried or if the date is expired
const nextEventToRetry = Array.from(this.routeInFailedState.values())
Expand All @@ -204,7 +204,7 @@ export class DOQueueHandler extends DurableObject<CloudflareEnv> {
}
}

async addToFailedState(msg: QueueMessage) {
async addToFailedState(msg: QueueMessage): Promise<void> {
debug(`Adding ${msg.MessageBody.host}${msg.MessageBody.url} to the failed state`);
const existingFailedState = this.routeInFailedState.get(msg.MessageDeduplicationId);

Expand Down Expand Up @@ -245,7 +245,7 @@ export class DOQueueHandler extends DurableObject<CloudflareEnv> {
await this.addAlarm();
}

async addAlarm() {
async addAlarm(): Promise<void> {
const existingAlarm = await this.ctx.storage.getAlarm({ allowConcurrency: false });
if (existingAlarm) return;
if (this.routeInFailedState.size === 0) return;
Expand All @@ -263,7 +263,7 @@ export class DOQueueHandler extends DurableObject<CloudflareEnv> {
// This function is used to restore the state of the durable object
// We don't restore the ongoing revalidations because we cannot know in which state they are
// We only restore the failed state and the alarm
async initState() {
async initState(): Promise<void> {
if (this.disableSQLite) return;
// We store the failed state as a blob, we don't want to do anything with it anyway besides restoring
this.sql.exec("CREATE TABLE IF NOT EXISTS failed_state (id TEXT PRIMARY KEY, data TEXT, buildId TEXT)");
Expand All @@ -290,7 +290,7 @@ export class DOQueueHandler extends DurableObject<CloudflareEnv> {
* @param msg
* @returns `true` if the route has been revalidated since the lastModified from the message, `false` otherwise
*/
checkSyncTable(msg: QueueMessage) {
checkSyncTable(msg: QueueMessage): boolean {
try {
if (this.disableSQLite) return false;
return (
Expand Down
4 changes: 2 additions & 2 deletions packages/cloudflare/src/api/overrides/cache-purge/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ interface PurgeOptions {
type: "durableObject" | "direct";
}

export const purgeCache = ({ type = "direct" }: PurgeOptions) => {
export const purgeCache = ({ type = "direct" }: PurgeOptions): CDNInvalidationHandler => {
return {
name: "cloudflare",
async invalidatePaths(paths) {
Expand All @@ -29,7 +29,7 @@ export const purgeCache = ({ type = "direct" }: PurgeOptions) => {
}
debugCache("cdnInvalidation", "Invalidated paths:", tags);
},
} satisfies CDNInvalidationHandler;
};
};

export default purgeCache;
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ class RegionalCache implements IncrementalCache {
return this.localCache;
}

protected getCacheUrlKey(key: string, cacheType?: CacheEntryType) {
protected getCacheUrlKey(key: string, cacheType?: CacheEntryType): string {
const buildId = process.env.NEXT_BUILD_ID ?? FALLBACK_BUILD_ID;
return "http://cache.local" + `/${buildId}/${key}`.replace(/\/+/g, "/") + `.${cacheType ?? "cache"}`;
}
Expand Down Expand Up @@ -235,7 +235,7 @@ class RegionalCache implements IncrementalCache {
* @param cache Incremental cache instance.
* @param opts Options for the regional cache.
*/
export function withRegionalCache(cache: IncrementalCache, opts: Options) {
export function withRegionalCache(cache: IncrementalCache, opts: Options): RegionalCache {
return new RegionalCache(cache, opts);
}

Expand Down
8 changes: 4 additions & 4 deletions packages/cloudflare/src/api/overrides/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export type IncrementalCacheEntry<CacheType extends CacheEntryType> = {
lastModified: number;
};

export const debugCache = (name: string, ...args: unknown[]) => {
export const debugCache = (name: string, ...args: unknown[]): void => {
if (process.env.NEXT_PRIVATE_DEBUG_CACHE) {
console.log(`[${name}] `, ...args);
}
Expand All @@ -26,7 +26,7 @@ export type KeyOptions = {
buildId: string | undefined;
};

export function computeCacheKey(key: string, options: KeyOptions) {
export function computeCacheKey(key: string, options: KeyOptions): string {
const { cacheType = "cache", prefix = DEFAULT_PREFIX, buildId = FALLBACK_BUILD_ID } = options;
const hash = createHash("sha256").update(key).digest("hex");
return `${prefix}/${buildId}/${hash}.${cacheType}`.replace(/\/+/g, "/");
Expand All @@ -39,7 +39,7 @@ export function isPurgeCacheEnabled(): boolean {
return cdnInvalidation !== undefined && cdnInvalidation !== "dummy";
}

export async function purgeCacheByTags(tags: string[]) {
export async function purgeCacheByTags(tags: string[]): Promise<void> {
const { env } = getCloudflareContext();
// We have a durable object for purging cache
// We should use it
Expand All @@ -55,7 +55,7 @@ export async function purgeCacheByTags(tags: string[]) {
}
}

export async function internalPurgeCacheByTags(env: CloudflareEnv, tags: string[]) {
export async function internalPurgeCacheByTags(env: CloudflareEnv, tags: string[]): Promise<string> {
if (!env.CACHE_PURGE_ZONE_ID || !env.CACHE_PURGE_API_TOKEN) {
// THIS IS A NO-OP
error("No cache zone ID or API token provided. Skipping cache purge.");
Expand Down
2 changes: 1 addition & 1 deletion packages/cloudflare/src/api/overrides/queue/do-queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { getCloudflareContext } from "../../cloudflare-context.js";

export default {
name: "durable-queue",
send: async (msg: QueueMessage) => {
send: async (msg: QueueMessage): Promise<void> => {
const durableObject = getCloudflareContext().env.NEXT_CACHE_DO_QUEUE;
if (!durableObject) throw new IgnorableError("No durable object binding for cache revalidation");

Expand Down
7 changes: 4 additions & 3 deletions packages/cloudflare/src/api/overrides/queue/queue-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ interface QueueCachingOptions {
const DEFAULT_QUEUE_CACHE_TTL_SEC = 5;

class QueueCache implements Queue {
readonly name;
readonly name: string;
readonly regionalCacheTtlSec: number;
readonly waitForQueueAck: boolean;
cache: Cache | undefined;
Expand All @@ -36,7 +36,7 @@ class QueueCache implements Queue {
this.waitForQueueAck = options.waitForQueueAck ?? false;
}

async send(msg: QueueMessage) {
async send(msg: QueueMessage): Promise<void> {
try {
const isCached = await this.isInCache(msg);
if (isCached) {
Expand Down Expand Up @@ -119,4 +119,5 @@ class QueueCache implements Queue {
}
}

export default (originalQueue: Queue, opts: QueueCachingOptions = {}) => new QueueCache(originalQueue, opts);
export default (originalQueue: Queue, opts: QueueCachingOptions = {}): QueueCache =>
new QueueCache(originalQueue, opts);
Original file line number Diff line number Diff line change
Expand Up @@ -185,18 +185,18 @@ export class D1NextModeTagCache implements NextModeTagCache {
};
}

protected getCacheKey(key: string) {
protected getCacheKey(key: string): string {
return `${this.getBuildId()}/${key}`.replaceAll("//", "/");
}

protected getBuildId() {
protected getBuildId(): string {
return process.env.NEXT_BUILD_ID ?? FALLBACK_BUILD_ID;
}

/**
* @returns request scoped in-memory cache for tag values, or undefined if ALS is not available.
*/
protected getItemsCache() {
protected getItemsCache(): Map<string, D1TagValue | null> | undefined {
const store = globalThis.__openNextAls?.getStore();
return store?.requestCache.getOrCreate<string, D1TagValue | null>("d1-nextMode:tagItems");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,11 @@ class ShardedDOTagCache implements NextModeTagCache {
* The following methods are public only because they are accessed from the tests
*/

public async performWriteTagsWithRetry(doId: DOId, tags: NormalizedTagInput[], retryNumber = 0) {
public async performWriteTagsWithRetry(
doId: DOId,
tags: NormalizedTagInput[],
retryNumber = 0
): Promise<void> {
try {
const stub = this.getDurableObjectStub(doId);
await stub.writeTags(tags);
Expand All @@ -269,7 +273,7 @@ class ShardedDOTagCache implements NextModeTagCache {
return `http://local.cache/shard/${doId.shardId}?tag=${encodeURIComponent(tag)}`;
}

public async getCacheInstance() {
public async getCacheInstance(): Promise<Cache | undefined> {
if (!this.localCache && this.opts.regionalCache) {
this.localCache = await caches.open("sharded-do-tag-cache");
}
Expand Down Expand Up @@ -326,7 +330,7 @@ class ShardedDOTagCache implements NextModeTagCache {
optsKey: CacheTagKeyOptions,
stub: DurableObjectStub<DOShardedTagCache>,
prefetchedTagData?: Record<string, TagData>
) {
): Promise<void> {
if (!this.opts.regionalCache) return;
const cache = await this.getCacheInstance();
if (!cache) return;
Expand Down Expand Up @@ -368,7 +372,7 @@ class ShardedDOTagCache implements NextModeTagCache {
* Deletes the regional cache for the given tags
* This is used to ensure that the cache is cleared when the tags are revalidated
*/
public async deleteRegionalCache(optsKey: CacheTagKeyOptions) {
public async deleteRegionalCache(optsKey: CacheTagKeyOptions): Promise<void> {
// We never want to crash because of the cache
try {
if (!this.opts.regionalCache) return;
Expand Down Expand Up @@ -397,7 +401,7 @@ class ShardedDOTagCache implements NextModeTagCache {
}: {
tags: string[];
generateAllReplicas?: boolean;
}) {
}): CacheTagKeyOptions[] {
// Here we'll start by splitting soft tags from hard tags
// This will greatly increase the cache hit rate for the soft tag (which are the most likely to cause issue because of load)
const softTags = this.generateDOIdArray({ tags, shardType: "soft", generateAllReplicas });
Expand Down Expand Up @@ -637,4 +641,4 @@ interface CacheTagKeyOptions {
tags: string[];
}

export default (opts?: ShardedDOTagCacheOptions) => new ShardedDOTagCache(opts);
export default (opts?: ShardedDOTagCacheOptions): ShardedDOTagCache => new ShardedDOTagCache(opts);
Original file line number Diff line number Diff line change
Expand Up @@ -211,18 +211,18 @@ export class KVNextModeTagCache implements NextModeTagCache {
return isDisabled ? undefined : kv;
}

protected getCacheKey(key: string) {
protected getCacheKey(key: string): string {
return `${this.getBuildId()}/${key}`.replaceAll("//", "/");
}

protected getBuildId() {
protected getBuildId(): string {
return process.env.NEXT_BUILD_ID ?? FALLBACK_BUILD_ID;
}

/**
* @returns request scoped in-memory cache for tag values, or undefined if ALS is not available.
*/
protected getItemsCache() {
protected getItemsCache(): Map<string, KVTagValue | null> | undefined {
const store = globalThis.__openNextAls?.getStore();
return store?.requestCache.getOrCreate<string, KVTagValue | null>("kv-nextMode:tagItems");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import type { TagCacheMetaFile } from "@opennextjs/aws/types/cache.js";
/**
* Generates SQL statements that can be used to initialize the cache assets manifest in an SQL data store.
*/
export function compileCacheAssetsManifestSqlFile(options: BuildOptions, metaFiles: TagCacheMetaFile[]) {
export function compileCacheAssetsManifestSqlFile(
options: BuildOptions,
metaFiles: TagCacheMetaFile[]
): void {
const outputPath = path.join(options.outputDir, "cloudflare/cache-assets-manifest.sql");

mkdirSync(path.dirname(outputPath), { recursive: true });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { extractProjectEnvVars } from "../../utils/extract-project-env-vars.js";
/**
* Compiles the values extracted from the project's env files to the output directory for use in the worker.
*/
export function compileEnvFiles(buildOpts: BuildOptions) {
export function compileEnvFiles(buildOpts: BuildOptions): void {
const envDir = path.join(buildOpts.outputDir, "cloudflare");
fs.mkdirSync(envDir, { recursive: true });
["production", "development", "test"].forEach((mode) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { build } from "esbuild";
/**
* Compiles the initialization code for the workerd runtime
*/
export async function compileImages(options: BuildOptions) {
export async function compileImages(options: BuildOptions): Promise<void> {
const currentDir = path.join(path.dirname(fileURLToPath(import.meta.url)));
const templatesDir = path.join(currentDir, "../../templates");
const imagesPath = path.join(templatesDir, "images.js");
Expand Down
Loading
Loading