fix(core): Improve nested DNS record management and worker script multipart handling
This commit is contained in:
		| @@ -1,5 +1,12 @@ | |||||||
| # Changelog | # Changelog | ||||||
|  |  | ||||||
|  | ## 2025-04-26 - 6.3.1 - fix(core) | ||||||
|  | Improve nested DNS record management and worker script multipart handling | ||||||
|  |  | ||||||
|  | - Add tests for creating, updating, and removing nested subdomain A records | ||||||
|  | - Refine TXT record cleaning by filtering records with matching name and type | ||||||
|  | - Clarify multipart form data handling for worker script updates and creation | ||||||
|  |  | ||||||
| ## 2025-04-26 - 6.3.0 - feat(core) | ## 2025-04-26 - 6.3.0 - feat(core) | ||||||
| Release 6.2.0: Improved async iterator support, enhanced error handling and refined API interfaces for better type safety and consistent behavior. | Release 6.2.0: Improved async iterator support, enhanced error handling and refined API interfaces for better type safety and consistent behavior. | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										46
									
								
								test/test.ts
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								test/test.ts
									
									
									
									
									
								
							| @@ -149,6 +149,52 @@ tap.test('should update A record content', async (tools) => { | |||||||
|   console.log(`Updated A record for ${subdomain} to 192.168.1.1`); |   console.log(`Updated A record for ${subdomain} to 192.168.1.1`); | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | // Nested subdomain DNS record tests | ||||||
|  | tap.test('should create A record for nested subdomain', async (tools) => { | ||||||
|  |   tools.timeout(600000); | ||||||
|  |   const nestedSubdomain = `${randomPrefix}-nested.sub.bleu.de`; | ||||||
|  |   const result = await testCloudflareAccount.convenience.createRecord( | ||||||
|  |     nestedSubdomain, | ||||||
|  |     'A', | ||||||
|  |     '127.0.0.5', | ||||||
|  |     120 | ||||||
|  |   ); | ||||||
|  |   expect(result).toBeTypeOf('object'); | ||||||
|  |   console.log(`Created nested A record for ${nestedSubdomain}`); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | tap.test('should get A record for nested subdomain', async (tools) => { | ||||||
|  |   tools.timeout(600000); | ||||||
|  |   const nestedSubdomain = `${randomPrefix}-nested.sub.bleu.de`; | ||||||
|  |   const record = await testCloudflareAccount.convenience.getRecord(nestedSubdomain, 'A'); | ||||||
|  |   expect(record).toBeTypeOf('object'); | ||||||
|  |   expect(record.content).toEqual('127.0.0.5'); | ||||||
|  |   console.log(`Successfully retrieved nested A record for ${nestedSubdomain}`); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | tap.test('should update A record for nested subdomain', async (tools) => { | ||||||
|  |   tools.timeout(600000); | ||||||
|  |   const nestedSubdomain = `${randomPrefix}-nested.sub.bleu.de`; | ||||||
|  |   const result = await testCloudflareAccount.convenience.updateRecord( | ||||||
|  |     nestedSubdomain, | ||||||
|  |     'A', | ||||||
|  |     '127.0.0.6', | ||||||
|  |     120 | ||||||
|  |   ); | ||||||
|  |   expect(result).toBeTypeOf('object'); | ||||||
|  |   expect(result.content).toEqual('127.0.0.6'); | ||||||
|  |   console.log(`Updated nested A record for ${nestedSubdomain}`); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | tap.test('should remove nested subdomain A record', async (tools) => { | ||||||
|  |   tools.timeout(600000); | ||||||
|  |   const nestedSubdomain = `${randomPrefix}-nested.sub.bleu.de`; | ||||||
|  |   await testCloudflareAccount.convenience.removeRecord(nestedSubdomain, 'A'); | ||||||
|  |   const record = await testCloudflareAccount.convenience.getRecord(nestedSubdomain, 'A'); | ||||||
|  |   expect(record).toBeUndefined(); | ||||||
|  |   console.log(`Successfully removed nested A record for ${nestedSubdomain}`); | ||||||
|  | }); | ||||||
|  |  | ||||||
| tap.test('should clean TXT records', async (tools) => { | tap.test('should clean TXT records', async (tools) => { | ||||||
|   tools.timeout(600000); |   tools.timeout(600000); | ||||||
|   const subdomain = `${randomPrefix}-txt-test.bleu.de`; |   const subdomain = `${randomPrefix}-txt-test.bleu.de`; | ||||||
|   | |||||||
| @@ -3,6 +3,6 @@ | |||||||
|  */ |  */ | ||||||
| export const commitinfo = { | export const commitinfo = { | ||||||
|   name: '@apiclient.xyz/cloudflare', |   name: '@apiclient.xyz/cloudflare', | ||||||
|   version: '6.3.0', |   version: '6.3.1', | ||||||
|   description: 'A TypeScript client for managing Cloudflare accounts, zones, DNS records, and workers with ease.' |   description: 'A TypeScript client for managing Cloudflare accounts, zones, DNS records, and workers with ease.' | ||||||
| } | } | ||||||
|   | |||||||
| @@ -229,15 +229,17 @@ export class CloudflareAccount { | |||||||
|         const domain = new plugins.smartstring.Domain(domainNameArg); |         const domain = new plugins.smartstring.Domain(domainNameArg); | ||||||
|         const zoneId = await this.convenience.getZoneId(domain.zoneName); |         const zoneId = await this.convenience.getZoneId(domain.zoneName); | ||||||
|          |          | ||||||
|         const records = await this.convenience.listRecords(domainNameArg); |         // List all records in the zone for this domain | ||||||
|  |         const records = await this.convenience.listRecords(domain.zoneName); | ||||||
|          |          | ||||||
|         if (!Array.isArray(records)) { |         if (!Array.isArray(records)) { | ||||||
|           logger.log('warn', `Expected records array for ${domainNameArg} but got ${typeof records}`); |           logger.log('warn', `Expected records array for ${domainNameArg} but got ${typeof records}`); | ||||||
|           return; |           return; | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         // Only delete records matching the specified name and type | ||||||
|         const recordsToDelete = records.filter((recordArg) => { |         const recordsToDelete = records.filter((recordArg) => { | ||||||
|           return recordArg.type === typeArg; |           return recordArg.type === typeArg && recordArg.name === domainNameArg; | ||||||
|         }); |         }); | ||||||
|          |          | ||||||
|         logger.log('info', `Found ${recordsToDelete.length} ${typeArg} records to delete for ${domainNameArg}`); |         logger.log('info', `Found ${recordsToDelete.length} ${typeArg} records to delete for ${domainNameArg}`); | ||||||
|   | |||||||
| @@ -167,11 +167,15 @@ export class CloudflareWorker { | |||||||
|     try { |     try { | ||||||
|       logger.log('info', `Updating script for worker ${this.id}`); |       logger.log('info', `Updating script for worker ${this.id}`); | ||||||
|        |        | ||||||
|       // Use the official client to update the script |       // Use the official client to update the script (upload new content) | ||||||
|       const updatedWorker = await this.workerManager.cfAccount.apiAccount.workers.scripts.content.update(this.id, { |       const updatedWorker = await this.workerManager.cfAccount.apiAccount.workers.scripts.content.update(this.id, { | ||||||
|         account_id: this.workerManager.cfAccount.preselectedAccountId, |         account_id: this.workerManager.cfAccount.preselectedAccountId, | ||||||
|         "CF-WORKER-BODY-PART": scriptContent, |         // name the multipart part for the updated script code | ||||||
|         metadata: {} |         metadata: { body_part: 'script' }, | ||||||
|  |         /* header to indicate which part contains the script */ | ||||||
|  |         'CF-WORKER-BODY-PART': 'script', | ||||||
|  |         // include the new script as a form part named 'script' | ||||||
|  |         script: scriptContent, | ||||||
|       }); |       }); | ||||||
|        |        | ||||||
|       // Update this instance with new data |       // Update this instance with new data | ||||||
|   | |||||||
| @@ -22,11 +22,15 @@ export class WorkerManager { | |||||||
|     } |     } | ||||||
|      |      | ||||||
|     try { |     try { | ||||||
|       // Use the official client to create/update the worker |       // Use the official client to create/update the worker (upload script content) | ||||||
|       await this.cfAccount.apiAccount.workers.scripts.content.update(workerName, { |       await this.cfAccount.apiAccount.workers.scripts.content.update(workerName, { | ||||||
|         account_id: this.cfAccount.preselectedAccountId, |         account_id: this.cfAccount.preselectedAccountId, | ||||||
|         "CF-WORKER-BODY-PART": workerScript, |         // name the multipart part for the script code | ||||||
|         metadata: {} |         metadata: { body_part: 'script' }, | ||||||
|  |         /* header to indicate which part contains the script */ | ||||||
|  |         'CF-WORKER-BODY-PART': 'script', | ||||||
|  |         // include the actual script as a form part named 'script' | ||||||
|  |         script: workerScript, | ||||||
|       }); |       }); | ||||||
|        |        | ||||||
|       // Create a new worker instance |       // Create a new worker instance | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user