diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b5b898d..809e1158 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +### 1.47.0 - 2026-02-24 +- Always use container relative URLs +- Remove ExperimentalFeatures.containerRelativeURL +- Update tests to assume container relative URLs +- Add justfile + ### 1.46.1 - 2026-02-17 - Update Array filter multi-value delimiter to ';' to match IN/NOT IN filter types to allow filter type conversion diff --git a/justfile b/justfile new file mode 100644 index 00000000..7a059607 --- /dev/null +++ b/justfile @@ -0,0 +1,102 @@ +# Note: this justfile should work for anyone using MacOS, however with some work we can probably get it to also work on +# Windows if we use the [unix] and [windows] attributes on the commands that execute shell scripts: +# https://just.systems/man/en/attributes.html#enabling-and-disabling-recipes180 + +[private] +default: + just --list + +currentBranch := `git branch --show-current` +branchAsTag := replace(currentBranch, '_', '-') +packageName := '@labkey/api' +pwd := `pwd` + +# We quote the paths from our environment variables so these variables will work even if the paths contains spaces +# We trim the trailing / from our environment variables so we can treat them consistently with our other paths +components := quote(trim_end_match(env('LABKEY_UI_COMPONENTS_HOME'), '/') / 'packages/components') +premium := quote(trim_end_match(env('LABKEY_UI_PREMIUM_HOME'), '/')) +distPath := 'node_modules' / packageName / 'dist' +sourceDist := pwd / 'dist/' +modulesToBump := components + ' ' + premium +copyLocations := append('/' + distPath, modulesToBump) + +# Builds the package +build: + npm run build + +# Copies built package to NODE_MODULES directory for every module listed in copyLocations +copy: + #!/usr/bin/env zsh + set -euo pipefail + for module in {{ copyLocations }}; do + echo '{{ GREEN }}'Copying built package to '{{CYAN}}'$module'{{ NORMAL }}' + rsync -ra {{ sourceDist }} $module + done + +# Builds the package and copies it to NODE_MODULES for every module listed in copyLocations +bc: build copy + +# Bumps version to a prerelease version based on the current branch name +preVersion: + @echo {{ GREEN }}Bumping prerelease version with preid='{{CYAN}}'{{ branchAsTag }}{{ NORMAL }} + @npm version prerelease --preid {{ branchAsTag }} --no-git-tag-version + +# Publishes the current version with the current branch name as a tag +publishPreVersion: + @echo {{ GREEN }}Publishing prerelease package{{ NORMAL }} + @npm publish --tag {{ branchAsTag }} + +[private] +sleep: + @echo {{ GREEN }}"Sleeping so artifactory doesn't return 404"{{ NORMAL }} + @sleep 6 + +# Lists the modules in the 'modulesToBump' variable +listModules: + #!/usr/bin/env zsh + set -euo pipefail + for module in {{ modulesToBump }}; do + echo $module + done + +# Stored as a string because we want to execute this when scripts are run, not when the justfile is evaluated, so we +# always have the most up to date version. +currentVersionImport := quote("require('./package.json').version") + +# lists the current package version +version: + @echo $(node -p -e {{ currentVersionImport }}) + +# Bumps the @labkey/premium package to the current version in every module listed in the modulesToBump variable +bump: + #!/usr/bin/env zsh + set -euo pipefail + v=$(node -p -e {{ currentVersionImport }}) + echo '{{ GREEN }}'Bumping {{ packageName }} to '{{CYAN}}'$v'{{ NORMAL }}' + for module in {{ modulesToBump }}; do + pushd $module + echo '{{ GREEN }}'Bumping {{ packageName }} in '{{CYAN}}'$(pwd)'{{ NORMAL }}' + npm install --legacy-peer-deps --save-exact {{ packageName }}@$v + popd + done + +# Bumps the version to a prerelease version based on the current branch name, publishes the version, and bumps it in every module listed in modulesToBump +release: preVersion publishPreVersion sleep bump + +# Bumps the major version +major: + npm version major --no-git-tag-version + +# Bumps the minor version +minor: + npm version minor --no-git-tag-version + +# Bumps the patch version +patch: + npm version patch --no-git-tag-version + +# Publishes the current version, must be a production version +publish: + npm publish + +pb: publish sleep bump diff --git a/package-lock.json b/package-lock.json index e432717a..926b70fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@labkey/api", - "version": "1.46.1", + "version": "1.47.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@labkey/api", - "version": "1.46.1", + "version": "1.47.0", "license": "Apache-2.0", "devDependencies": { "@babel/core": "7.29.0", diff --git a/package.json b/package.json index efaa2a34..6bca497d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@labkey/api", - "version": "1.46.1", + "version": "1.47.0", "description": "JavaScript client API for LabKey Server", "scripts": { "build": "npm run build:dist && npm run build:docs", diff --git a/src/labkey/ActionURL.spec.ts b/src/labkey/ActionURL.spec.ts index 4cb5de47..a28c8a29 100644 --- a/src/labkey/ActionURL.spec.ts +++ b/src/labkey/ActionURL.spec.ts @@ -31,13 +31,13 @@ describe('ActionURL', () => { it('should build the correct URL', () => { const url = ActionURL.buildURL('project', 'getWebPart', 'MyContainer'); - expect(url).toEqual('/project/MyContainer/getWebPart.view'); + expect(url).toEqual('/MyContainer/project-getWebPart.view'); }); it('should build the correct URL with optional parameters', () => { const params = { listId: 50, returnUrl: 'home', array: [10, 'li'] }; const url = ActionURL.buildURL('project', 'getWebPart', 'MyContainer', params); - expect(url).toEqual('/project/MyContainer/getWebPart.view?listId=50&returnUrl=home&array=10&array=li'); + expect(url).toEqual('/MyContainer/project-getWebPart.view?listId=50&returnUrl=home&array=10&array=li'); }); }); diff --git a/src/labkey/ActionURL.ts b/src/labkey/ActionURL.ts index 11493c41..50a77c02 100644 --- a/src/labkey/ActionURL.ts +++ b/src/labkey/ActionURL.ts @@ -120,15 +120,10 @@ export function buildURL( if (action.indexOf('.') == -1) { action += '.view'; } - const query = queryString(parameters); - let newURL: string; - const { contextPath, experimental } = getServerContext(); - if (experimental && experimental.containerRelativeURL) { - newURL = contextPath + containerPath + controller + '-' + action; - } else { - newURL = contextPath + '/' + controller + containerPath + action; - } + const query = queryString(parameters); + const { contextPath } = getServerContext(); + let newURL = contextPath + containerPath + controller + '-' + action; if (query) { newURL += '?' + query; diff --git a/src/labkey/Assay.spec.ts b/src/labkey/Assay.spec.ts index bdd748e0..56bf5f7a 100644 --- a/src/labkey/Assay.spec.ts +++ b/src/labkey/Assay.spec.ts @@ -40,7 +40,7 @@ describe('assayList.api requests', () => { // Assert expect(requestSpy).toHaveBeenCalledWith( expect.objectContaining({ - url: '/assay/my/special/folder/assayList.api', + url: '/my/special/folder/assay-assayList.api', }) ); }); @@ -59,7 +59,7 @@ describe('assayList.api requests', () => { expect(requestSpy).toHaveBeenCalledWith( expect.objectContaining({ jsonData: { id: assayId }, - url: '/assay/my/special/folder/assayList.api', + url: '/my/special/folder/assay-assayList.api', }) ); }); @@ -78,7 +78,7 @@ describe('assayList.api requests', () => { expect(requestSpy).toHaveBeenCalledWith( expect.objectContaining({ jsonData: { name: assayName }, - url: '/assay/my/special/folder/assayList.api', + url: '/my/special/folder/assay-assayList.api', }) ); }); @@ -97,7 +97,7 @@ describe('assayList.api requests', () => { expect(requestSpy).toHaveBeenCalledWith( expect.objectContaining({ jsonData: { type: assayType }, - url: '/assay/my/special/folder/assayList.api', + url: '/my/special/folder/assay-assayList.api', }) ); }); @@ -117,7 +117,7 @@ describe('assayList.api requests', () => { expect(requestSpy).toHaveBeenCalledWith( expect.objectContaining({ jsonData: { id, name, plateEnabled, status, type }, - url: '/assay/assayList.api', + url: '/assay-assayList.api', }) ); }); diff --git a/src/labkey/Report.spec.ts b/src/labkey/Report.spec.ts index 6a6e1d92..6ed1fb16 100644 --- a/src/labkey/Report.spec.ts +++ b/src/labkey/Report.spec.ts @@ -35,7 +35,7 @@ describe('execute', () => { // Assert expect(requestSpy).toHaveBeenCalledWith( expect.objectContaining({ - url: '/reports/execute.api', + url: '/reports-execute.api', method: 'POST', jsonData: { reportId: 'db:123', diff --git a/src/labkey/constants.ts b/src/labkey/constants.ts index ceb77045..52636784 100644 --- a/src/labkey/constants.ts +++ b/src/labkey/constants.ts @@ -74,7 +74,6 @@ export interface Project { } export enum ExperimentalFeatures { - containerRelativeURL = 'containerRelativeURL', disableGuestAccount = 'disableGuestAccount', } diff --git a/src/labkey/query/Rows.spec.ts b/src/labkey/query/Rows.spec.ts index ffb0d1d7..e92ebc5f 100644 --- a/src/labkey/query/Rows.spec.ts +++ b/src/labkey/query/Rows.spec.ts @@ -40,7 +40,7 @@ describe('deleteRows', () => { rows, schemaName, }), - url: '/query/deleteRows.api', + url: '/query-deleteRows.api', }) ); }); @@ -69,7 +69,7 @@ describe('insertRows', () => { rows, schemaName, }), - url: '/query/insertRows.api', + url: '/query-insertRows.api', }) ); }); @@ -92,7 +92,7 @@ describe('insertRows', () => { expect.objectContaining({ method: 'POST', form: expect.anything(), - url: '/query/insertRows.api', + url: '/query-insertRows.api', }) ); expect(requestSpy).toHaveBeenCalledWith( @@ -117,7 +117,7 @@ describe('insertRows', () => { expect.objectContaining({ method: 'POST', form: expect.anything(), - url: '/query/insertRows.api', + url: '/query-insertRows.api', }) ); }); @@ -146,7 +146,7 @@ describe('updateRows', () => { rows, schemaName, }), - url: '/query/updateRows.api', + url: '/query-updateRows.api', }) ); }); @@ -169,7 +169,7 @@ describe('updateRows', () => { expect.objectContaining({ method: 'POST', form: expect.anything(), - url: '/query/updateRows.api', + url: '/query-updateRows.api', }) ); expect(requestSpy).toHaveBeenCalledWith( @@ -224,7 +224,7 @@ describe('saveRows', () => { jsonData: expect.objectContaining({ commands, }), - url: '/query/saveRows.api', + url: '/query-saveRows.api', }) ); }); @@ -267,7 +267,7 @@ describe('saveRows', () => { expect(requestSpy).toHaveBeenCalledWith( expect.objectContaining({ method: 'POST', - url: '/query/saveRows.api', + url: '/query-saveRows.api', }) ); const form = requestSpy.mock.lastCall[0].form; diff --git a/src/labkey/query/SelectRows.spec.ts b/src/labkey/query/SelectRows.spec.ts index ac7214c8..02040a63 100644 --- a/src/labkey/query/SelectRows.spec.ts +++ b/src/labkey/query/SelectRows.spec.ts @@ -88,7 +88,7 @@ describe('selectRows', () => { expect(requestSpy).toHaveBeenCalledWith( expect.objectContaining({ // default to container-free URL - url: '/query/getQuery.api', + url: '/query-getQuery.api', // default to 'GET' request method: 'GET', @@ -138,7 +138,7 @@ describe('selectRows -- optional parameters', () => { test('containerPath', () => { const containerPath = '/container'; - expect(selectRowsRequest({ containerPath })).toHaveProperty('url', '/query/container/getQuery.api'); + expect(selectRowsRequest({ containerPath })).toHaveProperty('url', '/container/query-getQuery.api'); }); test('dataRegionName', () => {