@datasworn-community/build-tools 0.2.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 +17 -0
- package/dist/cli/args.d.ts +3 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +10 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/datasworn-build.d.ts +3 -0
- package/dist/cli/datasworn-build.d.ts.map +1 -0
- package/dist/cli/datasworn-build.js +33 -0
- package/dist/cli/datasworn-build.js.map +1 -0
- package/dist/cli/datasworn-migrate.d.ts +3 -0
- package/dist/cli/datasworn-migrate.d.ts.map +1 -0
- package/dist/cli/datasworn-migrate.js +26 -0
- package/dist/cli/datasworn-migrate.js.map +1 -0
- package/dist/config.d.ts +3 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +10 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/rules-package-builder.d.ts +22 -0
- package/dist/rules-package-builder.d.ts.map +1 -0
- package/dist/rules-package-builder.js +84 -0
- package/dist/rules-package-builder.js.map +1 -0
- package/dist/schema.d.ts +8 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +18 -0
- package/dist/schema.js.map +1 -0
- package/dist/validators.d.ts +8 -0
- package/dist/validators.d.ts.map +1 -0
- package/dist/validators.js +35 -0
- package/dist/validators.js.map +1 -0
- package/package.json +60 -0
- package/schema-source/schema/Assets.ts +66 -0
- package/schema-source/schema/Atlas.ts +20 -0
- package/schema-source/schema/Defs.ts +126 -0
- package/schema-source/schema/DelveSites.ts +3 -0
- package/schema-source/schema/Entities.ts +1 -0
- package/schema-source/schema/Generic.ts +18 -0
- package/schema-source/schema/Moves.ts +1 -0
- package/schema-source/schema/Npcs.ts +80 -0
- package/schema-source/schema/Oracles.ts +20 -0
- package/schema-source/schema/Rarities.ts +36 -0
- package/schema-source/schema/Root.ts +94 -0
- package/schema-source/schema/Rules.ts +61 -0
- package/schema-source/schema/RulesPackages.ts +135 -0
- package/schema-source/schema/Symbols.ts +30 -0
- package/schema-source/schema/Truths.ts +53 -0
- package/schema-source/schema/Utils.ts +21 -0
- package/schema-source/schema/assets/Ability.ts +79 -0
- package/schema-source/schema/assets/Enhancement.ts +62 -0
- package/schema-source/schema/assets/Fields.ts +285 -0
- package/schema-source/schema/assets/common.ts +29 -0
- package/schema-source/schema/common/Fields.ts +327 -0
- package/schema-source/schema/common/Id.ts +64 -0
- package/schema-source/schema/common/Inputs.ts +374 -0
- package/schema-source/schema/common/Metadata.ts +142 -0
- package/schema-source/schema/common/Player.ts +17 -0
- package/schema-source/schema/common/Progress.ts +63 -0
- package/schema-source/schema/common/Range.ts +53 -0
- package/schema-source/schema/common/RollableValues.ts +152 -0
- package/schema-source/schema/common/Rolls.ts +108 -0
- package/schema-source/schema/common/Text.ts +95 -0
- package/schema-source/schema/common/index.ts +16 -0
- package/schema-source/schema/delve/DelveSite.ts +121 -0
- package/schema-source/schema/delve/DelveSiteDomain.ts +136 -0
- package/schema-source/schema/delve/DelveSiteTheme.ts +97 -0
- package/schema-source/schema/delve/common.ts +32 -0
- package/schema-source/schema/entities/EntityPrompt.ts +13 -0
- package/schema-source/schema/entities/index.ts +1 -0
- package/schema-source/schema/generic/CollectableNode.ts +75 -0
- package/schema-source/schema/generic/CollectionNode.ts +145 -0
- package/schema-source/schema/generic/Dictionary.ts +39 -0
- package/schema-source/schema/generic/EmbedOnlyNode.ts +19 -0
- package/schema-source/schema/generic/Enhance.ts +38 -0
- package/schema-source/schema/generic/IdNode.ts +40 -0
- package/schema-source/schema/generic/Mixin.ts +11 -0
- package/schema-source/schema/generic/NonCollectableNode.ts +38 -0
- package/schema-source/schema/generic/PrimaryTypeNode.ts +115 -0
- package/schema-source/schema/generic/SourcedNode.ts +51 -0
- package/schema-source/schema/index.ts +23 -0
- package/schema-source/schema/moves/ActionRoll.ts +152 -0
- package/schema-source/schema/moves/EmbeddedMove.ts +24 -0
- package/schema-source/schema/moves/Move.ts +26 -0
- package/schema-source/schema/moves/MoveCategory.ts +6 -0
- package/schema-source/schema/moves/MoveEnhancement.ts +29 -0
- package/schema-source/schema/moves/ProgressRoll.ts +184 -0
- package/schema-source/schema/moves/Trigger.ts +193 -0
- package/schema-source/schema/moves/common.ts +136 -0
- package/schema-source/schema/moves/index.ts +13 -0
- package/schema-source/schema/moves/utils.ts +132 -0
- package/schema-source/schema/object_type/ObjectType.ts +23 -0
- package/schema-source/schema/oracles/EmbeddedOracleRollable.ts +28 -0
- package/schema-source/schema/oracles/OracleCollection.ts +140 -0
- package/schema-source/schema/oracles/OracleRollable.ts +207 -0
- package/schema-source/schema/oracles/Table.ts +94 -0
- package/schema-source/schema/oracles/TableRow.ts +141 -0
- package/schema-source/schema/root/NiceSchema.ts +15 -0
- package/schema-source/schema/root/Root.ts +41 -0
- package/schema-source/schema/root/SchemaTransform.ts +89 -0
- package/schema-source/schema/root/SourceData.ts +151 -0
- package/schema-source/schema/rules/ConditionMeterRule.ts +25 -0
- package/schema-source/schema/rules/ImpactRule.ts +54 -0
- package/schema-source/schema/rules/SpecialTrackRule.ts +29 -0
- package/schema-source/schema/rules/StatRule.ts +23 -0
- package/schema-source/schema/rules/TagRule.ts +176 -0
- package/schema-source/schema/rules/TagSchema.ts +161 -0
- package/schema-source/schema/tags/canonicalTags.ts +29 -0
- package/schema-source/schema/tools/build/index.ts +48 -0
- package/schema-source/schema/tools/i18n/index.ts +9 -0
- package/schema-source/schema/utils/Computed.ts +82 -0
- package/schema-source/schema/utils/DiscriminatedUnion.ts +255 -0
- package/schema-source/schema/utils/EmbeddedNode.ts +172 -0
- package/schema-source/schema/utils/ExtractLiteralFromEnum.ts +22 -0
- package/schema-source/schema/utils/FlatIntersect.ts +107 -0
- package/schema-source/schema/utils/IfThen.ts +50 -0
- package/schema-source/schema/utils/MergeEnumSchemas.ts +16 -0
- package/schema-source/schema/utils/NonNullable.ts +6 -0
- package/schema-source/schema/utils/Nullable.ts +29 -0
- package/schema-source/schema/utils/ObjectLiteral.ts +16 -0
- package/schema-source/schema/utils/ObjectProperties.ts +4 -0
- package/schema-source/schema/utils/OmitMeta.ts +22 -0
- package/schema-source/schema/utils/OmitOptional.ts +27 -0
- package/schema-source/schema/utils/PartialExcept.ts +26 -0
- package/schema-source/schema/utils/SetNullable.ts +44 -0
- package/schema-source/schema/utils/SetOptional.ts +48 -0
- package/schema-source/schema/utils/UnionEnum.ts +82 -0
- package/schema-source/schema/utils/UnionEnumFromRecord.ts +36 -0
- package/schema-source/schema/utils/UnionOneOf.ts +80 -0
- package/schema-source/schema/utils/generateRulesetSchemas.ts +204 -0
- package/schema-source/schema/utils/string.ts +15 -0
- package/schema-source/schema/utils/typebox.ts +141 -0
- package/schema-source/scripts/const.ts +55 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { type Static, Type } from '@sinclair/typebox'
|
|
2
|
+
import TypeId from '../../pkg-core/IdElements/TypeId.js'
|
|
3
|
+
import JtdType from '../../scripts/json-typedef/typedef.js'
|
|
4
|
+
import Id, { RulesetId } from '../common/Id.js'
|
|
5
|
+
import { DiceExpression } from '../common/Rolls.js'
|
|
6
|
+
import { Dictionary } from '../generic/Dictionary.js'
|
|
7
|
+
import { JsonTypeDef } from '../Symbols.js'
|
|
8
|
+
import { Nullable, UnionEnum } from '../Utils.js'
|
|
9
|
+
import { type PascalCase, pascalCase } from '../utils/string.js'
|
|
10
|
+
import { TagSchema } from './TagSchema.js'
|
|
11
|
+
|
|
12
|
+
type _NodeSchemaName<T extends string> = PascalCase<T>
|
|
13
|
+
type EmbeddedNodeSchemaName<T extends string> = `Embedded${PascalCase<T>}`
|
|
14
|
+
type IdSchemaName<T extends string> = `${PascalCase<T>}Id`
|
|
15
|
+
type WildcardIdSchemaName<T extends string> = `${PascalCase<T>}IdWildcard`
|
|
16
|
+
|
|
17
|
+
function getNodeSchemaName<T extends string>(typeId: T) {
|
|
18
|
+
return pascalCase(typeId)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function getEmbeddedNodeSchemaName<T extends string>(typeId: T) {
|
|
22
|
+
return `Embedded${pascalCase(typeId)}` as EmbeddedNodeSchemaName<T>
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function getIdSchemaName<T extends string>(typeId: T) {
|
|
26
|
+
return `${pascalCase(typeId)}Id` as IdSchemaName<T>
|
|
27
|
+
}
|
|
28
|
+
function getWildcardIdSchemaName<T extends string>(typeId: T) {
|
|
29
|
+
return `${pascalCase(typeId)}IdWildcard` as WildcardIdSchemaName<T>
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const AnyPrimary = TypeId.Primary.map(getNodeSchemaName)
|
|
33
|
+
|
|
34
|
+
const _EmbedOnly = TypeId.EmbedOnly.map(getNodeSchemaName)
|
|
35
|
+
const _EmbeddedPrimary = TypeId.EmbeddablePrimary.map(getEmbeddedNodeSchemaName)
|
|
36
|
+
|
|
37
|
+
// TODO: could this be generated by iterating over objects and picking the ones with `tags` properties?
|
|
38
|
+
const AnyPrimaryId = AnyPrimary.map(getIdSchemaName)
|
|
39
|
+
const AnyPrimaryIdWildcard = AnyPrimary.map(getWildcardIdSchemaName)
|
|
40
|
+
|
|
41
|
+
export const CollectionType = UnionEnum<typeof TypeId.Collection>(
|
|
42
|
+
TypeId.Collection,
|
|
43
|
+
{
|
|
44
|
+
$id: 'CollectionType'
|
|
45
|
+
}
|
|
46
|
+
)
|
|
47
|
+
export type CollectionType = Static<typeof CollectionType>
|
|
48
|
+
|
|
49
|
+
export const CollectableType = UnionEnum(TypeId.Collectable, {
|
|
50
|
+
$id: 'CollectableType'
|
|
51
|
+
})
|
|
52
|
+
export type CollectableType = Static<typeof CollectableType>
|
|
53
|
+
|
|
54
|
+
export const NonCollectableType = UnionEnum(TypeId.NonCollectable, {
|
|
55
|
+
$id: 'NonCollectableType'
|
|
56
|
+
})
|
|
57
|
+
export type NonCollectableType = Static<typeof NonCollectableType>
|
|
58
|
+
|
|
59
|
+
export const EmbedOnlyType = UnionEnum(TypeId.EmbedOnly, {
|
|
60
|
+
$id: 'EmbedOnlyType'
|
|
61
|
+
})
|
|
62
|
+
export type EmbedOnlyType = Static<typeof EmbedOnlyType>
|
|
63
|
+
|
|
64
|
+
export const RuleType = UnionEnum(
|
|
65
|
+
['impact', 'condition_meter', 'special_track', 'stat'],
|
|
66
|
+
{ $id: 'RuleType' }
|
|
67
|
+
)
|
|
68
|
+
export type RuleType = Static<typeof RuleType>
|
|
69
|
+
|
|
70
|
+
export const TaggableNodeType = Type.Union(
|
|
71
|
+
[
|
|
72
|
+
Type.Ref(CollectableType),
|
|
73
|
+
Type.Ref(NonCollectableType),
|
|
74
|
+
Type.Ref(CollectionType),
|
|
75
|
+
Type.Ref(EmbedOnlyType),
|
|
76
|
+
Type.Ref(RuleType)
|
|
77
|
+
],
|
|
78
|
+
{
|
|
79
|
+
[JsonTypeDef]: {
|
|
80
|
+
schema: JtdType.Enum([
|
|
81
|
+
...TypeId.Primary,
|
|
82
|
+
...TypeId.EmbedOnly,
|
|
83
|
+
'impact',
|
|
84
|
+
'condition_meter',
|
|
85
|
+
'special_track',
|
|
86
|
+
'stat'
|
|
87
|
+
])
|
|
88
|
+
},
|
|
89
|
+
$id: 'TaggableNodeType'
|
|
90
|
+
}
|
|
91
|
+
)
|
|
92
|
+
export type TaggableNodeType = Static<typeof TaggableNodeType>
|
|
93
|
+
|
|
94
|
+
export { TagSchema }
|
|
95
|
+
|
|
96
|
+
export const TagRule = Type.Object(
|
|
97
|
+
{
|
|
98
|
+
node_types: Nullable(Type.Array(Type.Ref(TaggableNodeType)), {
|
|
99
|
+
description:
|
|
100
|
+
'Types of object that can receive this tag, or `null` if any type of object accepts it.',
|
|
101
|
+
default: null
|
|
102
|
+
}),
|
|
103
|
+
$schema: Type.Ref(TagSchema, {
|
|
104
|
+
description: 'The JSON schema for this tag value.'
|
|
105
|
+
})
|
|
106
|
+
},
|
|
107
|
+
{ $id: 'TagRule' }
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
// export const TagRule = DiscriminatedUnion(typedTags, 'value_type', {
|
|
111
|
+
// $id: 'TagRule'
|
|
112
|
+
// })
|
|
113
|
+
export type TagRule = Static<typeof TagRule>
|
|
114
|
+
|
|
115
|
+
const TagValueNonId = [
|
|
116
|
+
Type.Boolean(),
|
|
117
|
+
Type.Integer(),
|
|
118
|
+
Type.Ref(Id.DictKey), // from enums
|
|
119
|
+
Type.Ref(DiceExpression)
|
|
120
|
+
]
|
|
121
|
+
|
|
122
|
+
export const Tag = Type.Union(
|
|
123
|
+
[
|
|
124
|
+
...TagValueNonId,
|
|
125
|
+
...AnyPrimaryId.map((type) => Type.Ref(type)),
|
|
126
|
+
Type.Array(
|
|
127
|
+
Type.Union([
|
|
128
|
+
// Type.Ref(Id.DictKey), // from enums
|
|
129
|
+
// Type.Ref(Rolls.DiceExpression),
|
|
130
|
+
...AnyPrimaryIdWildcard.map((type) => Type.Ref(type))
|
|
131
|
+
])
|
|
132
|
+
)
|
|
133
|
+
],
|
|
134
|
+
{ $id: 'Tag', [JsonTypeDef]: { schema: JtdType.Any() as any } }
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
export const Tags = Type.Record(
|
|
138
|
+
RulesetId,
|
|
139
|
+
Dictionary(Type.Ref('Tag'), { title: 'RulesPackageTags' }),
|
|
140
|
+
{
|
|
141
|
+
releaseStage: 'experimental',
|
|
142
|
+
$id: 'Tags',
|
|
143
|
+
key: Id.RulesetId.pattern,
|
|
144
|
+
description:
|
|
145
|
+
'A dictionary of tags, keyed by the RulesPackageId that the tags are from.'
|
|
146
|
+
}
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
export const CoreTags = Type.Object(
|
|
150
|
+
{
|
|
151
|
+
supernatural: Type.Optional(
|
|
152
|
+
Type.Boolean({
|
|
153
|
+
description:
|
|
154
|
+
'This object is supernatural in nature, and is ideal for settings that feature supernatural or mythic powers.'
|
|
155
|
+
})
|
|
156
|
+
),
|
|
157
|
+
technological: Type.Optional(
|
|
158
|
+
Type.Boolean({
|
|
159
|
+
description:
|
|
160
|
+
'This object is technological in nature, and is ideal for settings that feature remarkable technologies.'
|
|
161
|
+
})
|
|
162
|
+
),
|
|
163
|
+
requires_allies: Type.Optional(
|
|
164
|
+
Type.Boolean({
|
|
165
|
+
description:
|
|
166
|
+
'This object requires allies to function, and is intended for co-op play, or guided play with allies. It is not appropriate for solo play.'
|
|
167
|
+
})
|
|
168
|
+
)
|
|
169
|
+
},
|
|
170
|
+
{ $id: 'CoreTags' }
|
|
171
|
+
)
|
|
172
|
+
const coreNamespaceId = '_core' as const
|
|
173
|
+
|
|
174
|
+
Tags.properties = {
|
|
175
|
+
[coreNamespaceId]: Type.Optional(Type.Ref(CoreTags))
|
|
176
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { type TSchema, Type } from '@sinclair/typebox'
|
|
2
|
+
import type { JSONSchema7 } from 'json-schema'
|
|
3
|
+
import { $schema } from '../../scripts/const.js'
|
|
4
|
+
import JtdType from '../../scripts/json-typedef/typedef.js'
|
|
5
|
+
import { DictKey } from '../common/Id.js'
|
|
6
|
+
import { JsonTypeDef, Typescript } from '../Symbols.js'
|
|
7
|
+
|
|
8
|
+
const validSchemaTypes = [
|
|
9
|
+
'boolean',
|
|
10
|
+
'integer',
|
|
11
|
+
'number',
|
|
12
|
+
'string',
|
|
13
|
+
'null'
|
|
14
|
+
] satisfies JSONSchema7['type']
|
|
15
|
+
|
|
16
|
+
export function isValidTagSchema(schema: TSchema) {
|
|
17
|
+
if (validSchemaTypes.includes(schema?.type)) return true
|
|
18
|
+
// some IDs are union schemas, these are fine
|
|
19
|
+
if (schema.$id?.endsWith('Id') || schema.$id?.endsWith('IdWildcard'))
|
|
20
|
+
return true
|
|
21
|
+
if ('enum' in schema) return true
|
|
22
|
+
if ('const' in schema) return true
|
|
23
|
+
if ('anyOf' in schema)
|
|
24
|
+
return (schema.anyOf as TSchema[]).every(isValidTagSchema)
|
|
25
|
+
|
|
26
|
+
return false
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const TagSchemaInteger = Type.Object(
|
|
30
|
+
{ type: Type.Const('integer') },
|
|
31
|
+
{ title: 'TagSchemaInteger', additionalProperties: true }
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
const TagSchemaFloat = Type.Object(
|
|
35
|
+
{
|
|
36
|
+
type: Type.Const('number')
|
|
37
|
+
},
|
|
38
|
+
{ title: 'TagSchemaFloat', additionalProperties: true }
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
const TagSchemaStringEnum = Type.Object(
|
|
42
|
+
{
|
|
43
|
+
enum: Type.Array(Type.Ref(DictKey))
|
|
44
|
+
},
|
|
45
|
+
{ title: 'TagSchemaStringEnum', additionalProperties: true }
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
const TagSchemaIntegerEnum = Type.Object(
|
|
49
|
+
{
|
|
50
|
+
enum: Type.Array(Type.Integer())
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
title: 'TagSchemaIntegerEnum',
|
|
54
|
+
additionalProperties: true
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
const TagSchemaBoolean = Type.Object(
|
|
59
|
+
{
|
|
60
|
+
type: Type.Const('boolean')
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
description: 'Schema for a true or false value.',
|
|
64
|
+
title: 'TagSchemaBoolean',
|
|
65
|
+
additionalProperties: true
|
|
66
|
+
}
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
const TagSchemaDataswornRef = Type.Object(
|
|
70
|
+
{
|
|
71
|
+
$ref: Type.Any()
|
|
72
|
+
// this a placeholder value.
|
|
73
|
+
// an enum is computed from all datasworn schemata at build time.
|
|
74
|
+
},
|
|
75
|
+
{ title: 'TagSchemaDataswornRef', additionalProperties: true }
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
// future additions - nested objects?
|
|
79
|
+
|
|
80
|
+
const _schemaKeyBlacklist = [
|
|
81
|
+
'$id',
|
|
82
|
+
'$defs',
|
|
83
|
+
'$schema',
|
|
84
|
+
'definitions',
|
|
85
|
+
'dependencies',
|
|
86
|
+
'if',
|
|
87
|
+
'then',
|
|
88
|
+
'else',
|
|
89
|
+
'allOf',
|
|
90
|
+
'anyOf',
|
|
91
|
+
'oneOf',
|
|
92
|
+
'not',
|
|
93
|
+
'additionalItems',
|
|
94
|
+
'additionalProperties'
|
|
95
|
+
] as const satisfies (keyof JSONSchema7)[]
|
|
96
|
+
|
|
97
|
+
// set here to use as a forward reference
|
|
98
|
+
const TagSchemaId = 'TagSchema' as const
|
|
99
|
+
|
|
100
|
+
const TagSchemaObject = Type.Object(
|
|
101
|
+
{
|
|
102
|
+
type: Type.Const('object'),
|
|
103
|
+
properties: Type.Record(DictKey, Type.Ref(TagSchemaId))
|
|
104
|
+
//
|
|
105
|
+
},
|
|
106
|
+
{ title: 'TagSchemaObject', additionalProperties: true }
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
const TagSchemaArray = Type.Object(
|
|
110
|
+
{
|
|
111
|
+
type: Type.Const('array'),
|
|
112
|
+
items: Type.Ref(TagSchemaId)
|
|
113
|
+
//
|
|
114
|
+
},
|
|
115
|
+
{ title: 'TagSchemaArray', additionalProperties: true }
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
export const TagSchema = Type.Intersect(
|
|
119
|
+
[
|
|
120
|
+
Type.Union([
|
|
121
|
+
TagSchemaDataswornRef as TSchema,
|
|
122
|
+
// enumerations
|
|
123
|
+
TagSchemaStringEnum,
|
|
124
|
+
TagSchemaIntegerEnum,
|
|
125
|
+
// primitives
|
|
126
|
+
TagSchemaBoolean,
|
|
127
|
+
TagSchemaInteger,
|
|
128
|
+
TagSchemaFloat,
|
|
129
|
+
// basic string schema intentionally omitted -- strings must be one of datasworn's subtypes or an enum.
|
|
130
|
+
TagSchemaObject,
|
|
131
|
+
TagSchemaArray
|
|
132
|
+
]),
|
|
133
|
+
Type.Ref($schema)
|
|
134
|
+
// Type.Not(
|
|
135
|
+
// Type.Record(
|
|
136
|
+
// Type.Enum(Object.fromEntries(schemaKeyBlacklist.map((v) => [v, v]))),
|
|
137
|
+
// Type.Any()
|
|
138
|
+
// )
|
|
139
|
+
// )
|
|
140
|
+
],
|
|
141
|
+
{
|
|
142
|
+
$id: TagSchemaId,
|
|
143
|
+
// TODO: JTD schema for JSON schema of JSON schema? :sob:
|
|
144
|
+
[JsonTypeDef]: { schema: JtdType.Any() as any },
|
|
145
|
+
// TODO: add json schema type stub lib as dependency; point at this type
|
|
146
|
+
[Typescript]: (identifier: string, _schema: TSchema) =>
|
|
147
|
+
`export type ${identifier} = Record<string, unknown>`,
|
|
148
|
+
description:
|
|
149
|
+
'JSON schema used to validate the tag data, with a mandatory description. Only a subset of all possible JSON schema are allowed, including references to some Datasworn types.',
|
|
150
|
+
releaseStage: 'experimental',
|
|
151
|
+
examples: [
|
|
152
|
+
Type.Boolean({
|
|
153
|
+
description: 'An example tag with a simple true/false value.'
|
|
154
|
+
}),
|
|
155
|
+
Type.Array(Type.Ref('OracleRollableIdWildcard'), {
|
|
156
|
+
description:
|
|
157
|
+
'An example tag with an array of oracle rollable ID wildcards.'
|
|
158
|
+
})
|
|
159
|
+
]
|
|
160
|
+
}
|
|
161
|
+
)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type TSchema, Type } from '@sinclair/typebox'
|
|
2
|
+
import { UnionEnum } from '../Utils.js'
|
|
3
|
+
|
|
4
|
+
const _TagsClassic = {}
|
|
5
|
+
const _TagsStarforged = {
|
|
6
|
+
recommended: Type.Boolean({
|
|
7
|
+
description: 'This object is ideal for use in Starforged.'
|
|
8
|
+
})
|
|
9
|
+
} satisfies Record<string, TSchema>
|
|
10
|
+
const _TagsDelve = {} satisfies Record<string, TSchema>
|
|
11
|
+
type _TagParams = {
|
|
12
|
+
schema: TSchema
|
|
13
|
+
node_types: []
|
|
14
|
+
}
|
|
15
|
+
const _TagsSunderedIsles = {
|
|
16
|
+
recommended: Type.Boolean({
|
|
17
|
+
description: 'This object is ideal for use in Sundered Isles.'
|
|
18
|
+
}),
|
|
19
|
+
cursed_version_of: Type.Array(Type.Ref('OracleRollableIdWildcard')),
|
|
20
|
+
// wrap these into their own objects: "cursed" and "curses"?
|
|
21
|
+
curse_behavior: Type.Array(UnionEnum(['replace_result', 'add_result'])),
|
|
22
|
+
cursed_by: Type.Array(Type.String()),
|
|
23
|
+
region: UnionEnum(['myriads', 'margins', 'reaches'])
|
|
24
|
+
// overland_region
|
|
25
|
+
// location
|
|
26
|
+
// faction_type
|
|
27
|
+
// ship_size
|
|
28
|
+
// treasure_size
|
|
29
|
+
} satisfies Record<string, TSchema>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type Static, Type } from '@sinclair/typebox'
|
|
2
|
+
import {
|
|
3
|
+
PKG_SCOPE_COMMUNITY,
|
|
4
|
+
PKG_SCOPE_OFFICIAL
|
|
5
|
+
} from '../../../scripts/const.js'
|
|
6
|
+
import { UnionEnumFromRecord } from '../../utils/UnionEnumFromRecord.js'
|
|
7
|
+
|
|
8
|
+
export const RulesPackageConfig = Type.Object({
|
|
9
|
+
id: Type.String({
|
|
10
|
+
description:
|
|
11
|
+
'The namespace ID for this data set. This is the first path element of all its object IDs.'
|
|
12
|
+
}),
|
|
13
|
+
description: Type.Optional(Type.String()),
|
|
14
|
+
type: Type.Union([Type.Literal('ruleset'), Type.Literal('expansion')]),
|
|
15
|
+
pkg: Type.Object({
|
|
16
|
+
name: Type.String({
|
|
17
|
+
description: 'The package ID, not including its scope (see `scope`).'
|
|
18
|
+
}),
|
|
19
|
+
private: Type.Boolean({ default: false }),
|
|
20
|
+
description: Type.String(),
|
|
21
|
+
keywords: Type.Array(Type.String()),
|
|
22
|
+
authors: Type.Array(
|
|
23
|
+
Type.Object({
|
|
24
|
+
name: Type.String(),
|
|
25
|
+
email: Type.String({ format: 'email' }),
|
|
26
|
+
url: Type.String({ format: 'uri' })
|
|
27
|
+
})
|
|
28
|
+
),
|
|
29
|
+
scope: UnionEnumFromRecord(
|
|
30
|
+
{
|
|
31
|
+
[PKG_SCOPE_OFFICIAL]: 'Official Ironsworn content.',
|
|
32
|
+
[PKG_SCOPE_COMMUNITY]:
|
|
33
|
+
'Ironsworn-compatible content from third parties.'
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
description: 'The namespace or scope used by the package.',
|
|
37
|
+
default: PKG_SCOPE_COMMUNITY
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
}),
|
|
41
|
+
paths: Type.Object({
|
|
42
|
+
source: Type.String(),
|
|
43
|
+
assets: Type.Optional(Type.Array(Type.String()))
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
// TODO: configure more of package construction from here, e.g. content of package.json
|
|
47
|
+
})
|
|
48
|
+
export type RulesPackageConfig = Static<typeof RulesPackageConfig>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type Static, Type } from '@sinclair/typebox'
|
|
2
|
+
|
|
3
|
+
export const Term = Type.Object({
|
|
4
|
+
context: Type.String(),
|
|
5
|
+
value: Type.Union([Type.String(), Type.Null()]),
|
|
6
|
+
source: Type.Array(Type.String()),
|
|
7
|
+
markdown: Type.Boolean(),
|
|
8
|
+
})
|
|
9
|
+
export type Term = Static<typeof Term>
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CloneType,
|
|
3
|
+
type SchemaOptions,
|
|
4
|
+
type Static,
|
|
5
|
+
type TObject,
|
|
6
|
+
type TSchema
|
|
7
|
+
} from '@sinclair/typebox'
|
|
8
|
+
|
|
9
|
+
/** Symbol indicating that this property is computed at build time, and is therefore optional in DataswornSource */
|
|
10
|
+
export const ComputedPropertyBrand = Symbol('ComputedProperty')
|
|
11
|
+
|
|
12
|
+
type ComputedOptions<
|
|
13
|
+
T extends TSchema,
|
|
14
|
+
ParentObject extends TObject
|
|
15
|
+
> = SchemaOptions & {
|
|
16
|
+
[ComputedPropertyBrand]:
|
|
17
|
+
| 'ComputedProperty'
|
|
18
|
+
| ComputedPropertyFn<T, ParentObject>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Create a schema that is computed at build time, and is therefore optional in DataswornSource */
|
|
22
|
+
// TODO: make it possible for this to supply a function that computes the property!
|
|
23
|
+
export function Computed<
|
|
24
|
+
T extends TSchema,
|
|
25
|
+
ParentObject extends TObject = TObject
|
|
26
|
+
>(
|
|
27
|
+
schema: T,
|
|
28
|
+
options: ComputedOptions<T, ParentObject> = {
|
|
29
|
+
[ComputedPropertyBrand]: 'ComputedProperty'
|
|
30
|
+
}
|
|
31
|
+
) {
|
|
32
|
+
return CloneType(schema, {
|
|
33
|
+
...options
|
|
34
|
+
}) as TComputed<T, ParentObject>
|
|
35
|
+
}
|
|
36
|
+
export type TComputed<
|
|
37
|
+
T extends TSchema,
|
|
38
|
+
ParentObject extends TObject = TObject
|
|
39
|
+
> = T & {
|
|
40
|
+
[ComputedPropertyBrand]:
|
|
41
|
+
| 'ComputedProperty'
|
|
42
|
+
| ComputedPropertyFn<T, ParentObject>
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
type ComputedPropertyFn<T extends TSchema, ParentObject extends TObject> = (
|
|
46
|
+
object: Static<ParentObject>,
|
|
47
|
+
property: string,
|
|
48
|
+
pointer: string
|
|
49
|
+
) => Static<T>
|
|
50
|
+
|
|
51
|
+
/** Symbol indicating that this property is optional in DataswornSource */
|
|
52
|
+
export const SourceOptionalBrand = Symbol('SourceOptional')
|
|
53
|
+
|
|
54
|
+
/** Flags a schema as being optional in DataswornSource. Mutates the original schema.
|
|
55
|
+
* @remarks Functionally similar to {@link Computed}, but with different semantics.
|
|
56
|
+
*/
|
|
57
|
+
export function setSourceOptional<T extends TSchema>(schema: T) {
|
|
58
|
+
if (schema == null) return schema
|
|
59
|
+
;(schema as TSourceOptional<T>)[SourceOptionalBrand] = 'SourceOptional'
|
|
60
|
+
return schema as TSourceOptional<T>
|
|
61
|
+
}
|
|
62
|
+
export type TSourceOptional<T extends TSchema> = T & {
|
|
63
|
+
[SourceOptionalBrand]: 'SourceOptional'
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export const GetSourceDataSchema = Symbol('GetSourceDataSchema')
|
|
67
|
+
|
|
68
|
+
/** Provide an override value */
|
|
69
|
+
export function setSourceDataSchema<
|
|
70
|
+
T extends TSchema,
|
|
71
|
+
SourceSchema extends TSchema
|
|
72
|
+
>(schema: T, sourceSchema: SourceSchema | ((schema: T) => SourceSchema)): T {
|
|
73
|
+
// @ts-expect-error
|
|
74
|
+
schema[GetSourceDataSchema] =
|
|
75
|
+
typeof sourceSchema === 'function' ? sourceSchema : () => sourceSchema
|
|
76
|
+
|
|
77
|
+
return schema as THasSourceSchema<T, SourceSchema>
|
|
78
|
+
}
|
|
79
|
+
export type THasSourceSchema<
|
|
80
|
+
T extends TSchema = TSchema,
|
|
81
|
+
SourceSchema extends TSchema = TSchema
|
|
82
|
+
> = T & { [GetSourceDataSchema]: (schema: T) => SourceSchema }
|