@geek-fun/serverlessinsight 0.6.10 → 0.6.11

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 CHANGED
@@ -333,10 +333,13 @@ When binding a custom domain that requires ownership verification:
333
333
 
334
334
  For OSS static website hosting, ServerlessInsight supports:
335
335
 
336
- | Domain Type | CNAME Target | Use Case |
337
- | ----------------- | -------------------------------- | ---------------------------------------------- |
338
- | Root domain (`@`) | `bucket.region.taihangcda.cn` | Bypasses DNS CNAME restriction on root domains |
339
- | Subdomain (`www`) | `bucket.oss-region.aliyuncs.com` | Standard OSS endpoint |
336
+ | Domain Type | CNAME Target | Use Case |
337
+ | ----------------- | ----------------------------- | ---------------------------------------------- |
338
+ | Root domain (`@`) | `bucket.region.taihangcda.cn` | Bypasses DNS CNAME restriction on root domains |
339
+ | Subdomain (`www`) | `bucket.region.taihangcda.cn` | Standard CNAME for all subdomains |
340
+ | Any subdomain | `bucket.region.taihangcda.cn` | Unified CNAME endpoint for all domain types |
341
+
342
+ > 💡 **Note**: All domain types now use the recommended `taihangcda.cn` CNAME endpoint, which is derived automatically from your bucket's actual extranet endpoint via the `GetBucketInfo` API.
340
343
 
341
344
  For detailed configuration, see [OSS Custom Domain Binding Guide](./docs/oss-custom-domain-binding.md).
342
345
 
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geek-fun/serverlessinsight",
3
- "version": "0.6.10",
3
+ "version": "0.6.11",
4
4
  "description": "Full life cycle cross providers serverless application management for your fast-growing business.",
5
5
  "homepage": "https://serverlessinsight.geekfun.club",
6
6
  "main": "dist/src/index.js",
@@ -40,8 +40,27 @@ const createOssOperations = (ossClient, region, dnsOps) => {
40
40
  const useBucket = (bucketName) => {
41
41
  ossClient.useBucket(bucketName);
42
42
  };
43
- const getOssEndpoint = (bucketName) => {
44
- return `${bucketName}.oss-${region}.aliyuncs.com`;
43
+ const getBucketExtranetEndpoint = async (bucketName) => {
44
+ const infoResult = await ossClient.getBucketInfo(bucketName);
45
+ const endpoint = infoResult.bucket.ExtranetEndpoint;
46
+ if (!endpoint) {
47
+ throw new Error(lang_1.lang.__('OSS_BUCKET_EXTRANET_ENDPOINT_NOT_FOUND', { bucketName }));
48
+ }
49
+ return endpoint;
50
+ };
51
+ const getCnameEndpointFromExtranet = (extranetEndpoint) => {
52
+ const suffix = '.aliyuncs.com';
53
+ if (!extranetEndpoint.endsWith(suffix)) {
54
+ throw new Error(lang_1.lang.__('OSS_BUCKET_ENDPOINT_INVALID_FORMAT', { extranetEndpoint }));
55
+ }
56
+ const withoutAliyun = extranetEndpoint.slice(0, -suffix.length);
57
+ const lastDotIndex = withoutAliyun.lastIndexOf('.');
58
+ if (lastDotIndex <= 0) {
59
+ throw new Error(lang_1.lang.__('OSS_BUCKET_ENDPOINT_INVALID_FORMAT', { extranetEndpoint }));
60
+ }
61
+ const bucketPart = withoutAliyun.slice(0, lastDotIndex);
62
+ const regionWithout = withoutAliyun.slice(lastDotIndex + 1).replace(/^oss-/, '');
63
+ return `${bucketPart}.${regionWithout}.taihangcda.cn`;
45
64
  };
46
65
  const buildCertificateXml = (cert) => {
47
66
  if (!cert)
@@ -222,26 +241,28 @@ const createOssOperations = (ossClient, region, dnsOps) => {
222
241
  }
223
242
  };
224
243
  const bindCustomDomain = async (bucketName, domain, certificate) => {
225
- const mainDomain = (0, domainUtils_1.extractMainDomain)(domain);
226
- const hostRecord = (0, domainUtils_1.extractHostRecord)(domain, mainDomain);
227
- const ossEndpoint = getOssEndpoint(bucketName);
228
- let cnameResult = await putBucketCname(bucketName, domain, certificate);
244
+ const normalizedDomain = (0, domainUtils_1.normalizeDomain)(domain);
245
+ const mainDomain = (0, domainUtils_1.extractMainDomain)(normalizedDomain);
246
+ const hostRecord = (0, domainUtils_1.extractHostRecord)(normalizedDomain, mainDomain);
247
+ const extranetEndpoint = await getBucketExtranetEndpoint(bucketName);
248
+ const ossEndpoint = getCnameEndpointFromExtranet(extranetEndpoint);
249
+ let cnameResult = await putBucketCname(bucketName, normalizedDomain, certificate);
229
250
  let txtRecordId;
230
251
  if (cnameResult.needVerification) {
231
- const verificationResult = await handleDomainOwnershipVerification(bucketName, domain, certificate);
252
+ const verificationResult = await handleDomainOwnershipVerification(bucketName, normalizedDomain, certificate);
232
253
  cnameResult = verificationResult;
233
254
  txtRecordId = verificationResult.txtRecordId;
234
255
  }
235
256
  const bucketCnameBound = cnameResult.success;
236
257
  if (certificate && bucketCnameBound) {
237
- logger_1.logger.info(lang_1.lang.__('OSS_BUCKET_CERT_BOUND', { domain }));
258
+ logger_1.logger.info(lang_1.lang.__('OSS_BUCKET_CERT_BOUND', { domain: normalizedDomain }));
238
259
  }
239
- await addCorsRuleForDomain(bucketName, domain);
260
+ await addCorsRuleForDomain(bucketName, normalizedDomain);
240
261
  if (!dnsOps) {
241
- logger_1.logger.warn(lang_1.lang.__('OSS_DNS_MANUAL_CONFIG_REQUIRED', { domain, cname: ossEndpoint }));
242
- return { domain, cname: ossEndpoint, bucketCnameBound, txtRecordId };
262
+ logger_1.logger.warn(lang_1.lang.__('OSS_DNS_MANUAL_CONFIG_REQUIRED', { domain: normalizedDomain, cname: ossEndpoint }));
263
+ return { domain: normalizedDomain, cname: ossEndpoint, bucketCnameBound, txtRecordId };
243
264
  }
244
- const result = await createOrFindDnsCnameRecord(domain, mainDomain, hostRecord, ossEndpoint, bucketCnameBound);
265
+ const result = await createOrFindDnsCnameRecord(normalizedDomain, mainDomain, hostRecord, ossEndpoint, bucketCnameBound);
245
266
  return { ...result, txtRecordId };
246
267
  };
247
268
  const logOssVerificationInstructions = (domain, fullTxtRecord, token) => {
@@ -699,7 +720,6 @@ const createOssOperations = (ossClient, region, dnsOps) => {
699
720
  },
700
721
  bindCustomDomain,
701
722
  unbindCustomDomain,
702
- getOssEndpoint,
703
723
  createCnameToken,
704
724
  };
705
725
  };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.deriveWwwDomain = exports.extractHostRecord = exports.extractMainDomain = void 0;
3
+ exports.deriveWwwDomain = exports.extractHostRecord = exports.extractMainDomain = exports.normalizeDomain = void 0;
4
4
  const MULTI_LEVEL_TLDS = new Set([
5
5
  // United Kingdom
6
6
  'co.uk',
@@ -93,6 +93,13 @@ const MULTI_LEVEL_TLDS = new Set([
93
93
  'gov.sg',
94
94
  'edu.sg',
95
95
  ]);
96
+ const normalizeDomain = (domain) => {
97
+ if (domain.startsWith('@.')) {
98
+ return domain.slice(2);
99
+ }
100
+ return domain;
101
+ };
102
+ exports.normalizeDomain = normalizeDomain;
96
103
  const extractMainDomain = (domainName) => {
97
104
  const parts = domainName.split('.');
98
105
  if (parts.length <= 2) {
@@ -329,6 +329,8 @@ exports.en = {
329
329
  OSS_BUCKET_PUBLIC_ACCESS_BLOCK_DISABLED: 'Disabled Block Public Access for bucket: {{bucketName}}',
330
330
  OSS_BUCKET_PUBLIC_ACCESS_BLOCK_DISABLE_FAILED: 'Failed to disable Block Public Access for bucket {{bucketName}}: {{error}}. ' +
331
331
  'You may need to manually disable Block Public Access in the Alibaba Cloud OSS Console.',
332
+ OSS_BUCKET_EXTRANET_ENDPOINT_NOT_FOUND: 'ExtranetEndpoint not found for bucket: {{bucketName}}. The bucket may not have public access enabled.',
333
+ OSS_BUCKET_ENDPOINT_INVALID_FORMAT: 'Invalid OSS endpoint format: {{extranetEndpoint}}. Expected format: {bucket}.oss-{region}.aliyuncs.com',
332
334
  // Tencent COS DNS messages
333
335
  COS_DNS_CNAME_CREATED: 'Created DNS CNAME record: {{domain}} -> {{cname}}',
334
336
  COS_DNS_CNAME_EXISTS: 'DNS CNAME record already exists: {{domain}} -> {{cname}}',
@@ -326,7 +326,9 @@ exports.zhCN = {
326
326
  OSS_CORS_RULE_REMOVED: '已移除自定义域名的 CORS 规则: {{domain}}',
327
327
  OSS_CORS_RULE_REMOVE_FAILED: '移除 {{domain}} 的 CORS 规则失败: {{error}}',
328
328
  OSS_BUCKET_PUBLIC_ACCESS_BLOCK_DISABLED: '已为存储桶禁用公共访问阻止: {{bucketName}}',
329
- OSS_BUCKET_PUBLIC_ACCESS_BLOCK_DISABLE_FAILED: '禁用存储桶 {{bucketName}} 的公共访问阻止失败: {{error}}。您可能需要在阿里云 OSS 控制台手动禁用公共访问阻止。',
329
+ OSS_BUCKET_PUBLIC_ACCESS_BLOCK_DISABLE_FAILED: '禁用存储桶 {{bucketName}} 的公共访问阻止失败:{{error}}。您可能需要在阿里云 OSS 控制台手动禁用公共访问阻止。',
330
+ OSS_BUCKET_EXTRANET_ENDPOINT_NOT_FOUND: '存储桶 {{bucketName}} 未找到外网访问端点。该存储桶可能未启用公共访问。',
331
+ OSS_BUCKET_ENDPOINT_INVALID_FORMAT: 'OSS 端点格式无效:{{extranetEndpoint}}。预期格式:{bucket}.oss-{region}.aliyuncs.com',
330
332
  // Tencent COS DNS messages
331
333
  COS_DNS_CNAME_CREATED: '已创建 DNS CNAME 记录: {{domain}} -> {{cname}}',
332
334
  COS_DNS_CNAME_EXISTS: 'DNS CNAME 记录已存在: {{domain}} -> {{cname}}',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geek-fun/serverlessinsight",
3
- "version": "0.6.10",
3
+ "version": "0.6.11",
4
4
  "description": "Full life cycle cross providers serverless application management for your fast-growing business.",
5
5
  "homepage": "https://serverlessinsight.geekfun.club",
6
6
  "main": "dist/src/index.js",