Conversation
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
| "./*": { | ||
| "import": "./dist/*", | ||
| "require": "./dist/*.cjs" | ||
| }, |
There was a problem hiding this comment.
Wildcard breaks directory exports
The wildcard maps imports such as @dokploy/server/constants to ./dist/constants, but the build emits dist/constants/index.js. Node's ESM resolver does not add the filename or resolve the directory index for package export targets. Because the Dokploy server bundle leaves package imports external, normal startup can fail with ERR_MODULE_NOT_FOUND. Please export directory-backed subpaths explicitly with their emitted filenames.
There was a problem hiding this comment.
Good catch, but not part of this change. That diff was the output of pnpm server:build (switch:prod rewrites package.json) swept into a commit by mistake. Removed from the branch; the PR no longer touches packages/server/package.json.
| </> | ||
| )} | ||
|
|
||
| {servers && servers.length > 0 && ( |
There was a problem hiding this comment.
The entire target selector, including the valid local Dokploy target, is hidden when withSSHKey returns no remote servers. In a self-hosted installation, a user duplicating a remote service can therefore be forced to keep its current server even though the backend permits duplication to Dokploy. The local option should be rendered independently of the remote-server list.
Knowledge Base Used: Dashboard and client state
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
Fixed in 7e86ea9. The selector now renders whenever there is at least one target other than "keep": the Dokploy host when it is allowed and the source is remote, or any listed server that is not the shared source. With no listed remote servers a remote source still gets Keep current server and Dokploy; a local source with no remotes gets no selector, since keep would be the only option.
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…rver Co-authored-by: Cursor <cursoragent@cursor.com>
00951cc to
7e86ea9
Compare
What is this PR about?
The Duplicate Services dialog gets a Target Server select. Today every duplicated application, compose stack and database keeps its source
serverId, so duplication cannot be used to stage a copy on another host. This adds the missing piece asked for in #5170: a copy that lands on a different remote server, or back on the Dokploy host, while the source keeps running. #5396 (transfer) moves a service and its data; this copies configuration only, the same way duplication always has.Behavior
remoteServersOnlyis on) and the organization's servers that have an SSH key, the same sourceadd-applicationuses.serverIdon every copy. Networks that are scoped to another server are dropped fromnetworkIds(applications, databases) and from each composeserviceNetworksentry, through the sameresolveNetworkIdsrule the transfer feature uses. The dialog says so before you confirm.API
project.duplicateaccepts an optionaltargetServer:The target is validated before any project or service row is written:
dokployis rejected in cloud mode or withremoteServersOnly;remoterequires a server the session can access (owner, or a member with thatserverIdinaccessedServers) that isactiveand of typedeploy. Existing callers that omittargetServerare unaffected.Changes
packages/server/src/services/duplicate.ts(new).assertDuplicateTargetServer,duplicateServerOverride, andduplicateService. The per-service duplication switch moved here from the router; each arm builds its payload through one helper, so the target-server override is applied in one place instead of eight.project.tsshrinks by ~390 lines.packages/server/src/db/schema/duplicate.ts(new).apiDuplicateTargetServerzod union and its type.packages/server/src/services/network.ts.resolveNetworkIdsmoved here fromtransfer.tsso both features share it. No behavior change.apps/dokploy/server/api/routers/project.ts.duplicatetakestargetServer, validates it up front, callsduplicateService, rethrowsTRPCErrorinstead of flattening every failure toBAD_REQUEST, and records the target in the audit metadata. The hand-written service type enum is nowz.enum(serviceType.enumValues).apps/dokploy/components/dashboard/project/duplicate-project.tsx. The select and the network warning.apps/dokploy/__test__/services/duplicate-target-server.test.ts(new). 15 cases covering the three target kinds, cloud andremoteServersOnlyrejection, inaccessible and inactive servers, and network filtering fornetworkIdsand composeserviceNetworks.Tested
Local instance on
canarywith two seeded remote servers, an application on each, a Postgres on the Dokploy host, a compose stack withserviceNetworks, and one server-scoped network per remote. Driven through the real dialog with Playwright and read back from Postgres:serviceNetworksentry, the remote-b network is kept,detachDokployNetworkis preserved, the source rows are untouched.serverIdreturnsUNAUTHORIZEDbefore any project row is created. An unknownkindis rejected by zod. OmittingtargetServerbehaves as before.pnpm typecheck,pnpm server:build,biome checkon the changed files clean.pnpm test: 1044 passed; the 4 failures inapplication.real.test.tsare pre-existing oncanaryon this machine (nixpacks/railpack not installed) and unrelated.Notes for review
project.duplicatenow rethrowsTRPCErroras is. Callers that keyed on every failure beingBAD_REQUESTwill seeUNAUTHORIZED,NOT_FOUNDorCONFLICTwhere those apply.Checklist
Before submitting this PR, please make sure that:
canarybranch.Issues related (if applicable)
Related to #5170 (closed with #5396, which its description calls a different operation).
Screenshots (if applicable)
See above.
The PR is not safe to merge until package subpaths resolve to emitted ESM files and the local Dokploy target remains selectable without remote-server results.
Summary
Reviews (1) · Last reviewed commit: "fix(duplicate): hide the shared source s..."