@lti-tool/core 0.11.1 → 0.12.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/CHANGELOG.md +12 -0
- package/dist/interfaces/index.d.ts +1 -0
- package/dist/interfaces/index.d.ts.map +1 -1
- package/dist/interfaces/ltiConfig.d.ts +23 -0
- package/dist/interfaces/ltiConfig.d.ts.map +1 -1
- package/dist/interfaces/ltiDynamicRegistrationSession.d.ts +14 -0
- package/dist/interfaces/ltiDynamicRegistrationSession.d.ts.map +1 -0
- package/dist/interfaces/ltiDynamicRegistrationSession.js +1 -0
- package/dist/interfaces/ltiStorage.d.ts +22 -0
- package/dist/interfaces/ltiStorage.d.ts.map +1 -1
- package/dist/ltiTool.d.ts +64 -1
- package/dist/ltiTool.d.ts.map +1 -1
- package/dist/ltiTool.js +87 -1
- package/dist/schemas/index.d.ts +5 -0
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/index.js +4 -0
- package/dist/schemas/lti13/dynamicRegistration/ltiDynamicRegistration.schema.d.ts +34 -0
- package/dist/schemas/lti13/dynamicRegistration/ltiDynamicRegistration.schema.d.ts.map +1 -0
- package/dist/schemas/lti13/dynamicRegistration/ltiDynamicRegistration.schema.js +28 -0
- package/dist/schemas/lti13/dynamicRegistration/ltiMessages.schema.d.ts +101 -0
- package/dist/schemas/lti13/dynamicRegistration/ltiMessages.schema.d.ts.map +1 -0
- package/dist/schemas/lti13/dynamicRegistration/ltiMessages.schema.js +51 -0
- package/dist/schemas/lti13/dynamicRegistration/openIDConfiguration.schema.d.ts +59 -0
- package/dist/schemas/lti13/dynamicRegistration/openIDConfiguration.schema.d.ts.map +1 -0
- package/dist/schemas/lti13/dynamicRegistration/openIDConfiguration.schema.js +53 -0
- package/dist/schemas/lti13/dynamicRegistration/registrationRequest.schema.d.ts +7 -0
- package/dist/schemas/lti13/dynamicRegistration/registrationRequest.schema.d.ts.map +1 -0
- package/dist/schemas/lti13/dynamicRegistration/registrationRequest.schema.js +5 -0
- package/dist/schemas/lti13/dynamicRegistration/registrationResponse.schema.d.ts +73 -0
- package/dist/schemas/lti13/dynamicRegistration/registrationResponse.schema.d.ts.map +1 -0
- package/dist/schemas/lti13/dynamicRegistration/registrationResponse.schema.js +61 -0
- package/dist/schemas/lti13/dynamicRegistration/toolRegistrationPayload.schema.d.ts +103 -0
- package/dist/schemas/lti13/dynamicRegistration/toolRegistrationPayload.schema.d.ts.map +1 -0
- package/dist/schemas/lti13/dynamicRegistration/toolRegistrationPayload.schema.js +49 -0
- package/dist/services/dynamicRegistration.service.d.ts +121 -0
- package/dist/services/dynamicRegistration.service.d.ts.map +1 -0
- package/dist/services/dynamicRegistration.service.js +312 -0
- package/dist/services/dynamicRegistrationHandlers/moodle.d.ts +48 -0
- package/dist/services/dynamicRegistrationHandlers/moodle.d.ts.map +1 -0
- package/dist/services/dynamicRegistrationHandlers/moodle.js +152 -0
- package/dist/utils/ltiPlatformCapabilities.d.ts +65 -0
- package/dist/utils/ltiPlatformCapabilities.d.ts.map +1 -0
- package/dist/utils/ltiPlatformCapabilities.js +73 -0
- package/package.json +2 -2
- package/src/interfaces/index.ts +1 -0
- package/src/interfaces/ltiConfig.ts +25 -0
- package/src/interfaces/ltiDynamicRegistrationSession.ts +14 -0
- package/src/interfaces/ltiStorage.ts +32 -0
- package/src/ltiTool.ts +122 -1
- package/src/schemas/index.ts +17 -0
- package/src/schemas/lti13/dynamicRegistration/ltiDynamicRegistration.schema.ts +31 -0
- package/src/schemas/lti13/dynamicRegistration/ltiMessages.schema.ts +59 -0
- package/src/schemas/lti13/dynamicRegistration/openIDConfiguration.schema.ts +60 -0
- package/src/schemas/lti13/dynamicRegistration/registrationRequest.schema.ts +8 -0
- package/src/schemas/lti13/dynamicRegistration/registrationResponse.schema.ts +67 -0
- package/src/schemas/lti13/dynamicRegistration/toolRegistrationPayload.schema.ts +55 -0
- package/src/services/dynamicRegistration.service.ts +406 -0
- package/src/services/dynamicRegistrationHandlers/moodle.ts +184 -0
- package/src/utils/ltiPlatformCapabilities.ts +86 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Zod schema for LTI platform-specific configuration within OpenID Connect Discovery.
|
|
4
|
+
* Contains LTI-specific metadata about the platform's capabilities and supported features.
|
|
5
|
+
*
|
|
6
|
+
* @property product_family_code - Platform identifier (e.g., 'moodle', 'canvas', 'sakai')
|
|
7
|
+
* @property version - Platform version string
|
|
8
|
+
* @property messages_supported - Array of LTI message types the platform supports
|
|
9
|
+
* @property variables - Optional array of custom variable names the platform supports
|
|
10
|
+
*/
|
|
11
|
+
export declare const ltiPlatformConfigurationSchema: z.ZodObject<{
|
|
12
|
+
product_family_code: z.ZodString;
|
|
13
|
+
version: z.ZodString;
|
|
14
|
+
messages_supported: z.ZodArray<z.ZodObject<{
|
|
15
|
+
type: z.ZodString;
|
|
16
|
+
placements: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
17
|
+
}, z.core.$loose>>;
|
|
18
|
+
variables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
19
|
+
}, z.core.$strip>;
|
|
20
|
+
/**
|
|
21
|
+
* Zod schema for validating OpenID Connect Discovery configuration from LTI 1.3 platforms.
|
|
22
|
+
* This configuration is fetched during dynamic registration to discover platform endpoints,
|
|
23
|
+
* supported features, and security requirements. Used to validate the response from the
|
|
24
|
+
* platform's /.well-known/openid_configuration endpoint.
|
|
25
|
+
*
|
|
26
|
+
* @property issuer - Platform's issuer URL (must match hostname of configuration endpoint)
|
|
27
|
+
* @property authorization_endpoint - OAuth 2.0 authorization endpoint for LTI launches
|
|
28
|
+
* @property registration_endpoint - Dynamic registration endpoint for tool registration
|
|
29
|
+
* @property jwks_uri - JSON Web Key Set endpoint for signature verification
|
|
30
|
+
* @property token_endpoint - OAuth 2.0 token endpoint for service access tokens
|
|
31
|
+
* @property scopes_supported - Array of OAuth scopes the platform supports (AGS, NRPS, etc.)
|
|
32
|
+
* @property https://purl.imsglobal.org/spec/lti-platform-configuration - LTI-specific platform metadata
|
|
33
|
+
*/
|
|
34
|
+
export declare const openIDConfigurationSchema: z.ZodObject<{
|
|
35
|
+
issuer: z.ZodURL;
|
|
36
|
+
authorization_endpoint: z.ZodURL;
|
|
37
|
+
registration_endpoint: z.ZodURL;
|
|
38
|
+
jwks_uri: z.ZodURL;
|
|
39
|
+
token_endpoint: z.ZodURL;
|
|
40
|
+
token_endpoint_auth_methods_supported: z.ZodArray<z.ZodString>;
|
|
41
|
+
token_endpoint_auth_signing_alg_values_supported: z.ZodArray<z.ZodString>;
|
|
42
|
+
scopes_supported: z.ZodArray<z.ZodString>;
|
|
43
|
+
response_types_supported: z.ZodArray<z.ZodString>;
|
|
44
|
+
id_token_signing_alg_values_supported: z.ZodArray<z.ZodString>;
|
|
45
|
+
claims_supported: z.ZodArray<z.ZodString>;
|
|
46
|
+
subject_types_supported: z.ZodArray<z.ZodString>;
|
|
47
|
+
authorization_server: z.ZodOptional<z.ZodString>;
|
|
48
|
+
'https://purl.imsglobal.org/spec/lti-platform-configuration': z.ZodObject<{
|
|
49
|
+
product_family_code: z.ZodString;
|
|
50
|
+
version: z.ZodString;
|
|
51
|
+
messages_supported: z.ZodArray<z.ZodObject<{
|
|
52
|
+
type: z.ZodString;
|
|
53
|
+
placements: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
54
|
+
}, z.core.$loose>>;
|
|
55
|
+
variables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
56
|
+
}, z.core.$strip>;
|
|
57
|
+
}, z.core.$loose>;
|
|
58
|
+
export type OpenIDConfiguration = z.infer<typeof openIDConfigurationSchema>;
|
|
59
|
+
//# sourceMappingURL=openIDConfiguration.schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openIDConfiguration.schema.d.ts","sourceRoot":"","sources":["../../../../src/schemas/lti13/dynamicRegistration/openIDConfiguration.schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAEzB;;;;;;;;GAQG;AACH,eAAO,MAAM,8BAA8B;;;;;;;;iBAYzC,CAAC;AAEH;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;iBAkB5B,CAAC;AAEX,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Zod schema for LTI platform-specific configuration within OpenID Connect Discovery.
|
|
4
|
+
* Contains LTI-specific metadata about the platform's capabilities and supported features.
|
|
5
|
+
*
|
|
6
|
+
* @property product_family_code - Platform identifier (e.g., 'moodle', 'canvas', 'sakai')
|
|
7
|
+
* @property version - Platform version string
|
|
8
|
+
* @property messages_supported - Array of LTI message types the platform supports
|
|
9
|
+
* @property variables - Optional array of custom variable names the platform supports
|
|
10
|
+
*/
|
|
11
|
+
export const ltiPlatformConfigurationSchema = z.object({
|
|
12
|
+
product_family_code: z.string(),
|
|
13
|
+
version: z.string(),
|
|
14
|
+
messages_supported: z.array(z
|
|
15
|
+
.object({
|
|
16
|
+
type: z.string(),
|
|
17
|
+
placements: z.array(z.string()).optional(),
|
|
18
|
+
})
|
|
19
|
+
.loose()),
|
|
20
|
+
variables: z.array(z.string()).optional(),
|
|
21
|
+
});
|
|
22
|
+
/**
|
|
23
|
+
* Zod schema for validating OpenID Connect Discovery configuration from LTI 1.3 platforms.
|
|
24
|
+
* This configuration is fetched during dynamic registration to discover platform endpoints,
|
|
25
|
+
* supported features, and security requirements. Used to validate the response from the
|
|
26
|
+
* platform's /.well-known/openid_configuration endpoint.
|
|
27
|
+
*
|
|
28
|
+
* @property issuer - Platform's issuer URL (must match hostname of configuration endpoint)
|
|
29
|
+
* @property authorization_endpoint - OAuth 2.0 authorization endpoint for LTI launches
|
|
30
|
+
* @property registration_endpoint - Dynamic registration endpoint for tool registration
|
|
31
|
+
* @property jwks_uri - JSON Web Key Set endpoint for signature verification
|
|
32
|
+
* @property token_endpoint - OAuth 2.0 token endpoint for service access tokens
|
|
33
|
+
* @property scopes_supported - Array of OAuth scopes the platform supports (AGS, NRPS, etc.)
|
|
34
|
+
* @property https://purl.imsglobal.org/spec/lti-platform-configuration - LTI-specific platform metadata
|
|
35
|
+
*/
|
|
36
|
+
export const openIDConfigurationSchema = z
|
|
37
|
+
.object({
|
|
38
|
+
issuer: z.url(),
|
|
39
|
+
authorization_endpoint: z.url(),
|
|
40
|
+
registration_endpoint: z.url(),
|
|
41
|
+
jwks_uri: z.url(),
|
|
42
|
+
token_endpoint: z.url(),
|
|
43
|
+
token_endpoint_auth_methods_supported: z.array(z.string()),
|
|
44
|
+
token_endpoint_auth_signing_alg_values_supported: z.array(z.string()),
|
|
45
|
+
scopes_supported: z.array(z.string()),
|
|
46
|
+
response_types_supported: z.array(z.string()),
|
|
47
|
+
id_token_signing_alg_values_supported: z.array(z.string()),
|
|
48
|
+
claims_supported: z.array(z.string()),
|
|
49
|
+
subject_types_supported: z.array(z.string()),
|
|
50
|
+
authorization_server: z.string().optional(),
|
|
51
|
+
'https://purl.imsglobal.org/spec/lti-platform-configuration': ltiPlatformConfigurationSchema,
|
|
52
|
+
})
|
|
53
|
+
.loose();
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
export declare const RegistrationRequestSchema: z.ZodObject<{
|
|
3
|
+
openid_configuration: z.ZodURL;
|
|
4
|
+
registration_token: z.ZodOptional<z.ZodString>;
|
|
5
|
+
}, z.core.$strip>;
|
|
6
|
+
export type RegistrationRequest = z.infer<typeof RegistrationRequestSchema>;
|
|
7
|
+
//# sourceMappingURL=registrationRequest.schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registrationRequest.schema.d.ts","sourceRoot":"","sources":["../../../../src/schemas/lti13/dynamicRegistration/registrationRequest.schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAEzB,eAAO,MAAM,yBAAyB;;;iBAGpC,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Zod schema for validating LTI 1.3 dynamic registration response from platforms.
|
|
4
|
+
* This response is returned after successfully registering a tool with an LTI platform.
|
|
5
|
+
* Contains the registered client credentials and configuration that the tool needs to store.
|
|
6
|
+
*
|
|
7
|
+
* @property client_id - Unique client identifier assigned by the platform
|
|
8
|
+
* @property registration_client_uri - Optional URI for managing this registration
|
|
9
|
+
* @property registration_access_token - Optional token for registration management
|
|
10
|
+
* @property application_type - Always 'web' for LTI tools
|
|
11
|
+
* @property response_types - OAuth response types, always ['id_token'] for LTI
|
|
12
|
+
* @property grant_types - OAuth grant types supported ('implicit', 'client_credentials')
|
|
13
|
+
* @property initiate_login_uri - Tool's login initiation endpoint
|
|
14
|
+
* @property redirect_uris - Array of valid redirect URIs for the tool
|
|
15
|
+
* @property client_name - Human-readable name of the registered tool
|
|
16
|
+
* @property jwks_uri - Tool's JSON Web Key Set endpoint for signature verification
|
|
17
|
+
* @property logo_uri - Optional URL to the tool's logo image
|
|
18
|
+
* @property token_endpoint_auth_method - Always 'private_key_jwt' for LTI 1.3
|
|
19
|
+
* @property contacts - Optional array of contact email addresses
|
|
20
|
+
* @property scope - Optional OAuth scopes granted to the tool
|
|
21
|
+
* @property https://purl.imsglobal.org/spec/lti-tool-configuration - LTI-specific tool configuration
|
|
22
|
+
*/
|
|
23
|
+
export declare const RegistrationResponseSchema: z.ZodObject<{
|
|
24
|
+
client_id: z.ZodString;
|
|
25
|
+
registration_client_uri: z.ZodOptional<z.ZodURL>;
|
|
26
|
+
registration_access_token: z.ZodOptional<z.ZodString>;
|
|
27
|
+
application_type: z.ZodLiteral<"web">;
|
|
28
|
+
response_types: z.ZodArray<z.ZodLiteral<"id_token">>;
|
|
29
|
+
grant_types: z.ZodArray<z.ZodEnum<{
|
|
30
|
+
implicit: "implicit";
|
|
31
|
+
client_credentials: "client_credentials";
|
|
32
|
+
}>>;
|
|
33
|
+
initiate_login_uri: z.ZodURL;
|
|
34
|
+
redirect_uris: z.ZodArray<z.ZodURL>;
|
|
35
|
+
client_name: z.ZodString;
|
|
36
|
+
jwks_uri: z.ZodURL;
|
|
37
|
+
logo_uri: z.ZodUnion<[z.ZodOptional<z.ZodURL>, z.ZodLiteral<"">]>;
|
|
38
|
+
token_endpoint_auth_method: z.ZodLiteral<"private_key_jwt">;
|
|
39
|
+
contacts: z.ZodOptional<z.ZodArray<z.ZodEmail>>;
|
|
40
|
+
scope: z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>;
|
|
41
|
+
'https://purl.imsglobal.org/spec/lti-tool-configuration': z.ZodObject<{
|
|
42
|
+
domain: z.ZodString;
|
|
43
|
+
target_link_uri: z.ZodOptional<z.ZodURL>;
|
|
44
|
+
custom_parameters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
45
|
+
claims: z.ZodArray<z.ZodString>;
|
|
46
|
+
messages: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
47
|
+
type: z.ZodLiteral<"LtiResourceLinkRequest">;
|
|
48
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
49
|
+
type: z.ZodLiteral<"LtiDeepLinkingRequest">;
|
|
50
|
+
target_link_uri: z.ZodOptional<z.ZodURL>;
|
|
51
|
+
label: z.ZodOptional<z.ZodString>;
|
|
52
|
+
placements: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
53
|
+
ContentArea: "ContentArea";
|
|
54
|
+
RichTextEditor: "RichTextEditor";
|
|
55
|
+
CourseNavigation: "CourseNavigation";
|
|
56
|
+
}>>>;
|
|
57
|
+
supported_types: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
58
|
+
file: "file";
|
|
59
|
+
ltiResourceLink: "ltiResourceLink";
|
|
60
|
+
html: "html";
|
|
61
|
+
link: "link";
|
|
62
|
+
image: "image";
|
|
63
|
+
}>>>;
|
|
64
|
+
supported_media_types: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
65
|
+
roles: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
66
|
+
custom_parameters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
67
|
+
}, z.core.$strip>], "type">>;
|
|
68
|
+
version: z.ZodOptional<z.ZodString>;
|
|
69
|
+
deployment_id: z.ZodOptional<z.ZodString>;
|
|
70
|
+
}, z.core.$strip>;
|
|
71
|
+
}, z.core.$strip>;
|
|
72
|
+
export type RegistrationResponse = z.infer<typeof RegistrationResponseSchema>;
|
|
73
|
+
//# sourceMappingURL=registrationResponse.schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registrationResponse.schema.d.ts","sourceRoot":"","sources":["../../../../src/schemas/lti13/dynamicRegistration/registrationResponse.schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AA0BzB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiBrC,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
import { LTIMessagesArraySchema } from './ltiMessages.schema';
|
|
3
|
+
/**
|
|
4
|
+
* Zod schema for LTI tool configuration within dynamic registration response.
|
|
5
|
+
* Contains tool-specific metadata returned by the platform after successful registration.
|
|
6
|
+
*
|
|
7
|
+
* @property domain - Tool's domain name for security validation
|
|
8
|
+
* @property target_link_uri - Optional default launch URL for the tool
|
|
9
|
+
* @property custom_parameters - Optional custom parameters passed to the tool
|
|
10
|
+
* @property claims - Array of JWT claims the tool requires (e.g., 'iss', 'sub', 'name', 'email')
|
|
11
|
+
* @property messages - Array of LTI message types the tool supports
|
|
12
|
+
* @property version - Optional tool version string
|
|
13
|
+
* @property deployment_id - Optional deployment identifier assigned by the platform
|
|
14
|
+
*/
|
|
15
|
+
const LTIToolConfigurationResponseSchema = z.object({
|
|
16
|
+
domain: z.string(),
|
|
17
|
+
target_link_uri: z.url().optional(),
|
|
18
|
+
custom_parameters: z.record(z.string(), z.string()).optional(),
|
|
19
|
+
claims: z.array(z.string()),
|
|
20
|
+
messages: LTIMessagesArraySchema,
|
|
21
|
+
version: z.string().optional(),
|
|
22
|
+
deployment_id: z.string().optional(),
|
|
23
|
+
});
|
|
24
|
+
/**
|
|
25
|
+
* Zod schema for validating LTI 1.3 dynamic registration response from platforms.
|
|
26
|
+
* This response is returned after successfully registering a tool with an LTI platform.
|
|
27
|
+
* Contains the registered client credentials and configuration that the tool needs to store.
|
|
28
|
+
*
|
|
29
|
+
* @property client_id - Unique client identifier assigned by the platform
|
|
30
|
+
* @property registration_client_uri - Optional URI for managing this registration
|
|
31
|
+
* @property registration_access_token - Optional token for registration management
|
|
32
|
+
* @property application_type - Always 'web' for LTI tools
|
|
33
|
+
* @property response_types - OAuth response types, always ['id_token'] for LTI
|
|
34
|
+
* @property grant_types - OAuth grant types supported ('implicit', 'client_credentials')
|
|
35
|
+
* @property initiate_login_uri - Tool's login initiation endpoint
|
|
36
|
+
* @property redirect_uris - Array of valid redirect URIs for the tool
|
|
37
|
+
* @property client_name - Human-readable name of the registered tool
|
|
38
|
+
* @property jwks_uri - Tool's JSON Web Key Set endpoint for signature verification
|
|
39
|
+
* @property logo_uri - Optional URL to the tool's logo image
|
|
40
|
+
* @property token_endpoint_auth_method - Always 'private_key_jwt' for LTI 1.3
|
|
41
|
+
* @property contacts - Optional array of contact email addresses
|
|
42
|
+
* @property scope - Optional OAuth scopes granted to the tool
|
|
43
|
+
* @property https://purl.imsglobal.org/spec/lti-tool-configuration - LTI-specific tool configuration
|
|
44
|
+
*/
|
|
45
|
+
export const RegistrationResponseSchema = z.object({
|
|
46
|
+
client_id: z.string(),
|
|
47
|
+
registration_client_uri: z.url().optional(),
|
|
48
|
+
registration_access_token: z.string().optional(),
|
|
49
|
+
application_type: z.literal('web'),
|
|
50
|
+
response_types: z.array(z.literal('id_token')),
|
|
51
|
+
grant_types: z.array(z.enum(['implicit', 'client_credentials'])), // Note: "implicit" not "implict"
|
|
52
|
+
initiate_login_uri: z.url(),
|
|
53
|
+
redirect_uris: z.array(z.url()),
|
|
54
|
+
client_name: z.string(),
|
|
55
|
+
jwks_uri: z.url(),
|
|
56
|
+
logo_uri: z.url().optional().or(z.literal('')),
|
|
57
|
+
token_endpoint_auth_method: z.literal('private_key_jwt'),
|
|
58
|
+
contacts: z.array(z.email()).optional(),
|
|
59
|
+
scope: z.string().optional().or(z.literal('')),
|
|
60
|
+
'https://purl.imsglobal.org/spec/lti-tool-configuration': LTIToolConfigurationResponseSchema,
|
|
61
|
+
});
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Zod schema for LTI tool configuration section within tool registration payload.
|
|
4
|
+
* Contains LTI-specific metadata about the tool being registered with the platform.
|
|
5
|
+
*
|
|
6
|
+
* @property domain - Tool's domain name for security validation and CORS policies
|
|
7
|
+
* @property description - Optional human-readable description of the tool's purpose
|
|
8
|
+
* @property target_link_uri - Default launch URL where the platform should send LTI requests
|
|
9
|
+
* @property claims - Array of JWT claims the tool requires from launch requests (e.g., 'iss', 'sub', 'name', 'email')
|
|
10
|
+
* @property messages - Array of LTI message types the tool supports (ResourceLink, DeepLinking, etc.)
|
|
11
|
+
*/
|
|
12
|
+
declare const LTIToolConfigurationSchema: z.ZodObject<{
|
|
13
|
+
domain: z.ZodString;
|
|
14
|
+
description: z.ZodOptional<z.ZodString>;
|
|
15
|
+
target_link_uri: z.ZodURL;
|
|
16
|
+
claims: z.ZodArray<z.ZodString>;
|
|
17
|
+
messages: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
18
|
+
type: z.ZodLiteral<"LtiResourceLinkRequest">;
|
|
19
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
20
|
+
type: z.ZodLiteral<"LtiDeepLinkingRequest">;
|
|
21
|
+
target_link_uri: z.ZodOptional<z.ZodURL>;
|
|
22
|
+
label: z.ZodOptional<z.ZodString>;
|
|
23
|
+
placements: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
24
|
+
ContentArea: "ContentArea";
|
|
25
|
+
RichTextEditor: "RichTextEditor";
|
|
26
|
+
CourseNavigation: "CourseNavigation";
|
|
27
|
+
}>>>;
|
|
28
|
+
supported_types: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
29
|
+
file: "file";
|
|
30
|
+
ltiResourceLink: "ltiResourceLink";
|
|
31
|
+
html: "html";
|
|
32
|
+
link: "link";
|
|
33
|
+
image: "image";
|
|
34
|
+
}>>>;
|
|
35
|
+
supported_media_types: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
36
|
+
roles: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
37
|
+
custom_parameters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
38
|
+
}, z.core.$strip>], "type">>;
|
|
39
|
+
}, z.core.$strip>;
|
|
40
|
+
/**
|
|
41
|
+
* Zod schema for validating LTI 1.3 dynamic registration payload sent to platforms.
|
|
42
|
+
* This payload is constructed by the tool and sent to the platform's registration endpoint
|
|
43
|
+
* to register the tool and request specific OAuth scopes and LTI services.
|
|
44
|
+
*
|
|
45
|
+
* @property application_type - Always 'web' for LTI tools
|
|
46
|
+
* @property response_types - OAuth response types, always ['id_token'] for LTI 1.3
|
|
47
|
+
* @property grant_types - OAuth grant types requested ('implicit' for launches, 'client_credentials' for services)
|
|
48
|
+
* @property initiate_login_uri - Tool's login initiation endpoint for OIDC flow
|
|
49
|
+
* @property redirect_uris - Array of valid redirect URIs where the platform can send responses
|
|
50
|
+
* @property client_name - Human-readable name of the tool being registered
|
|
51
|
+
* @property jwks_uri - Tool's JSON Web Key Set endpoint for signature verification
|
|
52
|
+
* @property logo_uri - Optional URL to the tool's logo image
|
|
53
|
+
* @property scope - Optional OAuth scopes being requested (AGS, NRPS, etc.)
|
|
54
|
+
* @property token_endpoint_auth_method - Always 'private_key_jwt' for LTI 1.3 security
|
|
55
|
+
* @property https://purl.imsglobal.org/spec/lti-tool-configuration - LTI-specific tool configuration
|
|
56
|
+
*/
|
|
57
|
+
export declare const ToolRegistrationPayloadSchema: z.ZodObject<{
|
|
58
|
+
application_type: z.ZodLiteral<"web">;
|
|
59
|
+
response_types: z.ZodArray<z.ZodLiteral<"id_token">>;
|
|
60
|
+
grant_types: z.ZodArray<z.ZodEnum<{
|
|
61
|
+
implicit: "implicit";
|
|
62
|
+
client_credentials: "client_credentials";
|
|
63
|
+
}>>;
|
|
64
|
+
initiate_login_uri: z.ZodURL;
|
|
65
|
+
redirect_uris: z.ZodArray<z.ZodURL>;
|
|
66
|
+
client_name: z.ZodString;
|
|
67
|
+
jwks_uri: z.ZodURL;
|
|
68
|
+
logo_uri: z.ZodOptional<z.ZodURL>;
|
|
69
|
+
scope: z.ZodOptional<z.ZodString>;
|
|
70
|
+
token_endpoint_auth_method: z.ZodLiteral<"private_key_jwt">;
|
|
71
|
+
'https://purl.imsglobal.org/spec/lti-tool-configuration': z.ZodObject<{
|
|
72
|
+
domain: z.ZodString;
|
|
73
|
+
description: z.ZodOptional<z.ZodString>;
|
|
74
|
+
target_link_uri: z.ZodURL;
|
|
75
|
+
claims: z.ZodArray<z.ZodString>;
|
|
76
|
+
messages: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
77
|
+
type: z.ZodLiteral<"LtiResourceLinkRequest">;
|
|
78
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
79
|
+
type: z.ZodLiteral<"LtiDeepLinkingRequest">;
|
|
80
|
+
target_link_uri: z.ZodOptional<z.ZodURL>;
|
|
81
|
+
label: z.ZodOptional<z.ZodString>;
|
|
82
|
+
placements: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
83
|
+
ContentArea: "ContentArea";
|
|
84
|
+
RichTextEditor: "RichTextEditor";
|
|
85
|
+
CourseNavigation: "CourseNavigation";
|
|
86
|
+
}>>>;
|
|
87
|
+
supported_types: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
88
|
+
file: "file";
|
|
89
|
+
ltiResourceLink: "ltiResourceLink";
|
|
90
|
+
html: "html";
|
|
91
|
+
link: "link";
|
|
92
|
+
image: "image";
|
|
93
|
+
}>>>;
|
|
94
|
+
supported_media_types: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
95
|
+
roles: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
96
|
+
custom_parameters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
97
|
+
}, z.core.$strip>], "type">>;
|
|
98
|
+
}, z.core.$strip>;
|
|
99
|
+
}, z.core.$strip>;
|
|
100
|
+
export type ToolRegistrationPayload = z.infer<typeof ToolRegistrationPayloadSchema>;
|
|
101
|
+
export type LTIToolConfiguration = z.infer<typeof LTIToolConfigurationSchema>;
|
|
102
|
+
export {};
|
|
103
|
+
//# sourceMappingURL=toolRegistrationPayload.schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolRegistrationPayload.schema.d.ts","sourceRoot":"","sources":["../../../../src/schemas/lti13/dynamicRegistration/toolRegistrationPayload.schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAIzB;;;;;;;;;GASG;AACH,QAAA,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAM9B,CAAC;AAEH;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAYxC,CAAC;AAEH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AACpF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
import { LTIMessagesArraySchema } from './ltiMessages.schema';
|
|
3
|
+
/**
|
|
4
|
+
* Zod schema for LTI tool configuration section within tool registration payload.
|
|
5
|
+
* Contains LTI-specific metadata about the tool being registered with the platform.
|
|
6
|
+
*
|
|
7
|
+
* @property domain - Tool's domain name for security validation and CORS policies
|
|
8
|
+
* @property description - Optional human-readable description of the tool's purpose
|
|
9
|
+
* @property target_link_uri - Default launch URL where the platform should send LTI requests
|
|
10
|
+
* @property claims - Array of JWT claims the tool requires from launch requests (e.g., 'iss', 'sub', 'name', 'email')
|
|
11
|
+
* @property messages - Array of LTI message types the tool supports (ResourceLink, DeepLinking, etc.)
|
|
12
|
+
*/
|
|
13
|
+
const LTIToolConfigurationSchema = z.object({
|
|
14
|
+
domain: z.string(),
|
|
15
|
+
description: z.string().optional(),
|
|
16
|
+
target_link_uri: z.url(),
|
|
17
|
+
claims: z.array(z.string()),
|
|
18
|
+
messages: LTIMessagesArraySchema,
|
|
19
|
+
});
|
|
20
|
+
/**
|
|
21
|
+
* Zod schema for validating LTI 1.3 dynamic registration payload sent to platforms.
|
|
22
|
+
* This payload is constructed by the tool and sent to the platform's registration endpoint
|
|
23
|
+
* to register the tool and request specific OAuth scopes and LTI services.
|
|
24
|
+
*
|
|
25
|
+
* @property application_type - Always 'web' for LTI tools
|
|
26
|
+
* @property response_types - OAuth response types, always ['id_token'] for LTI 1.3
|
|
27
|
+
* @property grant_types - OAuth grant types requested ('implicit' for launches, 'client_credentials' for services)
|
|
28
|
+
* @property initiate_login_uri - Tool's login initiation endpoint for OIDC flow
|
|
29
|
+
* @property redirect_uris - Array of valid redirect URIs where the platform can send responses
|
|
30
|
+
* @property client_name - Human-readable name of the tool being registered
|
|
31
|
+
* @property jwks_uri - Tool's JSON Web Key Set endpoint for signature verification
|
|
32
|
+
* @property logo_uri - Optional URL to the tool's logo image
|
|
33
|
+
* @property scope - Optional OAuth scopes being requested (AGS, NRPS, etc.)
|
|
34
|
+
* @property token_endpoint_auth_method - Always 'private_key_jwt' for LTI 1.3 security
|
|
35
|
+
* @property https://purl.imsglobal.org/spec/lti-tool-configuration - LTI-specific tool configuration
|
|
36
|
+
*/
|
|
37
|
+
export const ToolRegistrationPayloadSchema = z.object({
|
|
38
|
+
application_type: z.literal('web'),
|
|
39
|
+
response_types: z.array(z.literal('id_token')),
|
|
40
|
+
grant_types: z.array(z.enum(['implicit', 'client_credentials'])),
|
|
41
|
+
initiate_login_uri: z.url(),
|
|
42
|
+
redirect_uris: z.array(z.url()),
|
|
43
|
+
client_name: z.string(),
|
|
44
|
+
jwks_uri: z.url(),
|
|
45
|
+
logo_uri: z.url().optional(),
|
|
46
|
+
scope: z.string().optional(),
|
|
47
|
+
token_endpoint_auth_method: z.literal('private_key_jwt'),
|
|
48
|
+
'https://purl.imsglobal.org/spec/lti-tool-configuration': LTIToolConfigurationSchema,
|
|
49
|
+
});
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { BaseLogger } from 'pino';
|
|
2
|
+
import type { DynamicRegistrationConfig } from '../interfaces/ltiConfig.js';
|
|
3
|
+
import type { LTIDynamicRegistrationSession } from '../interfaces/ltiDynamicRegistrationSession.js';
|
|
4
|
+
import type { LTIStorage } from '../interfaces/ltiStorage.js';
|
|
5
|
+
import type { DynamicRegistrationForm } from '../schemas/lti13/dynamicRegistration/ltiDynamicRegistration.schema.js';
|
|
6
|
+
import { type OpenIDConfiguration } from '../schemas/lti13/dynamicRegistration/openIDConfiguration.schema.js';
|
|
7
|
+
import type { RegistrationRequest } from '../schemas/lti13/dynamicRegistration/registrationRequest.schema.js';
|
|
8
|
+
/**
|
|
9
|
+
* Service for handling LTI 1.3 dynamic registration workflows.
|
|
10
|
+
*
|
|
11
|
+
* Provides a complete implementation of the LTI 1.3 Dynamic Registration specification,
|
|
12
|
+
* enabling tools to automatically register with LTI platforms without manual configuration.
|
|
13
|
+
* Handles the full registration lifecycle from initiation to completion with security validation.
|
|
14
|
+
*
|
|
15
|
+
* ## Key Features
|
|
16
|
+
* - **Platform Discovery**: Fetches and validates OpenID Connect configuration from LTI platforms
|
|
17
|
+
* - **Security Validation**: Enforces hostname matching and session-based CSRF protection
|
|
18
|
+
* - **Vendor Support**: Provides platform-specific registration forms (Moodle, with extensibility for Canvas, Sakai, etc.)
|
|
19
|
+
* - **Service Selection**: Allows administrators to choose which LTI Advantage services to enable (AGS, NRPS, Deep Linking)
|
|
20
|
+
* - **Automatic Storage**: Persists client and deployment configurations for future launches
|
|
21
|
+
*
|
|
22
|
+
* ## Registration Flow
|
|
23
|
+
* 1. **Initiation**: Platform redirects to tool with registration request
|
|
24
|
+
* 2. **Discovery**: Tool fetches platform's OpenID Connect configuration
|
|
25
|
+
* 3. **Form Generation**: Tool presents service selection form to administrator
|
|
26
|
+
* 4. **Registration**: Tool submits registration payload to platform
|
|
27
|
+
* 5. **Storage**: Tool stores received client credentials and deployment information
|
|
28
|
+
*
|
|
29
|
+
* ## Security Features
|
|
30
|
+
* - Session-based registration with 15-minute expiration
|
|
31
|
+
* - CSRF protection via secure session tokens
|
|
32
|
+
* - Hostname validation between OIDC endpoint and issuer
|
|
33
|
+
* - One-time session consumption to prevent replay attacks
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* const service = new DynamicRegistrationService(
|
|
38
|
+
* storage,
|
|
39
|
+
* dynamicRegistrationConfig,
|
|
40
|
+
* logger
|
|
41
|
+
* );
|
|
42
|
+
*
|
|
43
|
+
* // Initiate registration
|
|
44
|
+
* const formHtml = await service.initiateDynamicRegistration(request, '/lti/register');
|
|
45
|
+
*
|
|
46
|
+
* // Complete registration
|
|
47
|
+
* const successHtml = await service.completeDynamicRegistration(formData);
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @see https://www.imsglobal.org/spec/lti-dr/v1p0 LTI 1.3 Dynamic Registration specification
|
|
51
|
+
*/
|
|
52
|
+
export declare class DynamicRegistrationService {
|
|
53
|
+
private storage;
|
|
54
|
+
private dynamicRegistrationConfig;
|
|
55
|
+
private logger;
|
|
56
|
+
constructor(storage: LTIStorage, dynamicRegistrationConfig: DynamicRegistrationConfig, logger: BaseLogger);
|
|
57
|
+
/**
|
|
58
|
+
* Fetches and validates the OpenID Connect configuration from an LTI platform during dynamic registration.
|
|
59
|
+
* Validates that the OIDC endpoint and issuer have matching hostnames for security.
|
|
60
|
+
*
|
|
61
|
+
* @param registrationRequest - Registration request containing openid_configuration URL and optional registration_token
|
|
62
|
+
* @returns Validated OpenID configuration with platform endpoints and supported features
|
|
63
|
+
* @throws {Error} When the configuration fetch fails, validation fails, or hostname mismatch detected
|
|
64
|
+
*/
|
|
65
|
+
fetchPlatformConfiguration(registrationRequest: RegistrationRequest): Promise<OpenIDConfiguration>;
|
|
66
|
+
/**
|
|
67
|
+
* Initiates LTI 1.3 dynamic registration by fetching platform configuration and generating registration form.
|
|
68
|
+
* Creates a temporary session and returns vendor-specific HTML form for service selection.
|
|
69
|
+
*
|
|
70
|
+
* @param registrationRequest - Registration request containing openid_configuration URL and optional registration_token
|
|
71
|
+
* @param requestPath - Current request path used to build form action URLs
|
|
72
|
+
* @returns HTML form for service selection and registration completion
|
|
73
|
+
* @throws {Error} When platform configuration fetch fails or session creation fails
|
|
74
|
+
*/
|
|
75
|
+
initiateDynamicRegistration(registrationRequest: RegistrationRequest, requestPath: string): Promise<string>;
|
|
76
|
+
/**
|
|
77
|
+
* Completes LTI 1.3 dynamic registration by processing form submission and storing client configuration.
|
|
78
|
+
* Validates session, registers with platform, stores client/deployment data, and returns success page.
|
|
79
|
+
*
|
|
80
|
+
* @param dynamicRegistrationForm - Validated form data containing selected services and session token
|
|
81
|
+
* @returns HTML success page with registration details and close button
|
|
82
|
+
* @throws {Error} When session is invalid, registration fails, or storage operations fail
|
|
83
|
+
*/
|
|
84
|
+
completeDynamicRegistration(dynamicRegistrationForm: DynamicRegistrationForm): Promise<string>;
|
|
85
|
+
/**
|
|
86
|
+
* Verifies and consumes a registration session token for security validation.
|
|
87
|
+
* Retrieves the session data and immediately deletes it to prevent replay attacks.
|
|
88
|
+
*
|
|
89
|
+
* @param sessionToken - UUID session token from the registration form
|
|
90
|
+
* @returns Session data if valid and not expired, undefined otherwise
|
|
91
|
+
*/
|
|
92
|
+
verifyRegistrationSession(sessionToken: string): Promise<LTIDynamicRegistrationSession | undefined>;
|
|
93
|
+
/**
|
|
94
|
+
* Builds array of LTI message types based on selected services during registration.
|
|
95
|
+
* Always includes ResourceLinkRequest, conditionally adds DeepLinkingRequest.
|
|
96
|
+
*
|
|
97
|
+
* @param selectedServices - Array of service names selected by administrator
|
|
98
|
+
* @param deepLinkingUri - URI where deep linking requests should be sent
|
|
99
|
+
* @returns Array of LTI message configurations for the registration payload
|
|
100
|
+
*/
|
|
101
|
+
private buildMessages;
|
|
102
|
+
/**
|
|
103
|
+
* Builds array of OAuth scopes based on selected LTI services during registration.
|
|
104
|
+
* Maps service selections to their corresponding LTI Advantage scope URIs.
|
|
105
|
+
*
|
|
106
|
+
* @param selectedServices - Array of service names selected by administrator ('ags', 'nrps', etc.)
|
|
107
|
+
* @returns Array of OAuth scope URIs to request from the platform
|
|
108
|
+
*/
|
|
109
|
+
private buildScopes;
|
|
110
|
+
/**
|
|
111
|
+
* Constructs the complete tool registration payload for platform submission.
|
|
112
|
+
* Combines tool configuration, selected services, and OAuth parameters into LTI 1.3 registration format.
|
|
113
|
+
*
|
|
114
|
+
* @param selectedServices - Array of service names selected by administrator
|
|
115
|
+
* @returns Complete registration payload ready for platform submission
|
|
116
|
+
*/
|
|
117
|
+
private buildRegistrationPayload;
|
|
118
|
+
private validateDynamicRegistrationResponse;
|
|
119
|
+
private getRegistrationSuccessHtml;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=dynamicRegistration.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dynamicRegistration.service.d.ts","sourceRoot":"","sources":["../../src/services/dynamicRegistration.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAEvC,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAC5E,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,gDAAgD,CAAC;AACpG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,uEAAuE,CAAC;AAErH,OAAO,EACL,KAAK,mBAAmB,EAEzB,MAAM,oEAAoE,CAAC;AAC5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oEAAoE,CAAC;AAS9G;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,qBAAa,0BAA0B;IAEnC,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,yBAAyB;IACjC,OAAO,CAAC,MAAM;gBAFN,OAAO,EAAE,UAAU,EACnB,yBAAyB,EAAE,yBAAyB,EACpD,MAAM,EAAE,UAAU;IAG5B;;;;;;;OAOG;IACG,0BAA0B,CAC9B,mBAAmB,EAAE,mBAAmB,GACvC,OAAO,CAAC,mBAAmB,CAAC;IAkC/B;;;;;;;;OAQG;IACG,2BAA2B,CAC/B,mBAAmB,EAAE,mBAAmB,EACxC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC;IAsClB;;;;;;;OAOG;IACG,2BAA2B,CAC/B,uBAAuB,EAAE,uBAAuB,GAC/C,OAAO,CAAC,MAAM,CAAC;IAoDlB;;;;;;OAMG;IACG,yBAAyB,CAC7B,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,6BAA6B,GAAG,SAAS,CAAC;IAQrD;;;;;;;OAOG;IACH,OAAO,CAAC,aAAa;IAoBrB;;;;;;OAMG;IACH,OAAO,CAAC,WAAW;IAoBnB;;;;;;OAMG;IACH,OAAO,CAAC,wBAAwB;YAkClB,mCAAmC;IAgBjD,OAAO,CAAC,0BAA0B;CAiDnC"}
|