Skip to content

Deno 2.0

Workspaces and monorepos

Directory Structure

.
├── deno.json
├── main.ts
└── packages
    ├── add
    │   ├── deno.json
    │   └── index.ts
    └── subtract
        ├── deno.json
        └── index.ts

workspaceの属性を使用。

json
{
  "workspace": [
    "packages/add",
    "packages/subtract"
  ]
}

packages/add

ts
export function add(a: number, b: number): number {
  return a + b
}
json
{
  "name": "@deno/add",
  "exports": "./index.ts"
}

packages/subtract

ts
import { add } from '@deno/add'

export function subtract(a: number, b: number): number {
  return add(a, -b)
}
json
{
  "name": "@deno/subtract",
  "exports": "./index.ts"
}
ts
import { add } from '@deno/add'
import { subtract } from '@deno/subtract'

console.log('Hello Deno')

const add_res = add(1, 2)
console.log(add_res)

const subtract_res = subtract(1, 2)
console.log(subtract_res)
sh
deno main.ts
Hello Deno
3
-1

Points to note

json
{
  "name": "@deno/add"
}

"exports":を指定しないと、

sh
deno main.ts
Warning "exports" field should be specified when specifying a "name".
    at file:///workspaces/deno-workspaces-test/packages/add/deno.json
error: Unknown export '.' for '@deno/add'.
  Package exports:

    at file:///workspaces/deno-workspaces-test/main.ts:1:21

Package management

  • Package management with new deno install, deno add, and deno remove commands

deno add

 バージョン指定しない場合、最新のパッケージ。

sh
deno add npm:hono
json
{
  "dependencies": {
    "hono": "^4.6.4"
  }
}

 パッケージ名の後ろに「@バージョン」をつけて行うことも可能。

sh
deno add npm:hono@4.0.0
json
{
  "dependencies": {
    "hono": "^4.0.0"
  }
}

--dev

 バージョン指定しない場合、最新のパッケージ。

sh
deno add --dev npm:vitest
json
{
  "devDependencies": {
    "vitest": "^2.1.2"
  }
}

 パッケージ名の後ろに「@バージョン」をつけて行うことも可能。

sh
deno add --dev npm:vitest@2.0.1
json
{
  "devDependencies": {
    "vitest": "^2.0.1"
  }
}

deno remove

remove before

json
{
  "dependencies": { "hono": "^4.6.4" },
  "devDependencies": {
    "vitest": "^2.1.3"
  }
}
sh
deno remove hono
Removed hono

remove after

json
{
  "devDependencies": { "vitest": "^2.1.3" }
}

remove before

json
{
  "devDependencies": { "vitest": "^2.1.3" }
}
sh
deno remove vitest

remove after

json
{
}

Points to note

deno addの時は、npm:honoだが、deno removeと時は、honoと指定する。

sh
deno remove npm:hono
No packages were removed

removeの時は、バージョンを指定しても削除できません。

sh
deno remove npm:hono@4.0.0
No packages were removed
sh
deno remove hono@4.0.0
No packages were removed

removeの時は、--devを使用しても削除できません。

sh
deno remove --dev vitest
error: unexpected argument '--dev' found

  tip: to pass '--dev' as a value, use '-- --dev'

Usage: deno remove [OPTIONS] [packages]...

deno install

 以下のような機能と同様。

  • npm install

  • pnpm install

  • yarn install

  • bun install

sh
deno install

Vitest Example

Directory Structure

.
├── deno.json
├── package.json
├── packages
│   └── fizz-buzz
│       ├── deno.json
│       ├── index.test.ts
│       └── index.ts
└── src
    └── index.ts
ts
import { fizzBuzz } from '@deno/fizz-buzz'

const fizz_buzz_result = fizzBuzz(15)
console.log(fizz_buzz_result)
sh
deno src/index.ts
FizzBuzz
ts
export const fizzBuzz = (number: number): string => {
  if (number % 15 === 0) return 'FizzBuzz'
  if (number % 3 === 0) return 'Fizz'
  if (number % 5 === 0) return 'Buzz'
  return number.toString()
}
ts
import { describe, expect, it } from 'vitest'
import { fizzBuzz } from './index.ts'

// deno-fmt-ignore
const input: number[] = [
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
    11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
    21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
    31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
    51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
    61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
    71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
    81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
    91, 92, 93, 94, 95, 96, 97, 98, 99, 100
]

// deno-fmt-ignore
const expected: string[] = [
    "1", "2", "Fizz", "4", "Buzz", "Fizz", "7", "8", "Fizz", "Buzz",
    "11", "Fizz", "13", "14", "FizzBuzz", "16", "17", "Fizz", "19", "Buzz",
    "Fizz", "22", "23", "Fizz", "Buzz", "26", "Fizz", "28", "29", "FizzBuzz",
    "31", "32", "Fizz", "34", "Buzz", "Fizz", "37", "38", "Fizz", "Buzz",
    "41", "Fizz", "43", "44", "FizzBuzz", "46", "47", "Fizz", "49", "Buzz",
    "Fizz", "52", "53", "Fizz", "Buzz", "56", "Fizz", "58", "59", "FizzBuzz",
    "61", "62", "Fizz", "64", "Buzz", "Fizz", "67", "68", "Fizz", "Buzz",
    "71", "Fizz", "73", "74", "FizzBuzz", "76", "77", "Fizz", "79", "Buzz",
    "Fizz", "82", "83", "Fizz", "Buzz", "86", "Fizz", "88", "89", "FizzBuzz",
    "91", "92", "Fizz", "94", "Buzz", "Fizz", "97", "98", "Fizz", "Buzz"
]

const testCases = input.map((i, o) => {
  return { input: i, expected: expected[o] }
})

describe('fizzBuzz test', () => {
  // fizzBuzz
  it.concurrent.each(testCases)('fizzBuzz($input) -> $expected', ({ input, expected }) => {
    const result = fizzBuzz(input)
    expect(result).toEqual(expected)
  })
})

Test

package.jsonscriptsからでも実行可能。

  • deno task can now run package.json scripts
json
{
  "scripts": {
    "test": "vitest"
  },
  "devDependencies": {
    "vitest": "^2.1.2"
  }
}
sh
deno task test
json
{
  "tasks": {
    "vitest": "vitest"
  }
}
sh
deno task test
Details
sh
Task test vitest

 DEV  v2.1.2 /workspaces/deno-workspaces-test

 packages/fizz-buzz/index.test.ts (100)
 fizzBuzz test (100)
 fizzBuzz(1) -> '1'
 fizzBuzz(2) -> '2'
 fizzBuzz(3) -> 'Fizz'
 fizzBuzz(4) -> '4'
 fizzBuzz(5) -> 'Buzz'
 fizzBuzz(6) -> 'Fizz'
 fizzBuzz(7) -> '7'
 fizzBuzz(8) -> '8'
 fizzBuzz(9) -> 'Fizz'
 fizzBuzz(10) -> 'Buzz'
 fizzBuzz(11) -> '11'
 fizzBuzz(12) -> 'Fizz'
 fizzBuzz(13) -> '13'
 fizzBuzz(14) -> '14'
 fizzBuzz(15) -> 'FizzBuzz'
 fizzBuzz(16) -> '16'
 fizzBuzz(17) -> '17'
 fizzBuzz(18) -> 'Fizz'
 fizzBuzz(19) -> '19'
 fizzBuzz(20) -> 'Buzz'
 fizzBuzz(21) -> 'Fizz'
 fizzBuzz(22) -> '22'
 fizzBuzz(23) -> '23'
 fizzBuzz(24) -> 'Fizz'
 fizzBuzz(25) -> 'Buzz'
 fizzBuzz(26) -> '26'
 fizzBuzz(27) -> 'Fizz'
 fizzBuzz(28) -> '28'
 fizzBuzz(29) -> '29'
 fizzBuzz(30) -> 'FizzBuzz'
 fizzBuzz(31) -> '31'
 fizzBuzz(32) -> '32'
 fizzBuzz(33) -> 'Fizz'
 fizzBuzz(34) -> '34'
 fizzBuzz(35) -> 'Buzz'
 fizzBuzz(36) -> 'Fizz'
 fizzBuzz(37) -> '37'
 fizzBuzz(38) -> '38'
 fizzBuzz(39) -> 'Fizz'
 fizzBuzz(40) -> 'Buzz'
 fizzBuzz(41) -> '41'
 fizzBuzz(42) -> 'Fizz'
 fizzBuzz(43) -> '43'
 fizzBuzz(44) -> '44'
 fizzBuzz(45) -> 'FizzBuzz'
 fizzBuzz(46) -> '46'
 fizzBuzz(47) -> '47'
 fizzBuzz(48) -> 'Fizz'
 fizzBuzz(49) -> '49'
 fizzBuzz(50) -> 'Buzz'
 fizzBuzz(51) -> 'Fizz'
 fizzBuzz(52) -> '52'
 fizzBuzz(53) -> '53'
 fizzBuzz(54) -> 'Fizz'
 fizzBuzz(55) -> 'Buzz'
 fizzBuzz(56) -> '56'
 fizzBuzz(57) -> 'Fizz'
 fizzBuzz(58) -> '58'
 fizzBuzz(59) -> '59'
 fizzBuzz(60) -> 'FizzBuzz'
 fizzBuzz(61) -> '61'
 fizzBuzz(62) -> '62'
 fizzBuzz(63) -> 'Fizz'
 fizzBuzz(64) -> '64'
 fizzBuzz(65) -> 'Buzz'
 fizzBuzz(66) -> 'Fizz'
 fizzBuzz(67) -> '67'
 fizzBuzz(68) -> '68'
 fizzBuzz(69) -> 'Fizz'
 fizzBuzz(70) -> 'Buzz'
 fizzBuzz(71) -> '71'
 fizzBuzz(72) -> 'Fizz'
 fizzBuzz(73) -> '73'
 fizzBuzz(74) -> '74'
 fizzBuzz(75) -> 'FizzBuzz'
 fizzBuzz(76) -> '76'
 fizzBuzz(77) -> '77'
 fizzBuzz(78) -> 'Fizz'
 fizzBuzz(79) -> '79'
 fizzBuzz(80) -> 'Buzz'
 fizzBuzz(81) -> 'Fizz'
 fizzBuzz(82) -> '82'
 fizzBuzz(83) -> '83'
 fizzBuzz(84) -> 'Fizz'
 fizzBuzz(85) -> 'Buzz'
 fizzBuzz(86) -> '86'
 fizzBuzz(87) -> 'Fizz'
 fizzBuzz(88) -> '88'
 fizzBuzz(89) -> '89'
 fizzBuzz(90) -> 'FizzBuzz'
 fizzBuzz(91) -> '91'
 fizzBuzz(92) -> '92'
 fizzBuzz(93) -> 'Fizz'
 fizzBuzz(94) -> '94'
 fizzBuzz(95) -> 'Buzz'
 fizzBuzz(96) -> 'Fizz'
 fizzBuzz(97) -> '97'
 fizzBuzz(98) -> '98'
 fizzBuzz(99) -> 'Fizz'
 fizzBuzz(100) -> 'Buzz'

 Test Files  1 passed (1)
      Tests  100 passed (100)
   Start at  12:41:35
   Duration  283ms (transform 36ms, setup 0ms, collect 41ms, tests 6ms, environment 0ms, prepare 105ms)