opennextjs-azure 0.1.1

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.
Files changed (32) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +194 -0
  3. package/dist/adapters/converters/azure-http.d.mts +22 -0
  4. package/dist/adapters/converters/azure-http.d.ts +22 -0
  5. package/dist/adapters/converters/azure-http.js +97 -0
  6. package/dist/adapters/wrappers/azure-functions.d.mts +10 -0
  7. package/dist/adapters/wrappers/azure-functions.d.ts +10 -0
  8. package/dist/adapters/wrappers/azure-functions.js +102 -0
  9. package/dist/cli/index.d.mts +2 -0
  10. package/dist/cli/index.d.ts +2 -0
  11. package/dist/cli/index.js +67 -0
  12. package/dist/config/index.d.mts +3 -0
  13. package/dist/config/index.d.ts +3 -0
  14. package/dist/config/index.js +68 -0
  15. package/dist/deploy.js +835 -0
  16. package/dist/index.d.mts +35 -0
  17. package/dist/index.d.ts +35 -0
  18. package/dist/index.js +20 -0
  19. package/dist/infrastructure/main.bicep +241 -0
  20. package/dist/overrides/incrementalCache/azure-blob.d.mts +23 -0
  21. package/dist/overrides/incrementalCache/azure-blob.d.ts +23 -0
  22. package/dist/overrides/incrementalCache/azure-blob.js +89 -0
  23. package/dist/overrides/queue/azure-queue.d.mts +19 -0
  24. package/dist/overrides/queue/azure-queue.d.ts +19 -0
  25. package/dist/overrides/queue/azure-queue.js +39 -0
  26. package/dist/overrides/tagCache/azure-table.d.mts +26 -0
  27. package/dist/overrides/tagCache/azure-table.d.ts +26 -0
  28. package/dist/overrides/tagCache/azure-table.js +104 -0
  29. package/dist/shared/opennextjs-azure.d619537c.d.mts +61 -0
  30. package/dist/shared/opennextjs-azure.d619537c.d.ts +61 -0
  31. package/infrastructure/main.bicep +241 -0
  32. package/package.json +99 -0
@@ -0,0 +1,35 @@
1
+ export { A as AzureConfig, a as AzureDeploymentTarget, d as defineAzureConfig } from './shared/opennextjs-azure.d619537c.mjs';
2
+ export { default as azureBlobCache } from './overrides/incrementalCache/azure-blob.mjs';
3
+ export { default as azureTableTagCache } from './overrides/tagCache/azure-table.mjs';
4
+ export { default as azureQueueRevalidation } from './overrides/queue/azure-queue.mjs';
5
+ export { default as azureFunctionsWrapper } from './adapters/wrappers/azure-functions.mjs';
6
+ export { default as azureHttpConverter } from './adapters/converters/azure-http.mjs';
7
+ import '@opennextjs/aws/types/open-next.js';
8
+ import '@opennextjs/aws/types/overrides.js';
9
+ import '@azure/functions';
10
+
11
+ interface ScaffoldOptions {
12
+ typescript?: boolean;
13
+ tailwind?: boolean;
14
+ eslint?: boolean;
15
+ srcDir?: boolean;
16
+ appRouter?: boolean;
17
+ importAlias?: string;
18
+ packageManager?: "npm" | "yarn" | "pnpm" | "bun";
19
+ }
20
+
21
+ declare function init(options?: ScaffoldOptions & {
22
+ scaffold?: boolean;
23
+ }): Promise<void>;
24
+
25
+ declare function build(configPath?: string): Promise<void>;
26
+
27
+ declare function deploy(options: {
28
+ appName?: string;
29
+ resourceGroup?: string;
30
+ location?: string;
31
+ environment?: "dev" | "staging" | "prod";
32
+ skipInfrastructure?: boolean;
33
+ }): Promise<void>;
34
+
35
+ export { build, deploy, init };
@@ -0,0 +1,35 @@
1
+ export { A as AzureConfig, a as AzureDeploymentTarget, d as defineAzureConfig } from './shared/opennextjs-azure.d619537c.js';
2
+ export { default as azureBlobCache } from './overrides/incrementalCache/azure-blob.js';
3
+ export { default as azureTableTagCache } from './overrides/tagCache/azure-table.js';
4
+ export { default as azureQueueRevalidation } from './overrides/queue/azure-queue.js';
5
+ export { default as azureFunctionsWrapper } from './adapters/wrappers/azure-functions.js';
6
+ export { default as azureHttpConverter } from './adapters/converters/azure-http.js';
7
+ import '@opennextjs/aws/types/open-next.js';
8
+ import '@opennextjs/aws/types/overrides.js';
9
+ import '@azure/functions';
10
+
11
+ interface ScaffoldOptions {
12
+ typescript?: boolean;
13
+ tailwind?: boolean;
14
+ eslint?: boolean;
15
+ srcDir?: boolean;
16
+ appRouter?: boolean;
17
+ importAlias?: string;
18
+ packageManager?: "npm" | "yarn" | "pnpm" | "bun";
19
+ }
20
+
21
+ declare function init(options?: ScaffoldOptions & {
22
+ scaffold?: boolean;
23
+ }): Promise<void>;
24
+
25
+ declare function build(configPath?: string): Promise<void>;
26
+
27
+ declare function deploy(options: {
28
+ appName?: string;
29
+ resourceGroup?: string;
30
+ location?: string;
31
+ environment?: "dev" | "staging" | "prod";
32
+ skipInfrastructure?: boolean;
33
+ }): Promise<void>;
34
+
35
+ export { build, deploy, init };
package/dist/index.js ADDED
@@ -0,0 +1,20 @@
1
+ export { defineAzureConfig } from './config/index.js';
2
+ export { b as build, d as deploy, i as init } from './deploy.js';
3
+ export { default as azureBlobCache } from './overrides/incrementalCache/azure-blob.js';
4
+ export { default as azureTableTagCache } from './overrides/tagCache/azure-table.js';
5
+ export { default as azureQueueRevalidation } from './overrides/queue/azure-queue.js';
6
+ export { default as azureFunctionsWrapper } from './adapters/wrappers/azure-functions.js';
7
+ export { default as azureHttpConverter } from './adapters/converters/azure-http.js';
8
+ import 'node:fs/promises';
9
+ import 'node:path';
10
+ import 'node:url';
11
+ import 'node:child_process';
12
+ import 'node:util';
13
+ import '@opennextjs/aws/build.js';
14
+ import 'node:fs';
15
+ import 'node:readline';
16
+ import '@azure/storage-blob';
17
+ import '@azure/data-tables';
18
+ import '@azure/storage-queue';
19
+ import 'node:stream';
20
+ import 'node:buffer';
@@ -0,0 +1,241 @@
1
+ // OpenNext Azure - Main Infrastructure Template
2
+ // This creates all resources needed to run a Next.js app on Azure
3
+ //
4
+ // DO NOT EDIT THIS FILE, IT IS AUTO-GENERATED.
5
+
6
+ @description('Name of the application (used as prefix for all resources)')
7
+ param appName string
8
+
9
+ @description('Location for all resources')
10
+ param location string = resourceGroup().location
11
+
12
+ @description('Environment (dev, staging, prod)')
13
+ @allowed(['dev', 'staging', 'prod'])
14
+ param environment string = 'dev'
15
+
16
+ @description('Node.js version for Functions')
17
+ @allowed(['20', '22'])
18
+ param nodeVersion string = '20'
19
+
20
+ @description('Enable Application Insights for monitoring and logging')
21
+ param enableApplicationInsights bool = false
22
+
23
+ // Variables
24
+ var uniqueSuffix = uniqueString(resourceGroup().id)
25
+ var sanitizedAppName = replace(toLower(appName), '-', '')
26
+ var maxAppNameLength = 24 - length(uniqueSuffix)
27
+ var truncatedAppName = length(sanitizedAppName) > maxAppNameLength
28
+ ? substring(sanitizedAppName, 0, maxAppNameLength)
29
+ : sanitizedAppName
30
+ var storageAccountName = '${truncatedAppName}${uniqueSuffix}'
31
+ var functionAppName = '${appName}-func-${environment}'
32
+ var appServicePlanName = '${appName}-plan-${environment}'
33
+ var containerName = 'nextjs-cache'
34
+ var tableName = 'nextjstags'
35
+ var queueName = 'nextjsrevalidation'
36
+ var applicationInsightsName = '${appName}-insights-${environment}'
37
+
38
+ // Application Insights (optional)
39
+ resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = if (enableApplicationInsights) {
40
+ name: applicationInsightsName
41
+ location: location
42
+ kind: 'web'
43
+ properties: {
44
+ Application_Type: 'web'
45
+ Request_Source: 'rest'
46
+ RetentionInDays: environment == 'prod' ? 90 : 30
47
+ publicNetworkAccessForIngestion: 'Enabled'
48
+ publicNetworkAccessForQuery: 'Enabled'
49
+ }
50
+ }
51
+
52
+ // Storage Account (for cache, static assets, and function storage)
53
+ resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
54
+ name: storageAccountName
55
+ location: location
56
+ sku: {
57
+ name: environment == 'prod' ? 'Standard_GRS' : 'Standard_LRS'
58
+ }
59
+ kind: 'StorageV2'
60
+ properties: {
61
+ minimumTlsVersion: 'TLS1_2'
62
+ supportsHttpsTrafficOnly: true
63
+ allowBlobPublicAccess: true
64
+ accessTier: 'Hot'
65
+ }
66
+
67
+ // Blob service for cache and static assets
68
+ resource blobService 'blobServices' = {
69
+ name: 'default'
70
+ properties: {
71
+ cors: {
72
+ corsRules: [
73
+ {
74
+ allowedOrigins: ['*']
75
+ allowedMethods: ['GET', 'HEAD']
76
+ maxAgeInSeconds: 3600
77
+ exposedHeaders: ['*']
78
+ allowedHeaders: ['*']
79
+ }
80
+ ]
81
+ }
82
+ }
83
+
84
+ // Container for Next.js cache
85
+ resource cacheContainer 'containers' = {
86
+ name: containerName
87
+ properties: {
88
+ publicAccess: 'None'
89
+ }
90
+ }
91
+
92
+ // Container for static assets (public CDN access)
93
+ resource assetsContainer 'containers' = {
94
+ name: 'assets'
95
+ properties: {
96
+ publicAccess: 'Blob'
97
+ }
98
+ }
99
+ }
100
+
101
+ // Table service for tag cache
102
+ resource tableService 'tableServices' = {
103
+ name: 'default'
104
+
105
+ resource tagTable 'tables' = {
106
+ name: tableName
107
+ }
108
+ }
109
+
110
+ // Queue service for ISR revalidation (revalidateTag/revalidatePath)
111
+ resource queueService 'queueServices' = {
112
+ name: 'default'
113
+
114
+ resource revalidationQueue 'queues' = {
115
+ name: queueName
116
+ }
117
+ }
118
+ }
119
+
120
+ // App Service Plan (Consumption or Premium based on environment)
121
+ resource appServicePlan 'Microsoft.Web/serverfarms@2023-01-01' = {
122
+ name: appServicePlanName
123
+ location: location
124
+ sku: {
125
+ name: environment == 'prod' ? 'EP1' : 'Y1' // EP1 = Premium, Y1 = Consumption
126
+ tier: environment == 'prod' ? 'ElasticPremium' : 'Dynamic'
127
+ }
128
+ kind: 'functionapp'
129
+ properties: {
130
+ reserved: true // Linux
131
+ }
132
+ }
133
+
134
+ // Function App
135
+ resource functionApp 'Microsoft.Web/sites@2023-01-01' = {
136
+ name: functionAppName
137
+ location: location
138
+ kind: 'functionapp,linux'
139
+ properties: {
140
+ serverFarmId: appServicePlan.id
141
+ siteConfig: {
142
+ linuxFxVersion: 'NODE|${nodeVersion}'
143
+ appSettings: concat([
144
+ {
145
+ name: 'AzureWebJobsStorage'
146
+ value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};AccountKey=${storageAccount.listKeys().keys[0].value};EndpointSuffix=core.windows.net'
147
+ }
148
+ {
149
+ name: 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING'
150
+ value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};AccountKey=${storageAccount.listKeys().keys[0].value};EndpointSuffix=core.windows.net'
151
+ }
152
+ {
153
+ name: 'WEBSITE_CONTENTSHARE'
154
+ value: toLower(functionAppName)
155
+ }
156
+ {
157
+ name: 'FUNCTIONS_EXTENSION_VERSION'
158
+ value: '~4'
159
+ }
160
+ {
161
+ name: 'FUNCTIONS_WORKER_RUNTIME'
162
+ value: 'node'
163
+ }
164
+ {
165
+ name: 'WEBSITE_NODE_DEFAULT_VERSION'
166
+ value: '~${nodeVersion}'
167
+ }
168
+ {
169
+ name: 'WEBSITE_RUN_FROM_PACKAGE'
170
+ value: '1'
171
+ }
172
+ {
173
+ name: 'AzureWebJobsDisableHomepage'
174
+ value: 'true'
175
+ }
176
+ // Next.js / OpenNext environment variables
177
+ {
178
+ name: 'AZURE_STORAGE_CONNECTION_STRING'
179
+ value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};AccountKey=${storageAccount.listKeys().keys[0].value};EndpointSuffix=core.windows.net'
180
+ }
181
+ {
182
+ name: 'AZURE_STORAGE_ACCOUNT_NAME'
183
+ value: storageAccountName
184
+ }
185
+ {
186
+ name: 'AZURE_STORAGE_CONTAINER_NAME'
187
+ value: containerName
188
+ }
189
+ {
190
+ name: 'AZURE_TABLE_NAME'
191
+ value: tableName
192
+ }
193
+ {
194
+ name: 'AZURE_QUEUE_NAME'
195
+ value: queueName
196
+ }
197
+ {
198
+ name: 'NODE_ENV'
199
+ value: 'production'
200
+ }
201
+ ], enableApplicationInsights ? [
202
+ {
203
+ name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
204
+ value: applicationInsights.properties.ConnectionString
205
+ }
206
+ {
207
+ name: 'ApplicationInsightsAgent_EXTENSION_VERSION'
208
+ value: '~3'
209
+ }
210
+ ] : [])
211
+
212
+ ftpsState: 'Disabled'
213
+ minTlsVersion: '1.2'
214
+ cors: {
215
+ allowedOrigins: ['*']
216
+ }
217
+ }
218
+ httpsOnly: true
219
+ }
220
+ }
221
+
222
+ // Outputs
223
+ output functionAppName string = functionApp.name
224
+ output functionAppUrl string = 'https://${functionApp.properties.defaultHostName}'
225
+ output storageAccountName string = storageAccount.name
226
+ output assetsUrl string = 'https://${storageAccount.name}.blob.${az.environment().suffixes.storage}/assets'
227
+ output resourceGroupName string = resourceGroup().name
228
+ output applicationInsightsName string = enableApplicationInsights ? applicationInsights.name : ''
229
+ output applicationInsightsInstrumentationKey string = enableApplicationInsights ? applicationInsights.properties.InstrumentationKey : ''
230
+
231
+ output deploymentInfo object = {
232
+ functionApp: functionAppName
233
+ storageAccount: storageAccountName
234
+ containerName: containerName
235
+ tableName: tableName
236
+ queueName: queueName
237
+ assetsUrl: 'https://${storageAccount.name}.blob.${az.environment().suffixes.storage}/assets'
238
+ functionUrl: 'https://${functionApp.properties.defaultHostName}'
239
+ appUrl: 'https://${functionApp.properties.defaultHostName}'
240
+ applicationInsights: enableApplicationInsights ? applicationInsightsName : null
241
+ }
@@ -0,0 +1,23 @@
1
+ import { IncrementalCache, CacheEntryType, WithLastModified, CacheValue } from '@opennextjs/aws/types/overrides.js';
2
+
3
+ /**
4
+ * Azure Blob Storage implementation of IncrementalCache.
5
+ *
6
+ * Stores Next.js ISR cache entries in Azure Blob Storage.
7
+ * Compatible with the S3 cache interface from @opennextjs/aws.
8
+ */
9
+ declare class AzureBlobIncrementalCache implements IncrementalCache {
10
+ name: string;
11
+ private containerClient;
12
+ constructor();
13
+ /**
14
+ * Builds the blob key path, mimicking S3 structure:
15
+ * [prefix]/[__fetch]/[buildId]/[key].[extension]
16
+ */
17
+ private buildBlobKey;
18
+ get<CacheType extends CacheEntryType = "cache">(key: string, cacheType?: CacheType): Promise<WithLastModified<CacheValue<CacheType>> | null>;
19
+ set<CacheType extends CacheEntryType = "cache">(key: string, value: CacheValue<CacheType>, cacheType?: CacheType): Promise<void>;
20
+ delete(key: string): Promise<void>;
21
+ }
22
+
23
+ export { AzureBlobIncrementalCache as default };
@@ -0,0 +1,23 @@
1
+ import { IncrementalCache, CacheEntryType, WithLastModified, CacheValue } from '@opennextjs/aws/types/overrides.js';
2
+
3
+ /**
4
+ * Azure Blob Storage implementation of IncrementalCache.
5
+ *
6
+ * Stores Next.js ISR cache entries in Azure Blob Storage.
7
+ * Compatible with the S3 cache interface from @opennextjs/aws.
8
+ */
9
+ declare class AzureBlobIncrementalCache implements IncrementalCache {
10
+ name: string;
11
+ private containerClient;
12
+ constructor();
13
+ /**
14
+ * Builds the blob key path, mimicking S3 structure:
15
+ * [prefix]/[__fetch]/[buildId]/[key].[extension]
16
+ */
17
+ private buildBlobKey;
18
+ get<CacheType extends CacheEntryType = "cache">(key: string, cacheType?: CacheType): Promise<WithLastModified<CacheValue<CacheType>> | null>;
19
+ set<CacheType extends CacheEntryType = "cache">(key: string, value: CacheValue<CacheType>, cacheType?: CacheType): Promise<void>;
20
+ delete(key: string): Promise<void>;
21
+ }
22
+
23
+ export { AzureBlobIncrementalCache as default };
@@ -0,0 +1,89 @@
1
+ import { BlobServiceClient } from '@azure/storage-blob';
2
+ import { getAzureConfig } from '../../config/index.js';
3
+
4
+ class AzureBlobIncrementalCache {
5
+ name = "azure-blob";
6
+ containerClient;
7
+ constructor() {
8
+ const { storage } = getAzureConfig();
9
+ const connectionString = storage.connectionString;
10
+ const accountName = storage.accountName;
11
+ const accountKey = storage.accountKey;
12
+ if (connectionString) {
13
+ const blobServiceClient = BlobServiceClient.fromConnectionString(connectionString);
14
+ this.containerClient = blobServiceClient.getContainerClient(storage.containerName || "nextjs-cache");
15
+ } else if (accountName && accountKey) {
16
+ const blobServiceClient = new BlobServiceClient(`https://${accountName}.blob.core.windows.net`, {
17
+ accountName,
18
+ accountKey
19
+ });
20
+ this.containerClient = blobServiceClient.getContainerClient(storage.containerName || "nextjs-cache");
21
+ }
22
+ }
23
+ /**
24
+ * Builds the blob key path, mimicking S3 structure:
25
+ * [prefix]/[__fetch]/[buildId]/[key].[extension]
26
+ */
27
+ buildBlobKey(key, cacheType = "cache") {
28
+ const { storage } = getAzureConfig();
29
+ const { NEXT_BUILD_ID } = process.env;
30
+ const prefix = storage.containerName || "";
31
+ const type = cacheType === "fetch" ? "__fetch" : "";
32
+ return [prefix, type, NEXT_BUILD_ID, cacheType === "fetch" ? key : `${key}.${cacheType}`].filter(Boolean).join("/");
33
+ }
34
+ async get(key, cacheType) {
35
+ try {
36
+ const blobKey = this.buildBlobKey(key, cacheType);
37
+ const blobClient = this.containerClient.getBlobClient(blobKey);
38
+ const downloadResponse = await blobClient.download();
39
+ if (!downloadResponse.readableStreamBody) {
40
+ return null;
41
+ }
42
+ const chunks = [];
43
+ for await (const chunk of downloadResponse.readableStreamBody) {
44
+ chunks.push(Buffer.from(chunk));
45
+ }
46
+ const content = Buffer.concat(chunks).toString("utf8");
47
+ const value = JSON.parse(content);
48
+ return {
49
+ value,
50
+ lastModified: downloadResponse.lastModified?.getTime()
51
+ };
52
+ } catch (error) {
53
+ if (error.statusCode === 404) {
54
+ return null;
55
+ }
56
+ process.stderr.write(`Failed to get from Azure Blob cache: ${error}
57
+ `);
58
+ return null;
59
+ }
60
+ }
61
+ async set(key, value, cacheType) {
62
+ try {
63
+ const blobKey = this.buildBlobKey(key, cacheType);
64
+ const blobClient = this.containerClient.getBlockBlobClient(blobKey);
65
+ const content = JSON.stringify(value);
66
+ await blobClient.upload(content, content.length, {
67
+ blobHTTPHeaders: {
68
+ blobContentType: "application/json"
69
+ }
70
+ });
71
+ } catch (error) {
72
+ process.stderr.write(`Failed to set Azure Blob cache: ${error}
73
+ `);
74
+ throw error;
75
+ }
76
+ }
77
+ async delete(key) {
78
+ try {
79
+ const blobKey = this.buildBlobKey(key, "cache");
80
+ const blobClient = this.containerClient.getBlobClient(blobKey);
81
+ await blobClient.deleteIfExists();
82
+ } catch (error) {
83
+ process.stderr.write(`Failed to delete from Azure Blob cache: ${error}
84
+ `);
85
+ }
86
+ }
87
+ }
88
+
89
+ export { AzureBlobIncrementalCache as default };
@@ -0,0 +1,19 @@
1
+ import { Queue, QueueMessage } from '@opennextjs/aws/types/overrides.js';
2
+
3
+ /**
4
+ * Azure Queue Storage implementation of the revalidation queue.
5
+ *
6
+ * Handles on-demand ISR revalidation triggered by:
7
+ * - revalidateTag('product')
8
+ * - revalidatePath('/products/123')
9
+ *
10
+ * The queue receives revalidation messages and triggers re-renders.
11
+ */
12
+ declare class AzureQueueRevalidation implements Queue {
13
+ name: string;
14
+ private queueClient;
15
+ constructor();
16
+ send(message: QueueMessage): Promise<void>;
17
+ }
18
+
19
+ export { AzureQueueRevalidation as default };
@@ -0,0 +1,19 @@
1
+ import { Queue, QueueMessage } from '@opennextjs/aws/types/overrides.js';
2
+
3
+ /**
4
+ * Azure Queue Storage implementation of the revalidation queue.
5
+ *
6
+ * Handles on-demand ISR revalidation triggered by:
7
+ * - revalidateTag('product')
8
+ * - revalidatePath('/products/123')
9
+ *
10
+ * The queue receives revalidation messages and triggers re-renders.
11
+ */
12
+ declare class AzureQueueRevalidation implements Queue {
13
+ name: string;
14
+ private queueClient;
15
+ constructor();
16
+ send(message: QueueMessage): Promise<void>;
17
+ }
18
+
19
+ export { AzureQueueRevalidation as default };
@@ -0,0 +1,39 @@
1
+ import { QueueServiceClient } from '@azure/storage-queue';
2
+ import { getAzureConfig } from '../../config/index.js';
3
+
4
+ class AzureQueueRevalidation {
5
+ name = "azure-queue";
6
+ queueClient;
7
+ constructor() {
8
+ const { storage } = getAzureConfig();
9
+ const connectionString = storage.connectionString;
10
+ const queueName = storage.queueName || "nextjsrevalidation";
11
+ if (connectionString) {
12
+ const queueServiceClient = QueueServiceClient.fromConnectionString(connectionString);
13
+ this.queueClient = queueServiceClient.getQueueClient(queueName);
14
+ }
15
+ }
16
+ async send(message) {
17
+ if (!this.queueClient) {
18
+ process.stderr.write("Azure Queue not configured. Skipping revalidation message.\n");
19
+ return;
20
+ }
21
+ try {
22
+ const messageContent = JSON.stringify({
23
+ host: message.MessageBody.host,
24
+ url: message.MessageBody.url,
25
+ lastModified: message.MessageBody.lastModified,
26
+ eTag: message.MessageBody.eTag,
27
+ deduplicationId: message.MessageDeduplicationId,
28
+ groupId: message.MessageGroupId
29
+ });
30
+ await this.queueClient.sendMessage(Buffer.from(messageContent).toString("base64"));
31
+ } catch (error) {
32
+ process.stderr.write(`Failed to send revalidation message: ${error}
33
+ `);
34
+ throw error;
35
+ }
36
+ }
37
+ }
38
+
39
+ export { AzureQueueRevalidation as default };
@@ -0,0 +1,26 @@
1
+ import { OriginalTagCache, OriginalTagCacheWriteInput } from '@opennextjs/aws/types/overrides.js';
2
+
3
+ /**
4
+ * Azure Table Storage implementation of TagCache.
5
+ *
6
+ * Stores tag-to-path mappings for Next.js revalidateTag/revalidatePath.
7
+ * Uses the "original" mode which requires pre-population but offers fast reads.
8
+ *
9
+ * Schema:
10
+ * - PartitionKey: tag (e.g., "buildId/product")
11
+ * - RowKey: path (e.g., "buildId/products/123")
12
+ * - revalidatedAt: timestamp
13
+ */
14
+ declare class AzureTableTagCache implements OriginalTagCache {
15
+ mode: "original";
16
+ name: string;
17
+ private tableClient;
18
+ constructor();
19
+ private buildKey;
20
+ getByTag(tag: string): Promise<string[]>;
21
+ getByPath(path: string): Promise<string[]>;
22
+ getLastModified(path: string, lastModified?: number): Promise<number>;
23
+ writeTags(tags: OriginalTagCacheWriteInput[]): Promise<void>;
24
+ }
25
+
26
+ export { AzureTableTagCache as default };
@@ -0,0 +1,26 @@
1
+ import { OriginalTagCache, OriginalTagCacheWriteInput } from '@opennextjs/aws/types/overrides.js';
2
+
3
+ /**
4
+ * Azure Table Storage implementation of TagCache.
5
+ *
6
+ * Stores tag-to-path mappings for Next.js revalidateTag/revalidatePath.
7
+ * Uses the "original" mode which requires pre-population but offers fast reads.
8
+ *
9
+ * Schema:
10
+ * - PartitionKey: tag (e.g., "buildId/product")
11
+ * - RowKey: path (e.g., "buildId/products/123")
12
+ * - revalidatedAt: timestamp
13
+ */
14
+ declare class AzureTableTagCache implements OriginalTagCache {
15
+ mode: "original";
16
+ name: string;
17
+ private tableClient;
18
+ constructor();
19
+ private buildKey;
20
+ getByTag(tag: string): Promise<string[]>;
21
+ getByPath(path: string): Promise<string[]>;
22
+ getLastModified(path: string, lastModified?: number): Promise<number>;
23
+ writeTags(tags: OriginalTagCacheWriteInput[]): Promise<void>;
24
+ }
25
+
26
+ export { AzureTableTagCache as default };