Version 0.5.0 (released 2026-10-13) adds fetch-all reads, server-side customer and product filters, property selection on list commands, generic table writes, and project delete. Most of it is additive, but a few changes break scripts that relied on 0.4.2 behavior. Use this page as a checklist. Upgrading from 0.3 or earlier? Read Upgrading to 0.4 first.
The stored login token moved on Windows from the roaming %APPDATA%\DevOp\devop-dk folder to the non-roaming %LOCALAPPDATA%\DevOp\devop-dk folder, with an owner-only access control list. config.json stays in %APPDATA%.
| Before | Now |
|---|---|
The token was in %APPDATA%\DevOp\devop-dk\token |
The first read by 0.5 moves it to %LOCALAPPDATA%\DevOp\devop-dk\token. If the move fails, the old file is used and left in place |
devop-dk logout and Remove-Login removed one file |
They remove the token at both locations |
A 0.4.2 CLI or module reads only the old %APPDATA% copy, so after a 0.5 tool has moved the token, the older one no longer finds the login. Update DevOp.DK.Plus.Cli and the DevOp.DK.Plus module at the same time. Linux and macOS are not affected.
| Before | Now |
|---|---|
--take accepted up to 10,000 on the list commands |
Breaking. The 18 fluent list commands (customer, customer transaction, customer group, product, product group, product category, product unit, employee, sales invoice, sales order, sales quote, sales recurring, sales person, payment mode, payment term, payment type, currency, project) accept 1 to 1000 and exit with code 2 before any request above that. Use --all to read more. The table commands keep their own limit |
| No way to read every record of a list | --all reads every record page by page and asks first on stderr ([y/N]). --yes skips the question. With redirected stdin, stdout, or stderr and no --yes, the command stops with exit code 2 before any request. --all cannot be combined with --take |
customer transaction list-for, project all, and project work-request list-for ran without a question |
Breaking for scripts. They always read every record, so they now ask the same question and take --yes. A script that runs them unattended must add --yes |
--json on a list printed one array after reading everything |
The fluent lists stream the array record by record. A failure or Ctrl+C after the first page leaves a truncated array on stdout with a non-zero exit code, so check the exit code before you use the file |
| (new) | --include and --exclude choose the properties DK Plus returns on 13 lists; a table under --include shows only the named columns |
| (new) | customer list filters on the server with --name, --sales-person, --country, --postal-code, --payment-term, --payment-mode, --email, --blocked, --vat-exempt, and --deleted; product list with --alias-item-code, --inactive, --on-web, and --deleted. The boolean filters take a value (--blocked false) |
| (new) | table create, table update, and table delete write generic table records; only delete needs --yes. project delete deletes a project (with --yes) |
A bad --include name ended with (Parameter 'propertyNames') |
The message no longer carries the .NET parameter-name suffix |
| Before | Now |
|---|---|
-Take accepted up to 10,000 |
Breaking. The 18 list cmdlets accept 1 to 1000. Use -All to read more |
Get-Project -All read the unpaged v1 endpoint |
Breaking. That endpoint is now Get-Project -Unpaged. -All pages through the list like the other list cmdlets |
Get-WorkRequest -Project X -All ran without a prompt |
Breaking for scripts. Every -All read (and Get-Project -Unpaged) confirms like a High-impact cmdlet. Pass -Confirm:$false in scripts; a host that cannot prompt fails before any request without it. -All:$false behaves as if -All were omitted |
Get-CustomerTransaction -Include/-Exclude without a page-only parameter selected the Page set and took DK Plus wire field names |
Breaking. They now select the list set and take public property names, so -Exclude ID fails. Add -Page (or another page-only parameter) to keep wire field names |
Get-Customer -N, -S, -Pa |
Breaking. These abbreviations are now ambiguous (-Number/-Name, -Search/-SalesPerson, -PageSize/-PaymentTerm/-PaymentMode) and the binder reports an error. Spell the parameter name out |
Get-CustomerTransaction -Customer X -All |
Still reads the customer's own list, and now fails with DkPlus.InvalidArgument when combined with -ModifiedSince, -PageSize, -Include, or -Exclude |
| (new) | Get-Customer and Get-Product gain the same server-side filters as the CLI (-Name, -Email, -Blocked, -OnWeb, ...), and 13 list cmdlets gain -Include/-Exclude with Tab completion |
| (new) | New-TableRecord, Update-TableRecord, Remove-TableRecord, and Remove-Project (147 cmdlets in total) |
Piping into Remove-Project asks once for the whole batch; calling it inside ForEach-Object prompts for every item. See Pipelines and updates.
| Before | Now |
|---|---|
client.Customer.Query() and client.Product.Query() returned IDkPlusQuery<DkPlusCustomer> and IDkPlusQuery<DkPlusProduct> |
They return ICustomerQuery and IProductQuery, which derive from IDkPlusQuery<T> and add the typed filters. Callers are binary-compatible. A var that holds the query and is reassigned from a helper returning IDkPlusQuery<T> needs an explicit type, and a custom implementation of IDkPlusCustomerResource or IDkPlusProductResource must add the new Query() member. IExternalErpClient is unchanged |
ForGroup("A1") on a customer or product query sent group=A1 |
The customer and product group is sent lowercase (group=a1), on the DK and the portable query alike. Live, DK Plus matched the customer group only in lowercase, so A1 used to return nothing |
| A continuation token from a 0.4.x customer or product query with an uppercase group | Rejected with ArgumentException, because the group in the filter hash is now lowercase. Restart the query without a token. Other 0.4.x tokens keep working |
| (new) | Customer filters ForName, ForSalesPerson, ForCountry, ForPostalCode, ForPaymentTerm, ForPaymentMode, ForEmail, Blocked, VatExempt, Deleted; product filters ForAliasItemCode, Inactive, OnWeb, Deleted. Text is sent lowercase and the country uppercase, and a name without * is a contains search. See Client API and queries |
| (new) | DkPlusProjections lists the property names Include and Exclude accept per model type |
| (new) | Project.DeleteAsync(number) and Project.DeleteByRecordIdAsync(recordId) delete through the generic table pjjob |
The library's Take() stays unbounded; only the CLI and the module cap --take/-Take at 1000.
These were checked against a live DK Plus company on 2026-10-13:
--name/-Name/ForName matches only with a wildcard, so the client turns Jón into *jón*. A value of several words matches nothing.IS currently match no customers; numeric codes do.--blocked false (Blocked(false)) and --deleted true select is not verified.