From 02e87555f41a616afa758abcf790386f908a3e75 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Tue, 23 Sep 2014 15:02:22 -0700 Subject: [PATCH] Handle schema loading --- spec/config-spec.coffee | 87 +++++++++++++++++++++++++++++++++++++++++ src/config.coffee | 41 +++++++++++++++++++ 2 files changed, 128 insertions(+) diff --git a/spec/config-spec.coffee b/spec/config-spec.coffee index 6b4852e26..45c3f4104 100644 --- a/spec/config-spec.coffee +++ b/spec/config-spec.coffee @@ -399,3 +399,90 @@ describe "Config", -> it "updates the config data and resumes saving", -> atom.config.set("hair", "blonde") expect(atom.config.save).toHaveBeenCalled() + + describe "when there is a schema specified", -> + schema = null + + describe '.setSchema(keyPath, schema)', -> + it 'sets defaults specified by the schema', -> + schema = + type: 'object' + properties: + anInt: + type: 'integer' + default: 12 + anObject: + type: 'object' + properties: + nestedInt: + type: 'integer' + default: 24 + nestedObject: + type: 'object' + properties: + superNestedInt: + type: 'integer' + default: 36 + + atom.config.setSchema('foo.bar', schema) + expect(atom.config.get("foo.bar.anInt")).toBe 12 + expect(atom.config.get("foo.bar.anObject")).toEqual + nestedInt: 24 + nestedObject: + superNestedInt: 36 + + it 'can set a non-object schema', -> + schema = + type: 'integer' + default: 12 + + atom.config.setSchema('foo.bar.anInt', schema) + expect(atom.config.get("foo.bar.anInt")).toBe 12 + expect(atom.config.getSchema('foo.bar.anInt')).toEqual + type: 'integer' + default: 12 + + it 'creates a properly nested schema', -> + schema = + type: 'object' + properties: + anInt: + type: 'integer' + default: 12 + + atom.config.setSchema('foo.bar', schema) + + expect(atom.config.schema).toEqual + type: 'object' + properties: + foo: + type: 'object' + properties: + bar: + type: 'object' + properties: + anInt: + type: 'integer' + default: 12 + + describe '.getSchema(keyPath)', -> + schema = + type: 'object' + properties: + anInt: + type: 'integer' + default: 12 + + atom.config.setSchema('foo.bar', schema) + + expect(atom.config.getSchema('foo.bar')).toEqual + type: 'object' + properties: + anInt: + type: 'integer' + default: 12 + + expect(atom.config.getSchema('foo.bar.anInt')).toEqual + type: 'integer' + default: 12 + diff --git a/src/config.coffee b/src/config.coffee index b0e6d64d3..911cffacb 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -31,6 +31,9 @@ class Config # Created during initialization, available as `atom.config` constructor: ({@configDirPath, @resourcePath}={}) -> @emitter = new Emitter + @schema = + type: 'object' + properties: {} @defaultSettings = {} @settings = {} @configFileHasErrors = false @@ -162,6 +165,13 @@ class Config isDefault: (keyPath) -> not _.valueForKeyPath(@settings, keyPath)? + getSchema: (keyPath) -> + keys = keyPath.split('.') + schema = @schema + for key in keys + schema = schema.properties[key] + schema + ### Section: To Deprecate ### @@ -300,6 +310,9 @@ class Config @watchSubscription = null setDefaults: (keyPath, defaults) -> + if typeof defaults isnt 'object' + return _.setValueForKeyPath(@defaultSettings, keyPath, defaults) + keys = keyPath.split('.') hash = @defaultSettings for key in keys @@ -310,6 +323,34 @@ class Config @emit 'updated' @emitter.emit 'did-change' + setSchema: (keyPath, schema) -> + unless typeof schema is "object" + throw new Error("Schemas can only be objects!") + + unless typeof schema.type? + throw new Error("Schema object's must have a type attribute") + + keys = keyPath.split('.') + rootSchema = @schema + for key in keys + rootSchema.type = 'object' + rootSchema.properties ?= {} + properties = rootSchema.properties + properties[key] ?= {} + rootSchema = properties[key] + + _.extend rootSchema, schema + @setDefaults(keyPath, @extractDefaultsFromSchema(schema)) + + extractDefaultsFromSchema: (schema) -> + if schema.default? + schema.default + else if schema.type is 'object' and schema.properties? and typeof schema.properties is "object" + defaults = {} + properties = schema.properties or {} + defaults[key] = @extractDefaultsFromSchema(value) for key, value of properties + defaults + update: -> return if @configFileHasErrors @save()