@skyblock-finance/actions 0.9.1 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -43,5 +43,5 @@
43
43
  "sideEffects": false,
44
44
  "type": "commonjs",
45
45
  "types": "dist/index.d.ts",
46
- "version": "0.9.1"
46
+ "version": "0.11.0"
47
47
  }
@@ -1,8 +1,11 @@
1
- import { actionSchema } from './schema'
2
- import { allActions } from './data'
3
- import { z } from 'zod/v4'
4
- import { describe, expect, test } from 'bun:test'
1
+ import { expect, test } from 'bun:test'
5
2
  import assert from 'node:assert'
3
+
4
+ import jsonStableStringify from 'json-stable-stringify'
5
+ import { z } from 'zod/v4'
6
+
7
+ import { allActions } from './data'
8
+ import { actionSchema } from './schema'
6
9
  import { ActionIoItem } from './types'
7
10
 
8
11
  test('all actions follow the schema', () => {
@@ -68,34 +71,57 @@ test('sumUp works', () => {
68
71
  )
69
72
  })
70
73
 
71
- describe('every action’s workbench inputs match its crafing grid', () => {
74
+ test('every action’s workbench inputs match its crafing grid', () => {
72
75
  for (const action of allActions) {
73
76
  for (const grid of action.place.filter((x) => x.type === 'workbench')) {
74
- test(`${JSON.stringify(action.outputs)} is valid`, () => {
75
- assert(grid.type === 'workbench')
77
+ assert(grid.type === 'workbench')
76
78
 
77
- const actual = sumUp(action.inputs.filter((x) => x.type === 'item'))
79
+ const actual = sumUp(action.inputs.filter((x) => x.type === 'item'))
78
80
 
79
- const expected = sumUp(grid.grid.filter((x) => x !== null))
81
+ const expected = sumUp(grid.grid.filter((x) => x !== null))
80
82
 
81
- expect(actual).toEqual(expected)
82
- })
83
+ expect(
84
+ actual,
85
+ `${JSON.stringify(action)} doesn't match its crafting grid`,
86
+ ).toEqual(expected)
83
87
  }
84
88
  }
85
89
  })
86
90
 
87
- describe('every action’s anvil inputs match its crafing grid', () => {
91
+ test('every action’s anvil inputs match its crafing grid', () => {
88
92
  for (const action of allActions) {
89
93
  for (const grid of action.place.filter((x) => x.type === 'anvil')) {
90
- test(`${JSON.stringify(action.outputs)} is valid`, () => {
91
- assert(grid.type === 'anvil')
94
+ assert(grid.type === 'anvil')
92
95
 
93
- const actual = sumUp(action.inputs.filter((x) => x.type === 'item'))
96
+ const actual = sumUp(action.inputs.filter((x) => x.type === 'item'))
97
+
98
+ const expected = sumUp([grid.left, grid.right])
99
+
100
+ expect(actual, `${JSON.stringify(action)} doesn't match`).toEqual(
101
+ expected,
102
+ )
103
+ }
104
+ }
105
+ })
106
+
107
+ test('no duplicate actions exist', () => {
108
+ const seen = new Set<string>()
109
+
110
+ for (const action of allActions) {
111
+ for (const place of action.place) {
112
+ const syntheticAction = {
113
+ ...action,
114
+ place,
115
+ }
116
+ const json = jsonStableStringify(syntheticAction)
94
117
 
95
- const expected = sumUp([grid.left, grid.right])
118
+ if (!json) throw new Error(`invalid action: ${JSON.stringify(action)}`)
96
119
 
97
- expect(actual).toEqual(expected)
98
- })
120
+ if (seen.has(json)) {
121
+ throw new Error(`duplicate action: ${json}`)
122
+ } else {
123
+ seen.add(json)
124
+ }
99
125
  }
100
126
  }
101
127
  })
package/source/data.ts CHANGED
@@ -1,20 +1,29 @@
1
- import { actions as _adventurer } from '../data/merchants/adventurer.json'
2
1
  import { actions as _bitsCrafts } from '../data/bits-crafts.json'
2
+ import { actions as _crimsonIsle } from '../data/crimson-isle.json'
3
+ import { actions as _forging } from '../data/forging.json'
4
+ import { actions as _gems } from '../data/gems.json'
5
+ import { actions as _gemstones } from '../data/gemstones.json'
6
+ import { actions as _adventurer } from '../data/merchants/adventurer.json'
3
7
  import { actions as _bubu } from '../data/merchants/bubu.json'
4
8
  import { actions as _bulvar } from '../data/merchants/bulvar.json'
5
- import { actions as _crimsonIsle } from '../data/crimson-isle.json'
6
9
  import { actions as _einary } from '../data/merchants/einary.json'
7
10
  import { actions as _elizabeth } from '../data/merchants/elizabeth.json'
8
11
  import { actions as _fishingMerchant } from '../data/merchants/fishing-merchant.json'
9
- import { actions as _gems } from '../data/gems.json'
10
- import { actions as _gemstones } from '../data/gemstones.json'
11
- import { actions as _northStarsCrafts } from '../data/north-stars-crafts.json'
12
+ import { actions as _hilda } from '../data/merchants/hilda.json'
13
+ import { actions as _marthos } from '../data/merchants/marthos.json'
12
14
  import { actions as _phillip } from '../data/merchants/phillip.json'
13
15
  import { actions as _plumberJoe } from '../data/merchants/plumber-joe.json'
14
16
  import { actions as _seymour } from '../data/merchants/seymour.json'
15
17
  import { actions as _skymart } from '../data/merchants/skymart.json'
16
18
  import { actions as _smithmonger } from '../data/merchants/smithmonger.json'
19
+ import { actions as _minionsBlaze } from '../data/minions/blaze.json'
20
+ import { actions as _minionsCaveSpider } from '../data/minions/cave-spider.json'
21
+ import { actions as _minionsCreeper } from '../data/minions/creeper.json'
22
+ import { actions as _minionsEnderman } from '../data/minions/enderman.json'
23
+ import { actions as _minionsGhast } from '../data/minions/ghast.json'
24
+ import { actions as _northStarsCrafts } from '../data/north-stars-crafts.json'
17
25
  import { actions as _wood } from '../data/wood.json'
26
+
18
27
  import { Action } from './types'
19
28
 
20
29
  // merchants
@@ -25,22 +34,33 @@ export const bulvar = _bulvar as Action[]
25
34
  export const einary = _einary as Action[]
26
35
  export const elizabeth = _elizabeth as Action[]
27
36
  export const fishingMerchant = _fishingMerchant as Action[]
37
+ export const hilda = _hilda as Action[]
38
+ export const marthos = _marthos as Action[]
28
39
  export const phillip = _phillip as Action[]
29
40
  export const plumberJoe = _plumberJoe as Action[]
30
41
  export const seymour = _seymour as Action[]
31
42
  export const skymart = _skymart as Action[]
32
43
  export const smithmonger = _smithmonger as Action[]
33
44
 
45
+ // minions
46
+
47
+ export const minionsBlaze = _minionsBlaze as Action[]
48
+ export const minionsCaveSpider = _minionsCaveSpider as Action[]
49
+ export const minionsCreeper = _minionsCreeper as Action[]
50
+ export const minionsEnderman = _minionsEnderman as Action[]
51
+ export const minionsGhast = _minionsGhast as Action[]
52
+
34
53
  // other
35
54
 
36
55
  export const bitsCrafts = _bitsCrafts as Action[]
37
56
  export const crimsonIsle = _crimsonIsle as Action[]
57
+ export const forging = _forging as Action[]
38
58
  export const gems = _gems as Action[]
39
59
  export const gemstones = _gemstones as Action[]
40
60
  export const northStarsCrafts = _northStarsCrafts as Action[]
41
61
  export const wood = _wood as Action[]
42
62
 
43
- export const allActions = [
63
+ export const allActions: Action[] = [
44
64
  ...adventurer,
45
65
  ...bitsCrafts,
46
66
  ...bubu,
@@ -49,8 +69,16 @@ export const allActions = [
49
69
  ...einary,
50
70
  ...elizabeth,
51
71
  ...fishingMerchant,
72
+ ...forging,
52
73
  ...gems,
53
74
  ...gemstones,
75
+ ...hilda,
76
+ ...marthos,
77
+ ...minionsBlaze,
78
+ ...minionsCaveSpider,
79
+ ...minionsCreeper,
80
+ ...minionsEnderman,
81
+ ...minionsGhast,
54
82
  ...northStarsCrafts,
55
83
  ...phillip,
56
84
  ...plumberJoe,
package/source/index.ts CHANGED
@@ -1,17 +1,22 @@
1
1
  export * from './data'
2
+ export { npcs } from './npcs'
3
+ export {
4
+ actionIoCrystalSchema,
5
+ actionIoCurrencySchema,
6
+ actionIoItemSchema,
7
+ actionIoSchema,
8
+ actionPlaceSchema,
9
+ actionRequirementSchema,
10
+ actionSchema,
11
+ npcIdSchema,
12
+ } from './schema'
2
13
  export {
3
14
  Action,
4
15
  ActionCurrency,
5
16
  ActionIo,
17
+ ActionIoCrystal,
6
18
  ActionIoCurrency,
7
19
  ActionIoItem,
20
+ ActionRequirement,
8
21
  NpcId,
9
22
  } from './types'
10
- export {
11
- actionIoItemSchema,
12
- actionIoSchema,
13
- actionPlaceSchema,
14
- actionSchema,
15
- npcIdSchema,
16
- } from './schema'
17
- export { npcs } from './npcs'
package/source/npcs.ts CHANGED
@@ -1,100 +1,114 @@
1
1
  import { NpcId } from './types'
2
2
 
3
3
  type NpcMetadata = {
4
- name: string
5
4
  links: {
6
5
  communityWiki: `https://hypixelskyblock.minecraft.wiki/${string}` | null
7
6
  hypixelWiki: `https://wiki.hypixel.net/${string}` | null
8
7
  }
8
+ name: string
9
9
  }
10
10
 
11
11
  const _npcs: Record<NpcId, NpcMetadata> = {
12
12
  ADVENTURER: {
13
- name: 'Adventurer',
14
13
  links: {
15
14
  communityWiki: 'https://hypixelskyblock.minecraft.wiki/w/Adventurer',
16
15
  hypixelWiki: 'https://wiki.hypixel.net/Adventurer',
17
16
  },
17
+ name: 'Adventurer',
18
18
  },
19
19
  ALCHEMIST: {
20
- name: 'Alchemist',
21
20
  links: {
22
21
  communityWiki: 'https://hypixelskyblock.minecraft.wiki/w/Alchemist',
23
22
  hypixelWiki: 'https://wiki.hypixel.net/Alchemist',
24
23
  },
24
+ name: 'Alchemist',
25
25
  },
26
26
  BUBU: {
27
- name: 'Bubu',
28
27
  links: {
29
28
  communityWiki: 'https://hypixelskyblock.minecraft.wiki/w/Bubu',
30
29
  hypixelWiki: 'https://wiki.hypixel.net/Bubu',
31
30
  },
31
+ name: 'Bubu',
32
32
  },
33
33
  BULVAR: {
34
- name: 'Bulvar',
35
34
  links: {
36
35
  communityWiki: 'https://hypixelskyblock.minecraft.wiki/w/Bulvar',
37
36
  hypixelWiki: 'https://wiki.hypixel.net/Bulvar',
38
37
  },
38
+ name: 'Bulvar',
39
39
  },
40
40
  EINARY: {
41
- name: 'Einary',
42
41
  links: {
43
42
  communityWiki: 'https://hypixelskyblock.minecraft.wiki/w/Einary',
44
43
  hypixelWiki: 'https://wiki.hypixel.net/Einary',
45
44
  },
45
+ name: 'Einary',
46
46
  },
47
47
  ELIZABETH: {
48
- name: 'Elizabeth',
49
48
  links: {
50
49
  communityWiki: 'https://hypixelskyblock.minecraft.wiki/w/Elizabeth',
51
50
  hypixelWiki: 'https://wiki.hypixel.net/Elizabeth',
52
51
  },
52
+ name: 'Elizabeth',
53
53
  },
54
54
  FISHING_MERCHANT: {
55
- name: 'Fishing Merchant',
56
55
  links: {
57
56
  communityWiki:
58
57
  'https://hypixelskyblock.minecraft.wiki/w/Fishing_Merchant',
59
58
  hypixelWiki: 'https://wiki.hypixel.net/Fishing_Merchant',
60
59
  },
60
+ name: 'Fishing Merchant',
61
+ },
62
+ HILDA: {
63
+ links: {
64
+ communityWiki: 'https://hypixelskyblock.minecraft.wiki/w/Hilda',
65
+ hypixelWiki: 'https://wiki.hypixel.net/Hilda',
66
+ },
67
+ name: 'Hilda',
68
+ },
69
+ MARTHOS: {
70
+ links: {
71
+ communityWiki: 'https://hypixelskyblock.minecraft.wiki/w/Marthos',
72
+ hypixelWiki: 'https://wiki.hypixel.net/Marthos',
73
+ },
74
+ name: 'Marthos',
61
75
  },
62
76
  PHILLIP: {
63
- name: 'Pesthunter Phillip',
64
77
  links: {
65
78
  communityWiki:
66
79
  'https://hypixelskyblock.minecraft.wiki/w/Pesthunter_Phillip',
67
80
  hypixelWiki: 'https://wiki.hypixel.net/Pesthunter_Phillip',
68
81
  },
82
+ name: 'Pesthunter Phillip',
83
+ },
84
+ PLUMBER_JOE: {
85
+ links: {
86
+ communityWiki: 'https://hypixelskyblock.minecraft.wiki/w/Plumber_Joe',
87
+ hypixelWiki: 'https://wiki.hypixel.net/Plumber_Joe',
88
+ },
89
+ name: 'Plumber Joe',
69
90
  },
70
91
  SEYMOUR: {
71
- name: 'Seymour',
72
92
  links: {
73
93
  communityWiki: 'https://hypixelskyblock.minecraft.wiki/w/Seymour',
74
94
  hypixelWiki: 'https://wiki.hypixel.net/Seymour',
75
95
  },
96
+ name: 'Seymour',
76
97
  },
77
98
  SKYMART: {
78
- name: 'SkyMart',
79
99
  links: {
80
100
  communityWiki:
81
101
  'https://hypixelskyblock.minecraft.wiki/w/The_Garden#The_Desk',
82
102
  hypixelWiki: 'https://wiki.hypixel.net/Garden#Desk',
83
103
  },
104
+ name: 'SkyMart',
84
105
  },
85
106
  SMITHMONGER: {
86
- name: 'Smithmonger',
87
107
  links: {
88
108
  communityWiki: 'https://hypixelskyblock.minecraft.wiki/w/Smithmonger',
89
109
  hypixelWiki: 'https://wiki.hypixel.net/Smithmonger',
90
110
  },
91
- },
92
- PLUMBER_JOE: {
93
- name: 'Plumber Joe',
94
- links: {
95
- communityWiki: 'https://hypixelskyblock.minecraft.wiki/w/Plumber_Joe',
96
- hypixelWiki: 'https://wiki.hypixel.net/Plumber_Joe',
97
- },
111
+ name: 'Smithmonger',
98
112
  },
99
113
  }
100
114
 
package/source/schema.ts CHANGED
@@ -1,31 +1,35 @@
1
1
  import { z } from 'zod/v4'
2
2
 
3
- export const actionIoItemSchema = z
4
- .object({
5
- amount: z.number(),
6
- id: z.string(),
7
- type: z.literal('item'),
8
- })
9
- .strict()
3
+ export const actionIoCrystalSchema = z.strictObject({
4
+ amount: z.number(),
5
+ id: z.string(),
6
+ type: z.literal('crystal'),
7
+ })
10
8
 
11
- export const actionIoCurrencySchema = z
12
- .object({
13
- amount: z.number(),
14
- id: z.enum([
15
- 'bit',
16
- 'coin',
17
- 'copper',
18
- 'gem',
19
- 'north-star',
20
- 'pest',
21
- 'second',
22
- 'usd',
23
- ]),
24
- type: z.literal('currency'),
25
- })
26
- .strict()
9
+ export const actionIoCurrencySchema = z.strictObject({
10
+ amount: z.number(),
11
+ id: z.enum([
12
+ 'bit',
13
+ 'coin',
14
+ 'copper',
15
+ 'gem',
16
+ 'forge-second',
17
+ 'north-star',
18
+ 'pest',
19
+ 'second',
20
+ 'usd',
21
+ ]),
22
+ type: z.literal('currency'),
23
+ })
24
+
25
+ export const actionIoItemSchema = z.strictObject({
26
+ amount: z.number(),
27
+ id: z.string(),
28
+ type: z.literal('item'),
29
+ })
27
30
 
28
31
  export const actionIoSchema = z.discriminatedUnion('type', [
32
+ actionIoCrystalSchema,
29
33
  actionIoCurrencySchema,
30
34
  actionIoItemSchema,
31
35
  ])
@@ -38,6 +42,8 @@ export const npcIdSchema = z.enum([
38
42
  'EINARY',
39
43
  'ELIZABETH',
40
44
  'FISHING_MERCHANT',
45
+ 'HILDA',
46
+ 'MARTHOS',
41
47
  'PHILLIP',
42
48
  'PLUMBER_JOE',
43
49
  'SEYMOUR',
@@ -51,6 +57,9 @@ export const actionPlaceSchema = z.discriminatedUnion('type', [
51
57
  right: actionIoItemSchema,
52
58
  type: z.literal('anvil'),
53
59
  }),
60
+ z.strictObject({
61
+ type: z.literal('forge'),
62
+ }),
54
63
  z.strictObject({
55
64
  id: npcIdSchema,
56
65
  type: z.literal('npc'),
@@ -65,17 +74,34 @@ export const actionPlaceSchema = z.discriminatedUnion('type', [
65
74
  }),
66
75
  ])
67
76
 
68
- export const actionSchema = z
69
- .object({
70
- inputs: z.array(actionIoSchema),
71
- outputs: z.array(actionIoSchema),
72
- place: z.array(actionPlaceSchema),
73
- })
74
- .strict()
77
+ /**
78
+ * NOTE: This schema uses uppercase to align 1-to-1 with the Skyblock Items API's requirements format.
79
+ */
80
+ export const actionRequirementSchema = z.discriminatedUnion('type', [
81
+ z.strictObject({
82
+ collection: z.enum(['GEMSTONE' /* to be added as-needed */]),
83
+ tier: z.int().min(1).max(10),
84
+ type: z.literal('COLLECTION'),
85
+ }),
86
+ z.strictObject({
87
+ level: z.int().min(1).max(60),
88
+ skill: z.enum(['MINING' /* to be added as-needed */]),
89
+ type: z.literal('SKILL'),
90
+ }),
91
+ z.strictObject({
92
+ tier: z.int().min(1).max(10),
93
+ type: z.literal('HEART_OF_THE_MOUNTAIN'),
94
+ }),
95
+ ])
96
+
97
+ export const actionSchema = z.strictObject({
98
+ inputs: z.array(actionIoSchema),
99
+ outputs: z.array(actionIoSchema),
100
+ place: z.array(actionPlaceSchema),
101
+ requirements: z.array(actionRequirementSchema).optional(),
102
+ })
75
103
 
76
- export const actionDefinitionSchema = z
77
- .object({
78
- actions: z.array(actionSchema),
79
- $schema: z.string().optional(),
80
- })
81
- .strict()
104
+ export const actionDefinitionSchema = z.strictObject({
105
+ $schema: z.string().optional(),
106
+ actions: z.array(actionSchema),
107
+ })
package/source/types.ts CHANGED
@@ -1,8 +1,11 @@
1
1
  import { z } from 'zod/v4'
2
+
2
3
  import {
4
+ actionIoCrystalSchema,
3
5
  actionIoCurrencySchema,
4
6
  actionIoItemSchema,
5
7
  actionIoSchema,
8
+ actionRequirementSchema,
6
9
  actionSchema,
7
10
  npcIdSchema,
8
11
  } from './schema'
@@ -10,6 +13,8 @@ import {
10
13
  export type Action = z.output<typeof actionSchema>
11
14
  export type ActionCurrency = z.output<typeof actionIoCurrencySchema.shape.id>
12
15
  export type ActionIo = z.output<typeof actionIoSchema>
16
+ export type ActionIoCrystal = z.output<typeof actionIoCrystalSchema>
13
17
  export type ActionIoCurrency = z.output<typeof actionIoCurrencySchema>
14
18
  export type ActionIoItem = z.output<typeof actionIoItemSchema>
19
+ export type ActionRequirement = z.output<typeof actionRequirementSchema>
15
20
  export type NpcId = z.output<typeof npcIdSchema>