Skip to content

Instantly share code, notes, and snippets.

@DaRaFF
Last active November 26, 2022 17:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save DaRaFF/bf2dafdfbc40add43e5c3f94b5a8dc00 to your computer and use it in GitHub Desktop.
Save DaRaFF/bf2dafdfbc40add43e5c3f94b5a8dc00 to your computer and use it in GitHub Desktop.
Flags Example
// server
module.exports = function (flagsApi) {
return {
index: function (req, res, next) {
const channelId = getChannelId(req)
if (!channelId) return res.error(400, {channel_id: 'missing mandatory parameter'})
flagsApi.list(channelId, function (err, flags) {
if (err) return res.error(err)
res.success({flags})
})
}
}
}
function getChannelId (req) {
return req.payload.query.channel_id || undefined
}
// Editor
const errorLog = require('@livingdocs/editor/app/scripts/modules/error_log')
angular.module('li-editing-api').factory('flagProxy',
function (storage, $q, errorReporter, ldEditApi) {
const {authedHttp} = ldEditApi
return {
list (channelId) {
return authedHttp.get('/nzz/flags', {params: {channel_id: channelId}})
.catch(function (error) {
errorReporter.networkError(error.status, 'get flag list')
errorLog.track('API error in flagProxy#list', error)
return $q.reject(error)
})
.then(response => response.data.flags)
}
}
})
// server
module.exports = {
title: 'Flags',
description: 'Flags endpoint',
path: '/nzz/flags',
endpoints: [{
method: 'get',
title: 'Get flags',
auth: true,
action: 'index',
fields: {
default: ['channel_id'],
allowed: ['channel_id']
},
query: {
properties: {
channel_id: {
type: 'string',
format: 'integer'
}
}
}
}]
}
// Editor
const _map = require('lodash/map')
module.exports = function ({metadata, $injector}) {
const flagProxy = $injector.get('flagProxy')
const editor = $injector.get('editor')
const {remoteDocument} = editor.workspace.draft
return {
getSelectables (name, cb) {
let flags = []
return flagProxy.list(remoteDocument.channelId).then(function (list) {
if (list) {
flags = _map(list, entry => ({name: entry, value: entry}))
flags = [{name: '--None--', value: ''}].concat(flags)
return cb(null, flags)
}
}
, function (error, status) {
console.error(`Error: Could not get flags list, ${error}`)
return cb(error)
})
},
// This sample service assumes a li-enum datatype on the server thus no name,
// value pair, just the value is set
select (identifier, selection) {
if (selection) {
return metadata.set(identifier, selection.value)
}
metadata.set(identifier, '')
},
initSelection (identifier) {
const val = metadata.get(identifier)
if (val) {
return {
name: val,
value: val
}
} else {
return {
name: '--None--',
value: ''
}
}
},
hasCustomItem () {
return false
},
getCustomItem () {
return ''
}
}
}
// server
const _ = require('lodash')
const aws = require('aws-sdk')
module.exports = function (config, channelApi) {
const bucket = config.get('flags:s3_bucket_config:bucket')
const s3 = new aws.S3({
accessKeyId: config.get('flags:s3_bucket_config:access_key'),
secretAccessKey: config.get('flags:s3_bucket_config:secret_key')
})
return {
// expose for tests
_s3: s3,
list: function (channelId, callback) {
channelApi.getChannelConfig({channelId}, function (err, channelConfig) {
// configKey: 'flags.file'
if (err) return callback(err)
const flagFile = _.get(channelConfig, 'custom.flags.file')
if (err) return callback(err)
if (!_.isString(flagFile)) {
return callback(new Error(
`flags: no flagfile has been configured in the channelConfig ${channelId}`
))
}
s3.getObject({
Bucket: bucket,
Key: flagFile.replace(/^\//, '')
}, function (err, res) {
if (err && err.code === 'NoSuchKey') return callback(null, [])
if (err) return callback(err)
let json
try {
json = JSON.parse(res.Body || '[]')
} catch (err) {
err.message = `flags.list parse error: ${err.message}`
return callback(err)
}
callback(null, json)
})
})
}
}
}
// server - flag feature
const _ = require('lodash')
const parseConfig = require('./parse_config')
const log = require('@livingdocs/server/app/modules/logging').child({ns: 'nzz-flags'})
module.exports = function (feature, server) {
const channelApi = server.features.api('li-projects').channel
const flagsApi = require('./flags_api')(server.config, channelApi)
feature.registerApi(flagsApi)
const channelConfigs = server.config.get('projects').channelConfigurations
const configValidations = channelConfigs.map((config) => {
const {settings} = config
if (!settings || config.v !== 2) {
return new Error(`Channel config is not v2 compatible: ${JSON.stringify(config)}`)
}
try {
parseConfig(feature.name, settings)
} catch (err) {
log.warn(`Could not load flags feature config for channel "${settings.handle}" due to: ${err}`)
return err
}
return settings
})
const channelsWithFlagsConfig = configValidations.filter(v => !(v instanceof Error))
if (_.isEmpty(channelsWithFlagsConfig)) {
log.info('Skipping flags feature init.')
return
}
return feature.registerResource({
routes: require('./flag_routes'),
controller: require('./flag_controller')(flagsApi)
})
}
// server
const ms = require('microschema')
const createFeatureConfig = require('../common/process-config')
module.exports = function (moduleName, config) {
return createFeatureConfig(moduleName, config)
.castTypes({boolean: true, number: true})
.validateSchema(ms.obj({
custom: ms.required.obj({
flags: ms.required.strictObj({
file: 'string:required'
})
})
}))
.getResult()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment