@cxbuilder/flow-config 1.0.2 → 2.0.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.
Files changed (35) hide show
  1. package/.jsii +145 -68
  2. package/CHANGELOG.md +38 -0
  3. package/README.md +8 -5
  4. package/dist/backend/FlowConfig/index.js +111 -16
  5. package/dist/backend/FlowConfig/index.js.map +3 -3
  6. package/dist/backend/GetConfig/index.js +1 -1
  7. package/dist/backend/GetConfig/index.js.map +2 -2
  8. package/dist/backend/Init/index.js +2 -1
  9. package/dist/backend/Init/index.js.map +2 -2
  10. package/dist/backend/Settings/index.js +255 -0
  11. package/dist/backend/Settings/index.js.map +7 -0
  12. package/dist/backend/Static/static/assets/index-Cejunttu.js +61 -0
  13. package/dist/backend/Static/static/assets/{index-NRh8x3FI.css → index-SZuscj14.css} +1 -1
  14. package/dist/backend/Static/static/index.html +3 -3
  15. package/dist/infrastructure/FlowConfigStack.d.ts +36 -14
  16. package/dist/infrastructure/FlowConfigStack.js +54 -18
  17. package/dist/infrastructure/GetConfig/index.js +2 -2
  18. package/dist/infrastructure/api/Api.d.ts +5 -2
  19. package/dist/infrastructure/api/Api.js +21 -15
  20. package/dist/infrastructure/api/Init/Init.interface.d.ts +4 -0
  21. package/dist/infrastructure/api/Init/Init.interface.js +1 -1
  22. package/dist/infrastructure/api/Init/index.js +2 -1
  23. package/dist/infrastructure/api/Settings/Settings.interface.d.ts +3 -0
  24. package/dist/infrastructure/api/Settings/Settings.interface.js +3 -0
  25. package/dist/infrastructure/api/Settings/index.d.ts +7 -0
  26. package/dist/infrastructure/api/Settings/index.js +21 -0
  27. package/dist/infrastructure/api/spec.yaml +122 -0
  28. package/dist/infrastructure/createLambda.js +1 -1
  29. package/dist/infrastructure/index.d.ts +1 -1
  30. package/dist/infrastructure/index.js +1 -1
  31. package/dist/infrastructure/tsconfig.tsbuildinfo +1 -1
  32. package/docs/Permissions-v1.md +132 -0
  33. package/docs/{Permissions.md → Permissions-v2.md} +15 -15
  34. package/package.json +1 -1
  35. package/dist/backend/Static/static/assets/index-Bx9Z3cF9.js +0 -61
@@ -0,0 +1,255 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // backend/Settings.ts
22
+ var Settings_exports = {};
23
+ __export(Settings_exports, {
24
+ handler: () => handler
25
+ });
26
+ module.exports = __toCommonJS(Settings_exports);
27
+ var import_client_dynamodb = require("@aws-sdk/client-dynamodb");
28
+ var import_lib_dynamodb = require("@aws-sdk/lib-dynamodb");
29
+
30
+ // backend/shared/logger.ts
31
+ var import_logger = require("@aws-lambda-powertools/logger");
32
+ var logger = new import_logger.Logger();
33
+
34
+ // backend/shared/respond.ts
35
+ var respond = /* @__PURE__ */ __name((statusCode, body) => ({
36
+ statusCode,
37
+ body
38
+ }), "respond");
39
+ var respondObject = /* @__PURE__ */ __name((statusCode, obj) => respond(statusCode, JSON.stringify(obj)), "respondObject");
40
+
41
+ // backend/shared/permissions.ts
42
+ var COGNITO_GROUPS = {
43
+ ADMIN: "FlowConfigAdmin",
44
+ EDIT: "FlowConfigEdit",
45
+ READ: "FlowConfigRead"
46
+ };
47
+ function extractCognitoGroups(claims) {
48
+ const groupsClaim = claims["cognito:groups"];
49
+ if (!groupsClaim) {
50
+ return [];
51
+ }
52
+ if (typeof groupsClaim === "string") {
53
+ return groupsClaim.split(",").map((group) => group.trim());
54
+ }
55
+ if (Array.isArray(groupsClaim)) {
56
+ return groupsClaim;
57
+ }
58
+ return [];
59
+ }
60
+ __name(extractCognitoGroups, "extractCognitoGroups");
61
+ function getAccessLevel(claims) {
62
+ const userGroups = extractCognitoGroups(claims);
63
+ if (userGroups.includes(COGNITO_GROUPS.ADMIN)) {
64
+ return "Full";
65
+ }
66
+ if (userGroups.includes(COGNITO_GROUPS.EDIT)) {
67
+ return "Edit";
68
+ }
69
+ if (userGroups.includes(COGNITO_GROUPS.READ)) {
70
+ return "Read";
71
+ }
72
+ return null;
73
+ }
74
+ __name(getAccessLevel, "getAccessLevel");
75
+
76
+ // backend/Settings.ts
77
+ var client = new import_client_dynamodb.DynamoDBClient({ region: process.env.AWS_REGION });
78
+ var docClient = import_lib_dynamodb.DynamoDBDocumentClient.from(client);
79
+ var env = process.env;
80
+ var SETTINGS_ITEM_ID = "application-settings";
81
+ var DEFAULT_SETTINGS = {
82
+ locales: [
83
+ {
84
+ code: "en-US",
85
+ name: "English (US)",
86
+ voices: ["Joanna"]
87
+ }
88
+ ]
89
+ };
90
+ function validateSettings(settings) {
91
+ if (!settings || typeof settings !== "object") {
92
+ return false;
93
+ }
94
+ if (!Array.isArray(settings.locales)) {
95
+ return false;
96
+ }
97
+ for (const locale of settings.locales) {
98
+ if (!locale || typeof locale !== "object") {
99
+ return false;
100
+ }
101
+ if (!locale.code || typeof locale.code !== "string") {
102
+ return false;
103
+ }
104
+ if (!locale.name || typeof locale.name !== "string") {
105
+ return false;
106
+ }
107
+ if (!Array.isArray(locale.voices)) {
108
+ return false;
109
+ }
110
+ for (const voice of locale.voices) {
111
+ if (typeof voice !== "string") {
112
+ return false;
113
+ }
114
+ }
115
+ const languageCodePattern = /^([a-z]{2,3}(-[A-Z]{2})?(-[A-Z]{3})?|arb)$/;
116
+ if (!languageCodePattern.test(locale.code)) {
117
+ return false;
118
+ }
119
+ }
120
+ return true;
121
+ }
122
+ __name(validateSettings, "validateSettings");
123
+ async function getSettings() {
124
+ try {
125
+ const command = new import_lib_dynamodb.GetCommand({
126
+ TableName: env.TABLE_NAME,
127
+ Key: { id: SETTINGS_ITEM_ID }
128
+ });
129
+ const response = await docClient.send(command);
130
+ if (!response.Item) {
131
+ logger.info("No settings found, returning default settings");
132
+ return DEFAULT_SETTINGS;
133
+ }
134
+ const item = response.Item;
135
+ return item.settings;
136
+ } catch (error) {
137
+ logger.error("Error retrieving settings from DynamoDB", error);
138
+ throw error;
139
+ }
140
+ }
141
+ __name(getSettings, "getSettings");
142
+ async function saveSettings(settings, userId) {
143
+ try {
144
+ const item = {
145
+ id: SETTINGS_ITEM_ID,
146
+ settings,
147
+ lastModified: (/* @__PURE__ */ new Date()).toISOString(),
148
+ lastModifiedBy: userId
149
+ };
150
+ const command = new import_lib_dynamodb.PutCommand({
151
+ TableName: env.TABLE_NAME,
152
+ Item: item
153
+ });
154
+ await docClient.send(command);
155
+ logger.info("Settings saved successfully", {
156
+ userId,
157
+ settingsCount: settings.locales.length
158
+ });
159
+ return settings;
160
+ } catch (error) {
161
+ logger.error("Error saving settings to DynamoDB", error);
162
+ throw error;
163
+ }
164
+ }
165
+ __name(saveSettings, "saveSettings");
166
+ async function handleGetSettings() {
167
+ try {
168
+ const settings = await getSettings();
169
+ return respondObject(200, settings);
170
+ } catch (error) {
171
+ logger.error("Error handling GET settings request", error);
172
+ return respondObject(500, {
173
+ code: "INTERNAL_ERROR",
174
+ message: "Failed to retrieve settings"
175
+ });
176
+ }
177
+ }
178
+ __name(handleGetSettings, "handleGetSettings");
179
+ async function handlePostSettings(event) {
180
+ try {
181
+ const claims = event.requestContext.authorizer?.claims || {};
182
+ const accessLevel = getAccessLevel(claims);
183
+ if (accessLevel !== "Full") {
184
+ logger.warn("Access denied - admin access required", {
185
+ userId: claims.sub,
186
+ accessLevel
187
+ });
188
+ return respondObject(403, {
189
+ code: "FORBIDDEN",
190
+ message: "Admin access required"
191
+ });
192
+ }
193
+ if (!event.body) {
194
+ return respondObject(400, {
195
+ code: "INVALID_REQUEST",
196
+ message: "Request body is required"
197
+ });
198
+ }
199
+ let settings;
200
+ try {
201
+ settings = JSON.parse(event.body);
202
+ } catch (error) {
203
+ return respondObject(400, {
204
+ code: "INVALID_JSON",
205
+ message: "Invalid JSON in request body"
206
+ });
207
+ }
208
+ if (!validateSettings(settings)) {
209
+ return respondObject(400, {
210
+ code: "INVALID_SETTINGS",
211
+ message: "Invalid settings format"
212
+ });
213
+ }
214
+ const userId = event.requestContext.authorizer?.claims?.sub || "unknown";
215
+ const savedSettings = await saveSettings(settings, userId);
216
+ return respondObject(200, savedSettings);
217
+ } catch (error) {
218
+ logger.error("Error handling POST settings request", error);
219
+ return respondObject(500, {
220
+ code: "INTERNAL_ERROR",
221
+ message: "Failed to save settings"
222
+ });
223
+ }
224
+ }
225
+ __name(handlePostSettings, "handlePostSettings");
226
+ var handler = /* @__PURE__ */ __name(async (event) => {
227
+ logger.info("Settings handler invoked", {
228
+ httpMethod: event.httpMethod,
229
+ path: event.path
230
+ });
231
+ try {
232
+ switch (event.httpMethod) {
233
+ case "GET":
234
+ return await handleGetSettings();
235
+ case "POST":
236
+ return await handlePostSettings(event);
237
+ default:
238
+ return respondObject(405, {
239
+ code: "METHOD_NOT_ALLOWED",
240
+ message: `Method ${event.httpMethod} not allowed`
241
+ });
242
+ }
243
+ } catch (error) {
244
+ logger.error("Unexpected error in settings handler", error);
245
+ return respondObject(500, {
246
+ code: "INTERNAL_ERROR",
247
+ message: "Internal server error"
248
+ });
249
+ }
250
+ }, "handler");
251
+ // Annotate the CommonJS export names for ESM import in node:
252
+ 0 && (module.exports = {
253
+ handler
254
+ });
255
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../backend/Settings.ts", "../../../backend/shared/logger.ts", "../../../backend/shared/respond.ts", "../../../backend/shared/permissions.ts"],
4
+ "sourcesContent": ["import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';\nimport { DynamoDBClient } from '@aws-sdk/client-dynamodb';\nimport {\n DynamoDBDocumentClient,\n GetCommand,\n PutCommand,\n} from '@aws-sdk/lib-dynamodb';\nimport { logger } from './shared/logger';\nimport { respondObject } from './shared/respond';\nimport { getAccessLevel } from './shared/permissions';\nimport { Settings } from './shared/models';\nimport { SettingsEnv } from '../infrastructure/api/Settings/Settings.interface';\n\nconst client = new DynamoDBClient({ region: process.env.AWS_REGION });\nconst docClient = DynamoDBDocumentClient.from(client);\n\nconst env = process.env as unknown as SettingsEnv;\n\n// Settings item ID - we use a single item to store all settings\nconst SETTINGS_ITEM_ID = 'application-settings';\n\n// Data structures - using shared types from models\n\ninterface SettingsItem {\n id: string;\n settings: Settings;\n lastModified: string;\n lastModifiedBy: string;\n}\n\n// Default settings\nconst DEFAULT_SETTINGS: Settings = {\n locales: [\n {\n code: 'en-US',\n name: 'English (US)',\n voices: ['Joanna'],\n },\n ],\n};\n\n/**\n * Validates the settings object\n */\nfunction validateSettings(settings: any): settings is Settings {\n if (!settings || typeof settings !== 'object') {\n return false;\n }\n\n if (!Array.isArray(settings.locales)) {\n return false;\n }\n\n // Validate each locale\n for (const locale of settings.locales) {\n if (!locale || typeof locale !== 'object') {\n return false;\n }\n\n if (!locale.code || typeof locale.code !== 'string') {\n return false;\n }\n\n if (!locale.name || typeof locale.name !== 'string') {\n return false;\n }\n\n if (!Array.isArray(locale.voices)) {\n return false;\n }\n\n // Validate voice IDs are strings\n for (const voice of locale.voices) {\n if (typeof voice !== 'string') {\n return false;\n }\n }\n\n // Validate language code format (Amazon Polly format)\n const languageCodePattern = /^([a-z]{2,3}(-[A-Z]{2})?(-[A-Z]{3})?|arb)$/;\n if (!languageCodePattern.test(locale.code)) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Get settings from DynamoDB\n */\nasync function getSettings(): Promise<Settings> {\n try {\n const command = new GetCommand({\n TableName: env.TABLE_NAME,\n Key: { id: SETTINGS_ITEM_ID },\n });\n\n const response = await docClient.send(command);\n\n if (!response.Item) {\n logger.info('No settings found, returning default settings');\n return DEFAULT_SETTINGS;\n }\n\n const item = response.Item as SettingsItem;\n return item.settings;\n } catch (error) {\n logger.error('Error retrieving settings from DynamoDB', error as Error);\n throw error;\n }\n}\n\n/**\n * Save settings to DynamoDB\n */\nasync function saveSettings(\n settings: Settings,\n userId: string\n): Promise<Settings> {\n try {\n const item: SettingsItem = {\n id: SETTINGS_ITEM_ID,\n settings,\n lastModified: new Date().toISOString(),\n lastModifiedBy: userId,\n };\n\n const command = new PutCommand({\n TableName: env.TABLE_NAME,\n Item: item,\n });\n\n await docClient.send(command);\n logger.info('Settings saved successfully', {\n userId,\n settingsCount: settings.locales.length,\n });\n\n return settings;\n } catch (error) {\n logger.error('Error saving settings to DynamoDB', error as Error);\n throw error;\n }\n}\n\n/**\n * Handle GET /api/settings\n */\nasync function handleGetSettings(): Promise<APIGatewayProxyResult> {\n try {\n const settings = await getSettings();\n\n return respondObject(200, settings);\n } catch (error) {\n logger.error('Error handling GET settings request', error as Error);\n return respondObject(500, {\n code: 'INTERNAL_ERROR',\n message: 'Failed to retrieve settings',\n });\n }\n}\n\n/**\n * Handle POST /api/settings\n */\nasync function handlePostSettings(\n event: APIGatewayProxyEvent\n): Promise<APIGatewayProxyResult> {\n try {\n // Get user claims and check access level\n const claims = event.requestContext.authorizer?.claims || {};\n const accessLevel = getAccessLevel(claims);\n\n // Check if user has admin access\n if (accessLevel !== 'Full') {\n logger.warn('Access denied - admin access required', {\n userId: claims.sub,\n accessLevel,\n });\n return respondObject(403, {\n code: 'FORBIDDEN',\n message: 'Admin access required',\n });\n }\n\n // Parse request body\n if (!event.body) {\n return respondObject(400, {\n code: 'INVALID_REQUEST',\n message: 'Request body is required',\n });\n }\n\n let settings: Settings;\n try {\n settings = JSON.parse(event.body);\n } catch (error) {\n return respondObject(400, {\n code: 'INVALID_JSON',\n message: 'Invalid JSON in request body',\n });\n }\n\n // Validate settings\n if (!validateSettings(settings)) {\n return respondObject(400, {\n code: 'INVALID_SETTINGS',\n message: 'Invalid settings format',\n });\n }\n\n // Get user ID from Cognito claims\n const userId = event.requestContext.authorizer?.claims?.sub || 'unknown';\n\n // Save settings\n const savedSettings = await saveSettings(settings, userId);\n\n return respondObject(200, savedSettings);\n } catch (error) {\n logger.error('Error handling POST settings request', error as Error);\n return respondObject(500, {\n code: 'INTERNAL_ERROR',\n message: 'Failed to save settings',\n });\n }\n}\n\n/**\n * Main Lambda handler\n */\nexport const handler = async (\n event: APIGatewayProxyEvent\n): Promise<APIGatewayProxyResult> => {\n logger.info('Settings handler invoked', {\n httpMethod: event.httpMethod,\n path: event.path,\n });\n\n try {\n // Route based on HTTP method\n switch (event.httpMethod) {\n case 'GET':\n return await handleGetSettings();\n case 'POST':\n return await handlePostSettings(event);\n default:\n return respondObject(405, {\n code: 'METHOD_NOT_ALLOWED',\n message: `Method ${event.httpMethod} not allowed`,\n });\n }\n } catch (error) {\n logger.error('Unexpected error in settings handler', error as Error);\n return respondObject(500, {\n code: 'INTERNAL_ERROR',\n message: 'Internal server error',\n });\n }\n};\n", "import { Logger } from '@aws-lambda-powertools/logger';\nimport { ConnectContactFlowEvent, Context } from 'aws-lambda';\n\nexport const logger = new Logger();\n\n/**\n * Call this method in your lambda handler to capture event details\n * @todo use logger.appendKeys to add attributes like ContactId\n */\nexport const logEvent = (event?: unknown, context?: Context) => {\n if (context) {\n logger.addContext(context);\n }\n if (event) {\n logger.logEventIfEnabled(event);\n }\n\n const ContactData = (event as ConnectContactFlowEvent)?.Details?.ContactData;\n if (ContactData) {\n const { InstanceARN, ContactId } = ContactData;\n logger.appendKeys({\n connectInstanceId: InstanceARN?.split('/').pop(),\n connectContactId: ContactId\n });\n }\n};\n", "// Utility functions for consistent API response\n\nimport { logger } from './logger';\n\nexport const respond = (statusCode: number, body: string) => ({\n statusCode,\n body,\n});\n\nexport const respondObject = (statusCode: number, obj?: object) =>\n respond(statusCode, JSON.stringify(obj));\n\nexport const respondMessage = (statusCode: number, message: string) =>\n respondObject(statusCode, { message });\n\n/**\n * Log error and respond with HTTP 500\n * Note: You can conditionally hide the message from the user based on environment\n */\nexport const respondError = (error: unknown) => {\n logger.error('Unhandled Server Error', error as Error);\n return respondMessage(500, (error as Error).message);\n};\n", "/**\n * Cognito User Groups permission validation utilities\n * \n * This module provides functions to validate user permissions based on\n * Cognito User Group membership for role-based access control (RBAC).\n */\n\nexport type AccessLevel = 'Full' | 'Edit' | 'Read';\nexport type Action = 'Create' | 'Read' | 'Edit' | 'Delete';\n\n/**\n * Cognito User Groups for FlowConfig application\n */\nexport const COGNITO_GROUPS = {\n ADMIN: 'FlowConfigAdmin',\n EDIT: 'FlowConfigEdit',\n READ: 'FlowConfigRead',\n} as const;\n\n/**\n * Extract Cognito groups from user claims\n * @param claims User claims from Cognito JWT token\n * @returns Array of group names the user belongs to\n */\nexport function extractCognitoGroups(claims: Record<string, string>): string[] {\n // Cognito includes groups in the 'cognito:groups' claim as a comma-separated string\n const groupsClaim = claims['cognito:groups'];\n if (!groupsClaim) {\n return [];\n }\n \n // Handle both string and array formats\n if (typeof groupsClaim === 'string') {\n return groupsClaim.split(',').map(group => group.trim());\n }\n \n // If it's already an array (in some cases), return it\n if (Array.isArray(groupsClaim)) {\n return groupsClaim;\n }\n \n return [];\n}\n\n/**\n * Check if user has any FlowConfig group membership\n * @param claims User claims from Cognito JWT token\n * @returns true if user belongs to at least one FlowConfig group\n */\nexport function hasFlowConfigAccess(claims: Record<string, string>): boolean {\n const userGroups = extractCognitoGroups(claims);\n const flowConfigGroups = Object.values(COGNITO_GROUPS);\n \n return userGroups.some(group => flowConfigGroups.includes(group as any));\n}\n\n/**\n * Get the highest access level for a user based on their group memberships\n * @param claims User claims from Cognito JWT token\n * @returns Highest access level or null if no access\n */\nexport function getAccessLevel(claims: Record<string, string>): AccessLevel | null {\n const userGroups = extractCognitoGroups(claims);\n \n // Check in order of highest to lowest priority\n if (userGroups.includes(COGNITO_GROUPS.ADMIN)) {\n return 'Full';\n }\n \n if (userGroups.includes(COGNITO_GROUPS.EDIT)) {\n return 'Edit';\n }\n \n if (userGroups.includes(COGNITO_GROUPS.READ)) {\n return 'Read';\n }\n \n return null;\n}\n\n/**\n * Check if user has permission to perform a specific action\n * @param claims User claims from Cognito JWT token\n * @param action The action being performed\n * @returns AccessLevel if authorized, null if not authorized\n */\nexport function checkActionPermission(\n claims: Record<string, string>,\n action: Action\n): AccessLevel | null {\n const accessLevel = getAccessLevel(claims);\n \n if (!accessLevel) {\n return null;\n }\n \n // Map actions to required access levels\n switch (action) {\n case 'Read':\n // All groups can read\n return accessLevel;\n \n case 'Edit':\n // Edit and Admin can edit values\n if (accessLevel === 'Edit' || accessLevel === 'Full') {\n return accessLevel;\n }\n return null;\n \n case 'Create':\n case 'Delete':\n // Only Admin can create or delete\n if (accessLevel === 'Full') {\n return accessLevel;\n }\n return null;\n \n default:\n return null;\n }\n}\n\n/**\n * Check if user can perform a structural change (add/remove fields)\n * Only FlowConfigAdmin users can perform structural changes\n * @param claims User claims from Cognito JWT token\n * @returns true if user can make structural changes\n */\nexport function canMakeStructuralChanges(claims: Record<string, string>): boolean {\n const accessLevel = getAccessLevel(claims);\n return accessLevel === 'Full';\n}\n\n/**\n * Validate that a user has permission for a flow config operation\n * This is the main function to be used by API endpoints\n * @param claims User claims from Cognito JWT token\n * @param _flowConfigId The flow config ID (not used in v1, but kept for v2 compatibility)\n * @param action The action being performed\n * @returns AccessLevel if authorized, null if not authorized\n */\nexport function validateFlowConfigPermission(\n claims: Record<string, string>,\n _flowConfigId: string,\n action: Action\n): AccessLevel | null {\n // In v1, all permissions are global (flowConfigId is ignored)\n // This parameter is kept for v2 compatibility when per-config permissions are added\n \n if (!hasFlowConfigAccess(claims)) {\n return null;\n }\n \n return checkActionPermission(claims, action);\n}"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }