Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement observable set #1592

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions src/api/object-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,22 @@ import {
IIsObservableObject,
IObservableArray,
ObservableMap,
ObservableSet,
ObservableObjectAdministration,
endBatch,
fail,
getAdministration,
invariant,
isObservableArray,
isObservableMap,
isObservableSet,
isObservableObject,
startBatch
} from "../internal"

export function keys<K>(map: ObservableMap<K, any>): ReadonlyArray<K>
export function keys<T>(ar: IObservableArray<T>): ReadonlyArray<number>
export function keys<T>(set: ObservableSet<T>): ReadonlyArray<T>
export function keys<T extends Object>(obj: T): ReadonlyArray<string>
export function keys(obj: any): any {
if (isObservableObject(obj)) {
Expand All @@ -24,16 +27,20 @@ export function keys(obj: any): any {
if (isObservableMap(obj)) {
return Array.from(obj.keys())
}
if (isObservableSet(obj)) {
return Array.from(obj.keys())
}
if (isObservableArray(obj)) {
return obj.map((_, index) => index)
}
return fail(
process.env.NODE_ENV !== "production" &&
"'keys()' can only be used on observable objects, arrays and maps"
"'keys()' can only be used on observable objects, arrays, sets and maps"
)
}

export function values<K, T>(map: ObservableMap<K, T>): ReadonlyArray<T>
export function values<T>(set: ObservableSet<T>): ReadonlyArray<T>
export function values<T>(ar: IObservableArray<T>): ReadonlyArray<T>
export function values<T = any>(obj: T): ReadonlyArray<any>
export function values(obj: any): string[] {
Expand All @@ -43,16 +50,20 @@ export function values(obj: any): string[] {
if (isObservableMap(obj)) {
return keys(obj).map(key => obj.get(key))
}
if (isObservableSet(obj)) {
return Array.from(obj.values())
}
if (isObservableArray(obj)) {
return obj.slice()
}
return fail(
process.env.NODE_ENV !== "production" &&
"'values()' can only be used on observable objects, arrays and maps"
"'values()' can only be used on observable objects, arrays, sets and maps"
)
}

export function entries<K, T>(map: ObservableMap<K, T>): ReadonlyArray<[K, T]>
export function entries<T>(set: ObservableSet<T>): ReadonlyArray<[T, T]>
export function entries<T>(ar: IObservableArray<T>): ReadonlyArray<[number, T]>
export function entries<T = any>(obj: T): ReadonlyArray<[string, any]>
export function entries(obj: any): any {
Expand All @@ -62,6 +73,9 @@ export function entries(obj: any): any {
if (isObservableMap(obj)) {
return keys(obj).map(key => [key, obj.get(key)])
}
if (isObservableSet(obj)) {
return Array.from(obj.entries())
}
if (isObservableArray(obj)) {
return obj.map((key, index) => [index, key])
}
Expand Down Expand Up @@ -113,13 +127,16 @@ export function set(obj: any, key: any, value?: any): void {
}

export function remove<K, V>(obj: ObservableMap<K, V>, key: K)
export function remove<T>(obj: ObservableSet<T>, key: T)
export function remove<T>(obj: IObservableArray<T>, index: number)
export function remove<T extends Object>(obj: T, key: string)
export function remove(obj: any, key: any): void {
if (isObservableObject(obj)) {
;((obj as any) as IIsObservableObject)[$mobx].remove(key)
} else if (isObservableMap(obj)) {
obj.delete(key)
} else if (isObservableSet(obj)) {
obj.delete(key)
} else if (isObservableArray(obj)) {
if (typeof key !== "number") key = parseInt(key, 10)
invariant(key >= 0, `Not a valid index: '${key}'`)
Expand All @@ -133,6 +150,7 @@ export function remove(obj: any, key: any): void {
}

export function has<K>(obj: ObservableMap<K, any>, key: K): boolean
export function has<T>(obj: ObservableSet<T>, key: T): boolean
export function has<T>(obj: IObservableArray<T>, index: number): boolean
export function has<T extends Object>(obj: T, key: string): boolean
export function has(obj: any, key: any): boolean {
Expand All @@ -142,6 +160,8 @@ export function has(obj: any, key: any): boolean {
return adm.has(key)
} else if (isObservableMap(obj)) {
return obj.has(key)
} else if (isObservableSet(obj)) {
return obj.has(key)
} else if (isObservableArray(obj)) {
return key >= 0 && key < obj.length
} else {
Expand Down
19 changes: 18 additions & 1 deletion src/api/observable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import {
IObservableArray,
IObservableDecorator,
IObservableMapInitialValues,
IObservableSetInitialValues,
IObservableObject,
IObservableValue,
ObservableMap,
ObservableSet,
ObservableValue,
createDecoratorForEnhancer,
createDynamicObservableObject,
Expand All @@ -14,6 +16,7 @@ import {
extendObservable,
fail,
isES6Map,
isES6Set,
isObservable,
isPlainObject,
refStructEnhancer,
Expand Down Expand Up @@ -88,7 +91,9 @@ function createObservable(v: any, arg2?: any, arg3?: any) {
? observable.array(v, arg2)
: isES6Map(v)
? observable.map(v, arg2)
: v
: isES6Set(v)
? observable.set(v, arg2)
: v

// this value could be converted to a new observable data structure, return it
if (res !== v) return res
Expand Down Expand Up @@ -116,6 +121,10 @@ export interface IObservableFactory {
export interface IObservableFactories {
box<T = any>(value?: T, options?: CreateObservableOptions): IObservableValue<T>
array<T = any>(initialValues?: T[], options?: CreateObservableOptions): IObservableArray<T>
set<T = any>(
initialValues?: IObservableSetInitialValues<T>,
options?: CreateObservableOptions
): ObservableSet<T>
map<K = any, V = any>(
initialValues?: IObservableMapInitialValues<K, V>,
options?: CreateObservableOptions
Expand Down Expand Up @@ -157,6 +166,14 @@ const observableFactories: IObservableFactories = {
const o = asCreateObservableOptions(options)
return new ObservableMap<K, V>(initialValues, getEnhancerFromOptions(o), o.name)
},
set<T = any>(
initialValues?: IObservableSetInitialValues<T>,
options?: CreateObservableOptions
): ObservableSet<T> {
if (arguments.length > 2) incorrectlyUsedAsDecorator("set")
const o = asCreateObservableOptions(options)
return new ObservableSet<T>(initialValues, getEnhancerFromOptions(o), o.name)
},
object<T = any>(
props: T,
decorators?: { [K in keyof T]: Function },
Expand Down
1 change: 1 addition & 0 deletions src/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export * from "./types/intercept-utils"
export * from "./types/listen-utils"
export * from "./types/observablearray"
export * from "./types/observablemap"
export * from "./types/observableset"
export * from "./types/observableobject"
export * from "./types/type-utils"
export * from "./utils/eq"
Expand Down
5 changes: 5 additions & 0 deletions src/mobx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ export {
IMapDidChange,
isObservableMap,
IObservableMapInitialValues,
ObservableSet,
isObservableSet,
ISetDidChange,
ISetWillChange,
IObservableSetInitialValues,
transaction,
observable,
IObservableFactory,
Expand Down
9 changes: 7 additions & 2 deletions src/types/modifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import {
deepEqual,
fail,
isES6Map,
isES6Set,
isObservable,
isObservableArray,
isObservableMap,
isObservableSet,
isObservableObject,
isPlainObject,
observable
Expand All @@ -22,20 +24,23 @@ export function deepEnhancer(v, _, name) {
if (Array.isArray(v)) return observable.array(v, { name })
if (isPlainObject(v)) return observable.object(v, undefined, { name })
if (isES6Map(v)) return observable.map(v, { name })
if (isES6Set(v)) return observable.set(v, { name })

return v
}

export function shallowEnhancer(v, _, name): any {
if (v === undefined || v === null) return v
if (isObservableObject(v) || isObservableArray(v) || isObservableMap(v)) return v
if (isObservableObject(v) || isObservableArray(v) || isObservableMap(v) || isObservableSet(v))
return v
if (Array.isArray(v)) return observable.array(v, { name, deep: false })
if (isPlainObject(v)) return observable.object(v, undefined, { name, deep: false })
if (isES6Map(v)) return observable.map(v, { name, deep: false })
if (isES6Set(v)) return observable.set(v, { name, deep: false })

return fail(
process.env.NODE_ENV !== "production" &&
"The shallow modifier / decorator can only used in combination with arrays, objects and maps"
"The shallow modifier / decorator can only used in combination with arrays, objects, maps and sets"
)
}

Expand Down
Loading