Skip to content

Commit

Permalink
Merge pull request #1545 from klembot/use-module-for-uuids
Browse files Browse the repository at this point in the history
Use library to create UUIDs
  • Loading branch information
klembot authored Jul 27, 2024
2 parents f868518 + c364203 commit 285256a
Show file tree
Hide file tree
Showing 16 changed files with 77 additions and 52 deletions.
24 changes: 22 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"npm": ">=8"
},
"dependencies": {
"@lukeed/uuid": "^2.0.1",
"@popperjs/core": "^2.9.1",
"@tabler/icons": "^1.119.0",
"@testing-library/dom": "^9.3.1",
Expand Down
5 changes: 0 additions & 5 deletions src/setupTests.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {toHaveNoViolations} from 'jest-axe';
import {configure} from '@testing-library/dom';
import '@testing-library/jest-dom';
import {faker} from '@faker-js/faker';
import 'jest-canvas-mock';

// Always mock these files so that Jest doesn't see import.meta.
Expand Down Expand Up @@ -51,9 +50,5 @@ afterEach(() => delete (window as any).matchMedia);
}
};

// ... and jsdom doesn't implement the crypto module, which we use to generate UUIDs.

(window as any).crypto.randomUUID = () => faker.string.uuid();

window.Element.prototype.releasePointerCapture = () => {};
window.Element.prototype.setPointerCapture = () => {};
3 changes: 2 additions & 1 deletion src/store/persistence/electron-ipc/story-formats/load.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {v4 as uuid} from '@lukeed/uuid';
import {TwineElectronWindow} from '../../../../electron/shared';
import {StoryFormatsState} from '../../../story-formats/story-formats.types';

Expand All @@ -15,7 +16,7 @@ export async function load(): Promise<StoryFormatsState> {
}

return storyFormats.map(data => ({
id: window.crypto.randomUUID(),
id: uuid(),
loadState: 'unloaded',
name: data.name,
selected: false,
Expand Down
3 changes: 2 additions & 1 deletion src/store/persistence/local-storage/prefs/save.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {v4 as uuid} from '@lukeed/uuid';
import {PrefsState} from '../../../prefs';

export function save(state: PrefsState) {
Expand All @@ -17,7 +18,7 @@ export function save(state: PrefsState) {
const ids: string[] = [];

for (const name in state) {
const id = window.crypto.randomUUID();
const id = uuid();

ids.push(id);
window.localStorage.setItem(
Expand Down
7 changes: 4 additions & 3 deletions src/store/persistence/local-storage/story-formats/save.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {v4 as uuid} from '@lukeed/uuid';
import {StoryFormatsState} from '../../../story-formats/story-formats.types';

export function save(state: StoryFormatsState) {
Expand All @@ -17,8 +18,8 @@ export function save(state: StoryFormatsState) {

const ids: string[] = [];

state.forEach(format => {
const id = window.crypto.randomUUID();
for (const format of state) {
const id = uuid();

// We have to remove the `properties` property if it exists, as that is
// dynamically added when loading.
Expand All @@ -34,7 +35,7 @@ export function save(state: StoryFormatsState) {
selected: undefined
})
);
});
}

window.localStorage.setItem('twine-storyformats', ids.join(','));
}
3 changes: 2 additions & 1 deletion src/store/stories/action-creators/create-story.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {v4 as uuid} from '@lukeed/uuid';
import {Thunk} from 'react-hook-thunk-reducer';
import {PrefsState} from '../../prefs';
import {StoriesAction, StoriesState, Story} from '../stories.types';
Expand All @@ -10,7 +11,7 @@ export function createStory(
prefs: PrefsState,
props: Partial<Omit<Story, 'id'>> & Pick<Story, 'name'>
): Thunk<StoriesState, StoriesAction> {
const id = window.crypto.randomUUID();
const id = uuid();

if (props.name.trim() === '') {
throw new Error('Story name cannot be empty');
Expand Down
7 changes: 4 additions & 3 deletions src/store/stories/action-creators/duplicate-story.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {v4 as uuid} from '@lukeed/uuid';
import {CreateStoryAction, Story} from '../stories.types';
import {unusedName} from '../../../util/unused-name';

Expand All @@ -8,21 +9,21 @@ export function duplicateStory(
story: Story,
stories: Story[]
): CreateStoryAction {
const id = window.crypto.randomUUID();
const id = uuid();

return {
type: 'createStory',
props: {
...story,
id,
ifid: window.crypto.randomUUID(),
ifid: uuid(),
name: unusedName(
story.name,
stories.map(story => story.name)
),
passages: story.passages.map(passage => ({
...passage,
id: window.crypto.randomUUID(),
id: uuid(),
story: id
}))
}
Expand Down
3 changes: 2 additions & 1 deletion src/store/stories/reducer/create-passage.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {v4 as uuid} from '@lukeed/uuid';
import {passageDefaults} from '../defaults';
import {Passage, Story, StoriesState} from '../stories.types';

Expand Down Expand Up @@ -34,7 +35,7 @@ export function createPassage(

const newPassage: Passage = {
...passageDefaults(),
id: window.crypto.randomUUID(),
id: uuid(),
...passageProps,
story: story.id
};
Expand Down
5 changes: 3 additions & 2 deletions src/store/stories/reducer/create-story.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {v4 as uuid} from '@lukeed/uuid';
import {passageDefaults, storyDefaults} from '../defaults';
import {Story, StoriesState} from '../stories.types';

Expand All @@ -20,9 +21,9 @@ export function createStory(state: StoriesState, storyProps: Partial<Story>) {
}

const story: Story = {
id: window.crypto.randomUUID(),
id: uuid(),
...storyDefaults(),
ifid: window.crypto.randomUUID().toUpperCase(),
ifid: uuid().toUpperCase(),
lastUpdate: new Date(),
passages: [],
tags: [],
Expand Down
20 changes: 11 additions & 9 deletions src/store/stories/reducer/repair/repair-passage.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {v4 as uuid} from '@lukeed/uuid';
import {passageDefaults} from '../../defaults';
import {Passage, Story} from '../../stories.types';

Expand Down Expand Up @@ -25,15 +26,16 @@ export function repairPassage(passage: Passage, parentStory: Story): Passage {
// Give the passage an ID if it has none.

if (typeof passage.id !== 'string' || passage.id === '') {
const newId = window.crypto.randomUUID();
const newId = uuid();

logRepair(passage, 'id', newId, 'was undefined or empty string');
repairs.id = window.crypto.randomUUID();
repairs.id = newId;
}

// Apply default properties to the passage.

Object.entries(passageDefs).forEach(([key, value]) => {
for (const key in passageDefs) {
const value = passageDefs[key as keyof typeof passageDefs];
const defKey = key as keyof typeof passageDefs;

if (
Expand All @@ -43,11 +45,11 @@ export function repairPassage(passage: Passage, parentStory: Story): Passage {
logRepair(passage, defKey, passageDefs[defKey]);
(repairs[defKey] as Passage[typeof defKey]) = passageDefs[defKey];
}
});
}

// Make passage coordinates 0 or greater.

['left', 'top'].forEach(pos => {
for (const pos of ['left', 'top']) {
const posKey = pos as keyof Passage;

if (
Expand All @@ -57,11 +59,11 @@ export function repairPassage(passage: Passage, parentStory: Story): Passage {
logRepair(passage, posKey, 0, 'was negative');
(repairs[posKey] as Passage[typeof posKey]) = 0;
}
});
}

// Make passage dimensions 5 or greater.

['height', 'width'].forEach(dim => {
for (const dim of ['height', 'width']) {
const dimKey = dim as keyof Passage;

if (
Expand All @@ -71,7 +73,7 @@ export function repairPassage(passage: Passage, parentStory: Story): Passage {
logRepair(passage, dimKey, 0, 'was less than 5');
(repairs[dimKey] as Passage[typeof dimKey]) = 5;
}
});
}

// Repair story property if it doesn't point to the parent story.

Expand All @@ -91,7 +93,7 @@ export function repairPassage(passage: Passage, parentStory: Story): Passage {
return otherPassage.id === passage.id;
})
) {
const newId = window.crypto.randomUUID();
const newId = uuid();

logRepair(
passage,
Expand Down
12 changes: 7 additions & 5 deletions src/store/stories/reducer/repair/repair-story.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {v4 as uuid} from '@lukeed/uuid';
import {satisfies} from 'semver';
import {Story} from '../../stories.types';
import {storyDefaults} from '../../defaults';
Expand Down Expand Up @@ -33,7 +34,7 @@ export function repairStory(
// Give the story an ID if it has none.

if (typeof story.id !== 'string' || story.id === '') {
const newId = window.crypto.randomUUID();
const newId = uuid();

logRepair(story, 'id', newId, 'was bad type or empty string');
repairs.id = newId;
Expand All @@ -42,16 +43,17 @@ export function repairStory(
// Give the story an IFID if it has none.

if (typeof story.ifid !== 'string' || story.id === '') {
const newIfid = window.crypto.randomUUID();
const newIfid = uuid();

logRepair(story, 'ifid', newIfid, 'was bad type or empty string');
repairs.ifid = newIfid;
}

// Apply default properties to the story.

Object.entries(storyDefs).forEach(([key, value]) => {
for (const key in storyDefs) {
const defKey = key as keyof typeof storyDefs;
const value = storyDefs[defKey];

if (
(typeof value === 'number' && !Number.isFinite(story[defKey])) ||
Expand All @@ -60,7 +62,7 @@ export function repairStory(
logRepair(story, defKey, storyDefs[defKey]);
(repairs[defKey] as Story[typeof defKey]) = storyDefs[defKey];
}
});
}

if (
typeof story.storyFormat !== 'string' ||
Expand Down Expand Up @@ -144,7 +146,7 @@ export function repairStory(
return otherStory.id === story.id;
})
) {
const newId = window.crypto.randomUUID();
const newId = uuid();

logRepair(story, 'id', newId, "conflicted with another story's ID");
repairs.id = newId;
Expand Down
13 changes: 6 additions & 7 deletions src/store/story-formats/reducer.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {v4 as uuid} from '@lukeed/uuid';
import {builtins} from './defaults';
import {
StoryFormat,
Expand Down Expand Up @@ -37,7 +38,7 @@ export const reducer: React.Reducer<StoryFormatsState, StoryFormatsAction> = (

// Add any builtins not present.

builtinFormats.forEach(builtinFormat => {
for (const builtinFormat of builtinFormats) {
if (
!result.some(
f =>
Expand All @@ -50,13 +51,14 @@ export const reducer: React.Reducer<StoryFormatsState, StoryFormatsAction> = (
);
result.push({
...builtinFormat,
id: window.crypto.randomUUID(),
id: uuid(),
loadState: 'unloaded',
selected: false,
userAdded: false
});
}
});
}

return result;
}

Expand All @@ -71,10 +73,7 @@ export const reducer: React.Reducer<StoryFormatsState, StoryFormatsAction> = (
return state;
}

return [
...state,
{...action.props, id: window.crypto.randomUUID(), loadState: 'unloaded'}
];
return [...state, {...action.props, id: uuid(), loadState: 'unloaded'}];

case 'delete':
return state.filter(f => f.id !== action.id);
Expand Down
3 changes: 2 additions & 1 deletion src/store/story-formats/story-formats-context.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {v4 as uuid} from '@lukeed/uuid';
import * as React from 'react';
import useThunkReducer from 'react-hook-thunk-reducer';
import {usePersistence} from '../persistence/use-persistence';
Expand All @@ -13,7 +14,7 @@ import {reducer} from './reducer';

const defaultBuiltins: StoryFormat[] = builtins().map(f => ({
...f,
id: window.crypto.randomUUID(),
id: uuid(),
loadState: 'unloaded',
selected: false,
userAdded: false
Expand Down
Loading

0 comments on commit 285256a

Please sign in to comment.