Skip to content

Commit

Permalink
Merge pull request #1539 from klembot/remove-tiny-uuid
Browse files Browse the repository at this point in the history
Remove tiny-uuid
  • Loading branch information
klembot authored Jul 1, 2024
2 parents 3dc7d3d + 3547b56 commit eafdb88
Show file tree
Hide file tree
Showing 17 changed files with 59 additions and 75 deletions.
6 changes: 0 additions & 6 deletions package-lock.json

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

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
"scroll": "^3.0.1",
"segseg": "^1.0.0",
"semver": "^7.3.4",
"tiny-uuid": "^1.0.0",
"ua-parser-js": "^0.7.33",
"use-error-boundary": "^2.0.6"
},
Expand Down
6 changes: 1 addition & 5 deletions src/externals.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,4 @@ declare module 'segseg' {
p3: SegSegVector,
p4: SegSegVector
): boolean;
}

declare module 'tiny-uuid' {
export default function (): string;
}
}
5 changes: 5 additions & 0 deletions src/setupTests.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
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 @@ -50,5 +51,9 @@ 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: 1 addition & 2 deletions src/store/persistence/electron-ipc/story-formats/load.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import uuid from 'tiny-uuid';
import {TwineElectronWindow} from '../../../../electron/shared';
import {StoryFormatsState} from '../../../story-formats/story-formats.types';

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

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

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

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

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

export function save(state: StoryFormatsState) {
// Delete existing formats in local storage, since we aren't bothering to
// preserve ids.

const previouslySerialized = window.localStorage.getItem(
'twine-storyformats'
);
const previouslySerialized =
window.localStorage.getItem('twine-storyformats');

if (previouslySerialized) {
previouslySerialized.split(',').forEach(id => {
Expand All @@ -20,7 +18,7 @@ export function save(state: StoryFormatsState) {
const ids: string[] = [];

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

// We have to remove the `properties` property if it exists, as that is
// dynamically added when loading.
Expand Down
3 changes: 1 addition & 2 deletions src/store/stories/action-creators/create-story.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {Thunk} from 'react-hook-thunk-reducer';
import uuid from 'tiny-uuid';
import {PrefsState} from '../../prefs';
import {StoriesAction, StoriesState, Story} from '../stories.types';

Expand All @@ -11,7 +10,7 @@ export function createStory(
prefs: PrefsState,
props: Partial<Omit<Story, 'id'>> & Pick<Story, 'name'>
): Thunk<StoriesState, StoriesAction> {
const id = uuid();
const id = window.crypto.randomUUID();

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

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

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

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

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

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

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

Expand Down Expand Up @@ -26,10 +25,10 @@ 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 = uuid();
const newId = window.crypto.randomUUID();

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

// Apply default properties to the passage.
Expand Down Expand Up @@ -92,7 +91,7 @@ export function repairPassage(passage: Passage, parentStory: Story): Passage {
return otherPassage.id === passage.id;
})
) {
const newId = uuid();
const newId = window.crypto.randomUUID();

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

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

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

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

logRepair(story, 'ifid', newIfid, 'was bad type or empty string');
repairs.ifid = newIfid;
Expand Down Expand Up @@ -145,7 +144,7 @@ export function repairStory(
return otherStory.id === story.id;
})
) {
const newId = uuid();
const newId = window.crypto.randomUUID();

logRepair(story, 'id', newId, "conflicted with another story's ID");
repairs.id = newId;
Expand Down
8 changes: 5 additions & 3 deletions src/store/story-formats/reducer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import uuid from 'tiny-uuid';
import {builtins} from './defaults';
import {
StoryFormat,
Expand Down Expand Up @@ -51,7 +50,7 @@ export const reducer: React.Reducer<StoryFormatsState, StoryFormatsAction> = (
);
result.push({
...builtinFormat,
id: uuid(),
id: window.crypto.randomUUID(),
loadState: 'unloaded',
selected: false,
userAdded: false
Expand All @@ -72,7 +71,10 @@ export const reducer: React.Reducer<StoryFormatsState, StoryFormatsAction> = (
return state;
}

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

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

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

export const StoryFormatsContext = React.createContext<StoryFormatsContextProps>(
{
export const StoryFormatsContext =
React.createContext<StoryFormatsContextProps>({
dispatch: () => {},
formats: []
}
);
});

StoryFormatsContext.displayName = 'StoryFormats';

Expand All @@ -35,22 +33,20 @@ export const useStoryFormatsContext = () =>
export const StoryFormatsContextProvider: React.FC = props => {
const {storyFormats} = usePersistence();
const {reportError} = useStoreErrorReporter();
const persistedReducer: React.Reducer<
StoryFormatsState,
StoryFormatsAction
> = React.useCallback(
(state, action) => {
const newState = reducer(state, action);

try {
storyFormats.saveMiddleware(newState, action);
} catch (error) {
reportError(error as Error, 'store.errors.cantPersistStoryFormats');
}
return newState;
},
[reportError, storyFormats]
);
const persistedReducer: React.Reducer<StoryFormatsState, StoryFormatsAction> =
React.useCallback(
(state, action) => {
const newState = reducer(state, action);

try {
storyFormats.saveMiddleware(newState, action);
} catch (error) {
reportError(error as Error, 'store.errors.cantPersistStoryFormats');
}
return newState;
},
[reportError, storyFormats]
);

const [state, dispatch] = useThunkReducer(persistedReducer, defaultBuiltins);

Expand Down
13 changes: 8 additions & 5 deletions src/util/import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
// the filesystem into local storage, and the app can't begin until it's done.

import defaults from 'lodash/defaults';
import uuid from 'tiny-uuid';
import {passageDefaults, storyDefaults, Passage, Story} from '../store/stories';

/**
Expand Down Expand Up @@ -70,8 +69,8 @@ function domToObject(storyEl: Element): ImportedStory {
const startPassagePid = storyEl.getAttribute('startnode');
let startPassageId: string | undefined = undefined;
const story: ImportedStory = {
ifid: storyEl.getAttribute('ifid') ?? uuid(),
id: uuid(),
ifid: storyEl.getAttribute('ifid') ?? window.crypto.randomUUID(),
id: window.crypto.randomUUID(),
lastUpdate: undefined,
name: storyEl.getAttribute('name') ?? undefined,
storyFormat: storyEl.getAttribute('format') ?? undefined,
Expand All @@ -96,7 +95,7 @@ function domToObject(storyEl: Element): ImportedStory {
return {...result, [tagName]: el.getAttribute('color')};
}, {}),
passages: query(storyEl, selectors.passageData).map(passageEl => {
const id = uuid();
const id = window.crypto.randomUUID();
const position = parseDimensions(passageEl.getAttribute('position'));
const size = parseDimensions(passageEl.getAttribute('size'));

Expand Down Expand Up @@ -141,7 +140,11 @@ export function importStories(
// Merge in defaults. We can't use object spreads here because undefined
// values would override defaults.

const story: Story = defaults(importedStory, {id: uuid()}, storyDefaults());
const story: Story = defaults(
importedStory,
{id: window.crypto.randomUUID()},
storyDefaults()
);

// Override the last update as requested.

Expand Down
Loading

0 comments on commit eafdb88

Please sign in to comment.