adapt-octopus 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +5 -0
- package/.eslintignore +1 -0
- package/.eslintrc.json +13 -0
- package/.github/dependabot.yml +11 -0
- package/README.md +49 -0
- package/bin/cli.js +12 -0
- package/lib/Octopus.js +117 -0
- package/lib/SchemaNode.js +328 -0
- package/package.json +24 -0
- package/utils/stripObject.js +5 -0
package/.editorconfig
ADDED
package/.eslintignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
node_modules
|
package/.eslintrc.json
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# To get started with Dependabot version updates, you'll need to specify which
|
|
2
|
+
# package ecosystems to update and where the package manifests are located.
|
|
3
|
+
# Please see the documentation for all configuration options:
|
|
4
|
+
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
|
5
|
+
|
|
6
|
+
version: 2
|
|
7
|
+
updates:
|
|
8
|
+
- package-ecosystem: "npm" # See documentation for possible values
|
|
9
|
+
directory: "/" # Location of package manifests
|
|
10
|
+
schedule:
|
|
11
|
+
interval: "weekly"
|
package/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# 🐙 adapt-octopus
|
|
2
|
+
|
|
3
|
+
Utility for converting old Adapt schema from the non-conformant `properties.schema` style into the new conformant JSON schema format.
|
|
4
|
+
|
|
5
|
+
## Command-line
|
|
6
|
+
|
|
7
|
+
The utility can be used directly from a command line. See below for details.
|
|
8
|
+
|
|
9
|
+
### Installation
|
|
10
|
+
|
|
11
|
+
Note: requires [Node.js](http://nodejs.org) to be installed.
|
|
12
|
+
|
|
13
|
+
From the command line, run:
|
|
14
|
+
|
|
15
|
+
```console
|
|
16
|
+
npm install -g adapt-security/adapt-octopus
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
To convert a single schema, simply run the following:
|
|
22
|
+
```console
|
|
23
|
+
adapt-octopus <inputPath> <id>
|
|
24
|
+
```
|
|
25
|
+
* ID should match the value of the _component/extension/menu/theme_ attribute in a plugin’s bower.json.
|
|
26
|
+
|
|
27
|
+
To convert all schemas in a framework source repository, run:
|
|
28
|
+
```console
|
|
29
|
+
adapt-octopus <inputPath>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Programmatic
|
|
33
|
+
|
|
34
|
+
The utility also exports a Node.js API for use programatically.
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
import octopus from 'adapt-security/adapt-octopus'
|
|
38
|
+
// to run for a single schema, use the following (returns a promise)
|
|
39
|
+
octopus.run(options);
|
|
40
|
+
// to run for multiple schemas, use the following (returns a promise)
|
|
41
|
+
octopus.runRecursive(options);
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Options
|
|
45
|
+
The following options can be passed to the run functions:
|
|
46
|
+
- **cwd**: the current working directory (used when searching and writing files)
|
|
47
|
+
- **inputPath**: _required when calling `run`_ should be the path to the input schema
|
|
48
|
+
- **inputId**: _required when calling `run`_ the type of the schema being converted (accepted values: `component`, `extension`, `menu`, `theme`)
|
|
49
|
+
- **logger**: an instance to a logger to be used when logging status messages (must export a `log` function)
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import Octopus from '../lib/Octopus.js'
|
|
4
|
+
|
|
5
|
+
async function run () {
|
|
6
|
+
const opts = { cwd: path.resolve(process.argv[2]), inputId: process.argv[3] }
|
|
7
|
+
process.argv.length === 4
|
|
8
|
+
? await Octopus.run(opts)
|
|
9
|
+
: await Octopus.runRecursive(opts)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
run()
|
package/lib/Octopus.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { EOL } from 'os'
|
|
2
|
+
import fs from 'fs/promises'
|
|
3
|
+
import path from 'path'
|
|
4
|
+
import SchemaNode from './SchemaNode.js'
|
|
5
|
+
|
|
6
|
+
export default class Octopus {
|
|
7
|
+
static async run (opts) {
|
|
8
|
+
await new Octopus(opts).start()
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
static async runRecursive (opts) {
|
|
12
|
+
const _recurse = async pluginDir => {
|
|
13
|
+
const hasNewSchemas = (await fs.readdir(path.join(pluginDir, 'schema'))).some(f => f.endsWith('.schema.json'))
|
|
14
|
+
if(hasNewSchemas && opts.force !== true) {
|
|
15
|
+
return
|
|
16
|
+
}
|
|
17
|
+
const bowerJson = JSON.parse(await fs.readFile(path.join(pluginDir, 'bower.json')))
|
|
18
|
+
const inputId = bowerJson.component || bowerJson.extension || bowerJson.menu || bowerJson.theme
|
|
19
|
+
const octopus = new Octopus({ ...opts, cwd: pluginDir, inputId })
|
|
20
|
+
await octopus.start()
|
|
21
|
+
}
|
|
22
|
+
const { name } = JSON.parse(await fs.readFile(path.join(opts.cwd, 'package.json')))
|
|
23
|
+
if (name !== 'adapt_framework') {
|
|
24
|
+
return await _recurse(opts.cwd)
|
|
25
|
+
}
|
|
26
|
+
await Promise.all(['components', 'extensions', 'menu', 'theme'].map(async f => {
|
|
27
|
+
try {
|
|
28
|
+
const dir = path.join(opts.cwd, 'src', f)
|
|
29
|
+
const contents = await fs.readdir(dir)
|
|
30
|
+
return await Promise.all(contents.map(async c => _recurse(path.join(dir, c))))
|
|
31
|
+
} catch (e) {}
|
|
32
|
+
}))
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
logger
|
|
36
|
+
inputPath
|
|
37
|
+
outputPath
|
|
38
|
+
inputId
|
|
39
|
+
inputSchema
|
|
40
|
+
outputSchema
|
|
41
|
+
|
|
42
|
+
constructor ({ inputPath = 'properties.schema', inputId, cwd, logger = console }) {
|
|
43
|
+
this.cwd = cwd || path.basename(inputPath)
|
|
44
|
+
this.inputPath = path.resolve(cwd, inputPath)
|
|
45
|
+
this.inputId = inputId
|
|
46
|
+
this.logger = logger
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async start () {
|
|
50
|
+
if (!this.inputPath) throw (new Error('No input path specified'))
|
|
51
|
+
if (!this.inputId) throw (new Error('No ID specified'))
|
|
52
|
+
|
|
53
|
+
this.inputSchema = JSON.parse(await fs.readFile(this.inputPath, 'utf8'))
|
|
54
|
+
await this.convert()
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async convert () {
|
|
58
|
+
const properties = this.inputSchema.properties
|
|
59
|
+
if (this.inputSchema.$ref === 'http://localhost/plugins/content/component/model.schema') {
|
|
60
|
+
await this.construct('course', {})
|
|
61
|
+
await this.construct('component')
|
|
62
|
+
return
|
|
63
|
+
}
|
|
64
|
+
if (this.inputSchema.$ref === 'http://localhost/plugins/content/theme/model.schema') {
|
|
65
|
+
await this.construct('theme', { properties: properties.variables })
|
|
66
|
+
}
|
|
67
|
+
if (properties?.pluginLocations) return await this.iterateLocations()
|
|
68
|
+
await this.construct(path.basename(this.inputPath, '.model.schema'))
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async iterateLocations () {
|
|
72
|
+
const locations = this.inputSchema.properties.pluginLocations.properties
|
|
73
|
+
|
|
74
|
+
for (const location of Object.entries(locations)) {
|
|
75
|
+
await this.construct(...location)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// ensure any globals are converted
|
|
79
|
+
if (!Object.keys(locations).includes('course')) {
|
|
80
|
+
await this.construct('course', {})
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async construct (type, schema = this.inputSchema) {
|
|
85
|
+
const properties = schema.properties
|
|
86
|
+
|
|
87
|
+
if (type !== 'course' || !(schema.globals || (schema.globals = this.inputSchema.globals))) {
|
|
88
|
+
if (!properties || !Object.keys(properties).length) return
|
|
89
|
+
delete schema.globals
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
this.outputSchema = new SchemaNode({
|
|
93
|
+
nodeType: 'root',
|
|
94
|
+
schemaType: type,
|
|
95
|
+
inputId: this.inputId,
|
|
96
|
+
inputSchema: schema,
|
|
97
|
+
logger: this.logger
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
this.outputPath = path.resolve(this.cwd, `schema/${type}.schema.json`)
|
|
101
|
+
await this.write()
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async write () {
|
|
105
|
+
try {
|
|
106
|
+
return await fs.readFile(this.outputPath)
|
|
107
|
+
// return this.logger.log(`JSON schema already exists at ${this.outputPath}, exiting`);
|
|
108
|
+
} catch (e) {
|
|
109
|
+
// carry on
|
|
110
|
+
}
|
|
111
|
+
const json = JSON.stringify(this.outputSchema, null, 2) + EOL
|
|
112
|
+
|
|
113
|
+
await fs.mkdir(path.dirname(this.outputPath), { recursive: true })
|
|
114
|
+
await fs.writeFile(this.outputPath, json)
|
|
115
|
+
this.logger.log(`converted JSON schema written to ${this.outputPath}`)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import stripObject from '../utils/stripObject.js'
|
|
2
|
+
|
|
3
|
+
export default class SchemaNode {
|
|
4
|
+
inputId
|
|
5
|
+
inputSchema
|
|
6
|
+
|
|
7
|
+
constructor (options) {
|
|
8
|
+
this.inputId = options.inputId
|
|
9
|
+
this.inputSchema = options.inputSchema
|
|
10
|
+
this.logger = options.logger
|
|
11
|
+
|
|
12
|
+
switch (options.nodeType) {
|
|
13
|
+
case 'root': {
|
|
14
|
+
const type = options.schemaType
|
|
15
|
+
const isCore = type === this.inputId
|
|
16
|
+
const isComponent = type === 'component'
|
|
17
|
+
const isExtension = (!isCore || type !== 'config') && type !== 'theme'
|
|
18
|
+
|
|
19
|
+
let schemaInner = {
|
|
20
|
+
required: this.getRequiredFields(),
|
|
21
|
+
properties: this.getProperties()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (isExtension) {
|
|
25
|
+
schemaInner = {
|
|
26
|
+
[isCore || isComponent ? '$merge' : '$patch']: {
|
|
27
|
+
source: { $ref: isCore ? 'content' : type },
|
|
28
|
+
with: schemaInner
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
$anchor: isCore ? type : `${this.inputId}-${type}`,
|
|
34
|
+
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
|
35
|
+
type: 'object',
|
|
36
|
+
...schemaInner
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
case 'properties':
|
|
40
|
+
return {
|
|
41
|
+
type: this.inputSchema.type,
|
|
42
|
+
isObjectId: this.getIsObjectId(),
|
|
43
|
+
title: this.getTitle(options.key),
|
|
44
|
+
description: this.getDescription(),
|
|
45
|
+
default: this.getDefault(),
|
|
46
|
+
enum: this.getEnumeratedValues(),
|
|
47
|
+
required: this.getRequiredFields(),
|
|
48
|
+
items: this.getItems(),
|
|
49
|
+
properties: this.getProperties(),
|
|
50
|
+
_adapt: this.getAdaptOptions(),
|
|
51
|
+
_backboneForms: this.getBackboneFormsOptions(),
|
|
52
|
+
_unrecognisedFields: this.getUnrecognisedFields()
|
|
53
|
+
}
|
|
54
|
+
case 'items':{
|
|
55
|
+
const properties = this.getItemsProperties()
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
type: properties ? this.getType() : 'object',
|
|
59
|
+
isObjectId: this.getIsObjectId(),
|
|
60
|
+
properties
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
getItemsProperties () {
|
|
67
|
+
const originalItems = this.inputSchema.properties
|
|
68
|
+
|
|
69
|
+
if (!originalItems) return
|
|
70
|
+
|
|
71
|
+
return Object.entries(originalItems).reduce((a, [key, inputSchema]) => {
|
|
72
|
+
a[key] = new SchemaNode({ nodeType: 'properties', key, inputSchema, logger: this.logger })
|
|
73
|
+
|
|
74
|
+
return a
|
|
75
|
+
}, {})
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
getProperties () {
|
|
79
|
+
const originalProperties = this.inputSchema.properties
|
|
80
|
+
const originalGlobals = this.inputSchema.globals
|
|
81
|
+
|
|
82
|
+
if (!originalProperties && !originalGlobals) return
|
|
83
|
+
|
|
84
|
+
const globals = {}
|
|
85
|
+
const properties = {}
|
|
86
|
+
|
|
87
|
+
if (originalGlobals) {
|
|
88
|
+
for (const [key, inputSchema] of Object.entries(originalGlobals)) {
|
|
89
|
+
globals[key] = new SchemaNode({
|
|
90
|
+
nodeType: 'properties',
|
|
91
|
+
key,
|
|
92
|
+
inputSchema,
|
|
93
|
+
logger: this.logger
|
|
94
|
+
})
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
properties._globals = {
|
|
98
|
+
type: 'object',
|
|
99
|
+
default: {},
|
|
100
|
+
properties: {
|
|
101
|
+
[`_${this.inputId}`]: {
|
|
102
|
+
type: 'object',
|
|
103
|
+
default: {},
|
|
104
|
+
properties: globals
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (originalProperties) {
|
|
111
|
+
for (const [key, inputSchema] of Object.entries(originalProperties)) {
|
|
112
|
+
properties[key] = new SchemaNode({
|
|
113
|
+
nodeType: 'properties',
|
|
114
|
+
key,
|
|
115
|
+
inputSchema,
|
|
116
|
+
logger: this.logger
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return properties
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
getType () {
|
|
125
|
+
const type = this.inputSchema.type
|
|
126
|
+
|
|
127
|
+
return type === 'objectid' ? 'string' : type
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
getTitle (key) {
|
|
131
|
+
const { title, legend } = this.inputSchema
|
|
132
|
+
|
|
133
|
+
if (title) return title
|
|
134
|
+
if (legend) return legend
|
|
135
|
+
if (key === 'pluginLocations') return
|
|
136
|
+
|
|
137
|
+
key = key.replace(/_/g, '').replace(/[A-Z]/g, ' $&').toLowerCase()
|
|
138
|
+
|
|
139
|
+
return key.charAt(0).toUpperCase() + key.slice(1)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
getDescription () {
|
|
143
|
+
const help = this.inputSchema.help
|
|
144
|
+
|
|
145
|
+
if (help) return help
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
getDefault () {
|
|
149
|
+
if (this.getIsObjectId()) return
|
|
150
|
+
|
|
151
|
+
const originalDefault = this.inputSchema.default
|
|
152
|
+
|
|
153
|
+
if (originalDefault !== undefined) return originalDefault
|
|
154
|
+
if (this.inputSchema.required || this.inputSchema.validators?.includes('required')) return
|
|
155
|
+
|
|
156
|
+
switch (this.inputSchema.type) {
|
|
157
|
+
case 'string':
|
|
158
|
+
return ''
|
|
159
|
+
case 'number':
|
|
160
|
+
return 0
|
|
161
|
+
case 'object':
|
|
162
|
+
return {}
|
|
163
|
+
case 'array':
|
|
164
|
+
if (!this.inputSchema.items) return []
|
|
165
|
+
break
|
|
166
|
+
case 'boolean':
|
|
167
|
+
return false
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
getEnumeratedValues () {
|
|
172
|
+
const { originalEnum, inputType } = this.inputSchema
|
|
173
|
+
|
|
174
|
+
if (originalEnum) return originalEnum
|
|
175
|
+
if (inputType?.type === 'Select') return inputType.options
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
getRequiredFields () {
|
|
179
|
+
const properties = this.inputSchema.properties
|
|
180
|
+
|
|
181
|
+
if (!properties) return
|
|
182
|
+
|
|
183
|
+
const requiredFields = Object.entries(properties).reduce((a, [key, value]) => {
|
|
184
|
+
if ((value.required === true || value.validators?.includes('required')) && value?.default === undefined) a.push(key)
|
|
185
|
+
|
|
186
|
+
return a
|
|
187
|
+
}, [])
|
|
188
|
+
|
|
189
|
+
if (!requiredFields.length) return
|
|
190
|
+
|
|
191
|
+
return requiredFields
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
getItems () {
|
|
195
|
+
const items = this.inputSchema.items
|
|
196
|
+
|
|
197
|
+
if (items) return new SchemaNode({ nodeType: 'items', inputSchema: items, logger: this.logger })
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
getIsObjectId () {
|
|
201
|
+
const inputType = this.inputSchema.inputType
|
|
202
|
+
const isAsset = (inputType?.type || inputType)?.startsWith('Asset')
|
|
203
|
+
|
|
204
|
+
if (isAsset || this.inputSchema.type === 'objectid') return true
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
getAdaptOptions () {
|
|
208
|
+
return stripObject({
|
|
209
|
+
editorOnly: this.inputSchema.editorOnly,
|
|
210
|
+
isSetting: this.inputSchema.isSetting,
|
|
211
|
+
translatable: this.inputSchema.translatable
|
|
212
|
+
})
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
getBackboneFormsOptions () {
|
|
216
|
+
const inputType = this.inputSchema.inputType
|
|
217
|
+
|
|
218
|
+
const getEditor = () => {
|
|
219
|
+
const type = this.inputSchema.type
|
|
220
|
+
|
|
221
|
+
const recognisedTypes = [
|
|
222
|
+
'string',
|
|
223
|
+
'number',
|
|
224
|
+
'object',
|
|
225
|
+
'array',
|
|
226
|
+
'boolean',
|
|
227
|
+
'objectid'
|
|
228
|
+
]
|
|
229
|
+
|
|
230
|
+
const editor = options.type || inputType
|
|
231
|
+
|
|
232
|
+
if (!recognisedTypes.includes(type)) {
|
|
233
|
+
this.logger.log(`Unrecognised type => ${type}`)
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (editor === 'QuestionButton' ||
|
|
237
|
+
(type === 'string' && editor === 'Text') ||
|
|
238
|
+
(type === 'number' && editor === 'Number') ||
|
|
239
|
+
(type === 'boolean' && editor === 'Checkbox')) {
|
|
240
|
+
return
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return editor
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const getValidators = () => {
|
|
247
|
+
let validators = this.inputSchema.validators
|
|
248
|
+
|
|
249
|
+
if (!validators) return
|
|
250
|
+
|
|
251
|
+
validators = this.inputSchema.validators.filter(validator => {
|
|
252
|
+
return validator === 'number'
|
|
253
|
+
? inputType !== 'Number'
|
|
254
|
+
: validator !== 'required'
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
if (!validators.length) return
|
|
258
|
+
|
|
259
|
+
return validators
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
let options = typeof inputType === 'object' ? inputType : {}
|
|
263
|
+
|
|
264
|
+
Object.assign(options, {
|
|
265
|
+
type: getEditor(),
|
|
266
|
+
titleHTML: this.inputSchema.titleHTML,
|
|
267
|
+
validators: getValidators(),
|
|
268
|
+
editorClass: this.inputSchema.editorClass,
|
|
269
|
+
editorAttrs: this.inputSchema.editorAttrs,
|
|
270
|
+
fieldClass: this.inputSchema.fieldClass,
|
|
271
|
+
fieldAttrs: this.inputSchema.fieldAttrs,
|
|
272
|
+
confirmDelete: this.inputSchema.confirmDelete
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
const splitTypes = options.type?.split(':')
|
|
276
|
+
|
|
277
|
+
switch (splitTypes?.length > 1 && splitTypes[0]) {
|
|
278
|
+
case 'Asset':
|
|
279
|
+
options.type = { type: 'Asset', media: splitTypes[1] }
|
|
280
|
+
break
|
|
281
|
+
case 'CodeEditor':
|
|
282
|
+
options.type = { type: 'CodeEditor', mode: splitTypes[1] }
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (options.type === 'Select') delete options.options
|
|
286
|
+
|
|
287
|
+
options = stripObject(options)
|
|
288
|
+
|
|
289
|
+
return (options && Object.keys(options).length === 1 && options.type) || options
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
getUnrecognisedFields () {
|
|
293
|
+
const recognisedKeys = [
|
|
294
|
+
'confirmDelete',
|
|
295
|
+
'default',
|
|
296
|
+
'description',
|
|
297
|
+
'editorAttrs',
|
|
298
|
+
'editorClass',
|
|
299
|
+
'editorOnly',
|
|
300
|
+
'enum',
|
|
301
|
+
'fieldAttrs',
|
|
302
|
+
'fieldClass',
|
|
303
|
+
'help',
|
|
304
|
+
'inputType',
|
|
305
|
+
'items',
|
|
306
|
+
'isSetting',
|
|
307
|
+
'legend',
|
|
308
|
+
'properties',
|
|
309
|
+
'required',
|
|
310
|
+
'title',
|
|
311
|
+
'titleHTML',
|
|
312
|
+
'translatable',
|
|
313
|
+
'type',
|
|
314
|
+
'validators'
|
|
315
|
+
]
|
|
316
|
+
|
|
317
|
+
const unrecognisedFields = {}
|
|
318
|
+
|
|
319
|
+
for (const [key, value] of Object.entries(this.inputSchema)) {
|
|
320
|
+
if (recognisedKeys.includes(key)) continue
|
|
321
|
+
|
|
322
|
+
this.logger.log(`Unrecognised field => "${key}": ${JSON.stringify(value)}`)
|
|
323
|
+
unrecognisedFields[key] = value
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
return stripObject(unrecognisedFields)
|
|
327
|
+
}
|
|
328
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "adapt-octopus",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Convert old Adapt schema into conformant JSON schema",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./lib/Octopus.js",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/tomgreenfield/adapt-octopus.git"
|
|
10
|
+
},
|
|
11
|
+
"license": "GPL-3.0",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/tomgreenfield/adapt-octopus/issues"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/tomgreenfield/adapt-octopus#readme",
|
|
16
|
+
"bin": "./bin/cli.js",
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"eslint": "^8.57.1",
|
|
19
|
+
"eslint-config-standard": "^17.1.0",
|
|
20
|
+
"eslint-plugin-import": "^2.31.0",
|
|
21
|
+
"eslint-plugin-node": "^11.1.0",
|
|
22
|
+
"eslint-plugin-promise": "^6.6.0"
|
|
23
|
+
}
|
|
24
|
+
}
|