scrabble-solver 2.18.10-alpha.0 → 2.18.10-alpha.1

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.
Files changed (33) hide show
  1. package/bun.lock +29 -29
  2. package/e2e/app.spec.ts +3 -3
  3. package/e2e/bugs/112-character-bonus.spec.ts +1 -1
  4. package/e2e/bugs/129-esc-sidebar.spec.ts +1 -1
  5. package/e2e/bugs/3-x-tile-in-polish.spec.ts +1 -1
  6. package/e2e/bugs/30-click-inside-radio-icon.spec.ts +1 -1
  7. package/e2e/bugs/333-disabled-radio-cursor.spec.ts +1 -1
  8. package/e2e/bugs/342-results-sorting.spec.ts +1 -1
  9. package/e2e/bugs/363-dictionary-input-unique-words.spec.ts +1 -1
  10. package/e2e/bugs/380-transliteration-when-pasting.spec.ts +1 -1
  11. package/e2e/bugs/398-digraphs-in-created-words.spec.ts +2 -2
  12. package/e2e/bugs/401-board-state-on-game-change.spec.ts +1 -1
  13. package/e2e/bugs/452-stale-translations-cache.spec.ts +1 -1
  14. package/e2e/features/198-highlight-unreachable-cells.spec.ts +1 -2
  15. package/e2e/features/430-highlight-unreachable-cells-results.spec.ts +1 -2
  16. package/e2e/features/91-hover-remaining-tile-highlights.spec.ts +3 -4
  17. package/e2e/features/hidden-coordinates-migration.spec.ts +1 -1
  18. package/e2e/features/words-preview.spec.ts +4 -4
  19. package/e2e/lib/actions.ts +17 -4
  20. package/e2e/lib/selectors.ts +1 -1
  21. package/package.json +3 -3
  22. package/.claude/settings.local.json +0 -38
  23. package/.github/workflows/build.yml +0 -16
  24. package/.github/workflows/bunx.yml +0 -66
  25. package/.github/workflows/deploy.yml +0 -32
  26. package/.github/workflows/e2e.yml +0 -26
  27. package/.github/workflows/npx.yml +0 -69
  28. package/.github/workflows/oxfmt.yml +0 -18
  29. package/.github/workflows/oxlint.yml +0 -19
  30. package/.github/workflows/unit.yml +0 -19
  31. package/playwright-report/index.html +0 -49
  32. package/test-results/.last-run.json +0 -4
  33. package/todo.txt +0 -5
package/bun.lock CHANGED
@@ -5,7 +5,7 @@
5
5
  "": {
6
6
  "name": "scrabble-solver",
7
7
  "dependencies": {
8
- "@scrabble-solver/scrabble-solver": "2.18.10-alpha.0",
8
+ "@scrabble-solver/scrabble-solver": "2.18.10-alpha.1",
9
9
  "open-cli": "9.0.0",
10
10
  "wait-on": "9.5.1",
11
11
  },
@@ -28,48 +28,48 @@
28
28
  },
29
29
  "packages/configs": {
30
30
  "name": "@scrabble-solver/configs",
31
- "version": "2.18.10-alpha.0",
31
+ "version": "2.18.10-alpha.1",
32
32
  "dependencies": {
33
- "@scrabble-solver/constants": "2.18.10-alpha.0",
34
- "@scrabble-solver/types": "2.18.10-alpha.0",
33
+ "@scrabble-solver/constants": "2.18.10-alpha.1",
34
+ "@scrabble-solver/types": "2.18.10-alpha.1",
35
35
  },
36
36
  },
37
37
  "packages/constants": {
38
38
  "name": "@scrabble-solver/constants",
39
- "version": "2.18.10-alpha.0",
39
+ "version": "2.18.10-alpha.1",
40
40
  },
41
41
  "packages/dictionaries": {
42
42
  "name": "@scrabble-solver/dictionaries",
43
- "version": "2.18.10-alpha.0",
43
+ "version": "2.18.10-alpha.1",
44
44
  "bin": {
45
45
  "remove-dictionaries": "bin/remove-dictionaries.js",
46
46
  "update-dictionaries": "bin/update-dictionaries.js",
47
47
  },
48
48
  "dependencies": {
49
49
  "@kamilmielnik/gaddag": "3.0.0",
50
- "@scrabble-solver/logger": "2.18.10-alpha.0",
51
- "@scrabble-solver/types": "2.18.10-alpha.0",
52
- "@scrabble-solver/word-lists": "2.18.10-alpha.0",
50
+ "@scrabble-solver/logger": "2.18.10-alpha.1",
51
+ "@scrabble-solver/types": "2.18.10-alpha.1",
52
+ "@scrabble-solver/word-lists": "2.18.10-alpha.1",
53
53
  },
54
54
  },
55
55
  "packages/logger": {
56
56
  "name": "@scrabble-solver/logger",
57
- "version": "2.18.10-alpha.0",
57
+ "version": "2.18.10-alpha.1",
58
58
  },
59
59
  "packages/scrabble-solver": {
60
60
  "name": "@scrabble-solver/scrabble-solver",
61
- "version": "2.18.10-alpha.0",
61
+ "version": "2.18.10-alpha.1",
62
62
  "dependencies": {
63
63
  "@floating-ui/react": "0.27.20",
64
64
  "@kamilmielnik/gaddag": "3.0.0",
65
65
  "@reduxjs/toolkit": "2.13.0",
66
- "@scrabble-solver/configs": "2.18.10-alpha.0",
67
- "@scrabble-solver/constants": "2.18.10-alpha.0",
68
- "@scrabble-solver/dictionaries": "2.18.10-alpha.0",
69
- "@scrabble-solver/logger": "2.18.10-alpha.0",
70
- "@scrabble-solver/solver": "2.18.10-alpha.0",
71
- "@scrabble-solver/types": "2.18.10-alpha.0",
72
- "@scrabble-solver/word-definitions": "2.18.10-alpha.0",
66
+ "@scrabble-solver/configs": "2.18.10-alpha.1",
67
+ "@scrabble-solver/constants": "2.18.10-alpha.1",
68
+ "@scrabble-solver/dictionaries": "2.18.10-alpha.1",
69
+ "@scrabble-solver/logger": "2.18.10-alpha.1",
70
+ "@scrabble-solver/solver": "2.18.10-alpha.1",
71
+ "@scrabble-solver/types": "2.18.10-alpha.1",
72
+ "@scrabble-solver/word-definitions": "2.18.10-alpha.1",
73
73
  "classnames": "2.5.1",
74
74
  "env-cmd": "11.0.0",
75
75
  "include-media": "2.0.0",
@@ -104,29 +104,29 @@
104
104
  },
105
105
  "packages/solver": {
106
106
  "name": "@scrabble-solver/solver",
107
- "version": "2.18.10-alpha.0",
107
+ "version": "2.18.10-alpha.1",
108
108
  "dependencies": {
109
109
  "@kamilmielnik/gaddag": "3.0.0",
110
- "@scrabble-solver/types": "2.18.10-alpha.0",
110
+ "@scrabble-solver/types": "2.18.10-alpha.1",
111
111
  },
112
112
  "devDependencies": {
113
- "@scrabble-solver/configs": "2.18.10-alpha.0",
114
- "@scrabble-solver/constants": "2.18.10-alpha.0",
115
- "@scrabble-solver/dictionaries": "2.18.10-alpha.0",
113
+ "@scrabble-solver/configs": "2.18.10-alpha.1",
114
+ "@scrabble-solver/constants": "2.18.10-alpha.1",
115
+ "@scrabble-solver/dictionaries": "2.18.10-alpha.1",
116
116
  },
117
117
  },
118
118
  "packages/types": {
119
119
  "name": "@scrabble-solver/types",
120
- "version": "2.18.10-alpha.0",
120
+ "version": "2.18.10-alpha.1",
121
121
  "dependencies": {
122
- "@scrabble-solver/constants": "2.18.10-alpha.0",
122
+ "@scrabble-solver/constants": "2.18.10-alpha.1",
123
123
  },
124
124
  },
125
125
  "packages/word-definitions": {
126
126
  "name": "@scrabble-solver/word-definitions",
127
- "version": "2.18.10-alpha.0",
127
+ "version": "2.18.10-alpha.1",
128
128
  "dependencies": {
129
- "@scrabble-solver/types": "2.18.10-alpha.0",
129
+ "@scrabble-solver/types": "2.18.10-alpha.1",
130
130
  "cheerio": "1.2.0",
131
131
  "follow-redirects": "1.16.2",
132
132
  "striptags": "3.2.0",
@@ -138,9 +138,9 @@
138
138
  },
139
139
  "packages/word-lists": {
140
140
  "name": "@scrabble-solver/word-lists",
141
- "version": "2.18.10-alpha.0",
141
+ "version": "2.18.10-alpha.1",
142
142
  "dependencies": {
143
- "@scrabble-solver/types": "2.18.10-alpha.0",
143
+ "@scrabble-solver/types": "2.18.10-alpha.1",
144
144
  "cheerio": "1.2.0",
145
145
  "follow-redirects": "1.16.2",
146
146
  "transliteration": "2.7.0",
package/e2e/app.spec.ts CHANGED
@@ -13,10 +13,10 @@ import {
13
13
  getRackTile,
14
14
  getResult,
15
15
  getSettingOption,
16
- getSettingsButton,
17
16
  getTooltip,
18
17
  hoverResult,
19
18
  moveMouseAway,
19
+ openSettingsModal,
20
20
  solve,
21
21
  typeRack,
22
22
  visitIndex,
@@ -31,7 +31,7 @@ test.describe('app', () => {
31
31
 
32
32
  test('has default setting values', async ({ page }) => {
33
33
  await visitIndex(page);
34
- await getSettingsButton(page).click();
34
+ await openSettingsModal(page);
35
35
 
36
36
  await expect(getSettingOption(page, 'Game', 'Scrabble')).toBeChecked();
37
37
  await expect(getSettingOption(page, 'Language', 'English (US)')).toBeChecked();
@@ -43,7 +43,7 @@ test.describe('app', () => {
43
43
  test.describe('full app test', () => {
44
44
  test('Scrabble - Polish', async ({ page }) => {
45
45
  await visitIndex(page);
46
- await getSettingsButton(page).click();
46
+ await openSettingsModal(page);
47
47
  await getSettingOption(page, 'Language', 'Polski').check();
48
48
  await closeModal(page);
49
49
  await typeRack(page, 'abł');
@@ -9,7 +9,7 @@ test.describe('#112 - Scrabble - Character bonus not applied', () => {
9
9
  test('correctly shows points for a result which gets a character bonus', async ({ page }) => {
10
10
  await Lib.visitIndex(page);
11
11
 
12
- await Lib.getSettingsButton(page).click();
12
+ await Lib.openSettingsModal(page);
13
13
  await Lib.getSettingOption(page, 'Language', 'Français').check();
14
14
  await Lib.closeModal(page);
15
15
  await Lib.typeRack(page, 'jours');
@@ -8,7 +8,7 @@ import * as Lib from '../lib';
8
8
  test.describe('#129 - Esc does not close the sidebar when letters input is focused', () => {
9
9
  test('Esc key closes the sidebar when rack is focused', async ({ page }) => {
10
10
  await Lib.visitIndex(page);
11
- await Lib.getSettingsButton(page).click();
11
+ await Lib.openSettingsModal(page);
12
12
  await Lib.typeRack(page, 'a');
13
13
  await page.keyboard.press('Escape');
14
14
 
@@ -8,7 +8,7 @@ import * as Lib from '../lib';
8
8
  test.describe('#3 - "X" tile is allowed in Polish', () => {
9
9
  test('does not accept "X" tile in Polish', async ({ page }) => {
10
10
  await Lib.visitIndex(page);
11
- await Lib.getSettingsButton(page).click();
11
+ await Lib.openSettingsModal(page);
12
12
  await Lib.getSettingOption(page, 'Language', 'Polski').check();
13
13
  await Lib.closeModal(page);
14
14
  await Lib.typeBoard(page, 'x', 'horizontal', { x: 7, y: 7 });
@@ -8,7 +8,7 @@ import * as Lib from '../lib';
8
8
  test.describe('#30 - Clicking inside an icon of non-first unchecked radio button does not select that option', () => {
9
9
  test('Clicking inside an icon of first unchecked radio button selects it', async ({ page }) => {
10
10
  await Lib.visitIndex(page);
11
- await Lib.getSettingsButton(page).click();
11
+ await Lib.openSettingsModal(page);
12
12
  await Lib.getSettingOption(page, 'Language', 'English (GB)').click();
13
13
 
14
14
  const icon = Lib.getSettingOption(page, 'Language', 'English (US)')
@@ -8,7 +8,7 @@ import * as Lib from '../lib';
8
8
  test.describe('#333 - Disabled radio button has cursor: pointer', () => {
9
9
  test('Disabled radio button has cursor: not-allowed', async ({ page }) => {
10
10
  await Lib.visitIndex(page);
11
- await Lib.getSettingsButton(page).click();
11
+ await Lib.openSettingsModal(page);
12
12
  await Lib.getSettingOption(page, 'Language', 'Polski').check();
13
13
  await Lib.getSettingOption(page, 'Gra', 'Scrabble').scrollIntoViewIfNeeded();
14
14
 
@@ -8,7 +8,7 @@ import * as Lib from '../lib';
8
8
  test.describe('#342 - Incorrect sorting when filtering', () => {
9
9
  test('correctly sorts valid results first when text filter is active', async ({ page }) => {
10
10
  await Lib.visitIndex(page);
11
- await Lib.getSettingsButton(page).click();
11
+ await Lib.openSettingsModal(page);
12
12
  await Lib.getSettingOption(page, 'Language', 'Polski').check();
13
13
  await Lib.closeModal(page);
14
14
  await Lib.typeBoard(page, 'bopie', 'horizontal', { x: 6, y: 3 });
@@ -13,7 +13,7 @@ test.describe('#363 - Dictionary input should display unique words', () => {
13
13
  });
14
14
 
15
15
  await Lib.visitIndex(page);
16
- await Lib.getSettingsButton(page).click();
16
+ await Lib.openSettingsModal(page);
17
17
  await Lib.getSettingOption(page, 'Language', 'Türkçe').check();
18
18
  await Lib.closeModal(page);
19
19
  await Lib.typeBoard(page, 'ponje', 'horizontal', { x: 3, y: 7 });
@@ -44,7 +44,7 @@ async function testTransliterationOnPaste(
44
44
  },
45
45
  ) {
46
46
  await Lib.visitIndex(page);
47
- await Lib.getSettingsButton(page).click();
47
+ await Lib.openSettingsModal(page);
48
48
  await Lib.getSettingOption(page, 'Language', language).check();
49
49
  await Lib.closeModal(page);
50
50
  await Lib.paste(Lib.getBoardTile(page, 0, 0), word);
@@ -8,11 +8,11 @@ import * as Lib from '../lib';
8
8
  test.describe('#398 - Solitary digraph tiles are recognised as created words', () => {
9
9
  test('should transliterate special characters when pasting in French', async ({ page }) => {
10
10
  await Lib.visitIndex(page);
11
- await Lib.getSettingsButton(page).click();
11
+ await Lib.openSettingsModal(page);
12
12
  await Lib.getSettingOption(page, 'Language', 'Español').check();
13
13
  await Lib.closeModal(page);
14
14
  await Lib.pasteBoard(page, 'chiclean', 'horizontal', { x: 3, y: 7 });
15
- await page.getByLabel('Palabras creadas', { exact: true }).click();
15
+ await Lib.openModal(page, page.getByLabel('Palabras creadas', { exact: true }));
16
16
 
17
17
  const modal = Lib.getOpenModal(page);
18
18
  await expect(modal.getByText('ch', { exact: true })).toHaveCount(0);
@@ -12,7 +12,7 @@ test.describe('#401 - Board state not preserved on game type change', () => {
12
12
  await Lib.visitIndex(page);
13
13
  await Lib.typeBoard(page, 'word', 'horizontal', { x: 7, y: 7 });
14
14
 
15
- await Lib.getSettingsButton(page).click();
15
+ await Lib.openSettingsModal(page);
16
16
  await Lib.getSettingOption(page, 'Game', 'Super Scrabble').check();
17
17
  await Lib.closeModal(page);
18
18
 
@@ -26,7 +26,7 @@ test.describe('#452 - Stale translations cache', () => {
26
26
  });
27
27
  await page.reload();
28
28
 
29
- await page.getByLabel('Created words', { exact: true }).click();
29
+ await Lib.openWordsModal(page);
30
30
  await expect(Lib.getOpenModal(page).getByRole('button', { name: 'Validity', exact: true })).toBeVisible();
31
31
  });
32
32
  });
@@ -70,8 +70,7 @@ test.describe('#198 - Highlight unreachable cells', () => {
70
70
  });
71
71
 
72
72
  async function setHighlightUnreachableCells(page: Page, value: 'Off' | 'On') {
73
- await Lib.getSettingsButton(page).click();
74
- await expect(Lib.getOpenModal(page)).toBeVisible();
73
+ await Lib.openSettingsModal(page);
75
74
  await Lib.getSettingOption(page, 'Highlight unreachable cells', value).check();
76
75
  await Lib.closeModal(page);
77
76
  }
@@ -60,8 +60,7 @@ test.describe('#430 - Highlight unreachable cells includes current results', ()
60
60
  });
61
61
 
62
62
  async function setHighlightUnreachableCells(page: Page, value: 'Off' | 'On') {
63
- await Lib.getSettingsButton(page).click();
64
- await expect(Lib.getOpenModal(page)).toBeVisible();
63
+ await Lib.openSettingsModal(page);
65
64
  await Lib.getSettingOption(page, 'Highlight unreachable cells', value).check();
66
65
  await Lib.closeModal(page);
67
66
  }
@@ -82,13 +82,12 @@ test.describe('#91 - Hovering remaining tile highlights all same tiles on the bo
82
82
  });
83
83
 
84
84
  async function openRemainingTilesModal(page: Page) {
85
- await page.getByLabel('Remaining tiles', { exact: true }).click();
86
- await expect(Lib.getOpenModal(page)).toBeVisible();
85
+ await Lib.openModal(page, page.getByLabel('Remaining tiles', { exact: true }));
87
86
  }
88
87
 
89
88
  async function openRemainingTilesModalFromMenu(page: Page) {
90
- await page.getByRole('button', { name: 'Menu', exact: true }).click();
91
- await Lib.getOpenModal(page).getByLabel('Remaining tiles', { exact: true }).click();
89
+ await Lib.openMenuModal(page);
90
+ await Lib.openModal(page, Lib.getOpenModal(page).getByLabel('Remaining tiles', { exact: true }));
92
91
  await expect(page.getByTestId('remaining-tile-a')).toBeVisible();
93
92
  }
94
93
 
@@ -16,7 +16,7 @@ test.describe('"hidden" coordinates migration', () => {
16
16
 
17
17
  await expect(Lib.getBoardContainer(page).getByText('A', { exact: true })).toBeVisible();
18
18
 
19
- await Lib.getSettingsButton(page).click();
19
+ await Lib.openSettingsModal(page);
20
20
  await expect(Lib.getSettingOption(page, 'Coordinates', 'Original')).toBeChecked();
21
21
  await Lib.closeModal(page);
22
22
 
@@ -39,7 +39,7 @@ test.describe('Words preview', () => {
39
39
  await Lib.getOpenModal(page).getByRole('button', { name: 'Preview', exact: true }).click();
40
40
  await Lib.expectTileHighlighted(Lib.getBoardTile(page, 3, 3));
41
41
 
42
- await page.getByRole('button', { name: 'Results', exact: true }).click();
42
+ await Lib.openModal(page, page.getByRole('button', { name: 'Results', exact: true }));
43
43
  const result = Lib.getOpenModal(page).getByTestId('result').first();
44
44
  await expect(result).not.toHaveAttribute('aria-current');
45
45
  await result.click();
@@ -77,7 +77,7 @@ test.describe('Words preview', () => {
77
77
  await Lib.getOpenModal(page).getByRole('button', { name: 'Preview', exact: true }).click();
78
78
  await Lib.expectTileHighlighted(Lib.getBoardTile(page, 3, 3));
79
79
 
80
- await Lib.getSettingsButton(page).click();
80
+ await Lib.openSettingsModal(page);
81
81
  await Lib.getSettingOption(page, 'Language', 'Polski').check();
82
82
  await Lib.closeModal(page);
83
83
 
@@ -127,8 +127,8 @@ test.describe('Words preview', () => {
127
127
  test('previewing from the menu-opened modal returns to the board', async ({ page }) => {
128
128
  await Lib.visitIndex(page);
129
129
  await Lib.typeBoard(page, 'cat', 'horizontal', { x: 3, y: 3 });
130
- await page.getByRole('button', { name: 'Menu', exact: true }).click();
131
- await Lib.getOpenModal(page).getByLabel('Created words', { exact: true }).click();
130
+ await Lib.openMenuModal(page);
131
+ await Lib.openModal(page, Lib.getOpenModal(page).getByLabel('Created words', { exact: true }));
132
132
 
133
133
  await expect(Lib.getWord(page, 0)).toHaveAttribute('aria-current', 'true');
134
134
 
@@ -12,6 +12,7 @@ import {
12
12
  getResult,
13
13
  getResultCandidatePicker,
14
14
  getResultsContainer,
15
+ getSettingsButton,
15
16
  getWord,
16
17
  } from './selectors';
17
18
 
@@ -39,13 +40,25 @@ export async function closeModal(page: Page): Promise<void> {
39
40
  }
40
41
 
41
42
  export async function openWordsModal(page: Page): Promise<void> {
42
- await page.getByLabel('Created words', { exact: true }).click();
43
- await expect(getOpenModal(page)).toBeVisible();
43
+ await openModal(page, page.getByLabel('Created words', { exact: true }));
44
44
  }
45
45
 
46
46
  export async function openResultsModal(page: Page): Promise<void> {
47
- await getResultCandidatePicker(page).click();
48
- await expect(getOpenModal(page)).toBeVisible();
47
+ await openModal(page, getResultCandidatePicker(page));
48
+ }
49
+
50
+ export async function openSettingsModal(page: Page): Promise<void> {
51
+ await openModal(page, getSettingsButton(page));
52
+ }
53
+
54
+ export async function openMenuModal(page: Page): Promise<void> {
55
+ await openModal(page, page.getByRole('button', { name: 'Menu', exact: true }));
56
+ }
57
+
58
+ export async function openModal(page: Page, trigger: Locator): Promise<void> {
59
+ const openModalsBeforeClick = await getOpenModal(page).count();
60
+ await trigger.click();
61
+ await expect(getOpenModal(page)).toHaveCount(openModalsBeforeClick + 1);
49
62
  }
50
63
 
51
64
  export async function closeModalWithButton(page: Page): Promise<void> {
@@ -5,7 +5,7 @@ export function getModal(page: Page): Locator {
5
5
  }
6
6
 
7
7
  export function getOpenModal(page: Page): Locator {
8
- return page.locator('.ReactModal__Overlay--after-open').getByRole('dialog');
8
+ return page.locator('.ReactModal__Overlay--after-open:not(.ReactModal__Overlay--before-close)').getByRole('dialog');
9
9
  }
10
10
 
11
11
  export function getBoardContainer(page: Page): Locator {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scrabble-solver",
3
- "version": "2.18.10-alpha.0",
3
+ "version": "2.18.10-alpha.1",
4
4
  "description": "Scrabble Solver 2 - Free, open-source, cross-platform, multi-language analysis tool for Scrabble, Scrabble Duel, Super Scrabble, Letter League, Crossplay, Literaki, Kelimelik, Wyrazy, and Wordfeud. Quickly find the top-scoring words using the given board and tiles.",
5
5
  "keywords": [
6
6
  "scrabble",
@@ -41,7 +41,7 @@
41
41
  "reinstall": "bun run clean && bun install && bun run build",
42
42
  "release": "bun run release:prepare && bun run test && nx release --skip-publish && bun run release:publish",
43
43
  "release:prepare": "bun run clean && bun install",
44
- "release:publish": "git push --follow-tags && npm publish --workspaces --include-workspace-root --access public --tag $(node -p \"/-/.test(require('./package.json').version) ? 'next' : 'latest'\") && gh release create $(node -p \"require('./package.json').version\") --draft --generate-notes --prerelease=$(node -p \"/-/.test(require('./package.json').version)\")",
44
+ "release:publish": "git push --follow-tags && npm publish --workspaces --include-workspace-root --access public --tag $(node -p \"/-/.test(require('./package.json').version) ? 'next' : 'latest'\") && gh release create $(node -p \"require('./package.json').version\") --repo kamilmielnik/scrabble-solver --draft --generate-notes --prerelease=$(node -p \"/-/.test(require('./package.json').version)\")",
45
45
  "screencast": "start-server-and-test start:app http://localhost:3333 screencast:record",
46
46
  "screencast:record": "bun scripts/record-screencast.ts",
47
47
  "start": "bun run --parallel --no-orphans 'start:*'",
@@ -78,7 +78,7 @@
78
78
  "packages/scrabble-solver"
79
79
  ],
80
80
  "dependencies": {
81
- "@scrabble-solver/scrabble-solver": "2.18.10-alpha.0",
81
+ "@scrabble-solver/scrabble-solver": "2.18.10-alpha.1",
82
82
  "open-cli": "9.0.0",
83
83
  "wait-on": "9.5.1"
84
84
  },
@@ -1,38 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Bash(npm run:*)",
5
- "Bash(ls:*)",
6
- "Bash(npm ls:*)",
7
- "Bash(npx next:*)",
8
- "Bash(npx tsc:*)",
9
- "Bash(yarn install:*)",
10
- "Bash(npm install:*)",
11
- "Bash(node:*)",
12
- "Bash(npm view:*)",
13
- "Bash(npx --yes oxfmt --help)",
14
- "Bash(npx --yes oxfmt --migrate=prettier)",
15
- "Bash(npm uninstall:*)",
16
- "Bash(grep:*)",
17
- "Bash(echo '.foo { color: red; }')",
18
- "Bash(npx oxfmt:*)",
19
- "Bash(rm /tmp/test.scss)",
20
- "Bash(gh issue *)",
21
- "Bash(npx jest *)",
22
- "Bash(xargs sed *)",
23
- "Bash(gh api *)",
24
- "Bash(find cypress/support -name \"index*\" -exec cat {} \\\\;)",
25
- "Bash(npx eslint *)",
26
- "Bash(file *.avif)",
27
- "Bash(which convert *)",
28
- "Bash(convert \"/home/kamil/desktop/ss/scrabble-word-game-pieces-arranged-grid-from-isolated-white-background_506134-13355.avif\" -resize 400x /tmp/ss3.png)",
29
- "Read(//tmp/**)",
30
- "Bash(du -b /tmp/rect-*.png)",
31
- "Bash(convert \"/tmp/rect-il_1080xN.4271871875_3ays.jpg.png\" -resize 600x /tmp/rect1-small.png)",
32
- "Bash(convert \"/tmp/rect-they-finished-scrabble-board-game-using-the-letters-made-out-of-tiles-S37FPF.jpg.png\" -resize 600x /tmp/rect2-small.png)",
33
- "Bash(convert *)",
34
- "Bash(xargs -I {} dirname {})",
35
- "Bash(xargs -I {} ls -1 {}/)"
36
- ]
37
- }
38
- }
@@ -1,16 +0,0 @@
1
- name: Build
2
-
3
- on:
4
- push:
5
- branches: [master]
6
- pull_request:
7
- branches: [master]
8
-
9
- jobs:
10
- build:
11
- runs-on: ubuntu-latest
12
- steps:
13
- - uses: actions/checkout@v6
14
- - uses: oven-sh/setup-bun@v2
15
- - run: bun install --frozen-lockfile
16
- - run: bun run build
@@ -1,66 +0,0 @@
1
- name: bunx
2
-
3
- on:
4
- push:
5
- branches: [master]
6
- schedule:
7
- - cron: '0 0 * * *' # every day at 00:00 UTC
8
- workflow_dispatch: # allow manual triggering
9
-
10
- jobs:
11
- bunx:
12
- runs-on: ubuntu-latest
13
- steps:
14
- - uses: oven-sh/setup-bun@v2
15
- - uses: actions/checkout@v6
16
- - name: Wait for the released version to be published on npm
17
- run: |
18
- VERSION=$(node -p "require('./package.json').version")
19
- echo "VERSION=$VERSION" >> "$GITHUB_ENV"
20
- echo "Target version: $VERSION"
21
- # Unscoped CLI package + every non-private workspace package, published
22
- # together by `bun run release`. All version in lockstep.
23
- PACKAGES=$(node -p "['scrabble-solver', ...require('fs').readdirSync('packages').map(d=>require('./packages/'+d+'/package.json')).filter(p=>!p.private).map(p=>p.name)].join(' ')")
24
- echo "Waiting for: $PACKAGES"
25
- for pkg in $PACKAGES; do
26
- for i in $(seq 1 60); do
27
- if [ "$(npm view "$pkg@$VERSION" version 2>/dev/null)" = "$VERSION" ]; then
28
- echo "✓ $pkg@$VERSION is available"
29
- break
30
- fi
31
- if [ "$i" -eq 60 ]; then
32
- echo "::error::Timed out waiting for $pkg@$VERSION on npm" >&2
33
- exit 1
34
- fi
35
- echo "… $pkg@$VERSION not available yet (attempt $i/60); sleeping 15s"
36
- sleep 15
37
- done
38
- done
39
- - name: Download published package
40
- run: |
41
- npm pack scrabble-solver@"$VERSION"
42
- mkdir work-dir
43
- tar -xzf scrabble-solver-*.tgz -C work-dir --strip-components=1
44
- - run: bun install --frozen-lockfile
45
- working-directory: work-dir
46
- - name: Pre-warm dictionaries cache
47
- run: node packages/dictionaries/bin/update-dictionaries.js
48
- working-directory: work-dir
49
- - name: Install Playwright browsers
50
- run: bunx playwright install --with-deps chromium
51
- working-directory: work-dir
52
- - name: Install the published package globally
53
- run: bun add --global scrabble-solver@${{ env.VERSION }}
54
- - name: Run e2e tests against the global binary
55
- run: bunx start-server-and-test scrabble-solver http://localhost:3333 'bunx playwright test'
56
- working-directory: work-dir
57
- env:
58
- PLAYWRIGHT_BASE_URL: http://localhost:3333
59
- - uses: actions/upload-artifact@v7
60
- if: failure()
61
- with:
62
- name: playwright-artifacts
63
- path: |
64
- work-dir/playwright-report
65
- work-dir/test-results
66
- if-no-files-found: ignore
@@ -1,32 +0,0 @@
1
- name: Deploy
2
-
3
- on:
4
- workflow_dispatch:
5
- inputs:
6
- branch:
7
- description: 'Branch to deploy'
8
- type: string
9
- required: true
10
- default: 'master'
11
-
12
- permissions: {}
13
-
14
- concurrency:
15
- group: deploy
16
-
17
- jobs:
18
- deploy:
19
- runs-on: ubuntu-latest
20
- steps:
21
- - name: Deploy
22
- env:
23
- BRANCH: ${{ inputs.branch }}
24
- DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
25
- DEPLOY_KNOWN_HOSTS: ${{ secrets.DEPLOY_KNOWN_HOSTS }}
26
- DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
27
- run: |
28
- install -d -m 700 ~/.ssh
29
- printf '%s\n' "$DEPLOY_SSH_KEY" > ~/.ssh/id_ed25519
30
- printf '%s\n' "$DEPLOY_KNOWN_HOSTS" > ~/.ssh/known_hosts
31
- chmod 600 ~/.ssh/id_ed25519
32
- ssh -o StrictHostKeyChecking=yes -o BatchMode=yes -o ConnectTimeout=30 "deploy@$DEPLOY_HOST" "$BRANCH"
@@ -1,26 +0,0 @@
1
- name: E2E
2
-
3
- on:
4
- push:
5
- branches: [master]
6
- pull_request:
7
- branches: [master]
8
-
9
- jobs:
10
- e2e:
11
- runs-on: ubuntu-latest
12
- steps:
13
- - uses: actions/checkout@v6
14
- - uses: oven-sh/setup-bun@v2
15
- - run: bun install --frozen-lockfile
16
- - run: bunx playwright install --with-deps chromium
17
- - run: bun run build
18
- - run: bunx start-server-and-test start:app http://localhost:3333 test-playwright:run
19
- - uses: actions/upload-artifact@v7
20
- if: failure()
21
- with:
22
- name: playwright-artifacts
23
- path: |
24
- playwright-report
25
- test-results
26
- if-no-files-found: ignore