diff --git a/.github/workflows/docker-io.yml b/.github/workflows/docker-io.yml index 8cbeb042..beff4589 100644 --- a/.github/workflows/docker-io.yml +++ b/.github/workflows/docker-io.yml @@ -1,6 +1,4 @@ name: Docker IO -permissions: - contents: write on: - push jobs: @@ -51,7 +49,7 @@ jobs: with: context: . file: docker/Dockerfile.io - platforms: linux/amd64,linux/arm64 + platforms: linux/amd64 push: true tags: | coderaiser/cloudcmd:io diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 5c81d368..1a85b29e 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -1,6 +1,4 @@ name: Docker CI -permissions: - contents: write on: push: tags: diff --git a/.madrun.js b/.madrun.js index efa8ce98..7452328c 100644 --- a/.madrun.js +++ b/.madrun.js @@ -21,14 +21,14 @@ export default { 'start:dev', ]), 'lint:all': () => run('lint:progress'), - 'lint': () => 'redlint fix; putout .', + 'lint': () => 'redlint fix; putout . --rulesdir rules', 'lint:progress': () => run('lint', '-f progress'), 'watch:lint': () => 'nodemon -w client -w server -w test -w common -w .webpack -x "putout -s"', 'fresh:lint': () => run('lint', '--fresh'), 'lint:fresh': () => run('lint', '--fresh'), - 'fix:lint': async () => `putout --fix . && redlint fix`, + 'fix:lint': async () => `putout --rulesdir rules --fix . && redlint fix`, 'lint:stream': () => run('lint', '-f stream'), - 'test': () => [testEnv, `tape '{test}/**/*.js' '{bin,client,static,common,server}/**/*.spec.js' -f fail`], + 'test': () => [testEnv, `tape '{test,test-e2e}/**/*.js' '{bin,client,static,common,server}/**/*.spec.js' -f fail`], 'test:e2e': () => `tape 'test-e2e/**/*.js'`, 'test:client': () => `tape 'test/client/**/*.js'`, 'test:server': () => `tape 'test/**/*.js' 'server/**/*.spec.js' 'common/**/*.spec.js'`, @@ -39,7 +39,7 @@ export default { 'coverage': async () => [testEnv, `c8 ${await cutEnv('test')}`], 'coverage:report': () => 'c8 report --reporter=lcov', 'report': () => 'c8 report --reporter=lcov', - '6to5': () => [buildEnv, 'rspack build --config rspack.config.js'], + '6to5': () => [buildEnv, 'webpack --progress'], '6to5:client': () => run('6to5', '--mode production'), '6to5:client:dev': async () => await run('6to5', '--mode development', { NODE_ENV: 'development', diff --git a/.rspack/css.js b/.webpack/css.js similarity index 53% rename from .rspack/css.js rename to .webpack/css.js index 10d28250..311290cc 100644 --- a/.rspack/css.js +++ b/.webpack/css.js @@ -1,18 +1,19 @@ import {env} from 'node:process'; -import {rspack} from '@rspack/core'; +import CssMinimizerPlugin from 'css-minimizer-webpack-plugin'; +import MiniCssExtractPlugin from 'mini-css-extract-plugin'; -const {CssExtractRspackPlugin} = rspack; const isDev = env.NODE_ENV === 'development'; +const clean = (a) => a.filter(Boolean); -const plugins = [ - new CssExtractRspackPlugin({ +const plugins = clean([ + new MiniCssExtractPlugin({ filename: '[name].css', }), -]; +]); const rules = [{ test: /\.css$/i, - use: [CssExtractRspackPlugin.loader, { + use: [MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { url: true, @@ -32,7 +33,13 @@ export default { optimization: { minimize: !isDev, minimizer: [ - new rspack.LightningCssMinimizerRspackPlugin(), + new CssMinimizerPlugin({ + minimizerOptions: { + preset: ['default', { + svgo: false, + }], + }, + }), ], }, }; diff --git a/.rspack/html.js b/.webpack/html.js similarity index 100% rename from .rspack/html.js rename to .webpack/html.js diff --git a/.rspack/js.js b/.webpack/js.js similarity index 81% rename from .rspack/js.js rename to .webpack/js.js index 251d85f6..fdc88556 100644 --- a/.rspack/js.js +++ b/.webpack/js.js @@ -1,15 +1,12 @@ import {resolve, sep} from 'node:path'; -import {fileURLToPath} from 'node:url'; import {env} from 'node:process'; -import {rspack} from '@rspack/core'; - -const resolveModule = (a) => fileURLToPath(import.meta.resolve(a)); +import webpack from 'webpack'; +import WebpackBar from 'webpackbar'; const { EnvironmentPlugin, NormalModuleReplacementPlugin, - ProvidePlugin, -} = rspack; +} = webpack; const modules = './modules'; const dirModules = './client/modules'; @@ -25,31 +22,27 @@ const dist = resolve(rootDir, 'dist'); const distDev = resolve(rootDir, 'dist-dev'); const devtool = isDev ? 'eval' : 'source-map'; -const noParse = (a) => a.endsWith('.spec.js'); +const notEmpty = (a) => a; +const clean = (array) => array.filter(notEmpty); -// codegen.macro is a babel-macro (build-time codegen), not supported by -// Rspack's native SWC transform, so client/sw/sw.js (the only file that -// uses it) keeps going through babel-loader. Everything else uses -// Rspack's built-in SWC loader, which is the main source of the speedup. -const rules = [{ - test: /sw\/sw\.js$/, - exclude: /node_modules/, - loader: 'babel-loader', -}, { - test: /\.[mc]?js$/, - exclude: [/node_modules/, /sw\/sw\.js$/], - loader: 'builtin:swc-loader', - options: { - jsc: { - parser: { - syntax: 'ecmascript', - }, - }, - env: { - targets: 'defaults', - }, +const noParse = (a) => a.endsWith('.spec.js'); +const options = { + babelrc: true, +}; + +const rules = clean([ + !isDev && { + test: /\.[mc]?js$/, + exclude: /node_modules/, + loader: 'babel-loader', }, -}]; + isDev && { + test: /\.[mc]?js$/, + exclude: /node_modules/, + loader: 'babel-loader', + options, + }, +]); const plugins = [ new NormalModuleReplacementPlugin(/^node:/, (resource) => { @@ -59,7 +52,8 @@ const plugins = [ new EnvironmentPlugin({ NODE_ENV, }), - new ProvidePlugin({ + new WebpackBar(), + new webpack.ProvidePlugin({ process: 'process/browser', }), ]; @@ -105,9 +99,9 @@ export default { 'node:path': 'path', }, fallback: { - path: resolveModule('path-browserify'), - process: resolveModule('process/browser'), - util: resolveModule('util'), + path: import.meta.resolve('path-browserify'), + process: import.meta.resolve('process/browser'), + util: import.meta.resolve('util'), }, }, devtool, @@ -162,7 +156,7 @@ export default { }, plugins, performance: { - maxEntrypointSize: 800_000, + maxEntrypointSize: 600_000, maxAssetSize: 600_000, }, }; diff --git a/client/dom/current-file.spec.js b/client/dom/current-file.spec.js index 85b18a29..6bf0509b 100644 --- a/client/dom/current-file.spec.js +++ b/client/dom/current-file.spec.js @@ -19,13 +19,14 @@ test('current-file: setCurrentName: setAttribute', (t) => { currentFile.setCurrentName('hello', current); - globalThis.DOM = DOM; - globalThis.CloudCmd = CloudCmd; - t.calledWith(setAttribute, [ 'data-name', 'js-file-aGVsbG8=', ], 'should call setAttribute'); + + globalThis.DOM = DOM; + globalThis.CloudCmd = CloudCmd; + t.end(); }); @@ -40,13 +41,14 @@ test('current-file: setCurrentName: setAttribute: cyrillic', (t) => { currentFile.setCurrentName('ай', current); - globalThis.DOM = DOM; - globalThis.CloudCmd = CloudCmd; - t.calledWith(setAttribute, [ 'data-name', 'js-file-JUQwJUIwJUQwJUI5', ], 'should call setAttribute'); + + globalThis.DOM = DOM; + globalThis.CloudCmd = CloudCmd; + t.end(); }); @@ -74,10 +76,11 @@ test('current-file: emit', (t) => { currentFile.setCurrentName('hello', current); + t.calledWith(emit, ['current-file', current], 'should call emit'); + globalThis.DOM = DOM; globalThis.CloudCmd = CloudCmd; - t.calledWith(emit, ['current-file', current], 'should call emit'); t.end(); }); @@ -93,12 +96,14 @@ test('current-file: setCurrentName: return', (t) => { globalThis.CloudCmd = getCloudCmd(); const current = create(); + const result = currentFile.setCurrentName('hello', current); + t.equal(result, link, 'should return link'); + globalThis.DOM = DOM; globalThis.CloudCmd = CloudCmd; - t.equal(result, link, 'should return link'); t.end(); }); diff --git a/client/dom/dom-tree.spec.js b/client/dom/dom-tree.spec.js index 53b376c7..13f56f6d 100644 --- a/client/dom/dom-tree.spec.js +++ b/client/dom/dom-tree.spec.js @@ -1,16 +1,7 @@ -import {test, stub} from 'supertape'; +import test from 'supertape'; import {create} from 'auto-globals'; import {tryCatch} from 'try-catch'; -import { - isContainClass, - getByTag, - getById, - getByClass, - getByDataName, - getByClassAll, - hide, - show, -} from './dom-tree.js'; +import {isContainClass} from './dom-tree.js'; test('dom: isContainClass: no element', (t) => { const [e] = tryCatch(isContainClass); @@ -47,106 +38,3 @@ test('dom: isContainClass: contains: array', (t) => { t.calledWith(contains, [className], 'should call contains'); t.end(); }); - -test('dom: getByTag', (t) => { - const getElementsByTagName = stub(); - const element = { - getElementsByTagName, - }; - - getByTag('div', element); - - t.calledWith(getElementsByTagName, ['div'], 'should call getElementsByTagName'); - t.end(); -}); - -test('dom: getById', (t) => { - const querySelector = stub(); - const element = { - querySelector, - }; - - getById('my-id', element); - - t.calledWith(querySelector, ['#my-id'], 'should call querySelector with id selector'); - t.end(); -}); - -test('dom: getByClassAll', (t) => { - const getElementsByClassName = stub(); - const element = { - getElementsByClassName, - }; - - getByClassAll('my-class', element); - - t.calledWith(getElementsByClassName, ['my-class'], 'should call getElementsByClassName'); - t.end(); -}); - -test('dom: getByClass: calls getByClassAll', (t) => { - const element = { - getElementsByClassName: stub().returns(['first']), - }; - - const result = getByClass('my-class', element); - - t.equal(result, 'first', 'should return first element from class list'); - t.end(); -}); - -test('dom: getByDataName', (t) => { - const querySelector = stub(); - const element = { - querySelector, - }; - - getByDataName('hello', element); - - t.calledWith(querySelector, ['[data-name="hello"]'], 'should call querySelector with data-name selector'); - t.end(); -}); - -test('dom: hide', (t) => { - const add = stub(); - const element = { - classList: { - add, - }, - }; - - hide(element); - - t.calledWith(add, ['hidden'], 'should add hidden class'); - t.end(); -}); - -test('dom: show', (t) => { - const remove = stub(); - const element = { - classList: { - remove, - }, - }; - - show(element); - - t.calledWith(remove, ['hidden'], 'should remove hidden class'); - t.end(); -}); - -test('dom: getByClassAll: without element uses document', (t) => { - const getElementsByClassName = stub(); - const prevDocument = globalThis.document; - - globalThis.document = { - getElementsByClassName, - }; - - getByClassAll('my-class'); - - globalThis.document = prevDocument; - - t.calledWith(getElementsByClassName, ['my-class'], 'should fallback to document when no element'); - t.end(); -}); diff --git a/client/dom/index.js b/client/dom/index.js index a82b6f72..f6ce6bc7 100644 --- a/client/dom/index.js +++ b/client/dom/index.js @@ -442,7 +442,11 @@ export function getFilenames(files) { if (name === '..') allFiles.shift(); - return allFiles.map(DOM.getCurrentName); + const names = allFiles.map((current) => { + return DOM.getCurrentName(current); + }); + + return names; } /** diff --git a/client/dom/load-remote.js b/client/dom/load-remote.js index 5be8e327..43af0cf5 100644 --- a/client/dom/load-remote.js +++ b/client/dom/load-remote.js @@ -33,19 +33,13 @@ export const loadRemote = callbackify(async (name, options) => { local = [module.local]; } - const localURL = []; + const localURL = local.map((url) => prefix + url); - for (const url of local) { - localURL.push(prefix + url); - } - - const remoteURL = []; - - for (const tmpl of remoteTmpls) { - remoteURL.push(rendy(tmpl, { + const remoteURL = remoteTmpls.map((tmpl) => { + return rendy(tmpl, { version, - })); - } + }); + }); if (online) { const [e] = await tryToCatch(load.parallel, remoteURL); diff --git a/client/key/binder.spec.js b/client/key/binder.spec.js deleted file mode 100644 index f9d54fdd..00000000 --- a/client/key/binder.spec.js +++ /dev/null @@ -1,28 +0,0 @@ -import {test} from 'supertape'; -import {createBinder} from './binder.js'; - -test('client: key: binder: isBind: default', (t) => { - const binder = createBinder(); - - t.notOk(binder.isBind(), 'should not be bind by default'); - t.end(); -}); - -test('client: key: binder: setBind', (t) => { - const binder = createBinder(); - - binder.setBind(); - - t.ok(binder.isBind(), 'should be bind'); - t.end(); -}); - -test('client: key: binder: unsetBind', (t) => { - const binder = createBinder(); - - binder.setBind(); - binder.unsetBind(); - - t.notOk(binder.isBind(), 'should not be bind'); - t.end(); -}); diff --git a/client/key/vim/find.spec.js b/client/key/vim/find.spec.js index 191a3652..59c9a249 100644 --- a/client/key/vim/find.spec.js +++ b/client/key/vim/find.spec.js @@ -1,12 +1,6 @@ import test from 'supertape'; import {getDOM} from './globals.fixture.js'; -import { - _next, - _previous, - find, - findNext, - findPrevious, -} from './find.js'; +import {_next, _previous} from './find.js'; globalThis.DOM = getDOM(); @@ -17,39 +11,9 @@ test('cloudcmd: client: vim: _next', (t) => { t.end(); }); -test('cloudcmd: client: vim: _next: increment', (t) => { - const result = _next(0, 2); - - t.equal(result, 1, 'should return 1'); - t.end(); -}); - test('cloudcmd: client: vim: _previous', (t) => { const result = _previous(0, 2); t.equal(result, 1, 'should return 1'); t.end(); }); - -test('cloudcmd: client: vim: _previous: decrement', (t) => { - const result = _previous(1, 2); - - t.equal(result, 0, 'should return 0'); - t.end(); -}); - -test('cloudcmd: client: vim: findNext: after find', (t) => { - find('a', ['alpha', 'beta', 'apple']); - const result = findNext(); - - t.equal(result, 'beta', 'should return next found name'); - t.end(); -}); - -test('cloudcmd: client: vim: findPrevious: after find', (t) => { - find('a', ['alpha', 'beta', 'apple']); - const result = findPrevious(); - - t.equal(result, 'apple', 'should return previous found name'); - t.end(); -}); diff --git a/client/key/vim/index.spec.js b/client/key/vim/index.spec.js index 231c6577..e1ca4eee 100644 --- a/client/key/vim/index.spec.js +++ b/client/key/vim/index.spec.js @@ -1,7 +1,6 @@ import {test, stub} from 'supertape'; import {getDOM, getCloudCmd} from './globals.fixture.js'; import vim, {selectFile as vimSelectFile} from './index.js'; -import * as finder from './find.js'; globalThis.DOM = getDOM(); globalThis.CloudCmd = getCloudCmd(); @@ -676,81 +675,3 @@ test('cloudcmd: client: vim: rename', async (t) => { t.calledWithNoArgs(renameCurrent); t.end(); }); - -test('cloudcmd: client: key: cc: operationCopy', (t) => { - const show = stub(); - const preventDefault = stub(); - - const Operation = { - show, - }; - - const event = { - preventDefault, - }; - - vim('c', event, { - Operation, - }); - - vim('c', event, { - Operation, - }); - - t.calledWith(show, ['copy'], 'should show copy operation'); - t.end(); -}); - -test('cloudcmd: client: key: mm: operationMove', (t) => { - const show = stub(); - const preventDefault = stub(); - - const Operation = { - show, - }; - - const event = { - preventDefault, - }; - - vim('m', event, { - Operation, - }); - - vim('m', event, { - Operation, - }); - - t.calledWith(show, ['move'], 'should show move operation'); - t.end(); -}); - -test('cloudcmd: client: key: n: findNext: real', (t) => { - const setCurrentByName = stub(); - - finder.find('a', ['alpha', 'beta', 'apple']); - - const event = {}; - - vim('n', event, { - setCurrentByName, - }); - - t.calledWith(setCurrentByName, ['beta'], 'should set current by next found name'); - t.end(); -}); - -test('cloudcmd: client: key: N: findPrevious: real', (t) => { - const setCurrentByName = stub(); - - finder.find('a', ['alpha', 'beta', 'apple']); - - const event = {}; - - vim('N', event, { - setCurrentByName, - }); - - t.calledWith(setCurrentByName, ['apple'], 'should set current by previous found name'); - t.end(); -}); diff --git a/client/modules/config/input.spec.js b/client/modules/config/input.spec.js index 9d0866cd..537c1632 100644 --- a/client/modules/config/input.spec.js +++ b/client/modules/config/input.spec.js @@ -1,10 +1,5 @@ -import {test, stub} from 'supertape'; -import { - convert, - getName, - getValue, - setValue, -} from './input.js'; +import {test} from 'supertape'; +import {convert} from './input.js'; test('cloudcmd: client: config: input: convert', (t) => { const result = convert({ @@ -18,123 +13,3 @@ test('cloudcmd: client: config: input: convert', (t) => { t.deepEqual(result, expected); t.end(); }); - -test('cloudcmd: client: config: input: convert: bool', (t) => { - const result = convert({ - auth: true, - }); - - const expected = { - auth: ' checked', - }; - - t.deepEqual(result, expected); - t.end(); -}); - -test('cloudcmd: client: config: input: convert: bool false', (t) => { - const result = convert({ - auth: false, - }); - - const expected = { - auth: '', - }; - - t.deepEqual(result, expected); - t.end(); -}); - -test('cloudcmd: client: config: input: getName', (t) => { - const getAttribute = stub().returns('js-hello'); - const element = { - getAttribute, - }; - - const result = getName(element); - - t.equal(result, 'hello', 'should strip js- prefix'); - t.end(); -}); - -test('cloudcmd: client: config: input: getValue: checkbox', (t) => { - const querySelector = stub().returns({ - type: 'checkbox', - checked: true, - }); - - const element = { - querySelector, - }; - - const result = getValue('auth', element); - - t.ok(result, 'should return checked value'); - t.end(); -}); - -test('cloudcmd: client: config: input: getValue: number', (t) => { - const querySelector = stub().returns({ - type: 'number', - value: '42', - }); - - const element = { - querySelector, - }; - - const result = getValue('port', element); - - t.equal(result, 42, 'should return number'); - t.end(); -}); - -test('cloudcmd: client: config: input: getValue: default', (t) => { - const querySelector = stub().returns({ - type: 'text', - value: 'hello', - }); - - const element = { - querySelector, - }; - - const result = getValue('name', element); - - t.equal(result, 'hello', 'should return value as is'); - t.end(); -}); - -test('cloudcmd: client: config: input: setValue: checkbox', (t) => { - const el = { - type: 'checkbox', - checked: false, - }; - - const querySelector = stub().returns(el); - const element = { - querySelector, - }; - - setValue('auth', true, element); - - t.ok(el.checked, 'should set checked'); - t.end(); -}); - -test('cloudcmd: client: config: input: setValue: default', (t) => { - const el = { - type: 'text', - value: 'old', - }; - - const querySelector = stub().returns(el); - const element = { - querySelector, - }; - - setValue('name', 'new', element); - - t.equal(el.value, 'new', 'should set value'); - t.end(); -}); diff --git a/client/modules/view/index.spec.js b/client/modules/view/index.spec.js index abfbe3f4..8d184548 100644 --- a/client/modules/view/index.spec.js +++ b/client/modules/view/index.spec.js @@ -31,10 +31,8 @@ test('cloudcmd: client: view: initConfig', (t) => { test('cloudcmd: client: view: initConfig: no options', (t) => { const config = _initConfig(); - const result = typeof config; - const expected = 'object'; - t.equal(result, expected); + t.equal(typeof config, 'object'); t.end(); }); diff --git a/client/sw/register.spec.js b/client/sw/register.spec.js index 52699f0b..47420ba7 100644 --- a/client/sw/register.spec.js +++ b/client/sw/register.spec.js @@ -65,7 +65,7 @@ test('sw: register: registerSW: http', async (t, {location, navigator}) => { test('sw: register: registerSW: https self-signed', async (t, {location, navigator}) => { Object.assign(location, { - protocol: 'https:', + protocol: 'https', hostname: 'self-signed.badssl.com', }); diff --git a/common/cloudfunc.spec.js b/common/cloudfunc.spec.js index b679feeb..dca24b5a 100644 --- a/common/cloudfunc.spec.js +++ b/common/cloudfunc.spec.js @@ -2,17 +2,12 @@ import {readFileSync} from 'node:fs'; import test from 'supertape'; import {montag} from 'montag'; import * as cheerio from 'cheerio'; -import {tryCatch} from 'try-catch'; import { _getSize, getPathLink, buildFromJSON, _getDataName, dateFormatter, - formatMsg, - getTitle, - getDotDot, - getHeaderField, } from '#common/cloudfunc'; const templatePath = new URL('../tmpl/fs', import.meta.url).pathname; @@ -226,97 +221,6 @@ test('cloudfunc: _getDataName', (t) => { t.end(); }); -test('cloudfunc: formatMsg: name', (t) => { - const result = formatMsg('hello', 'world'); - const expected = 'hello: ok("world")'; - - t.equal(result, expected, 'should format message with name'); - t.end(); -}); - -test('cloudfunc: formatMsg: no name', (t) => { - const result = formatMsg('hello'); - const expected = 'hello: ok'; - - t.equal(result, expected, 'should format message without name'); - t.end(); -}); - -test('cloudfunc: getTitle: no options', (t) => { - const result = getTitle(); - - t.ok(result, 'should return a title string even without options'); - t.end(); -}); - -test('cloudfunc: getTitle: with name', (t) => { - const result = getTitle({ - name: 'MyName', - }); - - t.match(result, 'MyName', 'should return title with name'); - t.end(); -}); - -test('cloudfunc: getHeaderField: sort not name', (t) => { - const result = getHeaderField('size', 'asc', 'name'); - - t.equal(result, 'name', 'should return plain name when sort does not match'); - t.end(); -}); - -test('cloudfunc: getHeaderField: sort name asc', (t) => { - const result = getHeaderField('name', 'asc', 'name'); - - t.equal(result, 'name', 'should return plain name when name asc'); - t.end(); -}); - -test('cloudfunc: getDotDot: root', (t) => { - const result = getDotDot('/'); - - t.equal(result, '/', 'should return / for root path'); - t.end(); -}); - -test('cloudfunc: getPathLink: /a/b/c', (t) => { - const {pathLink} = template; - const result = getPathLink('/a/b/c/', '', pathLink); - - t.ok(result, 'should build path link for 3-segment path'); - t.end(); -}); - -test('cloudfunc: getPathLink: no url', (t) => { - const [error] = tryCatch(getPathLink); - - t.equal(error.message, 'url could not be empty!', 'should throw when url is empty'); - t.end(); -}); - -test('cloudfunc: getPathLink: no template', (t) => { - const [error] = tryCatch(getPathLink, '/'); - - t.equal(error.message, 'template could not be empty!', 'should throw when template is empty'); - t.end(); -}); - -test('cloudfunc: getHeaderField: sort name desc', (t) => { - const result = getHeaderField('name', 'desc', 'name'); - const expected = 'name↓'; - - t.equal(result, expected, 'should return name with down arrow'); - t.end(); -}); - -test('cloudfunc: getDotDot: normal path', (t) => { - const result = getDotDot('/hello/world/'); - const expected = '/hello'; - - t.equal(result, expected, 'should return parent directory'); - t.end(); -}); - test('cloudfunc: buildFromJSON: formatDate', (t) => { const data = { path: '/media/', diff --git a/common/util.spec.js b/common/util.spec.js index 5a19a8be..6a32848c 100644 --- a/common/util.spec.js +++ b/common/util.spec.js @@ -5,8 +5,6 @@ import { getRegExp, escapeRegExp, getExt, - time, - timeEnd, } from '#common/util'; test('getExt: no extension', (t) => { @@ -108,31 +106,11 @@ test('util: getRegExp: no', (t) => { }); test('util: escapeRegExp: no str', (t) => { - const result = escapeRegExp(1); - const expected = 1; - - t.equal(result, expected); + t.equal(escapeRegExp(1), 1); t.end(); }); test('util: escapeRegExp', (t) => { - const result = escapeRegExp('#hello'); - const expected = '\\#hello'; - - t.equal(result, expected); - t.end(); -}); - -test('util: time', (t) => { - const [error] = tryCatch(time, 'test'); - - t.notOk(error, 'should not throw'); - t.end(); -}); - -test('util: timeEnd', (t) => { - const [error] = tryCatch(timeEnd, 'test'); - - t.notOk(error, 'should not throw'); + t.equal(escapeRegExp('#hello'), '\\#hello'); t.end(); }); diff --git a/package.json b/package.json index f680e519..4c50b3fc 100644 --- a/package.json +++ b/package.json @@ -151,10 +151,10 @@ "yargs-parser": "^22.0.0" }, "devDependencies": { - "@babel/code-frame": "^8.0.0", - "@babel/core": "^8.0.1", - "@babel/plugin-transform-optional-chaining": "^8.0.1", - "@babel/preset-env": "^8.0.2", + "@babel/code-frame": "^7.22.5", + "@babel/core": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.21.0", + "@babel/preset-env": "^7.0.0", "@cloudcmd/clipboard": "^2.0.0", "@cloudcmd/create-element": "^2.0.0", "@cloudcmd/modal": "^4.0.0", @@ -162,8 +162,6 @@ "@cloudcmd/stub": "^5.0.0", "@iocmd/wait": "^2.1.0", "@putout/eslint-flat": "^4.0.0", - "@rspack/cli": "^2.1.4", - "@rspack/core": "^2.1.4", "@supertape/loader-css": "^1.0.0", "@types/node-fetch": "^2.6.11", "auto-globals": "^4.0.0", @@ -173,6 +171,7 @@ "clean-css-loader": "^4.2.1", "codegen.macro": "^4.0.0", "css-loader": "^7.1.2", + "css-minimizer-webpack-plugin": "^8.0.0", "css-modules-require-hook": "^4.2.3", "cssnano-preset-default": "^8.0.1", "domtokenlist-shim": "^1.2.0", @@ -191,6 +190,7 @@ "load.js": "^3.0.0", "madrun": "^13.0.0", "memfs": "^4.2.0", + "mini-css-extract-plugin": "^2.9.2", "minor": "^1.2.2", "morgan": "^1.6.1", "multi-rename": "^3.0.0", @@ -205,7 +205,7 @@ "request": "^2.76.0", "rimraf": "^6.0.1", "scroll-into-view-if-needed": "^3.0.4", - "serve-once": "^4.0.1", + "serve-once": "^3.0.1", "smalltalk": "^5.0.0", "style-loader": "^4.0.0", "superc8": "^12.6.0", @@ -215,7 +215,10 @@ "unionfs": "^4.0.0", "url-loader": "^4.0.0", "util": "^0.12.5", - "webpack-merge": "^6.0.1" + "webpack": "^5.99.9", + "webpack-cli": "^7.0.2", + "webpack-merge": "^6.0.1", + "webpackbar": "^7.0.0" }, "imports": { "#css/": "./css/", diff --git a/rspack.config.js b/rspack.config.js deleted file mode 100644 index 5dcb033d..00000000 --- a/rspack.config.js +++ /dev/null @@ -1,10 +0,0 @@ -import {merge} from 'webpack-merge'; -import * as htmlConfig from './.rspack/html.js'; -import cssConfig from './.rspack/css.js'; -import jsConfig from './.rspack/js.js'; - -export default merge([ - jsConfig, - htmlConfig, - cssConfig, -]); diff --git a/server/cloudcmd.spec.js b/server/cloudcmd.spec.js index d79aa4c1..97949cd3 100644 --- a/server/cloudcmd.spec.js +++ b/server/cloudcmd.spec.js @@ -1,6 +1,6 @@ import path, {dirname} from 'node:path'; import {fileURLToPath} from 'node:url'; -import {serveOnce} from 'serve-once'; +import serveOnce from 'serve-once'; import {test, stub} from 'supertape'; import cloudcmd, { _isDev, @@ -10,9 +10,6 @@ import cloudcmd, { _initAuth, _getIndexPath, } from '#server/cloudcmd'; -import {connect} from '../test/before.js'; - -const noop = () => {}; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); @@ -161,20 +158,17 @@ test('cloudcmd: auth: accept: no auth', (t) => { test('cloudcmd: getIndexPath: production', (t) => { const isDev = false; + const name = path.join(__dirname, '..', 'dist', 'index.html'); - const result = _getIndexPath(isDev); - const expected = path.join(__dirname, '..', 'dist', 'index.html'); - - t.equal(result, expected); + t.equal(_getIndexPath(isDev), name); t.end(); }); test('cloudcmd: getIndexPath: development', (t) => { const isDev = true; - const result = _getIndexPath(isDev); - const expected = path.join(__dirname, '..', 'dist-dev', 'index.html'); + const name = path.join(__dirname, '..', 'dist-dev', 'index.html'); - t.equal(result, expected); + t.equal(_getIndexPath(isDev), name); t.end(); }); @@ -184,64 +178,3 @@ test('cloudcmd: sw', async (t) => { t.equal(status, 200, 'should return sw'); t.end(); }); - -test('cloudcmd: no params', (t) => { - const middle = cloudcmd(); - - t.ok(Array.isArray(middle), 'should return middleware list when no params passed'); - t.end(); -}); - -test('cloudcmd: listen: terminal', async (t) => { - const {done} = await connect({ - config: { - terminal: true, - }, - }); - - await done(); - - t.pass('should listen with terminal enabled'); - t.end(); -}); - -test('cloudcmd: middle: dropbox', async (t) => { - const {port, done} = await connect({ - config: { - dropbox: true, - dropboxToken: 'hello', - }, - }); - - const response = await fetch(`http://localhost:${port}/api/v1/dropbox/nonexistent`); - - await done(); - - t.ok(response.status, 'should mount dropbox route'); - t.end(); -}); - -test('cloudcmd: logout', async (t) => { - const {status} = await request.get('/logout'); - - t.equal(status, 401, 'should return 401 for /logout'); - t.end(); -}); - -test('cloudcmd: modules', (t) => { - const middle = cloudcmd({ - modules: { - hello: noop, - }, - }); - - t.ok(Array.isArray(middle), 'should return middleware list with modules'); - t.end(); -}); - -test('cloudcmd: setUrl: cloudcmd.js', async (t) => { - const {status} = await request.get('/cloudcmd.js'); - - t.equal(status, 200, 'should serve cloudcmd.js'); - t.end(); -}); diff --git a/server/distribute/log.spec.js b/server/distribute/log.spec.js index 1c6d1aa3..be50dcc3 100644 --- a/server/distribute/log.spec.js +++ b/server/distribute/log.spec.js @@ -32,32 +32,3 @@ test('distribute: log: config', (t) => { }, { checkAssertionsCount: false, }); - -test('distribute: log: stringToRGB', (t) => { - const result = log.stringToRGB('abc'); - - t.deepEqual(result, [97, 3, 294], 'should return [charCode, length, crc]'); - t.end(); -}); - -test('distribute: log: makeColor', (t) => { - const result = log.makeColor('hello'); - - t.match(result, 'hello', 'should return colored string containing the input'); - t.end(); -}); - -test('distribute: log: getDescription', (t) => { - const message = 'some error'; - const result = log.getDescription({ - message, - }); - - t.equal(result, message, 'should return message from error object'); - t.end(); -}); - -test('distribute: log: connectedStr', (t) => { - t.ok(log.connectedStr, 'should have connectedStr'); - t.end(); -}); diff --git a/server/env.spec.js b/server/env.spec.js index 5a8765f4..d8065b2c 100644 --- a/server/env.spec.js +++ b/server/env.spec.js @@ -54,16 +54,3 @@ test('cloudcmd: server: env: bool: number: 0', (t) => { t.notOk(result); t.end(); }); - -test('cloudcmd: server: env: bool: zero uppercase', (t) => { - const {CLOUDCMD_TERMINAL} = process.env; - - process.env.CLOUDCMD_TERMINAL = '0'; - - const result = env.bool('terminal'); - - process.env.CLOUDCMD_TERMINAL = CLOUDCMD_TERMINAL; - - t.notOk(result); - t.end(); -}); diff --git a/server/exit.spec.js b/server/exit.spec.js index 94d627ac..3b454818 100644 --- a/server/exit.spec.js +++ b/server/exit.spec.js @@ -4,46 +4,44 @@ import exit from './exit.js'; test('cloudcmd: exit: process.exit', (t) => { const {exit: exitOriginal} = process; - const exitStub = stub(); - process.exit = exitStub; + process.exit = stub(); exit(); + t.calledWith(process.exit, [1], 'should call process.exit'); process.exit = exitOriginal; - t.calledWith(exitStub, [1], 'should call process.exit'); t.end(); }); test('cloudcmd: exit: console.error', (t) => { const {exit: exitOriginal} = process; const {error} = console; - const errorStub = stub(); - console.error = errorStub; + console.error = stub(); process.exit = stub(); exit('hello world'); + t.calledWith(console.error, ['hello world'], 'should call console.error'); process.exit = exitOriginal; console.error = error; - t.calledWith(errorStub, ['hello world'], 'should call console.error'); t.end(); }); test('cloudcmd: exit.error: console.error: error', (t) => { const {exit: exitOriginal} = process; const {error} = console; - const errorStub = stub(); - console.error = errorStub; + console.error = stub(); process.exit = stub(); exit(Error('hello world')); + t.calledWith(console.error, ['hello world'], 'should call console.error'); + process.exit = exitOriginal; console.error = error; - t.calledWith(errorStub, ['hello world'], 'should call console.error'); t.end(); }); diff --git a/server/markdown/index.spec.js b/server/markdown/index.spec.js index f705915e..466271bd 100644 --- a/server/markdown/index.spec.js +++ b/server/markdown/index.spec.js @@ -3,7 +3,7 @@ import {join} from 'node:path'; import {promisify} from 'node:util'; import {tryToCatch} from 'try-to-catch'; import test from 'supertape'; -import {serveOnce} from 'serve-once'; +import serveOnce from 'serve-once'; import {cloudcmd} from '#server/cloudcmd'; import markdown from './index.js'; diff --git a/server/rest/index.js b/server/rest/index.js index c3a3eda0..68bec54e 100644 --- a/server/rest/index.js +++ b/server/rest/index.js @@ -32,8 +32,6 @@ const UserError = (msg) => { return error; }; -export const _UserError = UserError; - export default currify(({config, fs = _fs, moveFiles = _moveFiles}, request, response, next) => { const name = ponse.getPathName(request); const regExp = RegExp(`^${apiURL}`); @@ -155,8 +153,6 @@ function getPackReg(packer) { return /\.tar\.gz$/; } -export const _getPackReg = getPackReg; - function streamPack(cmd, response, packer) { const noop = () => {}; const filename = cmd.replace(getPackReg(packer), ''); @@ -176,8 +172,6 @@ function getCMD(cmd) { return cmd; } -export const _getCMD = getCMD; - const getMoveMsg = (names) => formatMsg('move', names); const getRenameMsg = (from, to) => { @@ -282,8 +276,6 @@ function rename(rootDir, from, to, fs, callback) { return fs.rename(fromRooted, toRooted, fn); } -export const _rename = rename; - function pack(from, to, names, config, fn) { const rootDir = config('root'); const packer = config('packer'); @@ -302,8 +294,6 @@ function pack(from, to, names, config, fn) { operation('pack', packer, from, to, names, fn); } -export const _pack = pack; - function extract(from, to, config, fn) { const rootDir = config('root'); @@ -317,8 +307,6 @@ function extract(from, to, config, fn) { operation('extract', config('packer'), from, to, fn); } -export const _extract = extract; - function getPacker(operation, packer) { if (operation === 'extract') return inly; @@ -329,8 +317,6 @@ function getPacker(operation, packer) { return jaguar.pack; } -export const _getPacker = getPacker; - function operation(op, packer, from, to, names, fn) { if (!fn) { fn = names; @@ -359,8 +345,6 @@ function operation(op, packer, from, to, names, fn) { }); } -export const _operation = operation; - function copy(from, to, names, fn) { copymitter(from, to, names) .on('error', fn) diff --git a/server/rest/index.spec.js b/server/rest/index.spec.js index 9c672095..0fd64d7c 100644 --- a/server/rest/index.spec.js +++ b/server/rest/index.spec.js @@ -1,4 +1,4 @@ -import {test, stub} from 'supertape'; +import {test} from 'supertape'; import {tryToCatch} from 'try-to-catch'; import { _formatMsg, @@ -6,11 +6,6 @@ import { _isRootWin32, _isRootAll, _onPUT, - _UserError, - _getPackReg, - _getCMD, - _rename, - _getPacker, } from './index.js'; test('rest: formatMsg', (t) => { @@ -75,104 +70,3 @@ test('rest: onPUT: no callback', async (t) => { t.equal(e.message, 'callback should be a function!', 'should throw when no callback'); t.end(); }); - -test('rest: UserError: message', (t) => { - const result = _UserError('hello'); - - t.equal(result.message, 'hello', 'should set message'); - t.end(); -}); - -test('rest: UserError: code', (t) => { - const result = _UserError('hello'); - - t.equal(result.code, 'EUSER', 'should set code'); - t.end(); -}); - -test('rest: getPackReg: zip', (t) => { - const result = _getPackReg('zip'); - - t.match('file.zip', result, 'should match .zip'); - t.end(); -}); - -test('rest: getPackReg: tar', (t) => { - const result = _getPackReg('tar'); - - t.match('file.tar.gz', result, 'should match .tar.gz'); - t.end(); -}); - -test('rest: getCMD: with slash', (t) => { - const result = _getCMD('/move'); - - t.equal(result, 'move', 'should strip leading slash'); - t.end(); -}); - -test('rest: getCMD: no slash', (t) => { - const result = _getCMD('move'); - - t.equal(result, 'move', 'should return as is'); - t.end(); -}); - -test('rest: rename: no from', (t) => { - const callback = stub(); - - _rename('/', null, 'to', null, callback); - - const msg = '"from" should be filled'; - - t.calledWith(callback, [ - _UserError(msg), - ], 'should return UserError'); - t.end(); -}); - -test('rest: rename: no to', (t) => { - const callback = stub(); - - _rename('/', 'from', null, null, callback); - - const msg = '"to" should be filled'; - - t.calledWith(callback, [ - _UserError(msg), - ], 'should return UserError'); - t.end(); -}); - -test('rest: rename: success', (t) => { - const callback = stub(); - const fs = { - rename: stub(), - }; - - _rename('/root', 'from', 'to', fs, callback); - - t.calledWith(fs.rename, ['/root/from', '/root/to', callback], 'should call fs.rename'); - t.end(); -}); - -test('rest: getPacker: extract', (t) => { - const result = _getPacker('extract', 'zip'); - - t.equal(typeof result, 'function', 'should return function'); - t.end(); -}); - -test('rest: getPacker: pack zip', (t) => { - const result = _getPacker('pack', 'zip'); - - t.equal(typeof result, 'function', 'should return function'); - t.end(); -}); - -test('rest: getPacker: pack tar', (t) => { - const result = _getPacker('pack', 'tar'); - - t.equal(typeof result, 'function', 'should return function'); - t.end(); -}); diff --git a/server/route.spec.js b/server/route.spec.js index ed19fdc6..7387a9fc 100644 --- a/server/route.spec.js +++ b/server/route.spec.js @@ -4,7 +4,7 @@ import {Readable} from 'node:stream'; import fs from 'node:fs'; import {tryToCatch} from 'try-to-catch'; import {test, stub} from 'supertape'; -import {serveOnce} from 'serve-once'; +import serveOnce from 'serve-once'; import {cloudcmd} from '#server/cloudcmd'; import {_getReadDir} from './route.js'; diff --git a/server/themes.spec.js b/server/themes.spec.js index 709896e8..1fc95ec8 100644 --- a/server/themes.spec.js +++ b/server/themes.spec.js @@ -30,21 +30,3 @@ test('themes: no args', (t) => { t.match(themes.light, css); t.end(); }); - -test('themes: production', (t) => { - const themes = getThemes({ - isDev: false, - }); - - t.ok(themes.dark, 'should have dark theme'); - t.end(); -}); - -test('themes: production: light', (t) => { - const themes = getThemes({ - isDev: false, - }); - - t.ok(themes.light, 'should have light theme'); - t.end(); -}); diff --git a/server/user-menu.spec.js b/server/user-menu.spec.js index 7c5fcf2c..bb78b4e8 100644 --- a/server/user-menu.spec.js +++ b/server/user-menu.spec.js @@ -2,7 +2,7 @@ import {dirname, join} from 'node:path'; import {fileURLToPath} from 'node:url'; import {readFileSync} from 'node:fs'; import {test, stub} from 'supertape'; -import {serveOnce} from 'serve-once'; +import serveOnce from 'serve-once'; import {putout} from 'putout'; import {userMenu} from './user-menu.js'; diff --git a/server/validate.spec.js b/server/validate.spec.js index 639f185c..76243e30 100644 --- a/server/validate.spec.js +++ b/server/validate.spec.js @@ -131,26 +131,3 @@ test('validate: theme: wrong', (t) => { t.calledWith(exit, [msg], 'should call exit'); t.end(); }); - -test('validate: menu: not valid', (t) => { - const exit = stub(); - const msg = 'cloudcmd --menu: could be "supermenu" or "aleman" only'; - - validate.menu('hello', { - exit, - }); - - t.calledWith(exit, [msg], 'should call fn'); - t.end(); -}); - -test('validate: menu: valid', (t) => { - const exit = stub(); - - validate.menu('supermenu', { - exit, - }); - - t.notCalled(exit, 'should not call fn'); - t.end(); -}); diff --git a/test-e2e/ratelimit.js b/test-e2e/ratelimit.js index 54cdbca8..632916c5 100644 --- a/test-e2e/ratelimit.js +++ b/test-e2e/ratelimit.js @@ -1,10 +1,15 @@ import process from 'node:process'; -import {spawn} from 'node:child_process'; import {test} from 'supertape'; +let i = 0; + test('cloudcmd: server: ratelimit: x-forwarded-for', async (t) => { const PORT = 3000; - const child = await run(PORT); + + process.env.PORT = PORT; + process.env.CLOUDCMD_LOG = 0; + + await import('../bin/cloudcmd.js'); const {status} = await fetch(`http://localhost:${PORT}`, { headers: { @@ -12,7 +17,7 @@ test('cloudcmd: server: ratelimit: x-forwarded-for', async (t) => { }, }); - child.kill(); + process.kill(process.pid, 'SIGUSR1'); t.notEqual(status, 500); t.end(); @@ -22,34 +27,18 @@ test('cloudcmd: server: ratelimit', async (t) => { const PORT = 3001; const STATUS = 429; - const child = await run(PORT); + process.env.PORT = PORT; + process.env.CLOUDCMD_LOG = 0; + + await import(`../bin/cloudcmd.js?${i++}`); for (let i = 0; i < 1000; i++) { await fetch(`http://localhost:${PORT}`); } const {status} = await fetch(`http://localhost:${PORT}`); - child.kill(); + process.kill(process.pid, 'SIGUSR1'); t.equal(status, STATUS); t.end(); }); - -function run(port) { - return new Promise((resolve, reject) => { - const child = spawn(new URL('../bin/cloudcmd.js', import.meta.url).pathname, [], { - env: { - ...process.env, - PORT: port, - }, - stdio: ['ignore', 'pipe', 'pipe'], - }); - - child.stdout.on('data', (a) => { - if (a.toString().includes('url')) - resolve(child); - }); - - child.on('error', reject); - }); -} diff --git a/test/before.js b/test/before.js index 08a50f04..970a4a4f 100644 --- a/test/before.js +++ b/test/before.js @@ -50,7 +50,8 @@ function before(options, fn = options) { })); server.listen(() => { - fn(server.address().port, promisify(after)); + fn(server + .address().port, promisify(after)); }); } diff --git a/test/rest/config.js b/test/rest/config.js index b45a0d18..737d422e 100644 --- a/test/rest/config.js +++ b/test/rest/config.js @@ -1,4 +1,4 @@ -import {serveOnce} from 'serve-once'; +import serveOnce from 'serve-once'; import test from 'supertape'; import {cloudcmd} from '#server/cloudcmd'; diff --git a/test/rest/copy.js b/test/rest/copy.js index e6d8a03f..f11ef7d4 100644 --- a/test/rest/copy.js +++ b/test/rest/copy.js @@ -1,7 +1,7 @@ import {dirname, join} from 'node:path'; import {fileURLToPath} from 'node:url'; import {mkdirSync} from 'node:fs'; -import {serveOnce} from 'serve-once'; +import serveOnce from 'serve-once'; import test from 'supertape'; import {rimraf} from 'rimraf'; import {cloudcmd} from '#server/cloudcmd'; diff --git a/test/rest/fs.js b/test/rest/fs.js index db438a71..721320a2 100644 --- a/test/rest/fs.js +++ b/test/rest/fs.js @@ -1,4 +1,4 @@ -import {serveOnce} from 'serve-once'; +import serveOnce from 'serve-once'; import test from 'supertape'; import {cloudcmd} from '#server/cloudcmd'; diff --git a/test/rest/move.js b/test/rest/move.js index 073c520f..696b36a3 100644 --- a/test/rest/move.js +++ b/test/rest/move.js @@ -1,7 +1,7 @@ import {EventEmitter} from 'node:events'; import wait from '@iocmd/wait'; import {test, stub} from 'supertape'; -import {serveOnce} from 'serve-once'; +import serveOnce from 'serve-once'; import {cloudcmd} from '#server/cloudcmd'; test('cloudcmd: rest: move', async (t) => { diff --git a/test/rest/pack.js b/test/rest/pack.js index 4c7a49ed..8a970299 100644 --- a/test/rest/pack.js +++ b/test/rest/pack.js @@ -6,7 +6,7 @@ import test from 'supertape'; import tar from 'tar-stream'; import gunzip from 'gunzip-maybe'; import pullout from 'pullout'; -import {serveOnce} from 'serve-once'; +import serveOnce from 'serve-once'; import {cloudcmd} from '#server/cloudcmd'; const __filename = fileURLToPath(import.meta.url); diff --git a/test/rest/rename.js b/test/rest/rename.js index eb773dba..8dd8e1f8 100644 --- a/test/rest/rename.js +++ b/test/rest/rename.js @@ -2,7 +2,7 @@ import fs from 'node:fs'; import test from 'supertape'; import {Volume} from 'memfs'; import {ufs} from 'unionfs'; -import {serveOnce} from 'serve-once'; +import serveOnce from 'serve-once'; import {cloudcmd} from '#server/cloudcmd'; test('cloudcmd: rest: rename', async (t) => { diff --git a/test/server/env.js b/test/server/env.js index 34bc8959..323c0a99 100644 --- a/test/server/env.js +++ b/test/server/env.js @@ -4,37 +4,34 @@ import * as env from '../../server/env.js'; test('env: small', (t) => { process.env.cloudcmd_hello = 'world'; + t.equal(env.parse('hello'), 'world', 'should parse string from env'); delete process.env.cloudcmd_hello; - - t.equal(env.parse('hello'), 'world', 'should parse string from env'); t.end(); }); test('env: big', (t) => { process.env.CLOUDCMD_HELLO = 'world'; + t.equal(env.parse('hello'), 'world', 'should parse string from env'); delete process.env.CLOUDCMD_HELLO; - - t.equal(env.parse('hello'), 'world', 'should parse string from env'); t.end(); }); test('env: bool: false', (t) => { process.env.cloudcmd_terminal = 'false'; + t.notOk(env.bool('terminal'), 'should return false'); delete process.env.cloudcmd_terminal; - - t.notOk(env.bool('terminal'), 'should return false'); t.end(); }); test('env: bool: true', (t) => { process.env.cloudcmd_terminal = 'true'; - delete process.env.cloudcmd_terminal; - t.ok(env.bool('terminal'), 'should be true'); + + delete process.env.cloudcmd_terminal; t.end(); }); @@ -42,10 +39,9 @@ test('env: bool: undefined', (t) => { const {cloudcmd_terminal} = process.env; process.env.cloudcmd_terminal = undefined; + + t.notOk(env.bool('terminal'), 'should be undefined'); + process.env.cloudcmd_terminal = cloudcmd_terminal; - - const result = env.bool('terminal'); - - t.notOk(result); t.end(); }); diff --git a/test/server/modulas.js b/test/server/modulas.js index 0085449e..5c7c6d9e 100644 --- a/test/server/modulas.js +++ b/test/server/modulas.js @@ -1,7 +1,7 @@ import {createRequire} from 'node:module'; import {dirname, join} from 'node:path'; import {fileURLToPath} from 'node:url'; -import {serveOnce} from 'serve-once'; +import serveOnce from 'serve-once'; import {test, stub} from 'supertape'; import {cloudcmd} from '#server/cloudcmd'; import modulas from '../../server/modulas.js'; diff --git a/test/static.js b/test/static.js index 0f0da5cb..cdb6b9e7 100644 --- a/test/static.js +++ b/test/static.js @@ -1,5 +1,5 @@ import {Buffer} from 'node:buffer'; -import {serveOnce} from 'serve-once'; +import serveOnce from 'serve-once'; import test from 'supertape'; import criton from 'criton'; import {cloudcmd} from '#server/cloudcmd';