opennextjs-azure 0.1.2 → 0.1.4
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.
- package/README.md +8 -1
- package/dist/adapters/image-optimization.d.mts +20 -0
- package/dist/adapters/image-optimization.d.ts +20 -0
- package/dist/adapters/image-optimization.js +11 -0
- package/dist/adapters/wrappers/azure-functions.js +2 -2
- package/dist/adapters/wrappers/azure-image-optimization.d.mts +10 -0
- package/dist/adapters/wrappers/azure-image-optimization.d.ts +10 -0
- package/dist/adapters/wrappers/azure-image-optimization.js +151 -0
- package/dist/cli/index.js +39 -6
- package/dist/config/index.d.mts +1 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.js +12 -0
- package/dist/deploy.js +179 -58
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/infrastructure/main.bicep +12 -0
- package/dist/overrides/imageLoader/azure-blob.d.mts +5 -0
- package/dist/overrides/imageLoader/azure-blob.d.ts +5 -0
- package/dist/overrides/imageLoader/azure-blob.js +37 -0
- package/dist/overrides/imageOptimization/azure-cached.d.mts +6 -0
- package/dist/overrides/imageOptimization/azure-cached.d.ts +6 -0
- package/dist/overrides/imageOptimization/azure-cached.js +115 -0
- package/dist/shared/{opennextjs-azure.d619537c.d.mts → opennextjs-azure.279bd73d.d.mts} +3 -1
- package/dist/shared/{opennextjs-azure.d619537c.d.ts → opennextjs-azure.279bd73d.d.ts} +3 -1
- package/infrastructure/main.bicep +12 -0
- package/package.json +90 -91
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
[](https://www.npmjs.com/package/opennextjs-azure)
|
|
7
7
|
[](https://opensource.org/licenses/MIT)
|
|
8
8
|
|
|
9
|
-
Built on the [OpenNext](https://opennext.js.org) framework, this adapter brings native Next.js support to Azure Functions.
|
|
9
|
+
Built on the [OpenNext](https://opennext.js.org) framework, this adapter brings native Next.js support to Azure Functions with a Vercel-grade developer experience.
|
|
10
10
|
|
|
11
11
|

|
|
12
12
|
|
|
@@ -23,6 +23,7 @@ Azure Functions is Microsoft's serverless compute platform—comparable to AWS L
|
|
|
23
23
|
| Next.js Feature | Azure Implementation |
|
|
24
24
|
| -------------------------------------- | --------------------------------------------------------------- |
|
|
25
25
|
| Incremental Static Regeneration | Azure Blob Storage |
|
|
26
|
+
| Image Optimization | Azure Blob Storage with automatic caching |
|
|
26
27
|
| Streaming SSR | Azure Functions with Node.js streams |
|
|
27
28
|
| `revalidateTag()` / `revalidatePath()` | Azure Table Storage + Queue Storage |
|
|
28
29
|
| Fetch caching | Azure Blob Storage with build ID namespacing |
|
|
@@ -139,6 +140,12 @@ Converts between Azure Functions HTTP triggers and Next.js InternalEvent/Interna
|
|
|
139
140
|
- **Tag Cache:** Azure Table Storage maps tags → paths for `revalidateTag()`
|
|
140
141
|
- **Revalidation Queue:** Azure Queue Storage triggers on-demand regeneration
|
|
141
142
|
|
|
143
|
+
**Image Optimization:**
|
|
144
|
+
|
|
145
|
+
- **Source Images:** Loaded from `assets` blob container
|
|
146
|
+
- **Optimized Cache:** Processed images cached in `optimized-images` container to avoid re-processing
|
|
147
|
+
- **Processing:** Processing is done with the `sharp` library, which gets added for you during deployment.
|
|
148
|
+
|
|
142
149
|
**Build Process:**
|
|
143
150
|
Uses OpenNext's AWS build with Azure-specific overrides, then adds Azure Functions metadata (`host.json`, `function.json`) for v3 programming model.
|
|
144
151
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { InternalEvent, InternalResult } from '@opennextjs/aws/types/open-next.js';
|
|
2
|
+
import { OpenNextHandler, OpenNextHandlerOptions } from '@opennextjs/aws/types/overrides.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Azure Image Optimization Handler
|
|
6
|
+
*
|
|
7
|
+
* Wraps OpenNext's default image optimization handler with Azure Blob caching.
|
|
8
|
+
*
|
|
9
|
+
* When AZURE_IMAGE_OPTIMIZATION_CACHE=true:
|
|
10
|
+
* - First request: Loads from "assets", processes, caches in "optimized-images", returns
|
|
11
|
+
* - Subsequent requests: Returns from "optimized-images" cache (no processing)
|
|
12
|
+
*
|
|
13
|
+
* When AZURE_IMAGE_OPTIMIZATION_CACHE=false:
|
|
14
|
+
* - Every request processes the image (no caching)
|
|
15
|
+
*/
|
|
16
|
+
declare function createImageOptimizationHandler(): Promise<OpenNextHandler<InternalEvent, InternalResult>>;
|
|
17
|
+
declare const handler: OpenNextHandler<InternalEvent, InternalResult>;
|
|
18
|
+
declare function defaultHandler(event: InternalEvent, options?: OpenNextHandlerOptions): Promise<InternalResult>;
|
|
19
|
+
|
|
20
|
+
export { createImageOptimizationHandler, defaultHandler, handler };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { InternalEvent, InternalResult } from '@opennextjs/aws/types/open-next.js';
|
|
2
|
+
import { OpenNextHandler, OpenNextHandlerOptions } from '@opennextjs/aws/types/overrides.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Azure Image Optimization Handler
|
|
6
|
+
*
|
|
7
|
+
* Wraps OpenNext's default image optimization handler with Azure Blob caching.
|
|
8
|
+
*
|
|
9
|
+
* When AZURE_IMAGE_OPTIMIZATION_CACHE=true:
|
|
10
|
+
* - First request: Loads from "assets", processes, caches in "optimized-images", returns
|
|
11
|
+
* - Subsequent requests: Returns from "optimized-images" cache (no processing)
|
|
12
|
+
*
|
|
13
|
+
* When AZURE_IMAGE_OPTIMIZATION_CACHE=false:
|
|
14
|
+
* - Every request processes the image (no caching)
|
|
15
|
+
*/
|
|
16
|
+
declare function createImageOptimizationHandler(): Promise<OpenNextHandler<InternalEvent, InternalResult>>;
|
|
17
|
+
declare const handler: OpenNextHandler<InternalEvent, InternalResult>;
|
|
18
|
+
declare function defaultHandler(event: InternalEvent, options?: OpenNextHandlerOptions): Promise<InternalResult>;
|
|
19
|
+
|
|
20
|
+
export { createImageOptimizationHandler, defaultHandler, handler };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
async function createImageOptimizationHandler() {
|
|
2
|
+
const { defaultHandler: defaultHandler2 } = await import('@opennextjs/aws/adapters/image-optimization-adapter.js');
|
|
3
|
+
const { createCachedImageOptimizationHandler } = await import('../overrides/imageOptimization/azure-cached.js');
|
|
4
|
+
return createCachedImageOptimizationHandler(defaultHandler2);
|
|
5
|
+
}
|
|
6
|
+
const handler = await createImageOptimizationHandler();
|
|
7
|
+
async function defaultHandler(event, options) {
|
|
8
|
+
return handler(event, options);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export { createImageOptimizationHandler, defaultHandler, handler };
|
|
@@ -3,7 +3,6 @@ import { Writable } from 'node:stream';
|
|
|
3
3
|
const NULL_BODY_STATUSES = /* @__PURE__ */ new Set([101, 204, 205, 304]);
|
|
4
4
|
const STATIC_ASSET_PATTERNS = [
|
|
5
5
|
/^\/_next\/static\//,
|
|
6
|
-
/^\/_next\/data\//,
|
|
7
6
|
/^\/favicon\.ico$/,
|
|
8
7
|
/^\/robots\.txt$/,
|
|
9
8
|
/^\/sitemap\.xml$/,
|
|
@@ -17,11 +16,12 @@ const handler = async (handler2, converter) => async (context, request) => {
|
|
|
17
16
|
const internalEvent = await converter.convertFrom(request);
|
|
18
17
|
if (isStaticAssetRequest(internalEvent.rawPath)) {
|
|
19
18
|
const blobUrl = `https://${process.env.AZURE_STORAGE_ACCOUNT_NAME}.blob.core.windows.net/assets${internalEvent.rawPath}`;
|
|
19
|
+
const cacheControl = internalEvent.rawPath.startsWith("/_next/static/") ? "public, max-age=31536000, immutable" : "public, max-age=0, must-revalidate";
|
|
20
20
|
context.res = {
|
|
21
21
|
status: 301,
|
|
22
22
|
headers: {
|
|
23
23
|
Location: blobUrl,
|
|
24
|
-
"Cache-Control":
|
|
24
|
+
"Cache-Control": cacheControl
|
|
25
25
|
}
|
|
26
26
|
};
|
|
27
27
|
return;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { InternalEvent, InternalResult } from '@opennextjs/aws/types/open-next.js';
|
|
2
|
+
import { WrapperHandler } from '@opennextjs/aws/types/overrides.js';
|
|
3
|
+
|
|
4
|
+
declare const _default: {
|
|
5
|
+
name: string;
|
|
6
|
+
wrapper: WrapperHandler<InternalEvent, InternalResult>;
|
|
7
|
+
supportStreaming: boolean;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export { _default as default };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { InternalEvent, InternalResult } from '@opennextjs/aws/types/open-next.js';
|
|
2
|
+
import { WrapperHandler } from '@opennextjs/aws/types/overrides.js';
|
|
3
|
+
|
|
4
|
+
declare const _default: {
|
|
5
|
+
name: string;
|
|
6
|
+
wrapper: WrapperHandler<InternalEvent, InternalResult>;
|
|
7
|
+
supportStreaming: boolean;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export { _default as default };
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { Writable } from 'node:stream';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { BlobServiceClient } from '@azure/storage-blob';
|
|
4
|
+
|
|
5
|
+
const NULL_BODY_STATUSES = /* @__PURE__ */ new Set([101, 204, 205, 304]);
|
|
6
|
+
const { AZURE_STORAGE_CONNECTION_STRING, AZURE_STORAGE_ACCOUNT_NAME } = process.env;
|
|
7
|
+
const CACHE_CONTAINER = "optimized-images";
|
|
8
|
+
function getBlobClient(key) {
|
|
9
|
+
if (!AZURE_STORAGE_CONNECTION_STRING && !AZURE_STORAGE_ACCOUNT_NAME) {
|
|
10
|
+
throw new Error("Azure Storage connection string or account name must be defined");
|
|
11
|
+
}
|
|
12
|
+
const blobServiceClient = AZURE_STORAGE_CONNECTION_STRING ? BlobServiceClient.fromConnectionString(AZURE_STORAGE_CONNECTION_STRING) : new BlobServiceClient(`https://${AZURE_STORAGE_ACCOUNT_NAME}.blob.core.windows.net`);
|
|
13
|
+
const containerClient = blobServiceClient.getContainerClient(CACHE_CONTAINER);
|
|
14
|
+
return containerClient.getBlockBlobClient(key);
|
|
15
|
+
}
|
|
16
|
+
function computeCacheKey(event) {
|
|
17
|
+
const { query } = event;
|
|
18
|
+
const url = Array.isArray(query?.url) ? query.url[0] : query?.url || "";
|
|
19
|
+
const width = Array.isArray(query?.w) ? query.w[0] : query?.w || "0";
|
|
20
|
+
const quality = Array.isArray(query?.q) ? query.q[0] : query?.q || "75";
|
|
21
|
+
const hash = createHash("sha256").update(url).digest("hex").substring(0, 16);
|
|
22
|
+
return `${hash}/w${width}_q${quality}.cache`;
|
|
23
|
+
}
|
|
24
|
+
async function getCachedImage(cacheKey) {
|
|
25
|
+
try {
|
|
26
|
+
const blobClient = getBlobClient(cacheKey);
|
|
27
|
+
const exists = await blobClient.exists();
|
|
28
|
+
if (!exists) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const downloadResponse = await blobClient.download();
|
|
32
|
+
if (!downloadResponse.readableStreamBody) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
const chunks = [];
|
|
36
|
+
for await (const chunk of downloadResponse.readableStreamBody) {
|
|
37
|
+
chunks.push(Buffer.from(chunk));
|
|
38
|
+
}
|
|
39
|
+
return Buffer.concat(chunks);
|
|
40
|
+
} catch (error) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async function setCachedImage(cacheKey, buffer, contentType) {
|
|
45
|
+
try {
|
|
46
|
+
const blobClient = getBlobClient(cacheKey);
|
|
47
|
+
await blobClient.upload(buffer, buffer.length, {
|
|
48
|
+
blobHTTPHeaders: {
|
|
49
|
+
blobContentType: contentType,
|
|
50
|
+
blobCacheControl: "public,max-age=31536000,immutable"
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
process.stderr.write(`[ImageCache] \u2713 Cached ${buffer.length} bytes
|
|
54
|
+
`);
|
|
55
|
+
} catch (error) {
|
|
56
|
+
process.stderr.write(`[ImageCache] \u2717 Cache failed: ${error.message}
|
|
57
|
+
`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const handler = async (handler2, converter) => async (context, request) => {
|
|
61
|
+
try {
|
|
62
|
+
const internalEvent = await converter.convertFrom(request);
|
|
63
|
+
const cacheKey = computeCacheKey(internalEvent);
|
|
64
|
+
const cachedBuffer = await getCachedImage(cacheKey);
|
|
65
|
+
if (cachedBuffer) {
|
|
66
|
+
process.stderr.write(`[ImageCache] \u2713 Cache HIT
|
|
67
|
+
`);
|
|
68
|
+
context.res = {
|
|
69
|
+
status: 200,
|
|
70
|
+
headers: {
|
|
71
|
+
"Content-Type": "image/webp",
|
|
72
|
+
"Cache-Control": "public,max-age=31536000,immutable"
|
|
73
|
+
},
|
|
74
|
+
body: cachedBuffer
|
|
75
|
+
};
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
process.stderr.write(`[ImageCache] Cache MISS - processing...
|
|
79
|
+
`);
|
|
80
|
+
let streamFinished = null;
|
|
81
|
+
let resolveStream = null;
|
|
82
|
+
let processedBuffer = null;
|
|
83
|
+
let responseContentType = "image/webp";
|
|
84
|
+
const streamCreator = {
|
|
85
|
+
writeHeaders(prelude) {
|
|
86
|
+
const { statusCode, cookies, headers } = prelude;
|
|
87
|
+
responseContentType = headers["Content-Type"] || headers["content-type"] || "image/webp";
|
|
88
|
+
const responseHeaders = { ...headers };
|
|
89
|
+
if (cookies.length > 0) {
|
|
90
|
+
responseHeaders["set-cookie"] = cookies.join(", ");
|
|
91
|
+
}
|
|
92
|
+
if (NULL_BODY_STATUSES.has(statusCode)) {
|
|
93
|
+
context.res = {
|
|
94
|
+
status: statusCode,
|
|
95
|
+
headers: responseHeaders
|
|
96
|
+
};
|
|
97
|
+
return new Writable({
|
|
98
|
+
write(_chunk, _encoding, callback) {
|
|
99
|
+
callback();
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
streamFinished = new Promise((resolve) => {
|
|
104
|
+
resolveStream = resolve;
|
|
105
|
+
});
|
|
106
|
+
const chunks = [];
|
|
107
|
+
const writable = new Writable({
|
|
108
|
+
write(chunk, _encoding, callback) {
|
|
109
|
+
chunks.push(Buffer.from(chunk));
|
|
110
|
+
callback();
|
|
111
|
+
},
|
|
112
|
+
final(callback) {
|
|
113
|
+
const body = Buffer.concat(chunks);
|
|
114
|
+
processedBuffer = body;
|
|
115
|
+
context.res = {
|
|
116
|
+
status: statusCode,
|
|
117
|
+
headers: responseHeaders,
|
|
118
|
+
body
|
|
119
|
+
};
|
|
120
|
+
callback();
|
|
121
|
+
resolveStream?.();
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
return writable;
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
await handler2(internalEvent, { streamCreator });
|
|
128
|
+
if (streamFinished) {
|
|
129
|
+
await streamFinished;
|
|
130
|
+
}
|
|
131
|
+
if (processedBuffer && responseContentType) {
|
|
132
|
+
await setCachedImage(cacheKey, processedBuffer, responseContentType);
|
|
133
|
+
}
|
|
134
|
+
} catch (error) {
|
|
135
|
+
console.error("Image optimization error:", error);
|
|
136
|
+
context.res = {
|
|
137
|
+
status: 500,
|
|
138
|
+
headers: {
|
|
139
|
+
"Content-Type": "text/plain"
|
|
140
|
+
},
|
|
141
|
+
body: "Internal server error"
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
const azureImageOptimization = {
|
|
146
|
+
name: "azure-image-optimization",
|
|
147
|
+
wrapper: handler,
|
|
148
|
+
supportStreaming: true
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
export { azureImageOptimization as default };
|
package/dist/cli/index.js
CHANGED
|
@@ -222,6 +222,27 @@ async function checkStorageAccount(appName, resourceGroup, environment) {
|
|
|
222
222
|
details: `Status: ${account.Status}`
|
|
223
223
|
};
|
|
224
224
|
}
|
|
225
|
+
try {
|
|
226
|
+
const { stdout: staticFileStdout } = await execAsync$1(
|
|
227
|
+
`az storage blob list --account-name ${account.Name} --container-name assets --prefix _next/static --query '[0].name' -o tsv --only-show-errors 2>/dev/null || echo ""`
|
|
228
|
+
);
|
|
229
|
+
const sampleFile = staticFileStdout.trim();
|
|
230
|
+
if (sampleFile) {
|
|
231
|
+
const { stdout: cacheStdout } = await execAsync$1(
|
|
232
|
+
`az storage blob show --account-name ${account.Name} --container-name assets --name '${sampleFile}' --query 'properties.contentSettings.cacheControl' -o tsv --only-show-errors 2>/dev/null || echo ""`
|
|
233
|
+
);
|
|
234
|
+
const cacheControl = cacheStdout.trim();
|
|
235
|
+
const expectedCache = "public, max-age=31536000, immutable";
|
|
236
|
+
if (cacheControl !== expectedCache) {
|
|
237
|
+
return {
|
|
238
|
+
passed: false,
|
|
239
|
+
message: "Static asset cache headers misconfigured",
|
|
240
|
+
details: `${sampleFile.split("/").pop()} has '${cacheControl || "none"}' (expected '${expectedCache}')`
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
} catch {
|
|
245
|
+
}
|
|
225
246
|
return {
|
|
226
247
|
passed: true,
|
|
227
248
|
message: "Storage account healthy",
|
|
@@ -296,11 +317,23 @@ async function checkFunctionAppStatus(appName, resourceGroup, environment) {
|
|
|
296
317
|
details: `State: ${funcApp.State}`
|
|
297
318
|
};
|
|
298
319
|
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
320
|
+
const url = `https://${funcApp.DefaultHostName}`;
|
|
321
|
+
try {
|
|
322
|
+
const startTime = Date.now();
|
|
323
|
+
await execAsync$1(`curl -I -s -o /dev/null -w "%{http_code}" --max-time 10 "${url}" || echo "000"`);
|
|
324
|
+
const responseTime = Date.now() - startTime;
|
|
325
|
+
return {
|
|
326
|
+
passed: true,
|
|
327
|
+
message: "Function app running and responding",
|
|
328
|
+
details: `URL: ${url} (${responseTime}ms)`
|
|
329
|
+
};
|
|
330
|
+
} catch {
|
|
331
|
+
return {
|
|
332
|
+
passed: true,
|
|
333
|
+
message: "Function app running",
|
|
334
|
+
details: `URL: ${url} (HTTP check failed, but app is running)`
|
|
335
|
+
};
|
|
336
|
+
}
|
|
304
337
|
} catch (error) {
|
|
305
338
|
return {
|
|
306
339
|
passed: false,
|
|
@@ -500,7 +533,7 @@ program.command("init").description("Initialize Azure infrastructure in your pro
|
|
|
500
533
|
program.command("build").description("Build Next.js app for Azure deployment").option("-c, --config <path>", "Path to open-next.config.ts file").action(async (options) => {
|
|
501
534
|
await build(options.config);
|
|
502
535
|
});
|
|
503
|
-
program.command("deploy").description("Deploy Next.js app to Azure (provisions infrastructure + deploys)").option("-n, --app-name <name>", "Application name (overrides azure.config.json)").option("-g, --resource-group <name>", "Azure resource group name").option("-l, --location <location>", "Azure region").option("-e, --environment <env>", "Environment: dev, staging, or prod").option("--skip-infrastructure", "Skip infrastructure provisioning").action(async (options) => {
|
|
536
|
+
program.command("deploy").description("Deploy Next.js app to Azure (provisions infrastructure + deploys)").option("-n, --app-name <name>", "Application name (overrides azure.config.json)").option("-g, --resource-group <name>", "Azure resource group name").option("-l, --location <location>", "Azure region").option("-e, --environment <env>", "Environment: dev, staging, or prod").option("--skip-infrastructure", "Skip infrastructure provisioning").option("--skip-resource-checks", "Skip Azure resource validation checks (permissions, quota, providers)").action(async (options) => {
|
|
504
537
|
await deploy(options);
|
|
505
538
|
});
|
|
506
539
|
program.command("tail").description("Open Azure Portal Log Stream in browser (live logs)").option("-n, --app-name <name>", "Application name").option("-g, --resource-group <name>", "Azure resource group name").action(async (options) => {
|
package/dist/config/index.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import '@opennextjs/aws/types/open-next.js';
|
|
2
|
-
export { d as defineAzureConfig, g as getAzureConfig } from '../shared/opennextjs-azure.
|
|
2
|
+
export { d as defineAzureConfig, g as getAzureConfig } from '../shared/opennextjs-azure.279bd73d.mjs';
|
|
3
3
|
import '@opennextjs/aws/types/overrides.js';
|
package/dist/config/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import '@opennextjs/aws/types/open-next.js';
|
|
2
|
-
export { d as defineAzureConfig, g as getAzureConfig } from '../shared/opennextjs-azure.
|
|
2
|
+
export { d as defineAzureConfig, g as getAzureConfig } from '../shared/opennextjs-azure.279bd73d.js';
|
|
3
3
|
import '@opennextjs/aws/types/overrides.js';
|
package/dist/config/index.js
CHANGED
|
@@ -14,6 +14,9 @@ function defineAzureConfig(config = {}) {
|
|
|
14
14
|
middleware: config.middleware || {
|
|
15
15
|
external: false
|
|
16
16
|
},
|
|
17
|
+
imageOptimization: {
|
|
18
|
+
loader: resolveImageLoader(config.imageLoader)
|
|
19
|
+
},
|
|
17
20
|
dangerous: config.dangerous,
|
|
18
21
|
buildCommand: config.buildCommand,
|
|
19
22
|
buildOutputPath: config.buildOutputPath || ".",
|
|
@@ -48,6 +51,15 @@ function resolveQueue(value) {
|
|
|
48
51
|
}
|
|
49
52
|
return () => value;
|
|
50
53
|
}
|
|
54
|
+
function resolveImageLoader(value) {
|
|
55
|
+
if (!value || value === "azure-blob") {
|
|
56
|
+
return () => import('../overrides/imageLoader/azure-blob.js').then((m) => m.default);
|
|
57
|
+
}
|
|
58
|
+
if (typeof value === "function") {
|
|
59
|
+
return value;
|
|
60
|
+
}
|
|
61
|
+
return () => value;
|
|
62
|
+
}
|
|
51
63
|
function getAzureConfig() {
|
|
52
64
|
return {
|
|
53
65
|
deployment: {
|