Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="JavaScriptSettings">
|
||||
<option name="languageLevel" value="ES6" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
+8
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/rpdata-api.iml" filepath="$PROJECT_DIR$/.idea/rpdata-api.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
+29
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectTasksOptions">
|
||||
<TaskOptions isEnabled="true">
|
||||
<option name="arguments" value="fmt $FilePath$" />
|
||||
<option name="checkSyntaxErrors" value="true" />
|
||||
<option name="description" />
|
||||
<option name="exitCodeBehavior" value="ERROR" />
|
||||
<option name="fileExtension" value="go" />
|
||||
<option name="immediateSync" value="false" />
|
||||
<option name="name" value="go fmt" />
|
||||
<option name="output" value="$FilePath$" />
|
||||
<option name="outputFilters">
|
||||
<array />
|
||||
</option>
|
||||
<option name="outputFromStdout" value="false" />
|
||||
<option name="program" value="$GoExecPath$" />
|
||||
<option name="runOnExternalChanges" value="false" />
|
||||
<option name="scopeName" value="Project Files" />
|
||||
<option name="trackOnlyRoot" value="true" />
|
||||
<option name="workingDir" value="$ProjectFileDir$" />
|
||||
<envs>
|
||||
<env name="GOROOT" value="$GOROOT$" />
|
||||
<env name="GOPATH" value="$GOPATH$" />
|
||||
<env name="PATH" value="$GoBinDirs$" />
|
||||
</envs>
|
||||
</TaskOptions>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+586
@@ -0,0 +1,586 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="ac85876f-1087-49cc-8c50-039d9d6340d7" name="Default Changelist" comment="">
|
||||
<change afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/.idea/modules.xml" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/.idea/watcherTasks.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/database/mongodb/db.go" beforeDir="false" afterPath="$PROJECT_DIR$/database/mongodb/db.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/database/mongodb/tags.go" beforeDir="false" afterPath="$PROJECT_DIR$/database/mongodb/tags.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/go.mod" beforeDir="false" afterPath="$PROJECT_DIR$/go.mod" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/go.sum" beforeDir="false" afterPath="$PROJECT_DIR$/go.sum" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/graph2/complexity.go" beforeDir="false" afterPath="$PROJECT_DIR$/graph2/complexity.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/graph2/gqlgen.yml" beforeDir="false" afterPath="$PROJECT_DIR$/graph2/gqlgen.yml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/graph2/graph.go" beforeDir="false" afterPath="$PROJECT_DIR$/graph2/graph.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/graph2/resolvers/character.go" beforeDir="false" afterPath="$PROJECT_DIR$/graph2/resolvers/character.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/graph2/resolvers/resolvers.go" beforeDir="false" afterPath="$PROJECT_DIR$/graph2/resolvers/resolvers.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/graph2/types/log.go" beforeDir="false" afterPath="$PROJECT_DIR$/graph2/types/log.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/internal/auth/permitted.go" beforeDir="false" afterPath="$PROJECT_DIR$/internal/auth/permitted.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/models/changekeys/one.go" beforeDir="false" afterPath="$PROJECT_DIR$/models/changekeys/one.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/models/changes/submit.go" beforeDir="false" afterPath="$PROJECT_DIR$/models/changes/submit.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/models/character.go" beforeDir="false" afterPath="$PROJECT_DIR$/models/character.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/models/tag.go" beforeDir="false" afterPath="$PROJECT_DIR$/models/tag.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/models/tags/db.go" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/models/tags/list.go" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/repositories/repository.go" beforeDir="false" afterPath="$PROJECT_DIR$/repositories/repository.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/repositories/tag.go" beforeDir="false" afterPath="$PROJECT_DIR$/repositories/tag.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/services/services.go" beforeDir="false" afterPath="$PROJECT_DIR$/services/services.go" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/services/tags.go" beforeDir="false" afterPath="$PROJECT_DIR$/services/tags.go" afterDir="false" />
|
||||
</list>
|
||||
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="FileEditorManager">
|
||||
<leaf SIDE_TABS_SIZE_LIMIT_KEY="450">
|
||||
<file pinned="false" current-in-tab="true">
|
||||
<entry file="file://$PROJECT_DIR$/database/mongodb/characters.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="419">
|
||||
<caret line="109" column="4" selection-start-line="109" selection-start-column="4" selection-end-line="109" selection-end-column="4" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$USER_HOME$/go/pkg/mod/github.com/globalsign/mgo@v0.0.0-20180403085842-f76e4f9da92e/session.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="539">
|
||||
<caret line="2707" column="14" selection-start-line="2707" selection-start-column="5" selection-end-line="2707" selection-end-column="14" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/services/characters.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="1632">
|
||||
<caret line="63" column="25" lean-forward="true" selection-start-line="63" selection-start-column="25" selection-end-line="63" selection-end-column="25" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/models/changekeys/listed.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="288">
|
||||
<caret line="6" column="14" selection-start-line="6" selection-start-column="14" selection-end-line="6" selection-end-column="14" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/models/changekeys/many.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="816">
|
||||
<caret line="21" column="33" lean-forward="true" selection-start-line="21" selection-start-column="33" selection-end-line="21" selection-end-column="33" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/models/changekeys/one.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="851">
|
||||
<caret line="25" lean-forward="true" selection-start-line="25" selection-end-line="25" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/repositories/character.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="576">
|
||||
<caret line="12" column="4" selection-start-line="12" selection-start-column="4" selection-end-line="12" selection-end-column="4" />
|
||||
<folding>
|
||||
<element signature="e#22#80#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
</leaf>
|
||||
</component>
|
||||
<component name="FileTemplateManagerImpl">
|
||||
<option name="RECENT_TEMPLATES">
|
||||
<list>
|
||||
<option value="Go File" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="FindInProjectRecents">
|
||||
<findStrings>
|
||||
<find>delete(l.cache</find>
|
||||
<find>dataloade</find>
|
||||
</findStrings>
|
||||
</component>
|
||||
<component name="GOROOT" path="/usr/lib/go" />
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="GoLibraries">
|
||||
<option name="indexEntireGoPath" value="false" />
|
||||
</component>
|
||||
<component name="IdeDocumentHistory">
|
||||
<option name="CHANGED_PATHS">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/graph2/graphcore/exec_gen.go" />
|
||||
<option value="$PROJECT_DIR$/database/mongodb/tags.go" />
|
||||
<option value="$PROJECT_DIR$/repositories/tag.go" />
|
||||
<option value="$PROJECT_DIR$/services/services.go" />
|
||||
<option value="$PROJECT_DIR$/services/loaders/characterloader_gen.go" />
|
||||
<option value="$PROJECT_DIR$/graph2/tools.go" />
|
||||
<option value="$PROJECT_DIR$/tools.go" />
|
||||
<option value="$PROJECT_DIR$/repositories/character.go" />
|
||||
<option value="$PROJECT_DIR$/graph2/gqlgen.yml" />
|
||||
<option value="$PROJECT_DIR$/graph2/resolvers/resolvers.go" />
|
||||
<option value="$PROJECT_DIR$/graph2/resolvers/character.go" />
|
||||
<option value="$PROJECT_DIR$/database/mongodb/db.go" />
|
||||
<option value="$PROJECT_DIR$/services/tags.go" />
|
||||
<option value="$PROJECT_DIR$/graph2/complexity.go" />
|
||||
<option value="$PROJECT_DIR$/graph2/types/log.go" />
|
||||
<option value="$PROJECT_DIR$/graph2/graph.go" />
|
||||
<option value="$PROJECT_DIR$/services/loaders/loaders.go" />
|
||||
<option value="$PROJECT_DIR$/internal/auth/permitted.go" />
|
||||
<option value="$PROJECT_DIR$/models/changekeys/many.go" />
|
||||
<option value="$PROJECT_DIR$/models/changekeys/one.go" />
|
||||
<option value="$PROJECT_DIR$/models/token.go" />
|
||||
<option value="$PROJECT_DIR$/models/character.go" />
|
||||
<option value="$PROJECT_DIR$/services/characters.go" />
|
||||
<option value="$PROJECT_DIR$/database/mongodb/characters.go" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="JsFlowSettings">
|
||||
<service-enabled>true</service-enabled>
|
||||
<exe-path />
|
||||
<other-services-enabled>true</other-services-enabled>
|
||||
<auto-save>true</auto-save>
|
||||
</component>
|
||||
<component name="ProjectFrameBounds" extendedState="6">
|
||||
<option name="x" value="1220" />
|
||||
<option name="y" value="600" />
|
||||
<option name="width" value="1400" />
|
||||
<option name="height" value="1000" />
|
||||
</component>
|
||||
<component name="ProjectLevelVcsManager">
|
||||
<ConfirmationsSetting value="1" id="Add" />
|
||||
</component>
|
||||
<component name="ProjectView">
|
||||
<navigator proportions="" version="1">
|
||||
<foldersAlwaysOnTop value="true" />
|
||||
</navigator>
|
||||
<panes>
|
||||
<pane id="Scope" />
|
||||
<pane id="ProjectPane">
|
||||
<subPane>
|
||||
<expand>
|
||||
<path>
|
||||
<item name="rpdata-api" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="rpdata-api" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="rpdata-api" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="rpdata-api" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="database" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="rpdata-api" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="rpdata-api" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="database" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="mongodb" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="rpdata-api" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="rpdata-api" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="services" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="rpdata-api" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="External Libraries" type="cb654da1:ExternalLibrariesNode" />
|
||||
</path>
|
||||
</expand>
|
||||
<select />
|
||||
</subPane>
|
||||
</pane>
|
||||
</panes>
|
||||
</component>
|
||||
<component name="PropertiesComponent">
|
||||
<property name="ASKED_SHARE_PROJECT_CONFIGURATION_FILES" value="true" />
|
||||
<property name="DefaultGoTemplateProperty" value="Go File" />
|
||||
<property name="SHARE_PROJECT_CONFIGURATION_FILES" value="true" />
|
||||
<property name="WebServerToolWindowFactoryState" value="false" />
|
||||
<property name="configurable.Global.GOPATH.is.expanded" value="true" />
|
||||
<property name="configurable.Module.GOPATH.is.expanded" value="false" />
|
||||
<property name="configurable.Project.GOPATH.is.expanded" value="true" />
|
||||
<property name="go.gopath.indexing.explicitly.defined" value="true" />
|
||||
<property name="go.import.settings.migrated" value="true" />
|
||||
<property name="go.sdk.automatically.set" value="true" />
|
||||
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
|
||||
<property name="nodejs_package_manager_path" value="npm" />
|
||||
<property name="settings.editor.selected.configurable" value="reference.settingsdialog.IDE.editor.colors.Color Scheme Font" />
|
||||
</component>
|
||||
<component name="RecentsManager">
|
||||
<key name="MoveFile.RECENT_KEYS">
|
||||
<recent name="$PROJECT_DIR$" />
|
||||
</key>
|
||||
</component>
|
||||
<component name="RunDashboard">
|
||||
<option name="ruleStates">
|
||||
<list>
|
||||
<RuleState>
|
||||
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
|
||||
</RuleState>
|
||||
<RuleState>
|
||||
<option name="name" value="StatusDashboardGroupingRule" />
|
||||
</RuleState>
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="TodoView">
|
||||
<todo-panel id="selected-file">
|
||||
<is-autoscroll-to-source value="true" />
|
||||
</todo-panel>
|
||||
<todo-panel id="all">
|
||||
<are-packages-shown value="true" />
|
||||
<is-autoscroll-to-source value="true" />
|
||||
</todo-panel>
|
||||
</component>
|
||||
<component name="ToolWindowManager">
|
||||
<frame x="0" y="41" width="3840" height="2119" extended-state="6" />
|
||||
<editor active="true" />
|
||||
<layout>
|
||||
<window_info content_ui="combo" id="Project" order="0" sideWeight="0.5998948" visible="true" weight="0.109684326" />
|
||||
<window_info active="true" id="Structure" order="1" sideWeight="0.40010515" side_tool="true" visible="true" weight="0.109684326" />
|
||||
<window_info id="Favorites" order="2" side_tool="true" />
|
||||
<window_info anchor="bottom" id="GraphQL" />
|
||||
<window_info anchor="bottom" id="Message" order="0" />
|
||||
<window_info anchor="bottom" id="Find" order="1" />
|
||||
<window_info anchor="bottom" id="Run" order="2" weight="0.32993016" />
|
||||
<window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
|
||||
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
|
||||
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
|
||||
<window_info anchor="bottom" id="TODO" order="6" weight="0.32993016" />
|
||||
<window_info anchor="bottom" id="Docker" order="7" show_stripe_button="false" />
|
||||
<window_info anchor="bottom" id="Database Changes" order="8" />
|
||||
<window_info anchor="bottom" id="Version Control" order="9" />
|
||||
<window_info anchor="bottom" id="Terminal" order="10" />
|
||||
<window_info anchor="bottom" id="Event Log" order="11" side_tool="true" weight="0.32993016" />
|
||||
<window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
|
||||
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
|
||||
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
|
||||
<window_info anchor="right" id="Database" order="3" />
|
||||
</layout>
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="1" />
|
||||
</component>
|
||||
<component name="VgoProject">
|
||||
<integration-enabled>true</integration-enabled>
|
||||
</component>
|
||||
<component name="editorHistoryManager">
|
||||
<entry file="file://$PROJECT_DIR$/internal/store/space.go">
|
||||
<provider selected="true" editor-type-id="text-editor" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/database/mongodb/tags.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="1200">
|
||||
<caret line="34" column="27" selection-start-line="34" selection-start-column="27" selection-end-line="34" selection-end-column="27" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/repositories/tag.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="288">
|
||||
<caret line="10" column="49" selection-start-line="10" selection-start-column="42" selection-end-line="10" selection-end-column="49" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/.vscode/settings.json">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="144">
|
||||
<caret line="3" selection-start-line="3" selection-end-line="3" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/models/characters/list.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="-1095" />
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$USER_HOME$/go/pkg/mod/github.com/globalsign/mgo@v0.0.0-20180403085842-f76e4f9da92e/bulk.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="1608">
|
||||
<caret line="353" column="22" selection-start-line="353" selection-start-column="22" selection-end-line="353" selection-end-column="22" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/internal/store/db.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="-972" />
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/models/logs/find.go">
|
||||
<provider selected="true" editor-type-id="text-editor" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/models/logs/list.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="-432" />
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/models/logs/add.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="336">
|
||||
<caret line="7" column="22" selection-start-line="7" selection-start-column="22" selection-end-line="7" selection-end-column="22" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/internal/counter/counter.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="1305">
|
||||
<caret line="52" column="27" selection-start-line="52" selection-start-column="27" selection-end-line="52" selection-end-column="40" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/models/posts/remove.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="1056">
|
||||
<caret line="26" column="1" lean-forward="true" selection-start-line="26" selection-start-column="1" selection-end-line="26" selection-end-column="1" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/repositories/repository.go">
|
||||
<provider selected="true" editor-type-id="text-editor" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/models/characters/db.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="441">
|
||||
<caret line="34" selection-start-line="34" selection-end-line="52" selection-end-column="9" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/graph2/graphcore/input_gen.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="288">
|
||||
<caret line="6" selection-start-line="6" selection-end-line="6" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/graph2/schema/types/Character.gql">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="192">
|
||||
<caret line="4" lean-forward="true" selection-start-line="4" selection-end-line="4" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/tools.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="336">
|
||||
<caret line="7" selection-start-line="7" selection-end-line="7" />
|
||||
<folding>
|
||||
<element signature="e#30#74#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/go.mod">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="480">
|
||||
<caret line="10" column="22" selection-start-line="10" selection-start-column="22" selection-end-line="10" selection-end-column="22" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/database/database.go">
|
||||
<provider selected="true" editor-type-id="text-editor" />
|
||||
</entry>
|
||||
<entry file="file://$USER_HOME$/go/pkg/mod/github.com/globalsign/mgo@v0.0.0-20180403085842-f76e4f9da92e/bson/bson.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="582">
|
||||
<caret line="154" column="5" selection-start-line="154" selection-start-column="5" selection-end-line="154" selection-end-column="6" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/.drone.yml">
|
||||
<provider selected="true" editor-type-id="text-editor" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/graph2/gqlgen.yml">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="755">
|
||||
<caret line="23" column="10" lean-forward="true" selection-start-line="23" selection-start-column="10" selection-end-line="23" selection-end-column="10" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/graph2/resolvers/resolvers.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="336">
|
||||
<caret line="10" lean-forward="true" selection-start-line="10" selection-end-line="10" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/database/mongodb/db.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="803">
|
||||
<caret line="81" column="30" selection-start-line="81" selection-start-column="30" selection-end-line="81" selection-end-column="30" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/services/tags.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="720">
|
||||
<caret line="15" column="71" selection-start-line="15" selection-start-column="71" selection-end-line="15" selection-end-column="71" />
|
||||
<folding>
|
||||
<element signature="e#18#118#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/graph2/complexity.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="624">
|
||||
<caret line="13" column="13" lean-forward="true" selection-start-line="13" selection-start-column="13" selection-end-line="13" selection-end-column="13" />
|
||||
<folding>
|
||||
<element signature="e#16#377#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/services/services.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="528">
|
||||
<caret line="11" column="1" lean-forward="true" selection-start-line="11" selection-start-column="1" selection-end-line="11" selection-end-column="1" />
|
||||
<folding>
|
||||
<element signature="e#18#116#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/graph2/graphcore/exec_gen.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="587">
|
||||
<caret line="1596" selection-start-line="1596" selection-end-line="1596" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/graph2/graph.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="1283">
|
||||
<caret line="37" column="11" lean-forward="true" selection-start-line="37" selection-start-column="11" selection-end-line="37" selection-end-column="11" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/graph2/types/log.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="515">
|
||||
<caret line="30" column="26" selection-start-line="30" selection-start-column="26" selection-end-line="30" selection-end-column="26" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/services/loaders/characterloader_gen.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="587">
|
||||
<caret line="115" column="26" selection-start-line="115" selection-start-column="26" selection-end-line="115" selection-end-column="26" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/graph2/resolvers/character.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="899">
|
||||
<caret line="29" column="12" lean-forward="true" selection-start-line="29" selection-start-column="12" selection-end-line="29" selection-end-column="12" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/services/loaders/loaders.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="288">
|
||||
<caret line="6" selection-start-line="6" selection-end-line="6" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/models/changekeys/many.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="816">
|
||||
<caret line="21" column="33" lean-forward="true" selection-start-line="21" selection-start-column="33" selection-end-line="21" selection-end-column="33" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/models/changekeys/listed.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="288">
|
||||
<caret line="6" column="14" selection-start-line="6" selection-start-column="14" selection-end-line="6" selection-end-column="14" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/models/changes/submit.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="723">
|
||||
<caret line="72" column="25" lean-forward="true" selection-start-line="72" selection-start-column="25" selection-end-line="72" selection-end-column="25" />
|
||||
<folding>
|
||||
<element signature="e#17#136#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$USER_HOME$/go/pkg/mod/github.com/globalsign/mgo@v0.0.0-20180403085842-f76e4f9da92e/session.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="539">
|
||||
<caret line="2707" column="14" selection-start-line="2707" selection-start-column="5" selection-end-line="2707" selection-end-column="14" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/models/token.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="1235">
|
||||
<caret line="41" selection-start-line="41" selection-end-line="41" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/internal/auth/permitted.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="816">
|
||||
<caret line="29" column="32" lean-forward="true" selection-start-line="29" selection-start-column="32" selection-end-line="29" selection-end-column="32" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/models/character.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="1043">
|
||||
<caret line="45" column="14" selection-start-line="45" selection-start-column="14" selection-end-line="45" selection-end-column="14" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/models/changekeys/one.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="851">
|
||||
<caret line="25" lean-forward="true" selection-start-line="25" selection-end-line="25" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/services/characters.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="1632">
|
||||
<caret line="63" column="25" lean-forward="true" selection-start-line="63" selection-start-column="25" selection-end-line="63" selection-end-column="25" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/repositories/character.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="576">
|
||||
<caret line="12" column="4" selection-start-line="12" selection-start-column="4" selection-end-line="12" selection-end-column="4" />
|
||||
<folding>
|
||||
<element signature="e#22#80#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/database/mongodb/characters.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="419">
|
||||
<caret line="109" column="4" selection-start-line="109" selection-start-column="4" selection-end-line="109" selection-end-column="4" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,217 @@
|
||||
package mongodb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/globalsign/mgo"
|
||||
"github.com/globalsign/mgo/bson"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"git.aiterp.net/rpdata/api/repositories"
|
||||
)
|
||||
|
||||
type characterRepository struct {
|
||||
characters *mgo.Collection
|
||||
cidCounter *counter
|
||||
}
|
||||
|
||||
func newCharacterRepository(db *mgo.Database) (repositories.CharacterRepository, error) {
|
||||
collection := db.C("common.characters")
|
||||
|
||||
err := collection.EnsureIndexKey("name")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = collection.EnsureIndexKey("shortName")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = collection.EnsureIndexKey("author")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = collection.EnsureIndex(mgo.Index{
|
||||
Key: []string{"nicks"},
|
||||
Unique: true,
|
||||
DropDups: true,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = collection.EnsureIndex(mgo.Index{
|
||||
Key: []string{"$text:description"},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &characterRepository{
|
||||
characters: collection,
|
||||
cidCounter: newCounter(db, "auto_increment", "Character"),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *characterRepository) Find(ctx context.Context, id string) (*models.Character, error) {
|
||||
character := new(models.Character)
|
||||
err := r.characters.FindId(id).One(character)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return character, nil
|
||||
}
|
||||
|
||||
func (r *characterRepository) FindNick(ctx context.Context, nick string) (*models.Character, error) {
|
||||
character := new(models.Character)
|
||||
err := r.characters.Find(bson.M{"nick": nick}).One(character)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return character, nil
|
||||
}
|
||||
|
||||
func (r *characterRepository) List(ctx context.Context, filter models.CharacterFilter) ([]*models.Character, error) {
|
||||
query := bson.M{}
|
||||
if filter.Author != nil {
|
||||
query["author"] = *filter.Author
|
||||
}
|
||||
if len(filter.IDs) > 0 {
|
||||
query["_id"] = bson.M{"$in": filter.IDs}
|
||||
}
|
||||
if len(filter.Nicks) > 0 {
|
||||
query["nicks"] = bson.M{"$in": filter.Nicks}
|
||||
}
|
||||
if len(filter.Names) > 0 {
|
||||
query["$or"] = []bson.M{
|
||||
{"name": bson.M{"$in": filter.Names}},
|
||||
{"shortName": bson.M{"$in": filter.Names}},
|
||||
}
|
||||
}
|
||||
if filter.Search != nil {
|
||||
query["$text"] = bson.M{"$search": *filter.Search}
|
||||
}
|
||||
|
||||
characters := make([]*models.Character, 0, 32)
|
||||
err := r.characters.Find(query).All(&characters)
|
||||
if err != nil {
|
||||
if err == mgo.ErrNotFound {
|
||||
return characters, nil
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sort.Slice(characters, func(i, j int) bool {
|
||||
ni, _ := strconv.Atoi(characters[i].ID[1:])
|
||||
nj, _ := strconv.Atoi(characters[j].ID[1:])
|
||||
|
||||
return ni < nj
|
||||
})
|
||||
|
||||
return characters, nil
|
||||
}
|
||||
|
||||
func (r *characterRepository) Insert(ctx context.Context, character models.Character) (*models.Character, error) {
|
||||
nextId, err := r.cidCounter.Increment(1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
character.ID = "C" + strconv.Itoa(nextId)
|
||||
|
||||
err = r.characters.Insert(&character)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &character, nil
|
||||
}
|
||||
|
||||
func (r *characterRepository) Update(ctx context.Context, character models.Character, update models.CharacterUpdate) (*models.Character, error) {
|
||||
updateBson := bson.M{}
|
||||
if update.Name != nil {
|
||||
updateBson["name"] = *update.Name
|
||||
character.Name = *update.Name
|
||||
}
|
||||
if update.ShortName != nil {
|
||||
updateBson["shortName"] = *update.ShortName
|
||||
character.ShortName = *update.ShortName
|
||||
}
|
||||
if update.Description != nil {
|
||||
updateBson["description"] = *update.Description
|
||||
character.Description = *update.Description
|
||||
}
|
||||
|
||||
err := r.characters.UpdateId(character.ID, bson.M{"$set": updateBson})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &character, nil
|
||||
}
|
||||
|
||||
func (r *characterRepository) AddNick(ctx context.Context, character models.Character, nick string) (*models.Character, error) {
|
||||
if character.HasNick(nick) {
|
||||
return nil, errors.New("nick already exist")
|
||||
}
|
||||
|
||||
match := bson.M{
|
||||
"_id": character.ID,
|
||||
"nicks": bson.M{"$ne": nick},
|
||||
}
|
||||
|
||||
err := r.characters.Update(match, bson.M{"$push": bson.M{"nicks": nick}})
|
||||
if err == mgo.ErrNotFound {
|
||||
return nil, repositories.ErrNotFound
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newNicks := make([]string, len(character.Nicks), len(character.Nicks)+1)
|
||||
copy(newNicks, character.Nicks)
|
||||
character.Nicks = append(newNicks, nick)
|
||||
|
||||
return &character, nil
|
||||
}
|
||||
|
||||
func (r *characterRepository) RemoveNick(ctx context.Context, character models.Character, nick string) (*models.Character, error) {
|
||||
if !character.HasNick(nick) {
|
||||
return nil, errors.New("nick does not exist")
|
||||
}
|
||||
|
||||
match := bson.M{
|
||||
"_id": character.ID,
|
||||
"nicks": nick,
|
||||
}
|
||||
|
||||
err := r.characters.Update(match, bson.M{"$pull": bson.M{"nicks": nick}})
|
||||
if err == mgo.ErrNotFound {
|
||||
return nil, repositories.ErrNotFound
|
||||
} else if mErr, ok := err.(*mgo.LastError); ok && mErr.Code == 11000 {
|
||||
return nil, errors.New("The nick belongs to another character already")
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newNicks := make([]string, len(character.Nicks), len(character.Nicks)+1)
|
||||
copy(newNicks, character.Nicks)
|
||||
for i := range newNicks {
|
||||
if newNicks[i] == nick {
|
||||
newNicks = append(newNicks[:i], newNicks[i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
character.Nicks = newNicks
|
||||
|
||||
return &character, nil
|
||||
}
|
||||
|
||||
func (r *characterRepository) Delete(ctx context.Context, character models.Character) error {
|
||||
return r.characters.RemoveId(character.ID)
|
||||
}
|
||||
+52
-1
@@ -2,6 +2,7 @@ package mongodb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/globalsign/mgo/bson"
|
||||
"time"
|
||||
|
||||
"git.aiterp.net/rpdata/api/internal/config"
|
||||
@@ -31,8 +32,15 @@ func Init(cfg config.Database) (bundle *repositories.Bundle, closeFn func() erro
|
||||
|
||||
db := session.DB(cfg.Db)
|
||||
|
||||
characters, err := newCharacterRepository(db)
|
||||
if err != nil {
|
||||
session.Close()
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
bundle = &repositories.Bundle{
|
||||
Tags: newTagRepository(db),
|
||||
Characters: characters,
|
||||
Tags: newTagRepository(db),
|
||||
}
|
||||
|
||||
closeFn = func() error {
|
||||
@@ -42,3 +50,46 @@ func Init(cfg config.Database) (bundle *repositories.Bundle, closeFn func() erro
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type counter struct {
|
||||
coll *mgo.Collection
|
||||
category string
|
||||
name string
|
||||
}
|
||||
|
||||
func newCounter(db *mgo.Database, category, name string) *counter {
|
||||
return &counter{
|
||||
coll: db.C("core.counters"),
|
||||
category: category,
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *counter) WithName(name string) *counter {
|
||||
return &counter{
|
||||
coll: c.coll,
|
||||
category: c.category,
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *counter) Increment(amount int) (int, error) {
|
||||
type counterDoc struct {
|
||||
ID string `bson:"_id"`
|
||||
Value int `bson:"value"`
|
||||
}
|
||||
|
||||
id := c.category + "." + c.name
|
||||
doc := counterDoc{}
|
||||
|
||||
_, err := c.coll.Find(bson.M{"_id": id}).Apply(mgo.Change{
|
||||
Update: bson.M{"$inc": bson.M{"value": amount}},
|
||||
Upsert: true,
|
||||
ReturnNew: true,
|
||||
}, &doc)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
return doc.Value, nil
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ func newTagRepository(db *mgo.Database) repositories.TagRepository {
|
||||
}
|
||||
}
|
||||
|
||||
func (r *tagRepository) Find(ctx context.Context, kind, name string) (*models.Tag, error) {
|
||||
func (r *tagRepository) Find(ctx context.Context, kind models.TagKind, name string) (*models.Tag, error) {
|
||||
tags := make([]*models.Tag, 0, 1)
|
||||
err := r.stories.Find(bson.M{"listed": true, "tags": bson.M{"kind": kind, "name": name}}).Distinct("tag", &tags)
|
||||
if err != nil {
|
||||
@@ -30,7 +30,13 @@ func (r *tagRepository) Find(ctx context.Context, kind, name string) (*models.Ta
|
||||
return nil, repositories.ErrNotFound
|
||||
}
|
||||
|
||||
return tags[0], nil
|
||||
for _, tag := range tags {
|
||||
if tag.Kind == kind && tag.Name == name {
|
||||
return tag, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, repositories.ErrNotFound
|
||||
}
|
||||
|
||||
func (r *tagRepository) List(ctx context.Context, filter models.TagFilter) ([]*models.Tag, error) {
|
||||
|
||||
@@ -4,41 +4,35 @@ go 1.12
|
||||
|
||||
require (
|
||||
github.com/99designs/gqlgen v0.9.0
|
||||
github.com/agnivade/levenshtein v1.0.1
|
||||
github.com/beorn7/perks v1.0.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4
|
||||
github.com/globalsign/mgo v0.0.0-20180403085842-f76e4f9da92e
|
||||
github.com/go-ini/ini v1.35.0
|
||||
github.com/go-ini/ini v1.35.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.4.0
|
||||
github.com/golang/protobuf v1.3.1 // indirect
|
||||
github.com/google/go-cmp v0.3.0 // indirect
|
||||
github.com/gorilla/websocket v1.4.0
|
||||
github.com/gorilla/websocket v1.4.0 // indirect
|
||||
github.com/graph-gophers/dataloader v0.0.0-20180104184831-78139374585c
|
||||
github.com/hashicorp/golang-lru v0.5.0
|
||||
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0
|
||||
github.com/lib/pq v1.1.1 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.10.0 // indirect
|
||||
github.com/minio/minio-go v0.0.0-20180409193742-3d2d02921f05
|
||||
github.com/mitchellh/go-homedir v0.0.0-20161203194507-b8bc1bf76747
|
||||
github.com/opentracing/opentracing-go v1.0.2
|
||||
github.com/pkg/errors v0.8.1
|
||||
github.com/pmezard/go-difflib v1.0.0
|
||||
github.com/mitchellh/go-homedir v0.0.0-20161203194507-b8bc1bf76747 // indirect
|
||||
github.com/prometheus/client_golang v0.9.1
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 // indirect
|
||||
github.com/prometheus/common v0.4.0 // indirect
|
||||
github.com/prometheus/procfs v0.0.0-20190517135640-51af30a78b0e // indirect
|
||||
github.com/sirupsen/logrus v1.2.0
|
||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a // indirect
|
||||
github.com/stretchr/testify v1.3.0
|
||||
github.com/tidwall/pretty v1.0.0 // indirect
|
||||
github.com/urfave/cli v1.20.0
|
||||
github.com/vektah/dataloaden v0.3.0
|
||||
github.com/vektah/gqlparser v1.1.2
|
||||
go.mongodb.org/mongo-driver v1.0.3
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2
|
||||
golang.org/x/net v0.0.0-20190514140710-3ec191127204
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a
|
||||
golang.org/x/text v0.3.0
|
||||
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd
|
||||
google.golang.org/appengine v1.1.0
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 // indirect
|
||||
golang.org/x/net v0.0.0-20190514140710-3ec191127204 // indirect
|
||||
golang.org/x/text v0.3.0 // indirect
|
||||
google.golang.org/appengine v1.1.0 // indirect
|
||||
gopkg.in/ini.v1 v1.42.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.2
|
||||
)
|
||||
|
||||
|
||||
@@ -1,14 +1,5 @@
|
||||
github.com/99designs/gqlgen v0.5.1 h1:cRsbpZgX83PrXb0/hj5EkNdmaVN4l/Eii81Z8LCexgY=
|
||||
github.com/99designs/gqlgen v0.5.1/go.mod h1:KSQDfLlTTGmzlRgLGm6HeKKKo598l5E2svEM6Nz2Jnw=
|
||||
github.com/99designs/gqlgen v0.8.0 h1:ZBteuSgeeFwn+mztjDqQZQdVa9pqslmPnDeCovcnc0Y=
|
||||
github.com/99designs/gqlgen v0.8.0/go.mod h1:st7qHA6ssU3uRZkmv+wzrzgX4srvIqEIdE5iuRW8GhE=
|
||||
github.com/99designs/gqlgen v0.8.3 h1:I6bMglXNKkn4KlvkSMzqZw53e1N2FF9Gud4NmsOxqiA=
|
||||
github.com/99designs/gqlgen v0.8.3/go.mod h1:aLyJw9xUgdJxZ8EqNQxo2pGFhXXJ/hq8t7J4yn8TgI4=
|
||||
github.com/99designs/gqlgen v0.9.0 h1:g1arBPML74Vqv0L3Q+TqIhGXLspV+2MYtRLkBxuZrlE=
|
||||
github.com/99designs/gqlgen v0.9.0/go.mod h1:HrrG7ic9EgLPsULxsZh/Ti+p0HNWgR3XRuvnD0pb5KY=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/agnivade/levenshtein v1.0.0 h1:q+77q31bLT5jhN3BHKA1276nUEdbz7XjDa0o5dRKcZ0=
|
||||
github.com/agnivade/levenshtein v1.0.0/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
|
||||
github.com/agnivade/levenshtein v1.0.1 h1:3oJU7J3FGFmyhn8KHjmVaZCN5hxTr7GxgRue+sxIXdQ=
|
||||
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
@@ -18,14 +9,11 @@ github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/globalsign/mgo v0.0.0-20180403085842-f76e4f9da92e h1:hmrbHva/wKD6X4M7pgHVbg/KfVV1wwgr1NEkQaVD3rU=
|
||||
github.com/globalsign/mgo v0.0.0-20180403085842-f76e4f9da92e/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
||||
github.com/go-chi/chi v3.3.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||
@@ -33,18 +21,20 @@ github.com/go-ini/ini v1.35.0 h1:D/my3+xOfqZMkJpciRcyqU7XMBUgiZa9qXjZIa8uv2k=
|
||||
github.com/go-ini/ini v1.35.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/mux v1.6.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
@@ -56,6 +46,8 @@ github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCO
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0 h1:5B0uxl2lzNRVkJVg+uGHxWtRt4C0Wjc6kJKo5XYx8xE=
|
||||
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0/go.mod h1:IiEW3SEiiErVyFdH8NTuWjSifiEQKUoyK3LNqr2kCHU=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
@@ -64,6 +56,10 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
|
||||
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=
|
||||
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/minio/minio-go v0.0.0-20180409193742-3d2d02921f05 h1:YEyFCqmHcmbcTLqZ7yEAg7VIUat6PuDzGbIctZy888k=
|
||||
@@ -72,7 +68,6 @@ github.com/mitchellh/go-homedir v0.0.0-20161203194507-b8bc1bf76747 h1:eQox4Rh4ew
|
||||
github.com/mitchellh/go-homedir v0.0.0-20161203194507-b8bc1bf76747/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20180203102830-a4e142e9c047/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
||||
github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg=
|
||||
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
@@ -84,28 +79,24 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v0.9.1 h1:K47Rk0v/fkEfwfQet2KWhscE0cJzjgCCDBG2KHZoVno=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM=
|
||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.0-20190517135640-51af30a78b0e h1:zK8d1aZ+gw/Ne4uMfZTFRxj08PUOp+gGwm4HWUeGI1k=
|
||||
github.com/prometheus/procfs v0.0.0-20190517135640-51af30a78b0e/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||
github.com/shurcooL/vfsgen v0.0.0-20180121065927-ffb13db8def0/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
|
||||
github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2YqsZKovtsgrwcDH1RZhVbTKCjLp47XpqCDs=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
@@ -116,52 +107,42 @@ github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/vektah/dataloaden v0.2.0/go.mod h1:vxM6NuRlgiR0M6wbVTJeKp9vQIs81ZMfCYO+4yq/jbE=
|
||||
github.com/vektah/dataloaden v0.2.1-0.20190515034641-a19b9a6e7c9e/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=
|
||||
github.com/vektah/gqlparser v0.0.0-20180831041411-14e83ae06ec1 h1:FYOXUtr3sYR9shto7Q/aQ1B0Onyk77aws9wGOORiz+I=
|
||||
github.com/vektah/gqlparser v0.0.0-20180831041411-14e83ae06ec1/go.mod h1:K4QdSSpS2XiHHwzb18kWh3iBljB8rLC8okGXsnQy3Nc=
|
||||
github.com/vektah/gqlparser v1.1.0 h1:3668p2gUlO+PiS81x957Rpr3/FPRWG6cxgCXAvTS1hw=
|
||||
github.com/vektah/gqlparser v1.1.0/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
||||
github.com/vektah/dataloaden v0.3.0 h1:ZfVN2QD6swgvp+tDqdH/OIT/wu3Dhu0cus0k5gIZS84=
|
||||
github.com/vektah/dataloaden v0.3.0/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U=
|
||||
github.com/vektah/gqlparser v1.1.2 h1:ZsyLGn7/7jDNI+y4SEhI4yAxRChlv15pUHMjijT+e68=
|
||||
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
||||
go.mongodb.org/mongo-driver v1.0.3 h1:GKoji1ld3tw2aC+GX1wbr/J2fX13yNacEYoJ8Nhr0yU=
|
||||
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||
golang.org/x/crypto v0.0.0-20180411161317-d6449816ce06 h1:EOqG0JqGlLr+punVB69jvWCv/ErZKGlC7PMdyHfv+Bc=
|
||||
golang.org/x/crypto v0.0.0-20180411161317-d6449816ce06/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 h1:u+LnwYTOOW7Ukr/fppxEb1Nwz0AtPflrblfvUudpo+I=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20180404174746-b3c676e531a6/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180416171110-a35a21de978d h1:O2P57H5Cc+d+DJos+iweraI9rmzMYwV+45vkZdDY0Oo=
|
||||
golang.org/x/net v0.0.0-20180416171110-a35a21de978d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a h1:gOpx8G595UYyvj8UK4+OFyY4rx037g3fmfhe5SasG3U=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190514140710-3ec191127204 h1:4yG6GqBtw9C+UrLp6s2wtSniayy/Vd/3F7ffLE427XI=
|
||||
golang.org/x/net v0.0.0-20190514140710-3ec191127204/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180416112224-2f57af4873d0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5 h1:mzjBh+S5frKOsOBobWIMAbXavqjmgO17k/2puhcFR94=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20180911133044-677d2ff680c1 h1:dzEuQYa6+a3gROnSlgly5ERUm4SZKJt+dh+4iSbO+bI=
|
||||
golang.org/x/tools v0.0.0-20180911133044-677d2ff680c1/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6 h1:iZgcI2DDp6zW5v9Z/5+f0NuqoxNdmzg4hivjk2WLXpY=
|
||||
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd h1:oMEQDWVXVNpceQoVd1JN3CQ7LYJJzs5qWqZIUcxXHHw=
|
||||
golang.org/x/tools v0.0.0-20190515012406-7d7faa4812bd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/ini.v1 v1.42.0 h1:7N3gPTt50s8GuLortA00n8AqRTk75qOP98+mTPpgzRk=
|
||||
gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
|
||||
@@ -2,9 +2,9 @@ package graph2
|
||||
|
||||
import (
|
||||
"git.aiterp.net/rpdata/api/graph2/graphcore"
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"git.aiterp.net/rpdata/api/models/changes"
|
||||
"git.aiterp.net/rpdata/api/models/channels"
|
||||
"git.aiterp.net/rpdata/api/models/characters"
|
||||
"git.aiterp.net/rpdata/api/models/files"
|
||||
"git.aiterp.net/rpdata/api/models/logs"
|
||||
"git.aiterp.net/rpdata/api/models/posts"
|
||||
@@ -22,7 +22,7 @@ func complexity() (cr graphcore.ComplexityRoot) {
|
||||
cr.Query.Character = func(childComplexity int, id *string, nick *string) int {
|
||||
return childComplexity + findComplexity
|
||||
}
|
||||
cr.Query.Characters = func(childComplexity int, filter *characters.Filter) int {
|
||||
cr.Query.Characters = func(childComplexity int, filter *models.CharacterFilter) int {
|
||||
return childComplexity + listComplexity
|
||||
}
|
||||
cr.Query.Channel = func(childComplexity int, name string) int {
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ models:
|
||||
Character:
|
||||
model: git.aiterp.net/rpdata/api/models.Character
|
||||
CharactersFilter:
|
||||
model: git.aiterp.net/rpdata/api/models/characters.Filter
|
||||
model: git.aiterp.net/rpdata/api/models.CharacterFilter
|
||||
Channel:
|
||||
model: git.aiterp.net/rpdata/api/models.Channel
|
||||
ChannelsFilter:
|
||||
|
||||
+3
-3
@@ -27,15 +27,15 @@ func (r *rootResolver) Query() graphcore.QueryResolver {
|
||||
}
|
||||
|
||||
func (r *rootResolver) Mutation() graphcore.MutationResolver {
|
||||
return resolvers.MutationResolver
|
||||
return resolvers.MutationResolver(r.s)
|
||||
}
|
||||
|
||||
func (r *rootResolver) Subscription() graphcore.SubscriptionResolver {
|
||||
return resolvers.SubscriptionResolver
|
||||
return resolvers.SubscriptionResolver(r.s)
|
||||
}
|
||||
|
||||
func (r *rootResolver) Log() graphcore.LogResolver {
|
||||
return &types.LogResolver
|
||||
return types.LogResolver(r.s)
|
||||
}
|
||||
|
||||
func (r *rootResolver) Comment() graphcore.CommentResolver {
|
||||
|
||||
+14
-143
@@ -3,69 +3,41 @@ package resolvers
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"git.aiterp.net/rpdata/api/graph2/graphcore"
|
||||
"git.aiterp.net/rpdata/api/internal/auth"
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"git.aiterp.net/rpdata/api/models/changekeys"
|
||||
"git.aiterp.net/rpdata/api/models/changes"
|
||||
"git.aiterp.net/rpdata/api/models/characters"
|
||||
"git.aiterp.net/rpdata/api/models/logs"
|
||||
)
|
||||
|
||||
// Queries
|
||||
|
||||
func (r *queryResolver) Character(ctx context.Context, id *string, nick *string) (*models.Character, error) {
|
||||
if id != nil {
|
||||
character, err := characters.FindID(*id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &character, nil
|
||||
return r.s.Characters.Find(ctx, *id)
|
||||
} else if nick != nil {
|
||||
character, err := characters.FindNick(*nick)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &character, nil
|
||||
return r.s.Characters.FindNick(ctx, *nick)
|
||||
} else {
|
||||
return nil, errors.New("You must specify either an ID or a nick")
|
||||
}
|
||||
}
|
||||
|
||||
func (r *queryResolver) Characters(ctx context.Context, filter *characters.Filter) ([]*models.Character, error) {
|
||||
characters, err := characters.List(filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func (r *queryResolver) Characters(ctx context.Context, filter *models.CharacterFilter) ([]*models.Character, error) {
|
||||
if filter == nil {
|
||||
filter = &models.CharacterFilter{}
|
||||
}
|
||||
|
||||
characters2 := make([]*models.Character, len(characters))
|
||||
for i := range characters {
|
||||
characters2[i] = &characters[i]
|
||||
}
|
||||
|
||||
return characters2, nil
|
||||
return r.s.Characters.List(ctx, *filter)
|
||||
}
|
||||
|
||||
// Mutations
|
||||
|
||||
func (r *mutationResolver) AddCharacter(ctx context.Context, input graphcore.CharacterAddInput) (*models.Character, error) {
|
||||
token := auth.TokenFromContext(ctx)
|
||||
if !token.Permitted("member", "character.add") {
|
||||
return nil, errors.New("You are not permitted to add characters")
|
||||
}
|
||||
if len(input.Name) < 2 || len(input.Nick) < 2 {
|
||||
return nil, errors.New("You need to provide a name and a nick (min length: 2)")
|
||||
author := ""
|
||||
if input.Author != nil {
|
||||
author = *input.Author
|
||||
}
|
||||
|
||||
shortName := ""
|
||||
if input.ShortName != nil {
|
||||
shortName = *input.ShortName
|
||||
} else {
|
||||
shortName = strings.SplitN(input.Name, " ", 2)[0]
|
||||
}
|
||||
|
||||
description := ""
|
||||
@@ -73,122 +45,21 @@ func (r *mutationResolver) AddCharacter(ctx context.Context, input graphcore.Cha
|
||||
description = *input.Description
|
||||
}
|
||||
|
||||
author := token.UserID
|
||||
if input.Author != nil && *input.Author != author {
|
||||
if !token.Permitted("character.add") {
|
||||
return nil, errors.New("You are only permitted to add your own characters")
|
||||
}
|
||||
|
||||
author = *input.Author
|
||||
}
|
||||
|
||||
logs.ScheduleFullUpdate()
|
||||
|
||||
character, err := characters.Add(input.Nick, input.Name, shortName, author, description)
|
||||
if err != nil {
|
||||
return nil, errors.New("Adding character failed: " + err.Error())
|
||||
}
|
||||
|
||||
go changes.Submit("Character", "add", token.UserID, true, changekeys.Listed(character), character)
|
||||
|
||||
return &character, nil
|
||||
return r.s.Characters.Create(ctx, input.Nick, input.Name, shortName, author, description)
|
||||
}
|
||||
|
||||
func (r *mutationResolver) AddCharacterNick(ctx context.Context, input graphcore.CharacterNickInput) (*models.Character, error) {
|
||||
character, err := characters.FindID(input.ID)
|
||||
if err != nil {
|
||||
return nil, errors.New("Character not found")
|
||||
}
|
||||
|
||||
if len(input.Nick) < 2 {
|
||||
return nil, errors.New("You need to provide a valid nick (min length: 2)")
|
||||
}
|
||||
|
||||
token := auth.TokenFromContext(ctx)
|
||||
if !token.PermittedUser(character.Author, "member", "character.edit") {
|
||||
return nil, errors.New("You are not permitted to edit this character")
|
||||
}
|
||||
|
||||
logs.ScheduleFullUpdate()
|
||||
|
||||
character, err = characters.AddNick(character, input.Nick)
|
||||
if err != nil {
|
||||
return nil, errors.New("Failed to add nick: " + err.Error())
|
||||
}
|
||||
|
||||
go logs.ScheduleFullUpdate()
|
||||
go changes.Submit("Character", "edit", token.UserID, true, changekeys.Listed(character), character)
|
||||
|
||||
return &character, nil
|
||||
return r.s.Characters.AddNick(ctx, input.ID, input.Nick)
|
||||
}
|
||||
|
||||
func (r *mutationResolver) RemoveCharacterNick(ctx context.Context, input graphcore.CharacterNickInput) (*models.Character, error) {
|
||||
character, err := characters.FindID(input.ID)
|
||||
if err != nil {
|
||||
return nil, errors.New("Character not found")
|
||||
}
|
||||
|
||||
token := auth.TokenFromContext(ctx)
|
||||
if !token.PermittedUser(character.Author, "member", "character.edit") {
|
||||
return nil, errors.New("You are not permitted to edit this character")
|
||||
}
|
||||
|
||||
character, err = characters.RemoveNick(character, input.Nick)
|
||||
if err != nil {
|
||||
return nil, errors.New("Failed to remove nick: " + err.Error())
|
||||
}
|
||||
|
||||
go logs.ScheduleFullUpdate()
|
||||
go changes.Submit("Character", "edit", token.UserID, true, changekeys.Listed(character), character)
|
||||
|
||||
return &character, nil
|
||||
return r.s.Characters.RemoveNick(ctx, input.ID, input.Nick)
|
||||
}
|
||||
|
||||
func (r *mutationResolver) EditCharacter(ctx context.Context, input graphcore.CharacterEditInput) (*models.Character, error) {
|
||||
character, err := characters.FindID(input.ID)
|
||||
if err != nil {
|
||||
return nil, errors.New("Character not found")
|
||||
}
|
||||
|
||||
if input.Name != nil && len(*input.Name) < 2 {
|
||||
return nil, errors.New("You need to provide a valid name (min length: 2)")
|
||||
}
|
||||
if input.ShortName != nil && len(*input.ShortName) < 2 {
|
||||
return nil, errors.New("You need to provide a valid short name (min length: 2)")
|
||||
}
|
||||
|
||||
token := auth.TokenFromContext(ctx)
|
||||
if !token.PermittedUser(character.Author, "member", "character.edit") {
|
||||
return nil, errors.New("You are not permitted to edit this character")
|
||||
}
|
||||
|
||||
character, err = characters.Edit(character, input.Name, input.ShortName, input.Description)
|
||||
if err != nil {
|
||||
return nil, errors.New("Failed to edit character: " + err.Error())
|
||||
}
|
||||
|
||||
go changes.Submit("Character", "edit", token.UserID, true, changekeys.Listed(character), character)
|
||||
|
||||
return &character, nil
|
||||
return r.s.Characters.Update(ctx, input.ID, input.Name, input.ShortName, input.Description)
|
||||
}
|
||||
|
||||
func (r *mutationResolver) RemoveCharacter(ctx context.Context, input graphcore.CharacterRemoveInput) (*models.Character, error) {
|
||||
character, err := characters.FindID(input.ID)
|
||||
if err != nil {
|
||||
return nil, errors.New("Character not found")
|
||||
}
|
||||
|
||||
token := auth.TokenFromContext(ctx)
|
||||
if !token.PermittedUser(character.Author, "member", "character.remove") {
|
||||
return nil, errors.New("You are not permitted to remove this character")
|
||||
}
|
||||
|
||||
character, err = characters.Remove(character)
|
||||
if err != nil {
|
||||
return nil, errors.New("Failed to remove character: " + err.Error())
|
||||
}
|
||||
|
||||
go changes.Submit("Character", "remove", token.UserID, true, changekeys.Listed(character), character)
|
||||
|
||||
return &character, nil
|
||||
return r.s.Characters.Delete(ctx, input.ID)
|
||||
}
|
||||
|
||||
@@ -6,16 +6,20 @@ import (
|
||||
)
|
||||
|
||||
type queryResolver struct{ s *services.Bundle }
|
||||
type mutationResolver struct{}
|
||||
type subscriptionResolver struct{}
|
||||
type mutationResolver struct{ s *services.Bundle }
|
||||
type subscriptionResolver struct{ s *services.Bundle }
|
||||
|
||||
// QueryResolver has all the queries
|
||||
func QueryResolver(s *services.Bundle) graphcore.QueryResolver {
|
||||
return &queryResolver{s: s}
|
||||
}
|
||||
|
||||
// MutationResolver brings the mutagens.
|
||||
var MutationResolver *mutationResolver
|
||||
// MutationResolver brings the radioactive goop
|
||||
func MutationResolver(s *services.Bundle) graphcore.MutationResolver {
|
||||
return &mutationResolver{s: s}
|
||||
}
|
||||
|
||||
// SubscriptionResolver has the real-time magic.
|
||||
var SubscriptionResolver *subscriptionResolver
|
||||
func SubscriptionResolver(s *services.Bundle) graphcore.SubscriptionResolver {
|
||||
return &subscriptionResolver{s: s}
|
||||
}
|
||||
|
||||
+12
-16
@@ -3,13 +3,16 @@ package types
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"git.aiterp.net/rpdata/api/services"
|
||||
|
||||
"git.aiterp.net/rpdata/api/internal/loader"
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"git.aiterp.net/rpdata/api/models/posts"
|
||||
)
|
||||
|
||||
type logResolver struct{}
|
||||
type logResolver struct {
|
||||
characters *services.CharacterService
|
||||
}
|
||||
|
||||
func (r *logResolver) Channel(ctx context.Context, log *models.Log) (*models.Channel, error) {
|
||||
loader := loader.FromContext(ctx)
|
||||
@@ -21,22 +24,13 @@ func (r *logResolver) Channel(ctx context.Context, log *models.Log) (*models.Cha
|
||||
}
|
||||
|
||||
func (r *logResolver) Characters(ctx context.Context, log *models.Log) ([]*models.Character, error) {
|
||||
loader := loader.FromContext(ctx)
|
||||
if loader == nil {
|
||||
return nil, errors.New("no loader")
|
||||
if len(log.CharacterIDs) == 0 {
|
||||
return []*models.Character{}, nil
|
||||
}
|
||||
|
||||
characters, err := loader.Characters("id", log.CharacterIDs...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
characters2 := make([]*models.Character, len(characters))
|
||||
for i := range characters {
|
||||
characters2[i] = &characters[i]
|
||||
}
|
||||
|
||||
return characters2, nil
|
||||
return r.characters.List(ctx, models.CharacterFilter{
|
||||
IDs: log.CharacterIDs,
|
||||
})
|
||||
}
|
||||
|
||||
func (r *logResolver) Posts(ctx context.Context, log *models.Log, kinds []string) ([]*models.Post, error) {
|
||||
@@ -54,4 +48,6 @@ func (r *logResolver) Posts(ctx context.Context, log *models.Log, kinds []string
|
||||
}
|
||||
|
||||
// LogResolver is a resolver
|
||||
var LogResolver logResolver
|
||||
func LogResolver(s *services.Bundle) *logResolver {
|
||||
return &logResolver{characters: s.Characters}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"reflect"
|
||||
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
@@ -43,6 +44,8 @@ func CheckPermission(ctx context.Context, op string, obj interface{}) error {
|
||||
authorized = token.PermittedUser(v.Author, "member", "story."+op)
|
||||
case *models.User:
|
||||
authorized = token.Permitted("user." + op)
|
||||
default:
|
||||
log.Panicf("Invalid model %T: %#+v", v, v)
|
||||
}
|
||||
|
||||
if !authorized {
|
||||
|
||||
@@ -26,6 +26,10 @@ func One(object interface{}) models.ChangeKey {
|
||||
|
||||
id := ""
|
||||
v := reflect.ValueOf(object)
|
||||
for v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
if f := v.FieldByName("ID"); f.Kind() == reflect.String {
|
||||
id = f.String()
|
||||
} else if f = v.FieldByName("Name"); f.Kind() == reflect.String {
|
||||
|
||||
@@ -55,34 +55,50 @@ func Submit(model, op, author string, listed bool, keys []models.ChangeKey, obje
|
||||
switch object := object.(type) {
|
||||
case models.Log:
|
||||
change.Logs = append(change.Logs, object)
|
||||
case *models.Log:
|
||||
change.Logs = append(change.Logs, *object)
|
||||
case []models.Log:
|
||||
change.Logs = append(change.Logs, object...)
|
||||
case models.Character:
|
||||
change.Characters = append(change.Characters, object)
|
||||
case *models.Character:
|
||||
change.Characters = append(change.Characters, *object)
|
||||
case []models.Character:
|
||||
change.Characters = append(change.Characters, object...)
|
||||
case models.Channel:
|
||||
change.Channels = append(change.Channels, object)
|
||||
case *models.Channel:
|
||||
change.Channels = append(change.Channels, *object)
|
||||
case []models.Channel:
|
||||
change.Channels = append(change.Channels, object...)
|
||||
case models.Post:
|
||||
change.Posts = append(change.Posts, object)
|
||||
case *models.Post:
|
||||
change.Posts = append(change.Posts, *object)
|
||||
case []models.Post:
|
||||
change.Posts = append(change.Posts, object...)
|
||||
case models.Story:
|
||||
change.Stories = append(change.Stories, object)
|
||||
case *models.Story:
|
||||
change.Stories = append(change.Stories, *object)
|
||||
case []models.Story:
|
||||
change.Stories = append(change.Stories, object...)
|
||||
case models.Tag:
|
||||
change.Tags = append(change.Tags, object)
|
||||
case *models.Tag:
|
||||
change.Tags = append(change.Tags, *object)
|
||||
case []models.Tag:
|
||||
change.Tags = append(change.Tags, object...)
|
||||
case models.Chapter:
|
||||
change.Chapters = append(change.Chapters, object)
|
||||
case *models.Chapter:
|
||||
change.Chapters = append(change.Chapters, *object)
|
||||
case []models.Chapter:
|
||||
change.Chapters = append(change.Chapters, object...)
|
||||
case models.Comment:
|
||||
change.Comments = append(change.Comments, object)
|
||||
case *models.Comment:
|
||||
change.Comments = append(change.Comments, *object)
|
||||
case []models.Comment:
|
||||
change.Comments = append(change.Comments, object...)
|
||||
default:
|
||||
|
||||
+18
-1
@@ -34,4 +34,21 @@ func (character *Character) HasNick(nick string) bool {
|
||||
// ChangeObject in GQL.
|
||||
func (*Character) IsChangeObject() {
|
||||
panic("this method is a dummy, and so is its caller")
|
||||
}
|
||||
}
|
||||
|
||||
// CharacterFilter is a filter for character listing.
|
||||
type CharacterFilter struct {
|
||||
IDs []string
|
||||
Nicks []string
|
||||
Names []string
|
||||
Author *string
|
||||
Search *string
|
||||
Limit int
|
||||
}
|
||||
|
||||
// CharacterUpdate is an update for characters.
|
||||
type CharacterUpdate struct {
|
||||
Name *string
|
||||
ShortName *string
|
||||
Description *string
|
||||
}
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ func (e TagKind) MarshalGQL(w io.Writer) {
|
||||
fmt.Fprint(w, "\""+string(e), "\"")
|
||||
}
|
||||
|
||||
// TagFilter is a filter of tags.
|
||||
// TagFilter is a filter for tag listing.
|
||||
type TagFilter struct {
|
||||
Kind *TagKind `bson:"kind,omitempty"`
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package tags
|
||||
|
||||
import (
|
||||
"git.aiterp.net/rpdata/api/internal/store"
|
||||
"github.com/globalsign/mgo"
|
||||
)
|
||||
|
||||
var storyCollection *mgo.Collection
|
||||
|
||||
func init() {
|
||||
store.HandleInit(func(db *mgo.Database) {
|
||||
storyCollection = db.C("story.stories")
|
||||
})
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package tags
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"github.com/globalsign/mgo/bson"
|
||||
)
|
||||
|
||||
// List lists all tags
|
||||
func List() ([]models.Tag, error) {
|
||||
tags := make([]models.Tag, 0, 64)
|
||||
err := storyCollection.Find(bson.M{"listed": true, "tags": bson.M{"$ne": nil}}).Distinct("tags", &tags)
|
||||
|
||||
sort.Slice(tags, func(i, j int) bool {
|
||||
kindCmp := strings.Compare(string(tags[i].Kind), string(tags[j].Kind))
|
||||
if kindCmp != 0 {
|
||||
return kindCmp < 0
|
||||
}
|
||||
|
||||
return strings.Compare(tags[i].Name, tags[j].Name) < 0
|
||||
})
|
||||
|
||||
return tags, err
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
)
|
||||
|
||||
// CharacterRepository is an interface for a database using logs.
|
||||
type CharacterRepository interface {
|
||||
Find(ctx context.Context, id string) (*models.Character, error)
|
||||
FindNick(ctx context.Context, nick string) (*models.Character, error)
|
||||
List(ctx context.Context, filter models.CharacterFilter) ([]*models.Character, error)
|
||||
Insert(ctx context.Context, character models.Character) (*models.Character, error)
|
||||
Update(ctx context.Context, character models.Character, update models.CharacterUpdate) (*models.Character, error)
|
||||
AddNick(ctx context.Context, character models.Character, nick string) (*models.Character, error)
|
||||
RemoveNick(ctx context.Context, character models.Character, nick string) (*models.Character, error)
|
||||
Delete(ctx context.Context, character models.Character) error
|
||||
}
|
||||
@@ -4,7 +4,8 @@ import "errors"
|
||||
|
||||
// A Bundle is a set of repositories.
|
||||
type Bundle struct {
|
||||
Tags TagRepository
|
||||
Characters CharacterRepository
|
||||
Tags TagRepository
|
||||
}
|
||||
|
||||
// ErrNotFound should be returned instead of any database-specific not found error.
|
||||
|
||||
+1
-1
@@ -8,6 +8,6 @@ import (
|
||||
|
||||
// TagRepository is an interface for a database using logs.
|
||||
type TagRepository interface {
|
||||
Find(ctx context.Context, kind, name string) (*models.Tag, error)
|
||||
Find(ctx context.Context, kind models.TagKind, name string) (*models.Tag, error)
|
||||
List(ctx context.Context, filter models.TagFilter) ([]*models.Tag, error)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"git.aiterp.net/rpdata/api/internal/auth"
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"git.aiterp.net/rpdata/api/models/changekeys"
|
||||
"git.aiterp.net/rpdata/api/models/changes"
|
||||
"git.aiterp.net/rpdata/api/repositories"
|
||||
"git.aiterp.net/rpdata/api/services/loaders"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type CharacterService struct {
|
||||
characters repositories.CharacterRepository
|
||||
loader *loaders.CharacterLoader
|
||||
}
|
||||
|
||||
// Find uses the loader to find the character by the ID.
|
||||
func (s *CharacterService) Find(ctx context.Context, id string) (*models.Character, error) {
|
||||
return s.loader.Load(id)
|
||||
}
|
||||
|
||||
// Find uses the loader to find the character by the ID.
|
||||
func (s *CharacterService) FindNick(ctx context.Context, nick string) (*models.Character, error) {
|
||||
return s.characters.FindNick(ctx, nick)
|
||||
}
|
||||
|
||||
// List lists the characters. If the only filter active is `IDs`, the loader is used to batch together requests.
|
||||
func (s *CharacterService) List(ctx context.Context, filter models.CharacterFilter) ([]*models.Character, error) {
|
||||
if len(filter.IDs) > 0 && len(filter.Names) == 0 && len(filter.Nicks) == 0 && filter.Author == nil && filter.Search == nil {
|
||||
characters, errs := s.loader.LoadAll(filter.IDs)
|
||||
if len(characters) == 0 && len(errs) > 0 {
|
||||
if errs[0] == repositories.ErrNotFound {
|
||||
return []*models.Character{}, nil
|
||||
} else {
|
||||
return nil, errs[0]
|
||||
}
|
||||
}
|
||||
|
||||
if err := ctx.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var badIndices []int
|
||||
for i, character := range characters {
|
||||
if character == nil {
|
||||
badIndices = append(badIndices, i-len(badIndices))
|
||||
}
|
||||
}
|
||||
for _, index := range badIndices {
|
||||
characters = append(characters[:index], characters[index+1:]...)
|
||||
}
|
||||
|
||||
sort.Slice(characters, func(i, j int) bool {
|
||||
return strings.Compare(characters[i].ID, characters[j].ID) < 0
|
||||
})
|
||||
|
||||
return characters, nil
|
||||
}
|
||||
|
||||
return s.characters.List(ctx, filter)
|
||||
}
|
||||
|
||||
func (s *CharacterService) Create(ctx context.Context, nick, name, shortName, author, description string) (*models.Character, error) {
|
||||
token := auth.TokenFromContext(ctx)
|
||||
if token == nil {
|
||||
return nil, auth.ErrUnauthenticated
|
||||
}
|
||||
|
||||
if name == "" {
|
||||
return nil, errors.New("Name cannot be empty")
|
||||
}
|
||||
|
||||
if author == "" {
|
||||
author = token.UserID
|
||||
}
|
||||
|
||||
if shortName == "" {
|
||||
split := strings.SplitN(name, " ", 2)
|
||||
shortName = split[0]
|
||||
}
|
||||
|
||||
character := &models.Character{
|
||||
Name: name,
|
||||
ShortName: shortName,
|
||||
Author: author,
|
||||
Nicks: []string{nick},
|
||||
Description: description,
|
||||
}
|
||||
|
||||
err := auth.CheckPermission(ctx, "add", character)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
character, err = s.characters.Insert(ctx, *character)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//TODO: New change submit system
|
||||
go changes.Submit("Character", "add", token.UserID, true, changekeys.Listed(character), character)
|
||||
|
||||
return character, nil
|
||||
}
|
||||
|
||||
func (s *CharacterService) Update(ctx context.Context, id string, name, shortName, description *string) (*models.Character, error) {
|
||||
character, err := s.characters.Find(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = auth.CheckPermission(ctx, "edit", character)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
character, err = s.characters.Update(ctx, *character, models.CharacterUpdate{
|
||||
Name: name,
|
||||
ShortName: shortName,
|
||||
Description: description,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.loader.Clear(character.ID)
|
||||
s.loader.Prime(character.ID, character)
|
||||
|
||||
//TODO: New change submit system
|
||||
token := auth.TokenFromContext(ctx)
|
||||
go changes.Submit("Character", "edit", token.UserID, true, changekeys.Listed(character), character)
|
||||
|
||||
return character, nil
|
||||
}
|
||||
|
||||
func (s *CharacterService) AddNick(ctx context.Context, id string, nick string) (*models.Character, error) {
|
||||
character, err := s.characters.Find(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = auth.CheckPermission(ctx, "edit", character)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
character, err = s.characters.AddNick(ctx, *character, nick)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//TODO: New change submit system
|
||||
token := auth.TokenFromContext(ctx)
|
||||
go changes.Submit("Character", "edit", token.UserID, true, changekeys.Listed(character), character)
|
||||
|
||||
return character, nil
|
||||
}
|
||||
|
||||
func (s *CharacterService) RemoveNick(ctx context.Context, id string, nick string) (*models.Character, error) {
|
||||
character, err := s.characters.Find(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = auth.CheckPermission(ctx, "edit", character)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
character, err = s.characters.RemoveNick(ctx, *character, nick)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//TODO: New change submit system
|
||||
token := auth.TokenFromContext(ctx)
|
||||
go changes.Submit("Character", "edit", token.UserID, true, changekeys.Listed(character), character)
|
||||
|
||||
return character, nil
|
||||
}
|
||||
|
||||
func (s *CharacterService) Delete(ctx context.Context, id string) (*models.Character, error) {
|
||||
character, err := s.characters.Find(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = auth.CheckPermission(ctx, "edit", character)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = s.characters.Delete(ctx, *character)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//TODO: New change submit system
|
||||
token := auth.TokenFromContext(ctx)
|
||||
go changes.Submit("Character", "remove", token.UserID, true, changekeys.Listed(character), character)
|
||||
|
||||
return character, nil
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
// Code generated by github.com/vektah/dataloaden, DO NOT EDIT.
|
||||
|
||||
package loaders
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
)
|
||||
|
||||
// CharacterLoaderConfig captures the config to create a new CharacterLoader
|
||||
type CharacterLoaderConfig struct {
|
||||
// Fetch is a method that provides the data for the loader
|
||||
Fetch func(keys []string) ([]*models.Character, []error)
|
||||
|
||||
// Wait is how long wait before sending a batch
|
||||
Wait time.Duration
|
||||
|
||||
// MaxBatch will limit the maximum number of keys to send in one batch, 0 = not limit
|
||||
MaxBatch int
|
||||
}
|
||||
|
||||
// NewCharacterLoader creates a new CharacterLoader given a fetch, wait, and maxBatch
|
||||
func NewCharacterLoader(config CharacterLoaderConfig) *CharacterLoader {
|
||||
return &CharacterLoader{
|
||||
fetch: config.Fetch,
|
||||
wait: config.Wait,
|
||||
maxBatch: config.MaxBatch,
|
||||
}
|
||||
}
|
||||
|
||||
// CharacterLoader batches and caches requests
|
||||
type CharacterLoader struct {
|
||||
// this method provides the data for the loader
|
||||
fetch func(keys []string) ([]*models.Character, []error)
|
||||
|
||||
// how long to done before sending a batch
|
||||
wait time.Duration
|
||||
|
||||
// this will limit the maximum number of keys to send in one batch, 0 = no limit
|
||||
maxBatch int
|
||||
|
||||
// INTERNAL
|
||||
|
||||
// lazily created cache
|
||||
cache map[string]*models.Character
|
||||
|
||||
// the current batch. keys will continue to be collected until timeout is hit,
|
||||
// then everything will be sent to the fetch method and out to the listeners
|
||||
batch *characterLoaderBatch
|
||||
|
||||
// mutex to prevent races
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
type characterLoaderBatch struct {
|
||||
keys []string
|
||||
data []*models.Character
|
||||
error []error
|
||||
closing bool
|
||||
done chan struct{}
|
||||
}
|
||||
|
||||
// Load a Character by key, batching and caching will be applied automatically
|
||||
func (l *CharacterLoader) Load(key string) (*models.Character, error) {
|
||||
return l.LoadThunk(key)()
|
||||
}
|
||||
|
||||
// LoadThunk returns a function that when called will block waiting for a Character.
|
||||
// This method should be used if you want one goroutine to make requests to many
|
||||
// different data loaders without blocking until the thunk is called.
|
||||
func (l *CharacterLoader) LoadThunk(key string) func() (*models.Character, error) {
|
||||
l.mu.Lock()
|
||||
if it, ok := l.cache[key]; ok {
|
||||
l.mu.Unlock()
|
||||
return func() (*models.Character, error) {
|
||||
return it, nil
|
||||
}
|
||||
}
|
||||
if l.batch == nil {
|
||||
l.batch = &characterLoaderBatch{done: make(chan struct{})}
|
||||
}
|
||||
batch := l.batch
|
||||
pos := batch.keyIndex(l, key)
|
||||
l.mu.Unlock()
|
||||
|
||||
return func() (*models.Character, error) {
|
||||
<-batch.done
|
||||
|
||||
var data *models.Character
|
||||
if pos < len(batch.data) {
|
||||
data = batch.data[pos]
|
||||
}
|
||||
|
||||
var err error
|
||||
// its convenient to be able to return a single error for everything
|
||||
if len(batch.error) == 1 {
|
||||
err = batch.error[0]
|
||||
} else if batch.error != nil {
|
||||
err = batch.error[pos]
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
l.mu.Lock()
|
||||
l.unsafeSet(key, data)
|
||||
l.mu.Unlock()
|
||||
}
|
||||
|
||||
return data, err
|
||||
}
|
||||
}
|
||||
|
||||
// LoadAll fetches many keys at once. It will be broken into appropriate sized
|
||||
// sub batches depending on how the loader is configured
|
||||
func (l *CharacterLoader) LoadAll(keys []string) ([]*models.Character, []error) {
|
||||
results := make([]func() (*models.Character, error), len(keys))
|
||||
|
||||
for i, key := range keys {
|
||||
results[i] = l.LoadThunk(key)
|
||||
}
|
||||
|
||||
characters := make([]*models.Character, len(keys))
|
||||
errors := make([]error, len(keys))
|
||||
for i, thunk := range results {
|
||||
characters[i], errors[i] = thunk()
|
||||
}
|
||||
return characters, errors
|
||||
}
|
||||
|
||||
// LoadAllThunk returns a function that when called will block waiting for a Characters.
|
||||
// This method should be used if you want one goroutine to make requests to many
|
||||
// different data loaders without blocking until the thunk is called.
|
||||
func (l *CharacterLoader) LoadAllThunk(keys []string) func() ([]*models.Character, []error) {
|
||||
results := make([]func() (*models.Character, error), len(keys))
|
||||
for i, key := range keys {
|
||||
results[i] = l.LoadThunk(key)
|
||||
}
|
||||
return func() ([]*models.Character, []error) {
|
||||
characters := make([]*models.Character, len(keys))
|
||||
errors := make([]error, len(keys))
|
||||
for i, thunk := range results {
|
||||
characters[i], errors[i] = thunk()
|
||||
}
|
||||
return characters, errors
|
||||
}
|
||||
}
|
||||
|
||||
// Prime the cache with the provided key and value. If the key already exists, no change is made
|
||||
// and false is returned.
|
||||
// (To forcefully prime the cache, clear the key first with loader.clear(key).prime(key, value).)
|
||||
func (l *CharacterLoader) Prime(key string, value *models.Character) bool {
|
||||
l.mu.Lock()
|
||||
var found bool
|
||||
if _, found = l.cache[key]; !found {
|
||||
// make a copy when writing to the cache, its easy to pass a pointer in from a loop var
|
||||
// and end up with the whole cache pointing to the same value.
|
||||
cpy := *value
|
||||
l.unsafeSet(key, &cpy)
|
||||
}
|
||||
l.mu.Unlock()
|
||||
return !found
|
||||
}
|
||||
|
||||
// Clear the value at key from the cache, if it exists
|
||||
func (l *CharacterLoader) Clear(key string) {
|
||||
l.mu.Lock()
|
||||
delete(l.cache, key)
|
||||
l.mu.Unlock()
|
||||
}
|
||||
|
||||
func (l *CharacterLoader) unsafeSet(key string, value *models.Character) {
|
||||
if l.cache == nil {
|
||||
l.cache = map[string]*models.Character{}
|
||||
}
|
||||
l.cache[key] = value
|
||||
}
|
||||
|
||||
// keyIndex will return the location of the key in the batch, if its not found
|
||||
// it will add the key to the batch
|
||||
func (b *characterLoaderBatch) keyIndex(l *CharacterLoader, key string) int {
|
||||
for i, existingKey := range b.keys {
|
||||
if key == existingKey {
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
pos := len(b.keys)
|
||||
b.keys = append(b.keys, key)
|
||||
if pos == 0 {
|
||||
go b.startTimer(l)
|
||||
}
|
||||
|
||||
if l.maxBatch != 0 && pos >= l.maxBatch-1 {
|
||||
if !b.closing {
|
||||
b.closing = true
|
||||
l.batch = nil
|
||||
go b.end(l)
|
||||
}
|
||||
}
|
||||
|
||||
return pos
|
||||
}
|
||||
|
||||
func (b *characterLoaderBatch) startTimer(l *CharacterLoader) {
|
||||
time.Sleep(l.wait)
|
||||
l.mu.Lock()
|
||||
|
||||
// we must have hit a batch limit and are already finalizing this batch
|
||||
if b.closing {
|
||||
l.mu.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
l.batch = nil
|
||||
l.mu.Unlock()
|
||||
|
||||
b.end(l)
|
||||
}
|
||||
|
||||
func (b *characterLoaderBatch) end(l *CharacterLoader) {
|
||||
b.data, b.error = l.fetch(b.keys)
|
||||
close(b.done)
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package loaders
|
||||
|
||||
import (
|
||||
"context"
|
||||
"git.aiterp.net/rpdata/api/models"
|
||||
"git.aiterp.net/rpdata/api/repositories"
|
||||
"time"
|
||||
)
|
||||
|
||||
//go:generate go run github.com/vektah/dataloaden CharacterLoader string *git.aiterp.net/rpdata/api/models.Character
|
||||
|
||||
// CharacterLoaderFromRepository creates a new CharacterLoader
|
||||
func CharacterLoaderFromRepository(repo repositories.CharacterRepository) *CharacterLoader {
|
||||
return &CharacterLoader{
|
||||
wait: time.Millisecond * 1,
|
||||
maxBatch: 100,
|
||||
fetch: func(keys []string) ([]*models.Character, []error) {
|
||||
timeout, cancel := context.WithTimeout(context.Background(), time.Second*15)
|
||||
defer cancel()
|
||||
|
||||
characters, err := repo.List(timeout, models.CharacterFilter{
|
||||
IDs: keys,
|
||||
})
|
||||
if err != nil {
|
||||
errs := make([]error, len(keys))
|
||||
for i := range errs {
|
||||
errs[i] = err
|
||||
}
|
||||
|
||||
return nil, errs
|
||||
}
|
||||
|
||||
charMap := make(map[string]*models.Character, len(keys))
|
||||
|
||||
for _, character := range characters {
|
||||
charMap[character.ID] = character
|
||||
}
|
||||
|
||||
results := make([]*models.Character, len(keys))
|
||||
errs := make([]error, len(keys))
|
||||
|
||||
for i, key := range keys {
|
||||
if character, ok := charMap[key]; ok {
|
||||
results[i] = character
|
||||
} else {
|
||||
errs[i] = repositories.ErrNotFound
|
||||
}
|
||||
}
|
||||
|
||||
return results, errs
|
||||
},
|
||||
}
|
||||
}
|
||||
+11
-3
@@ -1,10 +1,14 @@
|
||||
package services
|
||||
|
||||
import "git.aiterp.net/rpdata/api/repositories"
|
||||
import (
|
||||
"git.aiterp.net/rpdata/api/repositories"
|
||||
"git.aiterp.net/rpdata/api/services/loaders"
|
||||
)
|
||||
|
||||
// A Bundle contains all services, like a bean bag in the more caffeinated language family.
|
||||
// A Bundle contains all services.
|
||||
type Bundle struct {
|
||||
Tags *TagService
|
||||
Tags *TagService
|
||||
Characters *CharacterService
|
||||
}
|
||||
|
||||
// NewBundle creates a new bundle.
|
||||
@@ -12,6 +16,10 @@ func NewBundle(repos *repositories.Bundle) *Bundle {
|
||||
bundle := &Bundle{}
|
||||
|
||||
bundle.Tags = &TagService{tags: repos.Tags}
|
||||
bundle.Characters = &CharacterService{
|
||||
characters: repos.Characters,
|
||||
loader: loaders.CharacterLoaderFromRepository(repos.Characters),
|
||||
}
|
||||
|
||||
return bundle
|
||||
}
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ type TagService struct {
|
||||
}
|
||||
|
||||
// FindTag finds one tag.
|
||||
func (s *TagService) FindTag(ctx context.Context, source, id string) (*models.Tag, error) {
|
||||
func (s *TagService) FindTag(ctx context.Context, source models.TagKind, id string) (*models.Tag, error) {
|
||||
return s.tags.Find(ctx, source, id)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user