Skip to content

Commit

Permalink
Initial commit with working version (barely)
Browse files Browse the repository at this point in the history
  • Loading branch information
eMaringolo committed Feb 23, 2019
1 parent bc138eb commit 51646bb
Show file tree
Hide file tree
Showing 15 changed files with 632 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .project
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
'srcDirectory' : 'src'
}
3 changes: 3 additions & 0 deletions src/.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
#format : #tonel
}
19 changes: 19 additions & 0 deletions src/BaselineOfCouchDB/BaselineOfCouchDB.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Class {
#name : #BaselineOfCouchDB,
#superclass : #BaselineOf,
#category : #BaselineOfCouchDB
}

{ #category : #baselines }
BaselineOfCouchDB >> baseline: spec [
<baseline>
spec
for: #common
do: [ spec
baseline: 'NeoJSON'
with: [ spec repository: 'github://svenvc/NeoJSON/repository' ].
spec
package: #'CouchDB-Client'
with: [ spec requires: #('NeoJSON') ].
spec group: 'default' with: #(#'CouchDB-Client') ]
]
1 change: 1 addition & 0 deletions src/BaselineOfCouchDB/package.st
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Package { #name : #BaselineOfCouchDB }
8 changes: 8 additions & 0 deletions src/CouchDB/CouchDBError.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"
CouchDBError is raised whenever we get an error response from the CouchDB server, eg: {error: {}} instead of {ok: true}
"
Class {
#name : #CouchDBError,
#superclass : #Error,
#category : #CouchDB
}
145 changes: 145 additions & 0 deletions src/CouchDB/CouchDatabase.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
"
Database provides an interface to a database running on a CouchDB server.
"
Class {
#name : #CouchDatabase,
#superclass : #CouchObject,
#category : #CouchDB
}

{ #category : #'api - database' }
CouchDatabase >> compact [
^self class post: address, '_compact'
]

{ #category : #'api - documents' }
CouchDatabase >> create: anObject [
| response |
response := self class post: address contents: (CouchDocument with: anObject).
^CouchDocument new
address: address / (response at: 'id');
revision: (response at: 'rev');
object: anObject;
yourself
]

{ #category : #'api - documents' }
CouchDatabase >> createAll: aCollectionOfObjects [

| saveAll response documents |
saveAll := (Dictionary new)
at: 'docs' put: aCollectionOfObjects;
yourself.
response := self class post: address , '_bulk_docs' contents: saveAll.
documents := OrderedCollection new.
response with: aCollectionOfObjects
do:
[:dictionary :object |
| document |
document := (self document: (dictionary at: 'id')
revision: (dictionary at: 'rev'))
object: object;
yourself.
documents add: document]. "at: 'new_revs'"
^documents
]

{ #category : #'api - views' }
CouchDatabase >> design: designName view: viewName [
^CouchView new
address: address;
design: designName;
name: viewName;
yourself
]

{ #category : #'api - documents' }
CouchDatabase >> document: id [
^self document: id revision: nil
]

{ #category : #'api - documents' }
CouchDatabase >> document: id revision: revision [
^CouchDocument new
address: address / id;
revision: revision;
yourself
]

{ #category : #'api - querying' }
CouchDatabase >> documents [
^self searchResults: (self class get: address / '_all_docs')
]

{ #category : #'api - querying' }
CouchDatabase >> documentsCount: count [
^self searchResults: (self class get: address, ('_all_docs?count=', count))
]

{ #category : #'api - querying' }
CouchDatabase >> documentsFrom: start [
^self searchResults: (self class get: address, ('_all_docs?startkey=', start))
]

{ #category : #'api - querying' }
CouchDatabase >> documentsFrom: start count: count [
^self searchResults: (self class get: address, ('_all_docs?startkey=', start, '&count=', count))
]

{ #category : #'api - querying' }
CouchDatabase >> documentsFrom: start to: end [
^self searchResults: (self class get: address, ('_all_docs?startkey=', start, '&endkey=', end))
]

{ #category : #'api - database' }
CouchDatabase >> name [
^self information at: 'db_name'
]

{ #category : #'api - querying' }
CouchDatabase >> reverseDocuments [
^self searchResults: (self class get: address, '_all_docs?descending=true')
]

{ #category : #'api - querying' }
CouchDatabase >> reverseDocumentsCount: count [
^self searchResults: (self class get: address, ('_all_docs?descending=true&count=', count))
]

{ #category : #'api - querying' }
CouchDatabase >> reverseDocumentsFrom: start [
^self searchResults: (self class get: address, ('_all_docs?descending=true&startkey=', start))
]

{ #category : #'api - querying' }
CouchDatabase >> reverseDocumentsFrom: start count: count [
^self searchResults: (self class get: address, ('_all_docs?descending=true&startkey=', start, '&count=', count))
]

{ #category : #'api - querying' }
CouchDatabase >> reverseDocumentsFrom: start to: end [
^self searchResults: (self class get: address, ('_all_docs?descending=true&startkey=', start, '&endkey=', end))
]

{ #category : #'api - documents' }
CouchDatabase >> save: aCouchDocument [
self saveAll: (Array with: aCouchDocument)
]

{ #category : #'api - documents' }
CouchDatabase >> saveAll: aCollectionOfDocuments [

| saveAll response |
saveAll := (Dictionary new)
at: 'docs' put: aCollectionOfDocuments;
yourself.
response := self client post: address , '_bulk_docs' contents: saveAll.
response with: aCollectionOfDocuments
do: [:dictionary :document | document revision: (dictionary at: 'rev')]. "at: 'new_revs'"
^response
]

{ #category : #private }
CouchDatabase >> searchResults: results [
^(results at: 'rows') collect: [:row | self document: (row at: 'id') revision: ((row at: 'value') at: 'rev')]
]
169 changes: 169 additions & 0 deletions src/CouchDB/CouchDocument.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
"
Document provides an interface to a document in a database running on a CouchDB server.
Instance Variables:
object <Object> the data/object for this document
revision <String> the revision id for this document
"
Class {
#name : #CouchDocument,
#superclass : #CouchObject,
#instVars : [
'object',
'revision'
],
#classVars : [
'Undefined'
],
#category : #CouchDB
}

{ #category : #'instance creation' }
CouchDocument class >> neoJsonMapping: mapper [
mapper
for: self
do: [ :mapping |
mapping mapAccessor: #id to: '_id'.
mapping mapInstVar: #revision to: '_rev'.
mapping
mapProperty: '+class'
getter: [ :receiver | receiver object class name asString ]
setter: [ :receiver :value | value asSymbol asClass ].
mapping mapInstVar: #object to: 'object' ]
]

{ #category : #'instance creation' }
CouchDocument class >> with: anObject [
^ self new
object: anObject;
yourself
]

{ #category : #'instance creation' }
CouchDocument class >> writeAttachment: uri contentType: aString bytes: aByteArray [
^self request: [:client |
| request |
request := (client requestClass put: uri).
request contentType: aString.
request doNotChunk.
request contentLength: aByteArray size.
request byteSource: aByteArray readStream.
client request: request.
client executeAndGetResponse
]
]

{ #category : #api }
CouchDocument >> delete [
| response |
revision ifNil: [self refresh].
response := self class delete: (address copy query: 'rev=', revision).
revision := response at: 'rev'.
^response
]

{ #category : #accessing }
CouchDocument >> id [
^ self address ifNotNil: [ :obj | obj lastPathSegment ]
]

{ #category : #'initialize-release' }
CouchDocument >> initialize [
super initialize.
object := self undefined
]

{ #category : #converting }
CouchDocument >> jsonWriteOn: aStream [
aStream nextPutAll: '{'.
aStream nextPutAll: '"_id":'.
self id jsonWriteOn: aStream.
self revision ifNotNil:
[aStream nextPutAll: ',"_rev":'.
self revision jsonWriteOn: aStream].
object jsonKeysAndValuesDo: [:key :value |
aStream nextPutAll: ','.
key jsonWriteOn: aStream.
aStream nextPutAll: ':'.
value jsonWriteOn: aStream].
aStream nextPutAll: '}'
]

{ #category : #accessing }
CouchDocument >> object [

object = #_undefined ifTrue: [ self refresh ].
^object
]

{ #category : #accessing }
CouchDocument >> object: anObject [
object := anObject
]

{ #category : #printing }
CouchDocument >> printOn: aStream [
super printOn: aStream.
revision ifNil: [^self].
aStream space; nextPutAll: revision
]

{ #category : #api }
CouchDocument >> refresh [
" Update this Document to the latest revision "

| response |
response := self information.
revision := response at: '_rev'.
((response includesKey: '+class')
and: [ response includesKey: 'object' ])
ifTrue: [ | class |
class := (response at: '+class') asSymbol asClass.
({Array. Dictionary. String. Integer} includes: class)
ifTrue: [ object := NeoJSONReader
fromString: (NeoJSONWriter toString: response object) ]
ifFalse: [ object := NeoJSONReader
fromString: (NeoJSONWriter toString: response object)
as: class ] ]
ifFalse: [ object := response ].
^ response
]

{ #category : #accessing }
CouchDocument >> revision [
^revision
]

{ #category : #accessing }
CouchDocument >> revision: anObject [
revision := anObject
]

{ #category : #api }
CouchDocument >> revisions [
^(self class get: (address copy query: 'revs_info=true')) at: '_revs_info' ifAbsent: [#()]
]

{ #category : #api }
CouchDocument >> save [
| response |
response := self class put: address contents: self.
revision := response at: 'rev'.
^response
]

{ #category : #'initialize-release' }
CouchDocument >> undefined [
^ #_undefined
]

{ #category : #api }
CouchDocument >> writeAttachment: nameString contentType: aString bytes: aByteArray [
| response |
revision ifNil: [self refresh].
response := self class writeAttachment: ((address asString, '/' , nameString) asURI query: 'rev=', revision) contentType: aString bytes: aByteArray.
revision := response at: 'rev'.
^response
]
Loading

0 comments on commit 51646bb

Please sign in to comment.