fix(core): Improve nested DNS record management and worker script multipart handling

This commit is contained in:
Philipp Kunz 2025-04-26 12:37:19 +00:00
parent e1c38ab7f8
commit 4b82cfbaae
6 changed files with 72 additions and 9 deletions

View File

@ -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.

View File

@ -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`;

View File

@ -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.'
} }

View File

@ -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}`);

View File

@ -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

View File

@ -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