@kravc/schema 2.7.6 → 2.8.0-alpha.0
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/README.md +19 -14
- package/dist/CredentialFactory.d.ts +345 -0
- package/dist/CredentialFactory.d.ts.map +1 -0
- package/dist/CredentialFactory.js +381 -0
- package/dist/CredentialFactory.js.map +1 -0
- package/dist/Schema.d.ts +448 -0
- package/dist/Schema.d.ts.map +1 -0
- package/dist/Schema.js +506 -0
- package/dist/Schema.js.map +1 -0
- package/dist/ValidationError.d.ts +70 -0
- package/dist/ValidationError.d.ts.map +1 -0
- package/dist/ValidationError.js +78 -0
- package/dist/ValidationError.js.map +1 -0
- package/dist/Validator.d.ts +483 -0
- package/dist/Validator.d.ts.map +1 -0
- package/dist/Validator.js +570 -0
- package/dist/Validator.js.map +1 -0
- package/dist/helpers/JsonSchema.d.ts +99 -0
- package/dist/helpers/JsonSchema.d.ts.map +1 -0
- package/dist/helpers/JsonSchema.js +3 -0
- package/dist/helpers/JsonSchema.js.map +1 -0
- package/dist/helpers/cleanupAttributes.d.ts +34 -0
- package/dist/helpers/cleanupAttributes.d.ts.map +1 -0
- package/dist/helpers/cleanupAttributes.js +113 -0
- package/dist/helpers/cleanupAttributes.js.map +1 -0
- package/dist/helpers/cleanupNulls.d.ts +27 -0
- package/dist/helpers/cleanupNulls.d.ts.map +1 -0
- package/dist/helpers/cleanupNulls.js +96 -0
- package/dist/helpers/cleanupNulls.js.map +1 -0
- package/dist/helpers/getReferenceIds.d.ts +169 -0
- package/dist/helpers/getReferenceIds.d.ts.map +1 -0
- package/dist/helpers/getReferenceIds.js +241 -0
- package/dist/helpers/getReferenceIds.js.map +1 -0
- package/dist/helpers/got.d.ts +60 -0
- package/dist/helpers/got.d.ts.map +1 -0
- package/dist/helpers/got.js +72 -0
- package/dist/helpers/got.js.map +1 -0
- package/dist/helpers/mapObjectProperties.d.ts +150 -0
- package/dist/helpers/mapObjectProperties.d.ts.map +1 -0
- package/dist/helpers/mapObjectProperties.js +229 -0
- package/dist/helpers/mapObjectProperties.js.map +1 -0
- package/dist/helpers/normalizeAttributes.d.ts +213 -0
- package/dist/helpers/normalizeAttributes.d.ts.map +1 -0
- package/dist/helpers/normalizeAttributes.js +243 -0
- package/dist/helpers/normalizeAttributes.js.map +1 -0
- package/dist/helpers/normalizeProperties.d.ts +168 -0
- package/dist/helpers/normalizeProperties.d.ts.map +1 -0
- package/dist/helpers/normalizeProperties.js +223 -0
- package/dist/helpers/normalizeProperties.js.map +1 -0
- package/dist/helpers/normalizeRequired.d.ts +159 -0
- package/dist/helpers/normalizeRequired.d.ts.map +1 -0
- package/dist/helpers/normalizeRequired.js +206 -0
- package/dist/helpers/normalizeRequired.js.map +1 -0
- package/dist/helpers/normalizeType.d.ts +81 -0
- package/dist/helpers/normalizeType.d.ts.map +1 -0
- package/dist/helpers/normalizeType.js +210 -0
- package/dist/helpers/normalizeType.js.map +1 -0
- package/dist/helpers/nullifyEmptyValues.d.ts +139 -0
- package/dist/helpers/nullifyEmptyValues.d.ts.map +1 -0
- package/dist/helpers/nullifyEmptyValues.js +191 -0
- package/dist/helpers/nullifyEmptyValues.js.map +1 -0
- package/dist/helpers/removeRequiredAndDefault.d.ts +106 -0
- package/dist/helpers/removeRequiredAndDefault.d.ts.map +1 -0
- package/dist/helpers/removeRequiredAndDefault.js +138 -0
- package/dist/helpers/removeRequiredAndDefault.js.map +1 -0
- package/dist/helpers/validateId.d.ts +39 -0
- package/dist/helpers/validateId.d.ts.map +1 -0
- package/dist/helpers/validateId.js +51 -0
- package/dist/helpers/validateId.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/ld/documentLoader.d.ts +8 -0
- package/dist/ld/documentLoader.d.ts.map +1 -0
- package/dist/ld/documentLoader.js +24 -0
- package/dist/ld/documentLoader.js.map +1 -0
- package/dist/ld/getLinkedDataAttributeType.d.ts +10 -0
- package/dist/ld/getLinkedDataAttributeType.d.ts.map +1 -0
- package/dist/ld/getLinkedDataAttributeType.js +32 -0
- package/dist/ld/getLinkedDataAttributeType.js.map +1 -0
- package/dist/ld/getLinkedDataContext.d.ts +19 -0
- package/dist/ld/getLinkedDataContext.d.ts.map +1 -0
- package/dist/ld/getLinkedDataContext.js +50 -0
- package/dist/ld/getLinkedDataContext.js.map +1 -0
- package/eslint.config.mjs +32 -52
- package/examples/credentials/createAccountCredential.ts +27 -0
- package/examples/credentials/createMineSweeperScoreCredential.ts +115 -0
- package/examples/index.ts +7 -0
- package/examples/schemas/FavoriteItemSchema.ts +27 -0
- package/examples/{Preferences.yaml → schemas/Preferences.yaml} +2 -0
- package/examples/schemas/PreferencesSchema.ts +29 -0
- package/examples/schemas/ProfileSchema.ts +91 -0
- package/examples/schemas/Status.yaml +3 -0
- package/examples/schemas/StatusSchema.ts +12 -0
- package/jest.config.mjs +5 -0
- package/package.json +27 -20
- package/src/CredentialFactory.ts +392 -0
- package/src/Schema.ts +583 -0
- package/src/ValidationError.ts +90 -0
- package/src/Validator.ts +603 -0
- package/src/__tests__/CredentialFactory.test.ts +588 -0
- package/src/__tests__/Schema.test.ts +371 -0
- package/src/__tests__/ValidationError.test.ts +235 -0
- package/src/__tests__/Validator.test.ts +787 -0
- package/src/helpers/JsonSchema.ts +119 -0
- package/src/helpers/__tests__/cleanupAttributes.test.ts +943 -0
- package/src/helpers/__tests__/cleanupNulls.test.ts +772 -0
- package/src/helpers/__tests__/getReferenceIds.test.ts +975 -0
- package/src/helpers/__tests__/got.test.ts +193 -0
- package/src/helpers/__tests__/mapObjectProperties.test.ts +1126 -0
- package/src/helpers/__tests__/normalizeAttributes.test.ts +1435 -0
- package/src/helpers/__tests__/normalizeProperties.test.ts +727 -0
- package/src/helpers/__tests__/normalizeRequired.test.ts +669 -0
- package/src/helpers/__tests__/normalizeType.test.ts +772 -0
- package/src/helpers/__tests__/nullifyEmptyValues.test.ts +735 -0
- package/src/helpers/__tests__/removeRequiredAndDefault.test.ts +734 -0
- package/src/helpers/__tests__/validateId.test.ts +118 -0
- package/src/helpers/cleanupAttributes.ts +151 -0
- package/src/helpers/cleanupNulls.ts +106 -0
- package/src/helpers/getReferenceIds.ts +273 -0
- package/src/helpers/got.ts +73 -0
- package/src/helpers/mapObjectProperties.ts +272 -0
- package/src/helpers/normalizeAttributes.ts +247 -0
- package/src/helpers/normalizeProperties.ts +249 -0
- package/src/helpers/normalizeRequired.ts +233 -0
- package/src/helpers/normalizeType.ts +235 -0
- package/src/helpers/nullifyEmptyValues.ts +207 -0
- package/src/helpers/removeRequiredAndDefault.ts +151 -0
- package/src/helpers/validateId.ts +53 -0
- package/src/index.ts +13 -0
- package/src/ld/__tests__/documentLoader.test.ts +57 -0
- package/src/ld/__tests__/getLinkedDataAttributeType.test.ts +212 -0
- package/src/ld/__tests__/getLinkedDataContext.test.ts +378 -0
- package/src/ld/documentLoader.ts +28 -0
- package/src/ld/getLinkedDataAttributeType.ts +46 -0
- package/src/ld/getLinkedDataContext.ts +80 -0
- package/tsconfig.json +27 -0
- package/types/credentials-context.d.ts +14 -0
- package/types/security-context.d.ts +6 -0
- package/examples/Status.yaml +0 -3
- package/examples/createAccountCredential.js +0 -27
- package/examples/createMineSweeperScoreCredential.js +0 -63
- package/examples/index.js +0 -9
- package/src/CredentialFactory.js +0 -67
- package/src/CredentialFactory.spec.js +0 -131
- package/src/Schema.js +0 -104
- package/src/Schema.spec.js +0 -172
- package/src/ValidationError.js +0 -31
- package/src/Validator.js +0 -128
- package/src/Validator.spec.js +0 -355
- package/src/helpers/cleanupAttributes.js +0 -71
- package/src/helpers/cleanupNulls.js +0 -42
- package/src/helpers/getReferenceIds.js +0 -71
- package/src/helpers/mapObject.js +0 -65
- package/src/helpers/normalizeAttributes.js +0 -28
- package/src/helpers/normalizeProperties.js +0 -61
- package/src/helpers/normalizeRequired.js +0 -37
- package/src/helpers/normalizeType.js +0 -41
- package/src/helpers/nullifyEmptyValues.js +0 -57
- package/src/helpers/removeRequiredAndDefault.js +0 -30
- package/src/helpers/validateId.js +0 -19
- package/src/index.d.ts +0 -25
- package/src/index.js +0 -8
- package/src/ld/documentLoader.js +0 -25
- package/src/ld/documentLoader.spec.js +0 -12
- package/src/ld/getLinkedDataContext.js +0 -63
- package/src/ld/getLinkedDataType.js +0 -38
- /package/examples/{FavoriteItem.yaml → schemas/FavoriteItem.yaml} +0 -0
- /package/examples/{Profile.yaml → schemas/Profile.yaml} +0 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { get } from 'lodash';
|
|
2
|
+
|
|
3
|
+
export type PropertySchema = {
|
|
4
|
+
'@type'?: string;
|
|
5
|
+
$ref?: string;
|
|
6
|
+
type?: string;
|
|
7
|
+
format?: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/** Returns linked data attribute type for a property schema, unless @type is defined */
|
|
11
|
+
const getLinkedDataAttributeType = (propertySchema: PropertySchema): string | undefined => {
|
|
12
|
+
const isOverriden = !!get(propertySchema, '@type');
|
|
13
|
+
|
|
14
|
+
if (isOverriden) {
|
|
15
|
+
return get(propertySchema, '@type');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// TODO: Add support for all types and formats, extend schema library with
|
|
19
|
+
// support for additional formats, e.g. URL, Duration etc.
|
|
20
|
+
const { type, format } = propertySchema;
|
|
21
|
+
|
|
22
|
+
const isDate = format === 'date';
|
|
23
|
+
const isNumber = type === 'number';
|
|
24
|
+
const isInteger = type === 'integer';
|
|
25
|
+
const isDateTime = format === 'date-time';
|
|
26
|
+
|
|
27
|
+
if (isInteger) {
|
|
28
|
+
return 'schema:Integer';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (isNumber) {
|
|
32
|
+
return 'schema:Number';
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (isDate) {
|
|
36
|
+
return 'schema:Date';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (isDateTime) {
|
|
40
|
+
return 'schema:DateTime';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export default getLinkedDataAttributeType;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import getLinkedDataAttributeType, { type PropertySchema } from './getLinkedDataAttributeType';
|
|
2
|
+
|
|
3
|
+
export type { PropertySchema };
|
|
4
|
+
|
|
5
|
+
const SCHEMA_ORG_URI = 'https://schema.org/';
|
|
6
|
+
|
|
7
|
+
const PROTECTED_PROPERTIES = [
|
|
8
|
+
'id',
|
|
9
|
+
'type',
|
|
10
|
+
'schema'
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
type ContextProperty = {
|
|
14
|
+
'@id': string;
|
|
15
|
+
'@type'?: string;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
type ContextHeader = {
|
|
19
|
+
'@vocab': string;
|
|
20
|
+
'@version': number;
|
|
21
|
+
'@protected': boolean;
|
|
22
|
+
schema?: string;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type LinkedDataContext = ContextHeader & {
|
|
26
|
+
[key: string]: ContextProperty | string | number | boolean | undefined;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/** Returns linked data context for a properties object */
|
|
30
|
+
const getLinkedDataContext = (properties: Record<string, PropertySchema>, vocabUri: string): LinkedDataContext => {
|
|
31
|
+
const context = {} as Record<string, ContextProperty>;
|
|
32
|
+
|
|
33
|
+
// TODO: Add support for embedded object, array and enum.
|
|
34
|
+
for (const key in properties) {
|
|
35
|
+
const propertySchema = properties[key];
|
|
36
|
+
|
|
37
|
+
const isProtected =
|
|
38
|
+
PROTECTED_PROPERTIES.includes(key) ||
|
|
39
|
+
key.startsWith('@');
|
|
40
|
+
|
|
41
|
+
if (isProtected) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
context[key] = { '@id': key };
|
|
46
|
+
|
|
47
|
+
const { $ref } = propertySchema;
|
|
48
|
+
|
|
49
|
+
if ($ref) {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const linkedDataType = getLinkedDataAttributeType(propertySchema);
|
|
54
|
+
|
|
55
|
+
if (linkedDataType) {
|
|
56
|
+
context[key]['@type'] = linkedDataType;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const vocab = vocabUri.endsWith('/') || vocabUri.endsWith('#') ? vocabUri : `${vocabUri}#`;
|
|
61
|
+
|
|
62
|
+
const contextHeader = {
|
|
63
|
+
'@vocab': vocab,
|
|
64
|
+
'@version': 1.1,
|
|
65
|
+
'@protected': true
|
|
66
|
+
} as ContextHeader;
|
|
67
|
+
|
|
68
|
+
const isSchemaOrgDomain = vocab === SCHEMA_ORG_URI;
|
|
69
|
+
|
|
70
|
+
if (!isSchemaOrgDomain) {
|
|
71
|
+
contextHeader.schema = SCHEMA_ORG_URI;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
...contextHeader,
|
|
76
|
+
...context
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export default getLinkedDataContext;
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"rootDir": "./src",
|
|
4
|
+
"outDir": "./dist",
|
|
5
|
+
"target": "esnext",
|
|
6
|
+
"module": "nodenext",
|
|
7
|
+
"isolatedModules": true,
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"strictNullChecks": true,
|
|
11
|
+
"noUnusedLocals": true,
|
|
12
|
+
"noUnusedParameters": true,
|
|
13
|
+
"skipLibCheck": true,
|
|
14
|
+
"declaration": true,
|
|
15
|
+
"declarationMap": true,
|
|
16
|
+
"sourceMap": true
|
|
17
|
+
},
|
|
18
|
+
"include": [
|
|
19
|
+
"src",
|
|
20
|
+
"types"
|
|
21
|
+
],
|
|
22
|
+
"exclude": [
|
|
23
|
+
"node_modules",
|
|
24
|
+
"dist",
|
|
25
|
+
"**/*.test.ts"
|
|
26
|
+
]
|
|
27
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
declare module 'credentials-context' {
|
|
2
|
+
/**
|
|
3
|
+
* Map of credentials context URLs to their JSON-LD context documents
|
|
4
|
+
*/
|
|
5
|
+
export const contexts: Map<string, Record<string, unknown>>;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Constants for credentials context
|
|
9
|
+
*/
|
|
10
|
+
export const constants: {
|
|
11
|
+
CREDENTIALS_CONTEXT_V1_URL: string;
|
|
12
|
+
[key: string]: string;
|
|
13
|
+
};
|
|
14
|
+
}
|
package/examples/Status.yaml
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { Schema, CredentialFactory } = require('../src')
|
|
4
|
-
|
|
5
|
-
const accountSchema = new Schema({
|
|
6
|
-
id: {},
|
|
7
|
-
username: { required: true },
|
|
8
|
-
createdAt: { format: 'date-time', required: true },
|
|
9
|
-
dateOfBirth: { format: 'date' }
|
|
10
|
-
}, 'Account')
|
|
11
|
-
|
|
12
|
-
const factory = new CredentialFactory('https://example.com/schema/AccountV1', accountSchema)
|
|
13
|
-
|
|
14
|
-
const createAccountCredential = (holder, username) => {
|
|
15
|
-
const id = `https://example.com/account/${username}`
|
|
16
|
-
|
|
17
|
-
const createdAt = new Date().toISOString()
|
|
18
|
-
const subject = {
|
|
19
|
-
id: holder,
|
|
20
|
-
username,
|
|
21
|
-
createdAt
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return factory.createCredential(id, holder, subject)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
module.exports = createAccountCredential
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { Schema, CredentialFactory } = require('../src')
|
|
4
|
-
|
|
5
|
-
const GAME_NAME = 'MineSweeper'
|
|
6
|
-
const GAME_VERSION = '1.0'
|
|
7
|
-
|
|
8
|
-
const SCHEMA_ORG_URI = 'https://schema.org/'
|
|
9
|
-
|
|
10
|
-
const playerSchema = new Schema({
|
|
11
|
-
id: {},
|
|
12
|
-
hasVideoGameScore: { $ref: 'VideoGameScore', required: true }
|
|
13
|
-
}, 'Player')
|
|
14
|
-
|
|
15
|
-
const videoGameSchema = new Schema({
|
|
16
|
-
id: {},
|
|
17
|
-
name: { type: 'string', required: true },
|
|
18
|
-
version: { type: 'string', required: true }
|
|
19
|
-
}, 'VideoGame', SCHEMA_ORG_URI)
|
|
20
|
-
|
|
21
|
-
const videoGameScoreSchema = new Schema({
|
|
22
|
-
game: { $ref: 'VideoGame', required: true },
|
|
23
|
-
wins: { type: 'integer', required: true },
|
|
24
|
-
losses: { type: 'integer', required: true },
|
|
25
|
-
winRate: { type: 'number', required: true },
|
|
26
|
-
bestScore: { type: 'integer', required: true },
|
|
27
|
-
// TODO: Add duration as format:
|
|
28
|
-
endurance: { type: 'string', required: true, '@type': 'schema:Duration' },
|
|
29
|
-
dateCreated: { type: 'string', 'format': 'date-time', required: true },
|
|
30
|
-
bestRoundTime: { type: 'integer', required: true }
|
|
31
|
-
// difficultyLevel:
|
|
32
|
-
// enum:
|
|
33
|
-
// - EASY
|
|
34
|
-
// - MEDIUM
|
|
35
|
-
// - HARD
|
|
36
|
-
// required: true
|
|
37
|
-
}, 'VideoGameScore')
|
|
38
|
-
|
|
39
|
-
const CREDENTIAL_URI = `https://example.com/schema/${GAME_NAME}ScoreV1`
|
|
40
|
-
const SCHEMAS = [ playerSchema, videoGameSchema, videoGameScoreSchema ]
|
|
41
|
-
const factory = new CredentialFactory(CREDENTIAL_URI, SCHEMAS)
|
|
42
|
-
|
|
43
|
-
const createMineSweeperScoreCredential = (gameId, playerId, playerScore) => {
|
|
44
|
-
const credentialId = 'https://example.com/credentials/CREDENTIAL_ID'
|
|
45
|
-
|
|
46
|
-
const game = {
|
|
47
|
-
id: gameId,
|
|
48
|
-
name: GAME_NAME,
|
|
49
|
-
version: GAME_VERSION
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const player = {
|
|
53
|
-
id: playerId,
|
|
54
|
-
hasVideoGameScore: {
|
|
55
|
-
...playerScore,
|
|
56
|
-
game
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return factory.createCredential(credentialId, playerId, player)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
module.exports = createMineSweeperScoreCredential
|
package/examples/index.js
DELETED
package/src/CredentialFactory.js
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const Schema = require('./Schema')
|
|
4
|
-
const Validator = require('./Validator')
|
|
5
|
-
const validateId = require('./helpers/validateId')
|
|
6
|
-
const { constants } = require('credentials-context')
|
|
7
|
-
|
|
8
|
-
const { CREDENTIALS_CONTEXT_V1_URL } = constants
|
|
9
|
-
|
|
10
|
-
class CredentialFactory {
|
|
11
|
-
// TODO: Add exception when added two schemas with the same name.
|
|
12
|
-
constructor(uri, schemas) {
|
|
13
|
-
validateId('uri', uri)
|
|
14
|
-
|
|
15
|
-
this._types = [].concat(schemas).map(schema => {
|
|
16
|
-
if (schema.url) {
|
|
17
|
-
return schema
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return new Schema(schema, schema.id, uri)
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
this._uri = uri
|
|
24
|
-
this._context = {}
|
|
25
|
-
this._validator = new Validator(this._types)
|
|
26
|
-
|
|
27
|
-
for (const { id, linkedDataType } of this._types) {
|
|
28
|
-
this._context[id] = linkedDataType
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
get credentialType() {
|
|
33
|
-
const [ credentialType ] = this._uri.split('/').reverse()
|
|
34
|
-
|
|
35
|
-
return credentialType
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
get context() {
|
|
39
|
-
return {
|
|
40
|
-
[this.credentialType]: { '@id': this._uri },
|
|
41
|
-
...this._context
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
createCredential(id, holder, subject = {}) {
|
|
46
|
-
validateId('id', id)
|
|
47
|
-
validateId('holder', holder)
|
|
48
|
-
|
|
49
|
-
const type = [ 'VerifiableCredential', this.credentialType ]
|
|
50
|
-
|
|
51
|
-
const [ rootType ] = this._types
|
|
52
|
-
const credentialSubject = this._validator.validate(subject, rootType.id)
|
|
53
|
-
|
|
54
|
-
return {
|
|
55
|
-
'@context': [
|
|
56
|
-
CREDENTIALS_CONTEXT_V1_URL,
|
|
57
|
-
this.context
|
|
58
|
-
],
|
|
59
|
-
id,
|
|
60
|
-
type,
|
|
61
|
-
holder,
|
|
62
|
-
credentialSubject
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
module.exports = CredentialFactory
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const Schema = require('./Schema')
|
|
4
|
-
const { expect } = require('chai')
|
|
5
|
-
const { canonize } = require('jsonld')
|
|
6
|
-
const documentLoader = require('./ld/documentLoader')
|
|
7
|
-
const CredentialFactory = require('./CredentialFactory')
|
|
8
|
-
const {
|
|
9
|
-
createAccountCredential,
|
|
10
|
-
createMineSweeperScoreCredential
|
|
11
|
-
} = require('examples')
|
|
12
|
-
|
|
13
|
-
describe('CredentialFactory', () => {
|
|
14
|
-
describe('CredentialFactory.constructor(uri, schemas)', () => {
|
|
15
|
-
it('throws error if "uri" parameter is missing', () => {
|
|
16
|
-
expect(
|
|
17
|
-
() => new CredentialFactory()
|
|
18
|
-
).to.throw()
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
it('throws error if "uri" parameter is not a URL', () => {
|
|
22
|
-
expect(
|
|
23
|
-
() => new CredentialFactory('BAD_URL')
|
|
24
|
-
).to.throw()
|
|
25
|
-
})
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
describe('.createCredential(id, holder, subject = {}, subjectTypeId = null)', () => {
|
|
29
|
-
let factory
|
|
30
|
-
|
|
31
|
-
before(() => {
|
|
32
|
-
const videoGameSchema = new Schema({
|
|
33
|
-
id: {},
|
|
34
|
-
name: { type: 'string', required: true },
|
|
35
|
-
version: { type: 'string', required: true }
|
|
36
|
-
}, 'VideoGame', 'https://schema.org/')
|
|
37
|
-
|
|
38
|
-
factory = new CredentialFactory('https://example.com/StarCraft', videoGameSchema)
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
it('returns single schema based credential', async () => {
|
|
42
|
-
const credential = await createAccountCredential('did:PLAYER_ID', 'CAHTEP')
|
|
43
|
-
|
|
44
|
-
expect(credential).to.exist
|
|
45
|
-
await canonize(credential, { documentLoader })
|
|
46
|
-
|
|
47
|
-
const { credentialSubject: { createdAt } } = credential
|
|
48
|
-
expect(credential).to.eql({
|
|
49
|
-
'@context': [
|
|
50
|
-
'https://www.w3.org/2018/credentials/v1',
|
|
51
|
-
{
|
|
52
|
-
AccountV1: { '@id': 'https://example.com/schema/AccountV1' },
|
|
53
|
-
Account: {
|
|
54
|
-
'@id': 'https://example.com/schema/AccountV1#Account',
|
|
55
|
-
'@context': {
|
|
56
|
-
'@vocab': 'https://example.com/schema/AccountV1#',
|
|
57
|
-
'@version': 1.1,
|
|
58
|
-
'@protected': true,
|
|
59
|
-
schema: 'https://schema.org/',
|
|
60
|
-
username: { '@id': 'username' },
|
|
61
|
-
createdAt: { '@id': 'createdAt', '@type': 'schema:DateTime' },
|
|
62
|
-
dateOfBirth: { '@id': 'dateOfBirth', '@type': 'schema:Date' }
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
],
|
|
67
|
-
id: 'https://example.com/account/CAHTEP',
|
|
68
|
-
type: [ 'VerifiableCredential', 'AccountV1' ],
|
|
69
|
-
holder: 'did:PLAYER_ID',
|
|
70
|
-
credentialSubject: {
|
|
71
|
-
id: 'did:PLAYER_ID',
|
|
72
|
-
username: 'CAHTEP',
|
|
73
|
-
createdAt,
|
|
74
|
-
type: 'Account'
|
|
75
|
-
}
|
|
76
|
-
})
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
it('returns multiple schemas based credential', async () => {
|
|
80
|
-
const playerScore = {
|
|
81
|
-
wins: 5,
|
|
82
|
-
losses: 5,
|
|
83
|
-
winRate: 50,
|
|
84
|
-
UNDEFINED: 'VALUE',
|
|
85
|
-
bestScore: 23450,
|
|
86
|
-
endurance: 'P5M22S',
|
|
87
|
-
dateCreated: '2020-10-10T00:00:00Z',
|
|
88
|
-
bestRoundTime: 10000
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const credential = await createMineSweeperScoreCredential(
|
|
92
|
-
'did:GAME_ID',
|
|
93
|
-
'did:PLAYER_ID',
|
|
94
|
-
playerScore
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
expect(credential).to.exist
|
|
98
|
-
await canonize(credential, { documentLoader })
|
|
99
|
-
|
|
100
|
-
const { credentialSubject } = credential
|
|
101
|
-
expect(credentialSubject.type).to.equal('Player')
|
|
102
|
-
expect(credentialSubject.hasVideoGameScore.type).to.equal('VideoGameScore')
|
|
103
|
-
expect(credentialSubject.hasVideoGameScore.game.type).to.equal('VideoGame')
|
|
104
|
-
expect(credentialSubject.hasVideoGameScore.UNDEFINED).to.not.exist
|
|
105
|
-
|
|
106
|
-
const customContext = credential['@context'][1]
|
|
107
|
-
expect(customContext.VideoGame).to.eql({
|
|
108
|
-
'@id': 'https://schema.org/VideoGame',
|
|
109
|
-
'@context': {
|
|
110
|
-
'@protected': true,
|
|
111
|
-
'@version': 1.1,
|
|
112
|
-
'@vocab': 'https://schema.org/',
|
|
113
|
-
name: { '@id': 'name' },
|
|
114
|
-
version: { '@id': 'version' }
|
|
115
|
-
}
|
|
116
|
-
})
|
|
117
|
-
})
|
|
118
|
-
|
|
119
|
-
it('throws error if "id" parameter is missing', () => {
|
|
120
|
-
expect(
|
|
121
|
-
() => factory.createCredential()
|
|
122
|
-
).to.throw('Parameter "id" is required')
|
|
123
|
-
})
|
|
124
|
-
|
|
125
|
-
it('throws error if "holder" parameter is missing', () => {
|
|
126
|
-
expect(
|
|
127
|
-
() => factory.createCredential('did:CREDENTIAL_ID')
|
|
128
|
-
).to.throw('Parameter "holder" is required')
|
|
129
|
-
})
|
|
130
|
-
})
|
|
131
|
-
})
|
package/src/Schema.js
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { pick, cloneDeep } = require('lodash')
|
|
4
|
-
const validateId = require('./helpers/validateId')
|
|
5
|
-
const normalizeRequired = require('./helpers/normalizeRequired')
|
|
6
|
-
const normalizeProperties = require('./helpers/normalizeProperties')
|
|
7
|
-
const getLinkedDataContext = require('./ld/getLinkedDataContext')
|
|
8
|
-
const removeRequiredAndDefault = require('./helpers/removeRequiredAndDefault')
|
|
9
|
-
|
|
10
|
-
const UNDEFINED_SCHEMA_ID = 'UNDEFINED_SCHEMA_ID'
|
|
11
|
-
|
|
12
|
-
class Schema {
|
|
13
|
-
constructor(source = {}, id = UNDEFINED_SCHEMA_ID, url) {
|
|
14
|
-
this._id = id
|
|
15
|
-
this._url = url
|
|
16
|
-
this._source = source instanceof Schema ? source.source : source
|
|
17
|
-
|
|
18
|
-
if (url) {
|
|
19
|
-
validateId('url', url)
|
|
20
|
-
|
|
21
|
-
this._source.type = { required: true, type: 'string', default: id }
|
|
22
|
-
|
|
23
|
-
if (this._source.id) {
|
|
24
|
-
this._source.id = { required: true, type: 'string', format: 'url' }
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const uri =
|
|
28
|
-
(url.endsWith('/') || url.endsWith('#')) ? `${url}${id}` : `${url}#${id}`
|
|
29
|
-
|
|
30
|
-
this._linkedDataType = {
|
|
31
|
-
'@id': uri,
|
|
32
|
-
'@context': getLinkedDataContext(this._source, url)
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
normalizeProperties(this._source)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
get id() {
|
|
40
|
-
return this._id
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
get url() {
|
|
44
|
-
return this._url
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
get source() {
|
|
48
|
-
return cloneDeep(this._source)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
get jsonSchema() {
|
|
52
|
-
if (this._source.enum) {
|
|
53
|
-
return {
|
|
54
|
-
id: this._id,
|
|
55
|
-
...this.source
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const jsonSchema = {
|
|
60
|
-
id: this._id,
|
|
61
|
-
type: 'object',
|
|
62
|
-
properties: this.source
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
normalizeRequired(jsonSchema)
|
|
66
|
-
|
|
67
|
-
return jsonSchema
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
get linkedDataType() {
|
|
71
|
-
return this._linkedDataType
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
clone(id) {
|
|
75
|
-
return new Schema(this.source, id)
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
pure(id) {
|
|
79
|
-
const { properties: source } = removeRequiredAndDefault({ properties: this.source })
|
|
80
|
-
return new Schema(source, id)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
only(propertyNames, id) {
|
|
84
|
-
const source = pick(this.source, propertyNames)
|
|
85
|
-
return new Schema(source, id)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
extend(properties, id) {
|
|
89
|
-
return new Schema({ ...this.source, ...properties }, id)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
wrap(propertyName, options = { required: true }, id) {
|
|
93
|
-
const source = {
|
|
94
|
-
[propertyName]: {
|
|
95
|
-
properties: this.source,
|
|
96
|
-
...options
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return new Schema(source, id)
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
module.exports = Schema
|