@taskeren/bungie-api-ts 5.10.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/.babelrc +4 -0
- package/.gitattributes +2 -0
- package/.github/workflows/pr-build.yml +50 -0
- package/.github/workflows/publish.yml +48 -0
- package/.github/workflows/update.yml +55 -0
- package/.gitmodules +3 -0
- package/.nvmrc +1 -0
- package/.prettierrc +10 -0
- package/.vscode/extensions.json +8 -0
- package/.vscode/settings.json +7 -0
- package/LICENSE.md +21 -0
- package/README.md +97 -0
- package/api-src/.github/workflows/close-inactive.yml +24 -0
- package/api-src/CHANGELOG.md +271 -0
- package/api-src/CONTRIBUTING.md +19 -0
- package/api-src/LICENSE +28 -0
- package/api-src/README.md +378 -0
- package/api-src/openapi-2.json +44518 -0
- package/api-src/openapi.json +46467 -0
- package/build.sh +30 -0
- package/bungie-api-LICENSE +29 -0
- package/generated-src/app/api.ts +50 -0
- package/generated-src/app/index.ts +17 -0
- package/generated-src/app/interfaces.ts +119 -0
- package/generated-src/common.ts +985 -0
- package/generated-src/communitycontent/api.ts +36 -0
- package/generated-src/communitycontent/index.ts +16 -0
- package/generated-src/content/api.ts +142 -0
- package/generated-src/content/index.ts +17 -0
- package/generated-src/content/interfaces.ts +225 -0
- package/generated-src/core/api.ts +57 -0
- package/generated-src/core/index.ts +17 -0
- package/generated-src/core/interfaces.ts +151 -0
- package/generated-src/destiny2/api.ts +821 -0
- package/generated-src/destiny2/index.ts +17 -0
- package/generated-src/destiny2/interfaces.ts +15714 -0
- package/generated-src/destiny2/manifest.ts +341 -0
- package/generated-src/fireteam/api.ts +151 -0
- package/generated-src/fireteam/index.ts +17 -0
- package/generated-src/fireteam/interfaces.ts +183 -0
- package/generated-src/forum/api.ts +197 -0
- package/generated-src/forum/index.ts +17 -0
- package/generated-src/forum/interfaces.ts +171 -0
- package/generated-src/groupv2/api.ts +515 -0
- package/generated-src/groupv2/index.ts +17 -0
- package/generated-src/groupv2/interfaces.ts +773 -0
- package/generated-src/http.ts +52 -0
- package/generated-src/index.ts +37 -0
- package/generated-src/package.json.notyet +99 -0
- package/generated-src/platform.ts +39 -0
- package/generated-src/social/api.ts +115 -0
- package/generated-src/social/index.ts +17 -0
- package/generated-src/social/interfaces.ts +89 -0
- package/generated-src/tokens/api.ts +126 -0
- package/generated-src/tokens/index.ts +17 -0
- package/generated-src/tokens/interfaces.ts +102 -0
- package/generated-src/trending/api.ts +62 -0
- package/generated-src/trending/index.ts +17 -0
- package/generated-src/trending/interfaces.ts +188 -0
- package/generated-src/user/api.ts +130 -0
- package/generated-src/user/index.ts +17 -0
- package/generated-src/user/interfaces.ts +338 -0
- package/generator/generate-api.ts +254 -0
- package/generator/generate-common.ts +123 -0
- package/generator/generate-index.ts +45 -0
- package/generator/generate-interfaces.ts +173 -0
- package/generator/generate-manifest.ts +217 -0
- package/generator/generate-package-json.ts +45 -0
- package/generator/generate.ts +54 -0
- package/generator/http.ts +52 -0
- package/generator/missing-props.ts +11 -0
- package/generator/type-index.ts +184 -0
- package/generator/util.ts +131 -0
- package/lib/README.md +97 -0
- package/lib/app/api.d.ts +36 -0
- package/lib/app/api.js +15 -0
- package/lib/app/index.d.ts +16 -0
- package/lib/app/index.js +5 -0
- package/lib/app/interfaces.d.ts +108 -0
- package/lib/app/interfaces.js +17 -0
- package/lib/bungie-api-LICENSE +29 -0
- package/lib/common.d.ts +979 -0
- package/lib/common.js +923 -0
- package/lib/communitycontent/api.d.ts +31 -0
- package/lib/communitycontent/api.js +7 -0
- package/lib/communitycontent/index.d.ts +15 -0
- package/lib/communitycontent/index.js +4 -0
- package/lib/content/api.d.ts +111 -0
- package/lib/content/api.js +75 -0
- package/lib/content/index.d.ts +16 -0
- package/lib/content/index.js +5 -0
- package/lib/content/interfaces.d.ts +214 -0
- package/lib/content/interfaces.js +17 -0
- package/lib/core/api.d.ts +45 -0
- package/lib/core/api.js +18 -0
- package/lib/core/index.d.ts +16 -0
- package/lib/core/index.js +5 -0
- package/lib/core/interfaces.d.ts +144 -0
- package/lib/core/interfaces.js +10 -0
- package/lib/destiny2/api.d.ts +765 -0
- package/lib/destiny2/api.js +295 -0
- package/lib/destiny2/index.d.ts +16 -0
- package/lib/destiny2/index.js +5 -0
- package/lib/destiny2/interfaces.d.ts +15340 -0
- package/lib/destiny2/interfaces.js +826 -0
- package/lib/destiny2/manifest.d.ts +465 -0
- package/lib/destiny2/manifest.js +56 -0
- package/lib/fireteam/api.d.ts +131 -0
- package/lib/fireteam/api.js +50 -0
- package/lib/fireteam/index.d.ts +16 -0
- package/lib/fireteam/index.js +5 -0
- package/lib/fireteam/interfaces.d.ts +166 -0
- package/lib/fireteam/interfaces.js +33 -0
- package/lib/forum/api.d.ts +165 -0
- package/lib/forum/api.js +79 -0
- package/lib/forum/index.d.ts +16 -0
- package/lib/forum/index.js +5 -0
- package/lib/forum/interfaces.d.ts +147 -0
- package/lib/forum/interfaces.js +61 -0
- package/lib/groupv2/api.d.ts +484 -0
- package/lib/groupv2/api.js +154 -0
- package/lib/groupv2/index.d.ts +16 -0
- package/lib/groupv2/index.js +5 -0
- package/lib/groupv2/interfaces.d.ts +718 -0
- package/lib/groupv2/interfaces.js +100 -0
- package/lib/http.d.ts +18 -0
- package/lib/http.js +20 -0
- package/lib/index.d.ts +35 -0
- package/lib/index.js +24 -0
- package/lib/package.json +99 -0
- package/lib/platform.d.ts +36 -0
- package/lib/platform.js +9 -0
- package/lib/social/api.d.ts +101 -0
- package/lib/social/api.js +26 -0
- package/lib/social/index.d.ts +16 -0
- package/lib/social/index.js +5 -0
- package/lib/social/interfaces.d.ts +75 -0
- package/lib/social/interfaces.js +22 -0
- package/lib/tokens/api.d.ts +120 -0
- package/lib/tokens/api.js +38 -0
- package/lib/tokens/index.d.ts +16 -0
- package/lib/tokens/index.js +5 -0
- package/lib/tokens/interfaces.d.ts +88 -0
- package/lib/tokens/interfaces.js +5 -0
- package/lib/trending/api.d.ts +53 -0
- package/lib/trending/api.js +11 -0
- package/lib/trending/index.d.ts +16 -0
- package/lib/trending/index.js +5 -0
- package/lib/trending/interfaces.d.ts +171 -0
- package/lib/trending/interfaces.js +14 -0
- package/lib/user/api.d.ts +117 -0
- package/lib/user/api.js +35 -0
- package/lib/user/index.d.ts +16 -0
- package/lib/user/index.js +5 -0
- package/lib/user/interfaces.d.ts +320 -0
- package/lib/user/interfaces.js +28 -0
- package/package.json +60 -0
- package/test-consumer.ts +5 -0
- package/tests/__snapshots__/config-builders.test.ts.snap +343 -0
- package/tests/config-builders.test.ts +145 -0
- package/tests/manifest-fetcher.test.ts +43 -0
- package/tests/test-manifest.js +69 -0
- package/tsconfig-package.json +14 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export type HttpQueryParams = Record<string, string>;
|
|
2
|
+
|
|
3
|
+
export interface HttpClientConfig {
|
|
4
|
+
method: 'GET' | 'POST';
|
|
5
|
+
url: string;
|
|
6
|
+
/** Query string params */
|
|
7
|
+
params?: HttpQueryParams;
|
|
8
|
+
/** Request body */
|
|
9
|
+
body?: any;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A generic, minimal type for providing an HTTP client function.
|
|
14
|
+
* This gets the necessary config provided as an argument, and then
|
|
15
|
+
* should produce a promise for the parsed JSON as a result. The API
|
|
16
|
+
* helper functions will use this to return the right type.
|
|
17
|
+
*/
|
|
18
|
+
export type HttpClient = <Return>(config: HttpClientConfig) => Promise<Return>;
|
|
19
|
+
|
|
20
|
+
export function get<Return>(
|
|
21
|
+
http: HttpClient,
|
|
22
|
+
url: string,
|
|
23
|
+
params?: HttpQueryParams
|
|
24
|
+
): Promise<Return> {
|
|
25
|
+
return http(
|
|
26
|
+
params
|
|
27
|
+
? {
|
|
28
|
+
method: 'GET',
|
|
29
|
+
url,
|
|
30
|
+
params,
|
|
31
|
+
}
|
|
32
|
+
: {
|
|
33
|
+
method: 'GET',
|
|
34
|
+
url,
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function post<Return>(http: HttpClient, url: string, body?: any): Promise<Return> {
|
|
40
|
+
return http(
|
|
41
|
+
body
|
|
42
|
+
? {
|
|
43
|
+
method: 'POST',
|
|
44
|
+
url,
|
|
45
|
+
body,
|
|
46
|
+
}
|
|
47
|
+
: {
|
|
48
|
+
method: 'POST',
|
|
49
|
+
url,
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
2
|
+
import {
|
|
3
|
+
OpenAPIObject,
|
|
4
|
+
PathItemObject,
|
|
5
|
+
ParameterObject,
|
|
6
|
+
SchemaObject,
|
|
7
|
+
ReferenceObject,
|
|
8
|
+
} from 'openapi3-ts';
|
|
9
|
+
import {
|
|
10
|
+
getRef,
|
|
11
|
+
lastPart,
|
|
12
|
+
getReferencedTypes,
|
|
13
|
+
DefInfo,
|
|
14
|
+
interfaceName,
|
|
15
|
+
isRequestBodyObject,
|
|
16
|
+
} from './util.js';
|
|
17
|
+
|
|
18
|
+
export function computeTypeMaps(
|
|
19
|
+
pathPairsByTag: { [tag: string]: [string, PathItemObject][] },
|
|
20
|
+
doc: OpenAPIObject
|
|
21
|
+
) {
|
|
22
|
+
const allDefsEverywhere = new Set<string>();
|
|
23
|
+
const defsByTag: { [tag: string]: Set<string> } = {};
|
|
24
|
+
_.each(pathPairsByTag, (paths, tag) => {
|
|
25
|
+
const defs = findReachableComponents(paths, doc);
|
|
26
|
+
addAll(allDefsEverywhere, defs);
|
|
27
|
+
defsByTag[tag] = defs;
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Add manifest tables that aren't referenced by any API endpoint.
|
|
31
|
+
for (const [defName, def] of Object.entries(doc.components!.schemas!)) {
|
|
32
|
+
const typePath = `#/components/schemas/${defName}`;
|
|
33
|
+
if (
|
|
34
|
+
!allDefsEverywhere.has(typePath) &&
|
|
35
|
+
'type' in def &&
|
|
36
|
+
def.type === 'object' &&
|
|
37
|
+
def['x-mobile-manifest-name']
|
|
38
|
+
) {
|
|
39
|
+
console.log(`Found unreferenced manifest table ${typePath}`);
|
|
40
|
+
allDefsEverywhere.add(typePath);
|
|
41
|
+
addReachableComponentsFromComponent(allDefsEverywhere, typePath, doc);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const allTags = Object.keys(pathPairsByTag);
|
|
46
|
+
|
|
47
|
+
const componentsByFile: { [filename: string]: DefInfo[] } = {};
|
|
48
|
+
const componentByDef: { [def: string]: DefInfo } = {};
|
|
49
|
+
for (const def of allDefsEverywhere) {
|
|
50
|
+
const tags: string[] = [];
|
|
51
|
+
_.each(defsByTag, (defs: Set<string>, tag) => {
|
|
52
|
+
if (defs.has(def)) {
|
|
53
|
+
tags.push(tag);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
const info: DefInfo = {
|
|
57
|
+
def,
|
|
58
|
+
tags,
|
|
59
|
+
filename: chooseFile(def, tags, allTags),
|
|
60
|
+
interfaceName: interfaceName(def, doc),
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
componentsByFile[info.filename] = componentsByFile[info.filename] || [];
|
|
64
|
+
componentsByFile[info.filename].push(info);
|
|
65
|
+
componentByDef[info.def] = info;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return { componentsByFile, componentByDef };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// TODO: put enums in a separate file???
|
|
72
|
+
// TODO: put things ending in Request in a separate file?
|
|
73
|
+
// TODO: put manifest stuff in a separate file?
|
|
74
|
+
function chooseFile(def: string, tags: string[], allTags: string[]) {
|
|
75
|
+
const schemaName: string = _.last(def.split('/'))!;
|
|
76
|
+
const matchingTag = allTags.find((tag) => schemaName.startsWith(tag + '.'));
|
|
77
|
+
|
|
78
|
+
const filename = '/interfaces.ts';
|
|
79
|
+
if (matchingTag) {
|
|
80
|
+
return matchingTag.toLowerCase() + filename;
|
|
81
|
+
} else if (schemaName.startsWith('GroupsV2.')) {
|
|
82
|
+
return 'groupv2' + filename;
|
|
83
|
+
} else if (schemaName.startsWith('Destiny.')) {
|
|
84
|
+
return 'destiny2' + filename;
|
|
85
|
+
} else {
|
|
86
|
+
if (tags.length === 1) {
|
|
87
|
+
return tags[0].toLowerCase() + filename;
|
|
88
|
+
} else if (!tags.includes('Destiny2')) {
|
|
89
|
+
return 'platform.ts';
|
|
90
|
+
} else {
|
|
91
|
+
return 'common.ts';
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function findReachableComponents(paths: [string, PathItemObject][], doc: OpenAPIObject) {
|
|
97
|
+
const pathDefinitions = paths.reduce(
|
|
98
|
+
(memo: Set<string>, [_, pathDef]) => addAll(memo, findReachableComponentsFromPath(pathDef)),
|
|
99
|
+
new Set<string>()
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
const allDefinitions = new Set(pathDefinitions);
|
|
103
|
+
pathDefinitions.forEach((definition) =>
|
|
104
|
+
addReachableComponentsFromComponent(allDefinitions, definition, doc)
|
|
105
|
+
);
|
|
106
|
+
return allDefinitions;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function addAll<T>(first: Set<T>, second: Set<T>): Set<T> {
|
|
110
|
+
for (const value of second) {
|
|
111
|
+
first.add(value);
|
|
112
|
+
}
|
|
113
|
+
return first;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function findReachableComponentsFromPath(pathDef: PathItemObject): Set<string> {
|
|
117
|
+
const methodDef = pathDef.get || pathDef.post!;
|
|
118
|
+
const params = (methodDef.parameters || []) as ParameterObject[];
|
|
119
|
+
const paramTypes = new Set(
|
|
120
|
+
params.map((param) => getReferencedTypes(param.schema!)).filter((p) => p)
|
|
121
|
+
) as Set<string>;
|
|
122
|
+
|
|
123
|
+
const requestBody = methodDef.requestBody;
|
|
124
|
+
if (requestBody && isRequestBodyObject(requestBody)) {
|
|
125
|
+
const schema = requestBody.content['application/json'].schema!;
|
|
126
|
+
const paramType = getReferencedTypes(schema);
|
|
127
|
+
if (paramType) {
|
|
128
|
+
paramTypes.add(paramType);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const returnType = getReferencedTypes(methodDef.responses['200']);
|
|
133
|
+
if (returnType) {
|
|
134
|
+
paramTypes.add(returnType);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return paramTypes;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function addReachableComponentsFromComponent(
|
|
141
|
+
allDefinitions: Set<string>,
|
|
142
|
+
definition: string,
|
|
143
|
+
doc: OpenAPIObject
|
|
144
|
+
) {
|
|
145
|
+
const component = getRef(doc, definition);
|
|
146
|
+
if (!component) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (component && component.type === 'array') {
|
|
151
|
+
addDefinitions(allDefinitions, component.items!, doc);
|
|
152
|
+
} else if (component.type === 'object') {
|
|
153
|
+
if (component.properties) {
|
|
154
|
+
Object.values(component.properties).forEach((schema: SchemaObject | ReferenceObject) => {
|
|
155
|
+
addDefinitions(allDefinitions, schema, doc);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
(component.allOf || []).forEach((schema: SchemaObject | ReferenceObject) => {
|
|
159
|
+
addDefinitions(allDefinitions, schema, doc);
|
|
160
|
+
});
|
|
161
|
+
if (component.additionalProperties && typeof component.additionalProperties !== 'boolean') {
|
|
162
|
+
addDefinitions(allDefinitions, component.additionalProperties, doc);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function addDefinitions(allDefinitions: Set<string>, schema: SchemaObject, doc: OpenAPIObject) {
|
|
168
|
+
const newDefinition = getReferencedTypes(schema);
|
|
169
|
+
addDefinitionsFromComponent(allDefinitions, newDefinition, doc);
|
|
170
|
+
if (schema['x-mapped-definition']) {
|
|
171
|
+
addDefinitionsFromComponent(allDefinitions, schema['x-mapped-definition'].$ref, doc);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function addDefinitionsFromComponent(
|
|
176
|
+
allDefinitions: Set<string>,
|
|
177
|
+
definition: string | undefined,
|
|
178
|
+
doc: OpenAPIObject
|
|
179
|
+
) {
|
|
180
|
+
if (definition && !allDefinitions.has(definition)) {
|
|
181
|
+
allDefinitions.add(definition);
|
|
182
|
+
addReachableComponentsFromComponent(allDefinitions, definition, doc);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { SchemaObject, ReferenceObject, OpenAPIObject, RequestBodyObject } from 'openapi3-ts';
|
|
2
|
+
import _ from 'lodash';
|
|
3
|
+
|
|
4
|
+
export interface DefInfo {
|
|
5
|
+
def: string;
|
|
6
|
+
tags: string[];
|
|
7
|
+
filename: string;
|
|
8
|
+
interfaceName: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function resolveSchemaType(
|
|
12
|
+
schema: SchemaObject | ReferenceObject,
|
|
13
|
+
doc: OpenAPIObject
|
|
14
|
+
): string {
|
|
15
|
+
if (isReferenceObject(schema)) {
|
|
16
|
+
return interfaceName(schema.$ref, doc);
|
|
17
|
+
} else if (schema['x-enum-reference']) {
|
|
18
|
+
return interfaceName(schema['x-enum-reference'].$ref, doc);
|
|
19
|
+
} else {
|
|
20
|
+
return typeMapping(schema, doc);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function typeMapping(schema: SchemaObject, doc: OpenAPIObject): string {
|
|
25
|
+
switch (schema.type) {
|
|
26
|
+
case 'string':
|
|
27
|
+
return schema.format === 'byte' ? 'number' : 'string';
|
|
28
|
+
case 'integer':
|
|
29
|
+
// JS can't represent a 64-bit int as a number, so bungie.net returns it as a string in JSON
|
|
30
|
+
return schema.format === 'int64' ? 'string' : 'number';
|
|
31
|
+
|
|
32
|
+
case 'array':
|
|
33
|
+
return resolveSchemaType(schema.items!, doc) + '[]';
|
|
34
|
+
case 'object':
|
|
35
|
+
if (schema.allOf) {
|
|
36
|
+
return resolveSchemaType(schema.allOf[0], doc);
|
|
37
|
+
} else if (
|
|
38
|
+
schema.additionalProperties &&
|
|
39
|
+
schema['x-dictionary-key'] &&
|
|
40
|
+
typeof schema.additionalProperties !== 'boolean'
|
|
41
|
+
) {
|
|
42
|
+
const keySchema: SchemaObject | ReferenceObject = schema['x-dictionary-key'];
|
|
43
|
+
const key = isReferenceObject(keySchema) ? 'number' : resolveSchemaType(keySchema, doc);
|
|
44
|
+
const val = resolveSchemaType(schema.additionalProperties, doc);
|
|
45
|
+
const keyExp = key === 'number' || key === 'string' ? `key: ${key}` : `key in ${key}`;
|
|
46
|
+
return `{ [${keyExp}]: ${val} }`;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return schema.type!;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function getReferencedTypes(schema: SchemaObject | ReferenceObject): string | undefined {
|
|
54
|
+
if (isReferenceObject(schema)) {
|
|
55
|
+
return schema.$ref;
|
|
56
|
+
} else if (schema['x-enum-reference']) {
|
|
57
|
+
return schema['x-enum-reference'].$ref;
|
|
58
|
+
} else if (schema.items) {
|
|
59
|
+
return getReferencedTypes(schema.items!);
|
|
60
|
+
} else if (schema.allOf) {
|
|
61
|
+
return getReferencedTypes(schema.allOf[0]);
|
|
62
|
+
} else if (schema.additionalProperties && typeof schema.additionalProperties !== 'boolean') {
|
|
63
|
+
return getReferencedTypes(schema.additionalProperties);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function lcFirst(name: string): string {
|
|
68
|
+
return name[0].toLowerCase() + name.substring(1);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function lastPart(name: string): string {
|
|
72
|
+
return _.last(name.split(/[\.\/]/))!;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function getRef(doc: OpenAPIObject, ref: string): SchemaObject | undefined {
|
|
76
|
+
const path = ref.replace('#/', '').split('/');
|
|
77
|
+
let result = doc;
|
|
78
|
+
let pathSegment = path.shift();
|
|
79
|
+
while (pathSegment) {
|
|
80
|
+
result = result[pathSegment];
|
|
81
|
+
pathSegment = path.shift();
|
|
82
|
+
}
|
|
83
|
+
if (!result) {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
if (result.content) {
|
|
87
|
+
return result.content['application/json'].schema;
|
|
88
|
+
} else {
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function interfaceName(componentPath: string, doc: OpenAPIObject) {
|
|
94
|
+
const name = lastPart(componentPath);
|
|
95
|
+
const component = getRef(doc, componentPath);
|
|
96
|
+
if (!component) {
|
|
97
|
+
return 'any';
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const singleResponse = name.match(/SingleComponentResponseOf(.*)/);
|
|
101
|
+
if (singleResponse) {
|
|
102
|
+
return `SingleComponentResponse<${singleResponse[1]}>`;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const dictionaryResponse = name.match(/DictionaryComponentResponseOfu?int(?:64|32)And(.*)/);
|
|
106
|
+
if (dictionaryResponse) {
|
|
107
|
+
return `DictionaryComponentResponse<${dictionaryResponse[1]}>`;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (componentPath.includes('/responses/')) {
|
|
111
|
+
const property = component.properties!.Response;
|
|
112
|
+
if (property) {
|
|
113
|
+
const paramType = resolveSchemaType(property, doc);
|
|
114
|
+
return `ServerResponse<${paramType}>`;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return name;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function isRequestBodyObject(
|
|
122
|
+
requestBody: RequestBodyObject | ReferenceObject
|
|
123
|
+
): requestBody is RequestBodyObject {
|
|
124
|
+
return (requestBody as RequestBodyObject).content !== undefined;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function isReferenceObject(
|
|
128
|
+
schema: SchemaObject | ReferenceObject
|
|
129
|
+
): schema is ReferenceObject {
|
|
130
|
+
return (schema as ReferenceObject).$ref !== undefined;
|
|
131
|
+
}
|
package/lib/README.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Bungie API TypeScript support
|
|
2
|
+
|
|
3
|
+
This project implements TypeScript definitions and API helpers for the [Bungie.net API](https://github.com/Bungie-net/api). It's meant for use in [Destiny Item Manager](https://destinyitemmanager.com), but should be general enough to use in any project. The code is completely generated from Bungie's documentation - I considered using something like Swagger Codegen, but instead opted for a custom generator so we could make the result as nice as possible.
|
|
4
|
+
|
|
5
|
+
# Ports
|
|
6
|
+
|
|
7
|
+
Feel free to fork this and use it to generate for your favorite language!
|
|
8
|
+
|
|
9
|
+
- [Dart](https://github.com/marquesinijatinha/bungie-api-dart/)
|
|
10
|
+
|
|
11
|
+
# Install
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
pnpm add bungie-api-ts
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
# Interfaces and Enums
|
|
18
|
+
|
|
19
|
+
All the interface type definitions and enums are for type info only - everything will compile out. Only the API helpers produce real JavaScript output. You can import types from each service defined on Bungie.net:
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { DestinyInventoryComponent, DestinyInventoryItemDefinition } from 'bungie-api-ts/destiny2';
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
There are definitions for every type defined in the Bungie.net services. See [their documentation](https://bungie-net.github.io/multi/) for a list - the interface names are the last part of the full name (for example, `Destiny.Definitions.DestinyVendorActionDefinition` becomes `DestinyVendorActionDefinition`). There are a few exceptions, like `SingleComponentResponseOfDestinyInventoryComponent`, which have been mapped into nicer forms like `SingleComponentResponse<DestinyInventoryComponent>`, and the server responses, which are now `ServerResponse<T>` instead of something like `DestinyCharacterResponse`.
|
|
26
|
+
|
|
27
|
+
# API Helpers
|
|
28
|
+
|
|
29
|
+
In addition to the types, there are also simple helper functions for each API endpoint. They define the inputs and outputs to that endpoint, and will call a user-provided function with HTTP request info that you can then use to make an HTTP request. This pattern was used so the API helpers could provide full type information. These helpers are not a full API client - they assist in building one. An example:
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import { getProfile, HttpClientConfig } from 'bungie-api-ts/destiny2';
|
|
33
|
+
|
|
34
|
+
async function $http(config: HttpClientConfig) {
|
|
35
|
+
// fill in the API key, handle OAuth, etc., then make an HTTP request using the config.
|
|
36
|
+
return fetch(config.url, ...);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const profileInfo: ServerResponse<DestinyProfileResponse> = await getProfile($http, {
|
|
40
|
+
components: [DestinyComponentType.Profiles, DestinyComponentType.Characters],
|
|
41
|
+
destinyMembershipId: 12345,
|
|
42
|
+
membershipType: BungieMembershipType.TigerPsn
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
# Imports
|
|
47
|
+
|
|
48
|
+
It is possible to import all services from `bungie-api-ts` directly, but it's better to import the specific service and pick out what you want:
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
// good
|
|
52
|
+
import { getProfile, HttpClientConfig } from 'bungie-api-ts/destiny2';
|
|
53
|
+
getProfile(...);
|
|
54
|
+
|
|
55
|
+
// works, but not as good
|
|
56
|
+
import { Destiny2 } from 'bungie-api-ts';
|
|
57
|
+
Destiny2.getProfile(...);
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
# Manifest Helpers
|
|
61
|
+
|
|
62
|
+
The `destiny2` import also contains helpers for typing and downloading the Destiny manifest:
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { getDestinyManifestSlice, getDestinyManifest, type HttpClientConfig } from 'bungie-api-ts/destiny2';
|
|
66
|
+
|
|
67
|
+
async function $http(config: HttpClientConfig) {
|
|
68
|
+
// fill in the API key, handle OAuth, etc., then make an HTTP request using the config.
|
|
69
|
+
return fetch(config.url, ...);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const destinyManifest = await getDestinyManifest($http);
|
|
73
|
+
const manifestTables = getDestinyManifestSlice($http, {
|
|
74
|
+
destinyManifest: destinyManifest.Response,
|
|
75
|
+
tableNames: ['DestinyInventoryItemDefinition', 'DestinySocketDefinition'],
|
|
76
|
+
language: 'en',
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// manifestTables is an object with properties DestinyInventoryItemDefinition and DestinySocketDefinition
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
# Build
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
# setup
|
|
86
|
+
pnpm i && pnpm submodule
|
|
87
|
+
# run
|
|
88
|
+
pnpm start
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
# Updating API sources
|
|
92
|
+
|
|
93
|
+
Run the [update API sources](https://github.com/DestinyItemManager/bungie-api-ts/actions/workflows/update.yml) GitHub Action and it should create a new PR for the updated sources.
|
|
94
|
+
|
|
95
|
+
# Publishing
|
|
96
|
+
|
|
97
|
+
Update the version in `package.json`, and when the PR merges to `master`, a GitHub workflow will automatically publish to NPM. Don't forget to run `pnpm start` and commit all changed files!
|
package/lib/app/api.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bungie.Net API
|
|
3
|
+
* These endpoints constitute the functionality exposed by Bungie.net, both for more traditional website functionality and for connectivity to Bungie video games and their related functionality.
|
|
4
|
+
*
|
|
5
|
+
* OpenAPI spec version: 2.21.9
|
|
6
|
+
* Contact: support@bungie.com
|
|
7
|
+
*
|
|
8
|
+
* NOTE: This class is auto generated by the bungie-api-ts code generator program.
|
|
9
|
+
* https://github.com/DestinyItemManager/bungie-api-ts
|
|
10
|
+
* Do not edit these files manually.
|
|
11
|
+
*/
|
|
12
|
+
import { HttpClient } from '../http.js';
|
|
13
|
+
import { ApiUsage, Application } from './interfaces.js';
|
|
14
|
+
import { ServerResponse } from '../common.js';
|
|
15
|
+
export interface GetApplicationApiUsageParams {
|
|
16
|
+
/** ID of the application to get usage statistics. */
|
|
17
|
+
applicationId: number;
|
|
18
|
+
/** End time for query. Goes to now if not specified. */
|
|
19
|
+
end?: string;
|
|
20
|
+
/** Start time for query. Goes to 24 hours ago if not specified. */
|
|
21
|
+
start?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Get API usage by application for time frame specified. You can go as far back as
|
|
25
|
+
* 30 days ago, and can ask for up to a 48 hour window of time in a single request.
|
|
26
|
+
* You must be authenticated with at least the ReadUserData permission to access
|
|
27
|
+
* this endpoint.
|
|
28
|
+
*/
|
|
29
|
+
export declare function getApplicationApiUsage(
|
|
30
|
+
http: HttpClient,
|
|
31
|
+
params: GetApplicationApiUsageParams
|
|
32
|
+
): Promise<ServerResponse<ApiUsage>>;
|
|
33
|
+
/** Get list of applications created by Bungie. */
|
|
34
|
+
export declare function getBungieApplications(
|
|
35
|
+
http: HttpClient
|
|
36
|
+
): Promise<ServerResponse<Application[]>>;
|
package/lib/app/api.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { get } from '../http.js';
|
|
2
|
+
const API_BASE = 'https://www.bungie.net/Platform/App/';
|
|
3
|
+
export function getApplicationApiUsage(http, params) {
|
|
4
|
+
const strParams = {};
|
|
5
|
+
if (params.end !== undefined) {
|
|
6
|
+
strParams.end = params.end;
|
|
7
|
+
}
|
|
8
|
+
if (params.start !== undefined) {
|
|
9
|
+
strParams.start = params.start;
|
|
10
|
+
}
|
|
11
|
+
return get(http, `${API_BASE}ApiUsage/${params.applicationId}/`, strParams);
|
|
12
|
+
}
|
|
13
|
+
export function getBungieApplications(http) {
|
|
14
|
+
return get(http, `${API_BASE}FirstParty/`);
|
|
15
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bungie.Net API
|
|
3
|
+
* These endpoints constitute the functionality exposed by Bungie.net, both for more traditional website functionality and for connectivity to Bungie video games and their related functionality.
|
|
4
|
+
*
|
|
5
|
+
* OpenAPI spec version: 2.21.9
|
|
6
|
+
* Contact: support@bungie.com
|
|
7
|
+
*
|
|
8
|
+
* NOTE: This class is auto generated by the bungie-api-ts code generator program.
|
|
9
|
+
* https://github.com/DestinyItemManager/bungie-api-ts
|
|
10
|
+
* Do not edit these files manually.
|
|
11
|
+
*/
|
|
12
|
+
export * from '../common.js';
|
|
13
|
+
export * from '../platform.js';
|
|
14
|
+
export type { HttpClientConfig, HttpClient } from '../http.js';
|
|
15
|
+
export * from './api.js';
|
|
16
|
+
export * from './interfaces.js';
|
package/lib/app/index.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bungie.Net API
|
|
3
|
+
* These endpoints constitute the functionality exposed by Bungie.net, both for more traditional website functionality and for connectivity to Bungie video games and their related functionality.
|
|
4
|
+
*
|
|
5
|
+
* OpenAPI spec version: 2.21.9
|
|
6
|
+
* Contact: support@bungie.com
|
|
7
|
+
*
|
|
8
|
+
* NOTE: This class is auto generated by the bungie-api-ts code generator program.
|
|
9
|
+
* https://github.com/DestinyItemManager/bungie-api-ts
|
|
10
|
+
* Do not edit these files manually.
|
|
11
|
+
*/
|
|
12
|
+
import { UserInfoCard } from '../user/interfaces.js';
|
|
13
|
+
export interface ApiUsage {
|
|
14
|
+
/** Counts for on API calls made for the time range. */
|
|
15
|
+
readonly apiCalls: Series[];
|
|
16
|
+
/**
|
|
17
|
+
* Instances of blocked requests or requests that crossed the warn threshold during
|
|
18
|
+
* the time range.
|
|
19
|
+
*/
|
|
20
|
+
readonly throttledRequests: Series[];
|
|
21
|
+
}
|
|
22
|
+
export interface Series {
|
|
23
|
+
/** Collection of samples with time and value. */
|
|
24
|
+
readonly datapoints: Datapoint[];
|
|
25
|
+
/** Target to which to datapoints apply. */
|
|
26
|
+
readonly target: string;
|
|
27
|
+
}
|
|
28
|
+
export interface Datapoint {
|
|
29
|
+
/** Timestamp for the related count. */
|
|
30
|
+
readonly time: string;
|
|
31
|
+
/** Count associated with timestamp */
|
|
32
|
+
readonly count?: number;
|
|
33
|
+
}
|
|
34
|
+
export interface Application {
|
|
35
|
+
readonly applicationType: OAuthApplicationType;
|
|
36
|
+
/** Unique ID assigned to the application */
|
|
37
|
+
readonly applicationId: number;
|
|
38
|
+
/** Name of the application */
|
|
39
|
+
readonly name: string;
|
|
40
|
+
/** URL used to pass the user's authorization code to the application */
|
|
41
|
+
readonly redirectUrl: string;
|
|
42
|
+
/** Link to website for the application where a user can learn more about the app. */
|
|
43
|
+
readonly link: string;
|
|
44
|
+
/** Permissions the application needs to work */
|
|
45
|
+
readonly scope: string;
|
|
46
|
+
/** Value of the Origin header sent in requests generated by this application. */
|
|
47
|
+
readonly origin: string;
|
|
48
|
+
/** Current status of the application. */
|
|
49
|
+
readonly status: ApplicationStatus;
|
|
50
|
+
/** Date the application was first added to our database. */
|
|
51
|
+
readonly creationDate: string;
|
|
52
|
+
/** Date the application status last changed. */
|
|
53
|
+
readonly statusChanged: string;
|
|
54
|
+
/** Date the first time the application status entered the 'Public' status. */
|
|
55
|
+
readonly firstPublished: string;
|
|
56
|
+
/**
|
|
57
|
+
* List of team members who manage this application on Bungie.net. Will always
|
|
58
|
+
* consist of at least the application owner.
|
|
59
|
+
*/
|
|
60
|
+
readonly team: ApplicationDeveloper[];
|
|
61
|
+
/** An optional override for the Authorize view name. */
|
|
62
|
+
readonly overrideAuthorizeViewName: string;
|
|
63
|
+
}
|
|
64
|
+
export declare const enum OAuthApplicationType {
|
|
65
|
+
None = 0,
|
|
66
|
+
/**
|
|
67
|
+
* Indicates the application is server based and can keep its secrets from end
|
|
68
|
+
* users and other potential snoops.
|
|
69
|
+
*/
|
|
70
|
+
Confidential = 1,
|
|
71
|
+
/**
|
|
72
|
+
* Indicates the application runs in a public place, and it can't be trusted to
|
|
73
|
+
* keep a secret.
|
|
74
|
+
*/
|
|
75
|
+
Public = 2,
|
|
76
|
+
}
|
|
77
|
+
export declare const enum ApplicationStatus {
|
|
78
|
+
/** No value assigned */
|
|
79
|
+
None = 0,
|
|
80
|
+
/**
|
|
81
|
+
* Application exists and works but will not appear in any public catalog. New
|
|
82
|
+
* applications start in this state, test applications will remain in this state.
|
|
83
|
+
*/
|
|
84
|
+
Private = 1,
|
|
85
|
+
/** Active applications that can appear in an catalog. */
|
|
86
|
+
Public = 2,
|
|
87
|
+
/**
|
|
88
|
+
* Application disabled by the owner. All authorizations will be treated as
|
|
89
|
+
* terminated while in this state. Owner can move back to private or public state.
|
|
90
|
+
*/
|
|
91
|
+
Disabled = 3,
|
|
92
|
+
/**
|
|
93
|
+
* Application has been blocked by Bungie. It cannot be transitioned out of this
|
|
94
|
+
* state by the owner. Authorizations are terminated when an application is in this
|
|
95
|
+
* state.
|
|
96
|
+
*/
|
|
97
|
+
Blocked = 4,
|
|
98
|
+
}
|
|
99
|
+
export interface ApplicationDeveloper {
|
|
100
|
+
readonly role: DeveloperRole;
|
|
101
|
+
readonly apiEulaVersion: number;
|
|
102
|
+
readonly user: UserInfoCard;
|
|
103
|
+
}
|
|
104
|
+
export declare const enum DeveloperRole {
|
|
105
|
+
None = 0,
|
|
106
|
+
Owner = 1,
|
|
107
|
+
TeamMember = 2,
|
|
108
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export var OAuthApplicationType = {
|
|
2
|
+
None: 0,
|
|
3
|
+
Confidential: 1,
|
|
4
|
+
Public: 2,
|
|
5
|
+
};
|
|
6
|
+
export var ApplicationStatus = {
|
|
7
|
+
None: 0,
|
|
8
|
+
Private: 1,
|
|
9
|
+
Public: 2,
|
|
10
|
+
Disabled: 3,
|
|
11
|
+
Blocked: 4,
|
|
12
|
+
};
|
|
13
|
+
export var DeveloperRole = {
|
|
14
|
+
None: 0,
|
|
15
|
+
Owner: 1,
|
|
16
|
+
TeamMember: 2,
|
|
17
|
+
};
|