Added some railguards to the API
This commit is contained in:
parent
9955730876
commit
a3bec04088
6 changed files with 52 additions and 20 deletions
|
@ -10,12 +10,44 @@ import * as types from '@theatre/core/propTypes'
|
|||
import {InvalidArgumentError} from '@theatre/shared/utils/errors'
|
||||
import {validateName} from '@theatre/shared/utils/sanitizers'
|
||||
import userReadableTypeOfValue from '@theatre/shared/utils/userReadableTypeOfValue'
|
||||
import deepEqual from 'fast-deep-equal'
|
||||
export {types}
|
||||
|
||||
/**
|
||||
* Returns a project of the given id, or creates one if it doesn't already exist.
|
||||
*
|
||||
* If @theatre/studio is also loaded, then the state of the project will be managed by the studio.
|
||||
*
|
||||
* Usage:
|
||||
* ```ts
|
||||
* import {getProject} from '@theatre/core'
|
||||
* const config = {} // the config can be empty when starting a new project
|
||||
* const project = getProject("a-unique-id", config)
|
||||
* ```
|
||||
*
|
||||
* Usage with an explicit state:
|
||||
* ```ts
|
||||
* import {getProject} from '@theatre/core'
|
||||
* import state from './saved-state.json'
|
||||
* const config = {state} // here the config contains our saved state
|
||||
* const project = getProject("a-unique-id", config)
|
||||
* ```
|
||||
*/
|
||||
export function getProject(id: string, config: IProjectConfig = {}): IProject {
|
||||
const {...restOfConfig} = config
|
||||
if (projectsSingleton.has(id)) {
|
||||
return projectsSingleton.get(id)!.publicApi
|
||||
const existingProject = projectsSingleton.get(id)
|
||||
if (existingProject) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
if (!deepEqual(config, existingProject.config)) {
|
||||
throw new Error(
|
||||
`You seem to have called Theatre.getProject("${id}", config) twice, with different config objects. ` +
|
||||
`This is disallowed because changing the config of a project on the fly can lead to hard-to-debug issues.\n\n` +
|
||||
`You can fix this by either calling Theatre.getProject() once per project-id,` +
|
||||
` or calling it multiple times but with the exact same config.`,
|
||||
)
|
||||
}
|
||||
}
|
||||
return existingProject.publicApi
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
|
|
|
@ -91,7 +91,7 @@ describe(`SheetObject`, () => {
|
|||
},
|
||||
})
|
||||
|
||||
const seq = sheet.publicApi.sequence()
|
||||
const seq = sheet.publicApi.sequence
|
||||
|
||||
const objValues = iterateOver(
|
||||
prism(() => {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import trackValueAtTime from '@theatre/core/sequences/trackValueAtTime'
|
||||
import type Sheet from '@theatre/core/sheets/Sheet'
|
||||
import type {SheetObjectConfig} from '@theatre/core/sheets/TheatreSheet'
|
||||
import type {SheetObjectAddress} from '@theatre/shared/utils/addresses'
|
||||
import deepMergeWithCache from '@theatre/shared/utils/deepMergeWithCache'
|
||||
import type {SequenceTrackId} from '@theatre/shared/utils/ids'
|
||||
|
@ -53,17 +52,6 @@ export default class SheetObject implements IdentityDerivationProvider {
|
|||
this.publicApi = new TheatreSheetObject(this)
|
||||
}
|
||||
|
||||
overrideConfig(
|
||||
nativeObject: unknown,
|
||||
config: SheetObjectConfig<$IntentionalAny>,
|
||||
) {
|
||||
if (nativeObject !== this.nativeObject) {
|
||||
// @todo
|
||||
}
|
||||
|
||||
this.template.overrideConfig(nativeObject, config)
|
||||
}
|
||||
|
||||
getValues(): IDerivation<Pointer<SerializableMap>> {
|
||||
return this._cache.get('getValues()', () =>
|
||||
prism(() => {
|
||||
|
|
|
@ -10,6 +10,7 @@ import {InvalidArgumentError} from '@theatre/shared/utils/errors'
|
|||
import {validateAndSanitiseSlashedPathOrThrow} from '@theatre/shared/utils/slashedPaths'
|
||||
import type {$IntentionalAny} from '@theatre/shared/utils/types'
|
||||
import userReadableTypeOfValue from '@theatre/shared/utils/userReadableTypeOfValue'
|
||||
import deepEqual from 'fast-deep-equal'
|
||||
|
||||
export type SheetObjectConfig<
|
||||
Props extends PropTypeConfig_Compound<$IntentionalAny>,
|
||||
|
@ -25,7 +26,7 @@ export interface ISheet {
|
|||
config: SheetObjectConfig<Props>,
|
||||
): ISheetObject<Props>
|
||||
|
||||
sequence(): ISequence
|
||||
readonly sequence: ISequence
|
||||
}
|
||||
|
||||
export default class TheatreSheet implements ISheet {
|
||||
|
@ -49,14 +50,21 @@ export default class TheatreSheet implements ISheet {
|
|||
`sheet.object("${key}", ...)`,
|
||||
)
|
||||
|
||||
// @todo sanitize config
|
||||
|
||||
const existingObject = internal.getObject(sanitizedPath)
|
||||
|
||||
const nativeObject = null
|
||||
|
||||
if (existingObject) {
|
||||
existingObject.overrideConfig(nativeObject, config)
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
if (!deepEqual(config, existingObject.template.config)) {
|
||||
throw new Error(
|
||||
`You seem to have called sheet.object("${key}", config) twice, with different values for \`config\`. ` +
|
||||
`This is disallowed because changing the config of an object on the fly would make it difficult to reason about.\n\n` +
|
||||
`You can fix this by either re-using the existing object, or calling sheet.object("${key}", config) with the same config.`,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return existingObject.publicApi as $IntentionalAny
|
||||
} else {
|
||||
const object = internal.createObject(sanitizedPath, nativeObject, config)
|
||||
|
@ -64,7 +72,7 @@ export default class TheatreSheet implements ISheet {
|
|||
}
|
||||
}
|
||||
|
||||
sequence(): TheatreSequence {
|
||||
get sequence(): TheatreSequence {
|
||||
return privateAPI(this).getSequence().publicApi
|
||||
}
|
||||
|
||||
|
|
|
@ -87,5 +87,8 @@
|
|||
"typescript": "^4.4.2",
|
||||
"url-loader": "^4.1.1",
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22697,6 +22697,7 @@ fsevents@^1.2.7:
|
|||
esbuild-loader: ^2.13.1
|
||||
esbuild-register: ^2.5.0
|
||||
exec-loader: ^4.0.0
|
||||
fast-deep-equal: ^3.1.3
|
||||
file-loader: ^6.2.0
|
||||
fs-extra: ^10.0.0
|
||||
html-loader: ^2.1.2
|
||||
|
|
Loading…
Reference in a new issue