If you are using v1.0.0–v1.0.6 in v3 mode (default), the following methods had wrong HTTP status expectations, missing async job polling, or inconsistent headers:
Status code fixes (would reject successful v3 DELETE responses):
AppsDeployment.removeServiceBindings(),ServiceBindings._addV3/_removeV3(),ServiceInstances._removeV3()— now correctly accept both 202 and 204 where appropriate
Async job polling:
Jobs.getV3Job()andJobs.pollJob()now available for v3 async operation tracking (/v3/jobs/:guid)
Consistency fixes:
Organizations._getPrivateDomainsV3()no longer adds ineffectivevisibility=privatefilter- All
Organizationsv2/v3 methods now usegetAuthorizationHeader()
Upgrade to v1.0.7 for correct v3 behavior and async job support. No consumer code changes needed unless you want to use new polling helpers.
If you are using v1.0.0–v1.0.5 in v3 mode (default), the following methods had wrong HTTP status expectations or request body structures:
Status code fixes (would reject successful v3 DELETE responses):
AppsCore.remove(),Domains.remove(),BuildPacks.remove(),Users.remove()— now correctly expect 202 instead of 204
Request body fixes (CF API would reject the request):
Domains.add()—organization_guidnow nested inrelationshipsstructureUsers.add()— now sends{ guid }instead of{ username, origin }per v3 specOrganizationsQuota._translateToV3()— proper nestedapps/services/routes/domainsstructureSpacesQuota._translateToV3()— proper nestedapps/services/routesstructure
Upload fix:
HttpUtils.upload()now acceptsoptions.method— v3 package upload uses POST (was hardcoded PUT)
Upgrade to v1.0.6 for correct v3 behavior. If you pass v2-style quota options, no caller changes needed.
Breaking:
Users.add()in v3 now requires{ guid: "uaa-user-guid" }instead of{ username, origin }.
If you are using v1.0.0–v1.0.4 in v3 mode (default), the following methods called wrong endpoints:
AppsDeployment:getStats(),associateRoute(),getServiceBindings(),upload()(v3 path)Organizations:getUsers(),getManagers(),getAuditors()(v3 path)Spaces:getUsers(),getManagers(),getDevelopers(),getAuditors()(v3 path)
Upgrade to v1.0.5 to get correct v3 API endpoints. No consumer code changes needed.
If you upgraded to v1.0.0–v1.0.3 and hit the error:
Invalid endpoint URL: "undefined". Must be a valid http:// or https:// URL.
Upgrade to v1.0.4 — this fixes getInfo() in v3 mode. The standard auth pattern now works correctly:
// This works in v1.0.4+ (both v2 and v3):
const info = await cfController.getInfo();
usersUAA.setEndPoint(info.authorization_endpoint); // ✅ No longer undefined
// Or use the new convenience method (recommended):
const authEndpoint = await cfController.getAuthorizationEndpoint();
usersUAA.setEndPoint(authEndpoint);The cf-nodejs-client package has been renamed to cf-node-client and upgraded to version 1.0.0 with full Cloud Foundry API v3 support.
Key Changes:
- 📦 Package rename:
cf-nodejs-client→cf-node-client - 🚀 v3 is now default (v2 still available)
- ✅ 100% backward compatible with v2
- 🔄 Zero breaking changes to public APIs
# Remove old package
npm uninstall cf-nodejs-client
# Install new package
npm install cf-node-client@1.0.0Or manually update package.json:
{
"dependencies": {
"cf-node-client": "^1.0.0"
}
}Then run:
npm installBefore (v0.13.0):
const CloudController = require('cf-nodejs-client').CloudController;
const Apps = require('cf-nodejs-client').Apps;
const Organizations = require('cf-nodejs-client').Organizations;After (v1.0.0):
const CloudController = require('cf-node-client').CloudController;
const Apps = require('cf-node-client').Apps;
const Organizations = require('cf-node-client').Organizations;If your code explicitly sets v2, update it:
Before:
const cf = new CloudController(endpoint);
cf.setToken(token);
// v2 was default in 0.13.0
cf.getApps(); // Uses /v2/appsAfter (Option 1 - Keep using v2):
const cf = new CloudController(endpoint);
cf.setToken(token);
// v3 is now default, but you can explicitly use v2
cf.setApiVersion('v2');
cf.getApps(); // Uses /v2/appsAfter (Option 2 - Upgrade to v3):
const cf = new CloudController(endpoint);
cf.setToken(token);
// v3 is default - no changes to method calls!
cf.getApps(); // Uses /v3/apps (automatically)Run your test suite:
npm testAll existing code should work without modification!
// Upgrade package but stay on v2 API for now
cf.setApiVersion('v2');
// Your existing code works 100% as before
// No functional changes neededTimeline: Immediate
Risk: None
Recommended: For production systems that can't be tested
// Week 1: Upgrade package, stay on v2
cf.setApiVersion('v2');
// Week 2: Test v3 in specific module
const apps = new Apps(endpoint, token);
// apps now uses v3 by default - test it
// Week 3: Move to v3 across application
cf.setApiVersion('v3'); // This is now default anyway
// Week 4: Remove setApiVersion calls
// v3 is already the defaultTimeline: 4 weeks
Risk: Low (test each phase)
Recommended: For most production systems
// Just upgrade the package - that's it!
// Don't set API version explicitly
// v3 is used by default
// All your code continues to work
// But now uses v3 endpoints automaticallyTimeline: Immediate
Risk: Medium (requires testing)
Recommended: For dev/qa environments first
v2 and v3 use same query syntax:
cf.getApps({
q: 'name:my-app',
'page': 1,
'results-per-page': 50
});Responses are different but the SDK handles translation:
v2 Response:
{
total_results: 100,
total_pages: 5,
prev_url: '/v2/apps?page=1',
next_url: '/v2/apps?page=3',
resources: [
{ metadata: { guid: '...' }, entity: { name: 'app1' } }
]
}v3 Response:
{
pagination: {
total_results: 100,
total_pages: 5,
first: { href: '/v3/apps?page=1' },
last: { href: '/v3/apps?page=5' },
next: { href: '/v3/apps?page=3' }
},
resources: [
{ guid: '...', name: 'app1', ... }
]
}Important: The SDK normalizes these - your code doesn't need to change!
Some field names differ between v2 and v3:
| v2 | v3 | SDK Handles |
|---|---|---|
state: 'STARTED' |
stopped: false |
✅ Auto-translated |
memory |
memory_in_mb |
✅ Auto-translated |
instances |
instances |
✅ Same |
routes |
urls |
✅ Auto-translated |
The SDK handles these translations automatically - your code doesn't change!
Some endpoints were renamed in v3. The SDK handles routing automatically:
| Resource | v2 | v3 | Notes |
|---|---|---|---|
| Services | /v2/services |
/v3/service_offerings |
Major entity restructure |
| Events | /v2/events |
/v3/audit_events |
Renamed & improved |
| Jobs | /v2/jobs |
/v3/tasks |
Simpler model |
| Org Quotas | /v2/quota_definitions |
/v3/organization_quotas |
Clearer naming |
| Space Quotas | /v2/space_quota_definitions |
/v3/space_quotas |
Clearer naming |
| Bindings | /v2/service_bindings |
/v3/service_credential_bindings |
More specific |
No changes needed to your code - the SDK routes requests to correct endpoint based on API version!
Some operations only exist in v2. If you call them in v3 mode:
cf.setApiVersion('v3');
// This exists in both v2 and v3 - works!
cf.getOrganizations();
// This is v2-only - will throw with helpful error
cf.getOrganizationMemoryUsage(orgGuid);
// Error: "getOrganizationMemoryUsage only available in v2 API"// Switch to v2 temporarily for v2-only operations
const v3Instance = new CloudController(endpoint);
v3Instance.setToken(token);
const memoryUsage = v3Instance.getOrganizationMemoryUsage(orgGuid);
// Then switch back to v3
const orgs = v3Instance.setApiVersion('v3').getOrganizations();const CloudController = require('cf-node-client').CloudController;
async function test() {
const cf = new CloudController(process.env.CF_ENDPOINT);
cf.setToken(JSON.parse(process.env.CF_TOKEN));
// Test both APIs
console.log('Testing v3 API...');
cf.setApiVersion('v3');
const v3Apps = await cf.getApps();
console.log(`v3: Found ${v3Apps.resources.length} apps`);
console.log('Testing v2 API...');
cf.setApiVersion('v2');
const v2Apps = await cf.getApps();
console.log(`v2: Found ${v2Apps.resources.length} apps`);
// Should match (domain logic differences aside)
console.log('✅ Both APIs working!');
}
test().catch(console.error);npm testAll existing tests should pass without modification.
Fix: Update require statement:
// Change this:
const lib = require('cf-nodejs-client');
// To this:
const lib = require('cf-node-client');Fix: Switch to v2 temporarily or for that operation:
controller.setApiVersion('v2');
const result = await controller.someV2OnlyMethod();
controller.setApiVersion('v3');Fix: The SDK handles response format translation. If you're parsing responses manually:
// Before (parsing v2 responses):
const resource = response.resources[0];
const guid = resource.metadata.guid;
const name = resource.entity.name;
// After (SDK normalizes v3 response):
const resource = response.resources[0];
const guid = resource.guid; // No need for metadata.guid
const name = resource.name; // No need for entity.nameIf you're using the SDK methods (recommended), no changes needed!
Ensure you're encoding credential correctly:
const token = {
token_type: 'Bearer',
access_token: 'your-token-here',
expires_in: 3600
};
cf.setToken(token);v3 often provides better performance:
// v2: Fetch app, then fetch routes, then fetch services
const app = await cf.getApp(appGuid);
const routes = await cf.getRoutes({ q: `app_guid:${appGuid}` });
const services = await cf.getServiceBindings({ q: `app_guid:${appGuid}` });
// v3: Often includes relationships in single response
const app = await cf.getApp(appGuid, { include: 'routes,serviceBindings' });
const routes = app.relationships.routes;
const services = app.relationships.serviceBindings;// v3 supports more powerful filtering
cf.setApiVersion('v3');
const apps = await cf.getApps({
organization_guids: [orgGuid],
space_guids: [spaceGuid],
names: ['my-app']
});If you encounter issues:
-
Check the logs - Enable debug logging:
process.env.DEBUG = 'cf-node-client:*';
-
Review RELEASE_NOTES.md - All changes documented
-
Check examples - See examples/ for patterns
-
File an issue - GitHub issues welcome with reproduction steps
-
Stay updated - Watch for releases that fix issues
Q: Do I need to rewrite all my code?
A: No! All existing code continues to work without changes.
Q: Can I use both v2 and v3 in the same application?
A: Yes! Create two controller instances and use different versions:
const v2cf = new CloudController(endpoint);
v2cf.setApiVersion('v2');
const v3cf = new CloudController(endpoint);
v3cf.setApiVersion('v3');Q: What about the old cf-nodejs-client package?
A: It's unmaintained. Upgrade to cf-node-client for bug fixes and v3 support.
Q: Is there a performance impact from switching?
A: No, often v3 is faster (fewer API calls needed).
Q: What about rate limiting?
A: Same limits apply, v3 usually needs fewer requests.
Ready to upgrade? Let's go! 🚀