quidproquo-actionprocessor-awslambda 0.1.1 → 0.1.3
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/lib/commonjs/awsNamingUtils.d.ts +2 -0
- package/lib/commonjs/awsNamingUtils.js +24 -1
- package/lib/commonjs/getActionProcessor/core/ai/getAiPromptActionProcessor.js +11 -4
- package/lib/commonjs/getActionProcessor/core/ai/getAiPromptStreamActionProcessor.js +11 -4
- package/lib/commonjs/getActionProcessor/core/ai/logic/aiStreamPartMappers.js +8 -8
- package/lib/commonjs/getActionProcessor/core/ai/logic/createDriveFileResolver.d.ts +3 -0
- package/lib/commonjs/getActionProcessor/core/ai/logic/createDriveFileResolver.js +27 -0
- package/lib/commonjs/getActionProcessor/core/ai/logic/index.d.ts +1 -0
- package/lib/commonjs/getActionProcessor/core/ai/logic/index.js +1 -0
- package/lib/commonjs/getActionProcessor/core/ai/logic/toSdkMessages.d.ts +3 -2
- package/lib/commonjs/getActionProcessor/core/ai/logic/toSdkMessages.js +41 -24
- package/lib/commonjs/getActionProcessor/core/apiKeyValidation/getApiKeyValidationValidateActionProcessor.js +15 -11
- package/lib/commonjs/getActionProcessor/core/event/apiGatwayEvent/api/getEventGetRecordsActionProcessor.js +12 -1
- package/lib/commonjs/getActionProcessor/core/event/utils/parseMultipartFormData.d.ts +7 -1
- package/lib/commonjs/getActionProcessor/core/event/utils/parseMultipartFormData.js +77 -8
- package/lib/commonjs/getActionProcessor/core/eventBus/getEventBusSendMessagesActionProcessor.js +1 -1
- package/lib/commonjs/getActionProcessor/core/file/getFileStreamOpenActionProcessor.js +1 -3
- package/lib/commonjs/getActionProcessor/core/index.d.ts +1 -0
- package/lib/commonjs/getActionProcessor/core/index.js +3 -1
- package/lib/commonjs/getActionProcessor/core/keyValueStore/getKeyValueStoreUpsertActionProcessor.js +2 -0
- package/lib/commonjs/getActionProcessor/core/metric/getMetricPutActionProcessor.d.ts +2 -0
- package/lib/commonjs/getActionProcessor/core/metric/getMetricPutActionProcessor.js +51 -0
- package/lib/commonjs/getActionProcessor/core/metric/index.d.ts +2 -0
- package/lib/commonjs/getActionProcessor/core/metric/index.js +17 -0
- package/lib/commonjs/lambdaHandlers/helpers/logger.js +1 -3
- package/lib/commonjs/lambdas/dynamicModuleLoader/dynamicModuleLoader.js +8 -1
- package/lib/commonjs/logic/apiGateway/getApiKeyValue.d.ts +1 -0
- package/lib/commonjs/logic/apiGateway/{getApiKeys.js → getApiKeyValue.js} +10 -14
- package/lib/commonjs/logic/cognito/utils/transformCognitoResponse.js +1 -1
- package/lib/commonjs/logic/dynamo/putItem.d.ts +1 -0
- package/lib/commonjs/logic/dynamo/putItem.js +6 -4
- package/lib/commonjs/logic/dynamo/qpqDynamoOrm/buildDynamoUpdate.js +1 -5
- package/lib/commonjs/logic/federatedModuleStore/FederatedModuleLoadError.d.ts +10 -0
- package/lib/commonjs/logic/federatedModuleStore/FederatedModuleLoadError.js +26 -0
- package/lib/commonjs/logic/federatedModuleStore/FederatedModuleStoreManifest.d.ts +8 -0
- package/lib/commonjs/logic/federatedModuleStore/FederatedModuleStoreManifest.js +2 -0
- package/lib/commonjs/logic/federatedModuleStore/index.d.ts +4 -0
- package/lib/commonjs/logic/federatedModuleStore/index.js +20 -0
- package/lib/commonjs/logic/federatedModuleStore/loadFederatedStory.d.ts +3 -0
- package/lib/commonjs/logic/federatedModuleStore/loadFederatedStory.js +295 -0
- package/lib/commonjs/logic/federatedModuleStore/sharedPackages.d.ts +1 -0
- package/lib/commonjs/logic/federatedModuleStore/sharedPackages.js +10 -0
- package/lib/commonjs/logic/index.d.ts +1 -0
- package/lib/commonjs/logic/index.js +1 -0
- package/lib/commonjs/logic/s3/generatePresignedUploadUrl.js +4 -4
- package/lib/esm/awsNamingUtils.d.ts +2 -0
- package/lib/esm/awsNamingUtils.js +20 -0
- package/lib/esm/getActionProcessor/core/ai/getAiPromptActionProcessor.js +11 -4
- package/lib/esm/getActionProcessor/core/ai/getAiPromptStreamActionProcessor.js +11 -4
- package/lib/esm/getActionProcessor/core/ai/logic/aiStreamPartMappers.js +8 -8
- package/lib/esm/getActionProcessor/core/ai/logic/createDriveFileResolver.d.ts +3 -0
- package/lib/esm/getActionProcessor/core/ai/logic/createDriveFileResolver.js +14 -0
- package/lib/esm/getActionProcessor/core/ai/logic/index.d.ts +1 -0
- package/lib/esm/getActionProcessor/core/ai/logic/index.js +1 -0
- package/lib/esm/getActionProcessor/core/ai/logic/toSdkMessages.d.ts +3 -2
- package/lib/esm/getActionProcessor/core/ai/logic/toSdkMessages.js +27 -20
- package/lib/esm/getActionProcessor/core/apiKeyValidation/getApiKeyValidationValidateActionProcessor.js +16 -12
- package/lib/esm/getActionProcessor/core/event/apiGatwayEvent/api/getEventGetRecordsActionProcessor.js +14 -3
- package/lib/esm/getActionProcessor/core/event/utils/parseMultipartFormData.d.ts +7 -1
- package/lib/esm/getActionProcessor/core/event/utils/parseMultipartFormData.js +75 -7
- package/lib/esm/getActionProcessor/core/eventBus/getEventBusSendMessagesActionProcessor.js +1 -1
- package/lib/esm/getActionProcessor/core/file/getFileDeleteActionProcessor.js +1 -1
- package/lib/esm/getActionProcessor/core/file/getFileGenerateTemporarySecureUrlActionProcessor.js +1 -1
- package/lib/esm/getActionProcessor/core/file/getFileGenerateTemporaryUploadSecureUrlActionProcessor.js +1 -1
- package/lib/esm/getActionProcessor/core/file/getFileStreamOpenActionProcessor.js +1 -3
- package/lib/esm/getActionProcessor/core/index.d.ts +1 -0
- package/lib/esm/getActionProcessor/core/index.js +3 -0
- package/lib/esm/getActionProcessor/core/keyValueStore/getKeyValueStoreDeleteActionProcessor.js +1 -1
- package/lib/esm/getActionProcessor/core/keyValueStore/getKeyValueStoreGetActionProcessor.js +1 -1
- package/lib/esm/getActionProcessor/core/keyValueStore/getKeyValueStoreGetAllActionProcessor.js +1 -1
- package/lib/esm/getActionProcessor/core/keyValueStore/getKeyValueStoreQueryActionProcessor.js +1 -1
- package/lib/esm/getActionProcessor/core/keyValueStore/getKeyValueStoreScanActionProcessor.js +1 -1
- package/lib/esm/getActionProcessor/core/keyValueStore/getKeyValueStoreUpdateActionProcessor.js +1 -1
- package/lib/esm/getActionProcessor/core/keyValueStore/getKeyValueStoreUpsertActionProcessor.js +2 -0
- package/lib/esm/getActionProcessor/core/metric/getMetricPutActionProcessor.d.ts +2 -0
- package/lib/esm/getActionProcessor/core/metric/getMetricPutActionProcessor.js +43 -0
- package/lib/esm/getActionProcessor/core/metric/index.d.ts +2 -0
- package/lib/esm/getActionProcessor/core/metric/index.js +4 -0
- package/lib/esm/getActionProcessor/core/queue/getQueueSendMessageActionProcessor.js +1 -1
- package/lib/esm/lambdaHandlers/helpers/logger.js +1 -3
- package/lib/esm/lambdas/dynamicModuleLoader/dynamicModuleLoader.js +9 -2
- package/lib/esm/logic/apiGateway/getApiKeyValue.d.ts +1 -0
- package/lib/esm/logic/apiGateway/getApiKeyValue.js +12 -0
- package/lib/esm/logic/cognito/utils/transformCognitoResponse.js +2 -2
- package/lib/esm/logic/dynamo/putItem.d.ts +1 -0
- package/lib/esm/logic/dynamo/putItem.js +6 -0
- package/lib/esm/logic/dynamo/qpqDynamoOrm/buildDynamoUpdate.js +1 -5
- package/lib/esm/logic/federatedModuleStore/FederatedModuleLoadError.d.ts +10 -0
- package/lib/esm/logic/federatedModuleStore/FederatedModuleLoadError.js +23 -0
- package/lib/esm/logic/federatedModuleStore/FederatedModuleStoreManifest.d.ts +8 -0
- package/lib/esm/logic/federatedModuleStore/FederatedModuleStoreManifest.js +1 -0
- package/lib/esm/logic/federatedModuleStore/index.d.ts +4 -0
- package/lib/esm/logic/federatedModuleStore/index.js +4 -0
- package/lib/esm/logic/federatedModuleStore/loadFederatedStory.d.ts +3 -0
- package/lib/esm/logic/federatedModuleStore/loadFederatedStory.js +246 -0
- package/lib/esm/logic/federatedModuleStore/sharedPackages.d.ts +1 -0
- package/lib/esm/logic/federatedModuleStore/sharedPackages.js +7 -0
- package/lib/esm/logic/index.d.ts +1 -0
- package/lib/esm/logic/index.js +1 -0
- package/lib/esm/logic/s3/generatePresignedUploadUrl.js +5 -5
- package/package.json +8 -7
- package/lib/commonjs/logic/apiGateway/getApiKeys.d.ts +0 -2
- package/lib/esm/logic/apiGateway/getApiKeys.d.ts +0 -2
- package/lib/esm/logic/apiGateway/getApiKeys.js +0 -17
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.getMetricPutActionProcessor = void 0;
|
|
13
|
+
const quidproquo_core_1 = require("quidproquo-core");
|
|
14
|
+
// Emits the metric as a CloudWatch Embedded Metric Format (EMF) log line: CloudWatch
|
|
15
|
+
// extracts metrics from the function's log stream - no api calls, no extra IAM, no
|
|
16
|
+
// latency on the story. Cost: each unique metricName x dimension-combination is one
|
|
17
|
+
// custom metric (~$0.30/mo) - the standard dimensions are service/environment(/feature),
|
|
18
|
+
// so keep payload dimensions low-cardinality (never per-user / per-request ids).
|
|
19
|
+
const getProcessMetricPut = (qpqConfig) => {
|
|
20
|
+
// The namespace is the deployed app instance - app/environment(/feature) - mirroring how
|
|
21
|
+
// every qpq resource name embeds the deployment identity. Apps sharing an account can't
|
|
22
|
+
// merge same-named metrics, per-developer feature sandboxes (e.g. qpq/docgen/development/jane)
|
|
23
|
+
// never pollute mainline, and dimensions are reserved for slices WITHIN the deployment
|
|
24
|
+
// (service + caller-supplied).
|
|
25
|
+
const application = quidproquo_core_1.qpqCoreUtils.getApplicationName(qpqConfig);
|
|
26
|
+
const environment = quidproquo_core_1.qpqCoreUtils.getApplicationModuleEnvironment(qpqConfig);
|
|
27
|
+
const feature = quidproquo_core_1.qpqCoreUtils.getApplicationModuleFeature(qpqConfig);
|
|
28
|
+
const namespace = `qpq/${application}/${environment}${feature ? `/${feature}` : ''}`;
|
|
29
|
+
const service = quidproquo_core_1.qpqCoreUtils.getApplicationModuleName(qpqConfig);
|
|
30
|
+
return (_a) => __awaiter(void 0, [_a], void 0, function* ({ metricName, value, unit, dimensions }) {
|
|
31
|
+
const allDimensions = Object.assign({ service }, dimensions);
|
|
32
|
+
const emf = Object.assign(Object.assign({ _aws: {
|
|
33
|
+
Timestamp: Date.now(),
|
|
34
|
+
CloudWatchMetrics: [
|
|
35
|
+
{
|
|
36
|
+
Namespace: namespace,
|
|
37
|
+
Dimensions: [Object.keys(allDimensions)],
|
|
38
|
+
Metrics: [{ Name: metricName, Unit: unit !== null && unit !== void 0 ? unit : quidproquo_core_1.MetricUnit.count }],
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
} }, allDimensions), { [metricName]: value });
|
|
42
|
+
console.log(JSON.stringify(emf));
|
|
43
|
+
return (0, quidproquo_core_1.actionResult)(void 0);
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
const getMetricPutActionProcessor = (qpqConfig) => __awaiter(void 0, void 0, void 0, function* () {
|
|
47
|
+
return ({
|
|
48
|
+
[quidproquo_core_1.MetricActionType.Put]: getProcessMetricPut(qpqConfig),
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
exports.getMetricPutActionProcessor = getMetricPutActionProcessor;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.getMetricActionProcessor = void 0;
|
|
13
|
+
const getMetricPutActionProcessor_1 = require("./getMetricPutActionProcessor");
|
|
14
|
+
const getMetricActionProcessor = (qpqConfig, dynamicModuleLoader) => __awaiter(void 0, void 0, void 0, function* () {
|
|
15
|
+
return (Object.assign({}, (yield (0, getMetricPutActionProcessor_1.getMetricPutActionProcessor)(qpqConfig, dynamicModuleLoader))));
|
|
16
|
+
});
|
|
17
|
+
exports.getMetricActionProcessor = getMetricActionProcessor;
|
|
@@ -94,9 +94,7 @@ const createBufferedLogger = (bucketName, regionForBucket, ship) => {
|
|
|
94
94
|
let disabledLogCorrelations = [];
|
|
95
95
|
return {
|
|
96
96
|
enableLogs: (enable, reason, correlation) => __awaiter(void 0, void 0, void 0, function* () {
|
|
97
|
-
disabledLogCorrelations = enable
|
|
98
|
-
? disabledLogCorrelations.filter((dlc) => dlc !== correlation)
|
|
99
|
-
: [...disabledLogCorrelations, correlation];
|
|
97
|
+
disabledLogCorrelations = enable ? disabledLogCorrelations.filter((dlc) => dlc !== correlation) : [...disabledLogCorrelations, correlation];
|
|
100
98
|
}),
|
|
101
99
|
log: (result) => {
|
|
102
100
|
// Defer all work (including JSON.stringify) to a microtask so the caller is not blocked.
|
|
@@ -10,9 +10,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.dynamicModuleLoader = void 0;
|
|
13
|
-
// @ts-expect-error -
|
|
13
|
+
// @ts-expect-error - injected at build time by QpqPlugin (webpack virtual module)
|
|
14
14
|
const quidproquo_dynamic_loader_1 = require("quidproquo-dynamic-loader");
|
|
15
|
+
const federatedModuleStore_1 = require("../../logic/federatedModuleStore");
|
|
15
16
|
const dynamicModuleLoader = (qpqFunctionRuntime) => __awaiter(void 0, void 0, void 0, function* () {
|
|
17
|
+
// Tier 1: federated. undefined means "nothing published for this runtime" -> fall through.
|
|
18
|
+
const federatedStory = yield (0, federatedModuleStore_1.loadFederatedStory)(quidproquo_dynamic_loader_1.qpqConfig, qpqFunctionRuntime);
|
|
19
|
+
if (federatedStory !== undefined) {
|
|
20
|
+
return federatedStory;
|
|
21
|
+
}
|
|
22
|
+
// Tier 2: the statically bundled story (or a fail-fast throw for a thin shell).
|
|
16
23
|
return (0, quidproquo_dynamic_loader_1.qpqDynamicModuleLoader)(qpqFunctionRuntime);
|
|
17
24
|
});
|
|
18
25
|
exports.dynamicModuleLoader = dynamicModuleLoader;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const getApiKeyValue: (region: string, apiKeyId: string) => Promise<string | undefined>;
|
|
@@ -9,21 +9,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.
|
|
12
|
+
exports.getApiKeyValue = void 0;
|
|
13
13
|
const client_api_gateway_1 = require("@aws-sdk/client-api-gateway");
|
|
14
14
|
const createAwsClient_1 = require("../createAwsClient");
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
// Fetch a single api key's value by id - keys are read individually (not listed) so the
|
|
16
|
+
// IAM grant can be scoped per-key with tag conditions rather than the /apikeys collection.
|
|
17
|
+
const getApiKeyValue = (region, apiKeyId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
17
18
|
const apiGatewayClient = (0, createAwsClient_1.createAwsClient)(client_api_gateway_1.APIGatewayClient, { region });
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
return (((_a = res.items) === null || _a === void 0 ? void 0 : _a.filter((i) => keyNames.indexOf(i.name) >= 0).map((i) => ({
|
|
24
|
-
name: i.name,
|
|
25
|
-
value: i.value,
|
|
26
|
-
description: i.description,
|
|
27
|
-
}))) || []);
|
|
19
|
+
const res = yield apiGatewayClient.send(new client_api_gateway_1.GetApiKeyCommand({
|
|
20
|
+
apiKey: apiKeyId,
|
|
21
|
+
includeValue: true,
|
|
22
|
+
}));
|
|
23
|
+
return res.value;
|
|
28
24
|
});
|
|
29
|
-
exports.
|
|
25
|
+
exports.getApiKeyValue = getApiKeyValue;
|
|
@@ -7,7 +7,7 @@ const cognitoAuthenticationResultTypeToQpqAuthenticationInfo = (authResult, issu
|
|
|
7
7
|
// Parse the issueDateTime and add the expiresIn to get the expiration date
|
|
8
8
|
let issueDate = new Date(issueDateTime);
|
|
9
9
|
issueDate.setSeconds(issueDate.getSeconds() + (authResult.ExpiresIn || 0));
|
|
10
|
-
const expiresAt =
|
|
10
|
+
const expiresAt = (0, quidproquo_core_1.getQpqIsoDateTimeFromDate)(issueDate);
|
|
11
11
|
return {
|
|
12
12
|
accessToken: authResult.AccessToken,
|
|
13
13
|
idToken: authResult.IdToken,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { KvsKey } from 'quidproquo-core';
|
|
2
2
|
export interface PutItemOptions {
|
|
3
3
|
expires?: number;
|
|
4
|
+
ifNotExistsAttribute?: string;
|
|
4
5
|
}
|
|
5
6
|
export declare function putItem<Item, T extends object = any>(tableName: string, item: Item, attributes: KvsKey[], options: PutItemOptions, region: string): Promise<void>;
|
|
@@ -39,9 +39,11 @@ const convertObjectToDynamoItem = (obj) => {
|
|
|
39
39
|
function putItem(tableName, item, attributes, options, region) {
|
|
40
40
|
return __awaiter(this, void 0, void 0, function* () {
|
|
41
41
|
const dynamoDBClient = (0, createAwsClient_1.createAwsClient)(client_dynamodb_1.DynamoDBClient, { region });
|
|
42
|
-
yield dynamoDBClient.send(new client_dynamodb_1.PutItemCommand({
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
yield dynamoDBClient.send(new client_dynamodb_1.PutItemCommand(Object.assign({ TableName: tableName, Item: convertObjectToDynamoItem(item) }, (options.ifNotExistsAttribute
|
|
43
|
+
? {
|
|
44
|
+
ConditionExpression: 'attribute_not_exists(#ineAttr)',
|
|
45
|
+
ExpressionAttributeNames: { '#ineAttr': options.ifNotExistsAttribute },
|
|
46
|
+
}
|
|
47
|
+
: {}))));
|
|
46
48
|
});
|
|
47
49
|
}
|
|
@@ -120,11 +120,7 @@ const buildDynamoUpdateExpressionPart = (update, updateIndex) => {
|
|
|
120
120
|
}
|
|
121
121
|
};
|
|
122
122
|
// Types that generate SET expressions
|
|
123
|
-
const SET_ACTION_TYPES = [
|
|
124
|
-
quidproquo_core_1.KvsUpdateActionType.Set,
|
|
125
|
-
quidproquo_core_1.KvsUpdateActionType.SetIfNotExists,
|
|
126
|
-
quidproquo_core_1.KvsUpdateActionType.Increment
|
|
127
|
-
];
|
|
123
|
+
const SET_ACTION_TYPES = [quidproquo_core_1.KvsUpdateActionType.Set, quidproquo_core_1.KvsUpdateActionType.SetIfNotExists, quidproquo_core_1.KvsUpdateActionType.Increment];
|
|
128
124
|
const buildDynamoUpdateExpressionForClause = (clause, actionTypes, kvsUpdate) => {
|
|
129
125
|
const actions = kvsUpdate.filter((update) => actionTypes.includes(update.action));
|
|
130
126
|
if (actions.length === 0) {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare enum FederatedModuleLoadErrorCode {
|
|
2
|
+
unsupportedStoreUrl = "unsupportedStoreUrl",
|
|
3
|
+
manifestInvalid = "manifestInvalid",
|
|
4
|
+
containerLoadFailed = "containerLoadFailed",
|
|
5
|
+
storyNotExported = "storyNotExported"
|
|
6
|
+
}
|
|
7
|
+
export declare class FederatedModuleLoadError extends Error {
|
|
8
|
+
readonly code: FederatedModuleLoadErrorCode;
|
|
9
|
+
constructor(code: FederatedModuleLoadErrorCode, message: string);
|
|
10
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FederatedModuleLoadError = exports.FederatedModuleLoadErrorCode = void 0;
|
|
4
|
+
// Discriminable failures raised inside loadFederatedStory. All of them are ultimately
|
|
5
|
+
// caught there and turned into a fall-back-to-bundled (with a warning) - they exist so
|
|
6
|
+
// logs/backoff can tell WHY a store didn't load, not to crash the request.
|
|
7
|
+
var FederatedModuleLoadErrorCode;
|
|
8
|
+
(function (FederatedModuleLoadErrorCode) {
|
|
9
|
+
// Store URL wasn't s3:// or file:// (a config/env mistake).
|
|
10
|
+
FederatedModuleLoadErrorCode["unsupportedStoreUrl"] = "unsupportedStoreUrl";
|
|
11
|
+
// manifest.json parsed but is missing required fields (bad/partial publish).
|
|
12
|
+
FederatedModuleLoadErrorCode["manifestInvalid"] = "manifestInvalid";
|
|
13
|
+
// A version's files downloaded but the entry didn't expose a valid MF container.
|
|
14
|
+
FederatedModuleLoadErrorCode["containerLoadFailed"] = "containerLoadFailed";
|
|
15
|
+
// The manifest exposed the module, but it didn't export the requested story name
|
|
16
|
+
// (e.g. a story was renamed in the remote but the manifest still lists it).
|
|
17
|
+
FederatedModuleLoadErrorCode["storyNotExported"] = "storyNotExported";
|
|
18
|
+
})(FederatedModuleLoadErrorCode || (exports.FederatedModuleLoadErrorCode = FederatedModuleLoadErrorCode = {}));
|
|
19
|
+
class FederatedModuleLoadError extends Error {
|
|
20
|
+
constructor(code, message) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.code = code;
|
|
23
|
+
this.name = 'FederatedModuleLoadError';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.FederatedModuleLoadError = FederatedModuleLoadError;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./FederatedModuleLoadError"), exports);
|
|
18
|
+
__exportStar(require("./FederatedModuleStoreManifest"), exports);
|
|
19
|
+
__exportStar(require("./loadFederatedStory"), exports);
|
|
20
|
+
__exportStar(require("./sharedPackages"), exports);
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.loadFederatedStory = exports.resetFederatedModuleStoreCache = void 0;
|
|
46
|
+
const quidproquo_config_aws_1 = require("quidproquo-config-aws");
|
|
47
|
+
const quidproquoCore = __importStar(require("quidproquo-core"));
|
|
48
|
+
const quidproquo_core_1 = require("quidproquo-core");
|
|
49
|
+
const quidproquoWebserver = __importStar(require("quidproquo-webserver"));
|
|
50
|
+
const fs = __importStar(require("fs"));
|
|
51
|
+
const module_1 = require("module");
|
|
52
|
+
const path = __importStar(require("path"));
|
|
53
|
+
const url_1 = require("url");
|
|
54
|
+
const client_s3_1 = require("@aws-sdk/client-s3");
|
|
55
|
+
const runtime_1 = require("@module-federation/enhanced/runtime");
|
|
56
|
+
const createAwsClient_1 = require("../createAwsClient");
|
|
57
|
+
const FederatedModuleLoadError_1 = require("./FederatedModuleLoadError");
|
|
58
|
+
const sharedPackages_1 = require("./sharedPackages");
|
|
59
|
+
// How long a resolved state is served before the manifest is re-checked for a new
|
|
60
|
+
// version. Overridable per service (defineFederatedModuleStore recheckMs -> this env).
|
|
61
|
+
// Lower = faster pickup of new publishes at the cost of one small S3 GET per container
|
|
62
|
+
// per interval. The re-check runs in the BACKGROUND so it never blocks a request.
|
|
63
|
+
const DEFAULT_RECHECK_MS = 60000;
|
|
64
|
+
const getRecheckMs = () => {
|
|
65
|
+
const raw = process.env.federatedCodeStoreRecheckMs;
|
|
66
|
+
const parsed = raw ? parseInt(raw, 10) : NaN;
|
|
67
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : DEFAULT_RECHECK_MS;
|
|
68
|
+
};
|
|
69
|
+
let resolvedState;
|
|
70
|
+
let recheckAfter = 0;
|
|
71
|
+
let inflightResolve;
|
|
72
|
+
let hostInitialised = false;
|
|
73
|
+
// Test seam - forces the next call to re-resolve the store from env.
|
|
74
|
+
const resetFederatedModuleStoreCache = () => {
|
|
75
|
+
resolvedState = undefined;
|
|
76
|
+
recheckAfter = 0;
|
|
77
|
+
inflightResolve = undefined;
|
|
78
|
+
};
|
|
79
|
+
exports.resetFederatedModuleStoreCache = resetFederatedModuleStoreCache;
|
|
80
|
+
// ── Transport ────────────────────────────────────────────────────────────────
|
|
81
|
+
// Returns a function that reads a path RELATIVE to the store (e.g. 'manifest.json'
|
|
82
|
+
// or '<hash>/remoteEntry.js'). Two backends: s3:// for real deploys, file:// for
|
|
83
|
+
// local/dev and tests. The store URL already includes the per-service prefix, so
|
|
84
|
+
// callers pass only the in-service relative path.
|
|
85
|
+
const getFileFetcher = (storeUrl, qpqConfig) => {
|
|
86
|
+
if (storeUrl.startsWith('s3://')) {
|
|
87
|
+
const url = new URL(storeUrl);
|
|
88
|
+
const bucketName = url.host;
|
|
89
|
+
const keyPrefix = url.pathname.replace(/^\/|\/$/g, '');
|
|
90
|
+
const region = quidproquo_config_aws_1.qpqConfigAwsUtils.getApplicationModuleDeployRegion(qpqConfig);
|
|
91
|
+
// Pin the owner so a same-name bucket in another account can't be squatted to
|
|
92
|
+
// serve code we'd then require() with the service role's credentials.
|
|
93
|
+
const expectedBucketOwner = quidproquo_config_aws_1.qpqConfigAwsUtils.getApplicationModuleDeployAccountId(qpqConfig);
|
|
94
|
+
const s3Client = (0, createAwsClient_1.createAwsClient)(client_s3_1.S3Client, { region });
|
|
95
|
+
return (relativePath) => __awaiter(void 0, void 0, void 0, function* () {
|
|
96
|
+
var _a;
|
|
97
|
+
const response = yield s3Client.send(new client_s3_1.GetObjectCommand({
|
|
98
|
+
Bucket: bucketName,
|
|
99
|
+
Key: keyPrefix ? `${keyPrefix}/${relativePath}` : relativePath,
|
|
100
|
+
ExpectedBucketOwner: expectedBucketOwner,
|
|
101
|
+
}));
|
|
102
|
+
const bytes = yield ((_a = response.Body) === null || _a === void 0 ? void 0 : _a.transformToByteArray());
|
|
103
|
+
if (!bytes) {
|
|
104
|
+
throw new FederatedModuleLoadError_1.FederatedModuleLoadError(FederatedModuleLoadError_1.FederatedModuleLoadErrorCode.containerLoadFailed, `empty response reading [${relativePath}]`);
|
|
105
|
+
}
|
|
106
|
+
return Buffer.from(bytes);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
if (storeUrl.startsWith('file://')) {
|
|
110
|
+
const baseDirectory = (0, url_1.fileURLToPath)(storeUrl.endsWith('/') ? storeUrl : `${storeUrl}/`);
|
|
111
|
+
return (relativePath) => __awaiter(void 0, void 0, void 0, function* () { return fs.promises.readFile(path.join(baseDirectory, relativePath)); });
|
|
112
|
+
}
|
|
113
|
+
throw new FederatedModuleLoadError_1.FederatedModuleLoadError(FederatedModuleLoadError_1.FederatedModuleLoadErrorCode.unsupportedStoreUrl, `unsupported federated code store url [${storeUrl}]`);
|
|
114
|
+
};
|
|
115
|
+
// "Nothing published yet" is a legitimate not-found: the manifest key is absent
|
|
116
|
+
// (NoSuchKey/NotFound) or the store bucket isn't created yet, which happens normally
|
|
117
|
+
// when a lambda cold-starts between deploy phases (NoSuchBucket). We do NOT include
|
|
118
|
+
// AccessDenied: a permission failure is a real misconfiguration and must surface (as a
|
|
119
|
+
// warning, and be retried) rather than masquerade as 'not published'.
|
|
120
|
+
const isManifestNotFoundError = (error) => {
|
|
121
|
+
const name = (error === null || error === void 0 ? void 0 : error.name) || '';
|
|
122
|
+
const code = (error === null || error === void 0 ? void 0 : error.code) || '';
|
|
123
|
+
return ['NoSuchKey', 'NotFound', 'NoSuchBucket'].includes(name) || code === 'ENOENT';
|
|
124
|
+
};
|
|
125
|
+
// ── Module-federation shared scope ───────────────────────────────────────────
|
|
126
|
+
// The host provides the framework packages to the container's share scope so remote
|
|
127
|
+
// story code resolves the SAME module instances as the bundled runtime. The package
|
|
128
|
+
// list is shared with the remote build so the two can't drift (see sharedPackages).
|
|
129
|
+
const SHARED_LIBS = {
|
|
130
|
+
'quidproquo-core': quidproquoCore,
|
|
131
|
+
'quidproquo-webserver': quidproquoWebserver,
|
|
132
|
+
};
|
|
133
|
+
const getHostSharedModules = () => Object.fromEntries(sharedPackages_1.FEDERATED_SHARED_PACKAGE_NAMES.map((name) => [
|
|
134
|
+
name,
|
|
135
|
+
{
|
|
136
|
+
version: '0.0.0',
|
|
137
|
+
lib: () => SHARED_LIBS[name],
|
|
138
|
+
shareConfig: { singleton: true, requiredVersion: false },
|
|
139
|
+
},
|
|
140
|
+
]));
|
|
141
|
+
const ensureHostInitialised = () => {
|
|
142
|
+
if (hostInitialised) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
(0, runtime_1.init)({
|
|
146
|
+
name: 'qpq_federated_host',
|
|
147
|
+
remotes: [],
|
|
148
|
+
shared: getHostSharedModules(),
|
|
149
|
+
});
|
|
150
|
+
hostInitialised = true;
|
|
151
|
+
};
|
|
152
|
+
// ── Version loading ──────────────────────────────────────────────────────────
|
|
153
|
+
// Downloads a manifest's files (atomically) and registers the container with the MF
|
|
154
|
+
// runtime under a HASH-UNIQUE remote name, so loadRemote can't serve a previous
|
|
155
|
+
// version's module from its cache when the hash changes. Returns the runtime name.
|
|
156
|
+
// This is the step that actually puts a new version's code into effect.
|
|
157
|
+
const loadStoreVersion = (getFile, manifest) => __awaiter(void 0, void 0, void 0, function* () {
|
|
158
|
+
var _a, _b;
|
|
159
|
+
const cacheRoot = process.env.federatedCodeStoreCacheDir || '/tmp/qpq-federated-code';
|
|
160
|
+
const versionDirectory = path.join(cacheRoot, manifest.containerName, manifest.hash);
|
|
161
|
+
yield fs.promises.mkdir(versionDirectory, { recursive: true });
|
|
162
|
+
yield Promise.all(manifest.files.map((file) => __awaiter(void 0, void 0, void 0, function* () {
|
|
163
|
+
const localPath = path.join(versionDirectory, file);
|
|
164
|
+
// Files are immutable under their hash dir AND only ever appear via the atomic
|
|
165
|
+
// rename below, so an existing file is always complete and valid - this is what
|
|
166
|
+
// lets a re-check of an unchanged version skip re-downloading.
|
|
167
|
+
if (fs.existsSync(localPath)) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
const data = yield getFile(`${manifest.hash}/${file}`);
|
|
171
|
+
yield fs.promises.mkdir(path.dirname(localPath), { recursive: true });
|
|
172
|
+
// Write to a temp name then rename: rename is atomic on the same filesystem, so a
|
|
173
|
+
// crash/timeout mid-write never leaves a truncated file that a later invocation
|
|
174
|
+
// would trust via the existsSync check above.
|
|
175
|
+
const tempPath = `${localPath}.${process.pid}.tmp`;
|
|
176
|
+
yield fs.promises.writeFile(tempPath, data);
|
|
177
|
+
yield fs.promises.rename(tempPath, localPath);
|
|
178
|
+
})));
|
|
179
|
+
const entryPath = path.join(versionDirectory, manifest.entry);
|
|
180
|
+
const containerRequire = (0, module_1.createRequire)(entryPath);
|
|
181
|
+
const containerModule = containerRequire(entryPath);
|
|
182
|
+
const container = (_b = (_a = containerModule[manifest.containerName]) !== null && _a !== void 0 ? _a : containerModule.default) !== null && _b !== void 0 ? _b : containerModule;
|
|
183
|
+
if (typeof (container === null || container === void 0 ? void 0 : container.get) !== 'function' || typeof (container === null || container === void 0 ? void 0 : container.init) !== 'function') {
|
|
184
|
+
throw new FederatedModuleLoadError_1.FederatedModuleLoadError(FederatedModuleLoadError_1.FederatedModuleLoadErrorCode.containerLoadFailed, `[${manifest.entry}] does not export a module federation container named [${manifest.containerName}]`);
|
|
185
|
+
}
|
|
186
|
+
// entryGlobalName is the container's real (build-time) library name; the registered
|
|
187
|
+
// remote name is hash-unique so each version is a distinct loadRemote key.
|
|
188
|
+
globalThis[manifest.containerName] = container;
|
|
189
|
+
ensureHostInitialised();
|
|
190
|
+
const runtimeName = `${manifest.containerName}__${manifest.hash}`;
|
|
191
|
+
(0, runtime_1.registerRemotes)([
|
|
192
|
+
{
|
|
193
|
+
name: runtimeName,
|
|
194
|
+
entry: entryPath,
|
|
195
|
+
type: 'global',
|
|
196
|
+
entryGlobalName: manifest.containerName,
|
|
197
|
+
},
|
|
198
|
+
]);
|
|
199
|
+
return runtimeName;
|
|
200
|
+
});
|
|
201
|
+
// ── Probe & resolve (the caching state machine) ──────────────────────────────
|
|
202
|
+
// Reads the manifest and decides the current state. If the hash is unchanged from what
|
|
203
|
+
// we already loaded, keeps the existing container (no re-sync). Not-found -> unavailable.
|
|
204
|
+
const probeStore = (qpqConfig, storeUrl, current) => __awaiter(void 0, void 0, void 0, function* () {
|
|
205
|
+
const getFile = getFileFetcher(storeUrl, qpqConfig);
|
|
206
|
+
let manifest;
|
|
207
|
+
try {
|
|
208
|
+
manifest = JSON.parse((yield getFile('manifest.json')).toString('utf8'));
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
if (isManifestNotFoundError(error)) {
|
|
212
|
+
console.log(`federated code store [${storeUrl}] has no manifest - using bundled modules`);
|
|
213
|
+
return { available: false };
|
|
214
|
+
}
|
|
215
|
+
throw error;
|
|
216
|
+
}
|
|
217
|
+
if (!(manifest === null || manifest === void 0 ? void 0 : manifest.containerName) ||
|
|
218
|
+
!(manifest === null || manifest === void 0 ? void 0 : manifest.hash) ||
|
|
219
|
+
!(manifest === null || manifest === void 0 ? void 0 : manifest.entry) ||
|
|
220
|
+
!Array.isArray(manifest === null || manifest === void 0 ? void 0 : manifest.files) ||
|
|
221
|
+
typeof (manifest === null || manifest === void 0 ? void 0 : manifest.exposes) !== 'object' ||
|
|
222
|
+
manifest.exposes === null) {
|
|
223
|
+
throw new FederatedModuleLoadError_1.FederatedModuleLoadError(FederatedModuleLoadError_1.FederatedModuleLoadErrorCode.manifestInvalid, `invalid manifest in federated code store [${storeUrl}]`);
|
|
224
|
+
}
|
|
225
|
+
if ((current === null || current === void 0 ? void 0 : current.available) && current.manifest.hash === manifest.hash) {
|
|
226
|
+
return current;
|
|
227
|
+
}
|
|
228
|
+
const runtimeName = yield loadStoreVersion(getFile, manifest);
|
|
229
|
+
return { available: true, manifest, runtimeName };
|
|
230
|
+
});
|
|
231
|
+
// Resolves the store, re-checking the manifest after the recheck interval. The re-check
|
|
232
|
+
// runs in the background: a stale-but-usable state is served immediately so a request
|
|
233
|
+
// never blocks on S3; only the very first resolve (no state yet) awaits.
|
|
234
|
+
const resolveStore = (qpqConfig, storeUrl) => {
|
|
235
|
+
if (resolvedState && Date.now() < recheckAfter) {
|
|
236
|
+
return Promise.resolve(resolvedState);
|
|
237
|
+
}
|
|
238
|
+
if (!inflightResolve) {
|
|
239
|
+
inflightResolve = probeStore(qpqConfig, storeUrl, resolvedState)
|
|
240
|
+
.then((state) => {
|
|
241
|
+
resolvedState = state;
|
|
242
|
+
recheckAfter = Date.now() + getRecheckMs();
|
|
243
|
+
return state;
|
|
244
|
+
})
|
|
245
|
+
.catch((error) => {
|
|
246
|
+
// Back off and keep serving whatever we had (or unavailable). Surfaced as a
|
|
247
|
+
// warning so real errors (e.g. AccessDenied) are visible, not silent.
|
|
248
|
+
console.warn('federated code store check failed - keeping current modules', error);
|
|
249
|
+
recheckAfter = Date.now() + getRecheckMs();
|
|
250
|
+
resolvedState = resolvedState !== null && resolvedState !== void 0 ? resolvedState : { available: false };
|
|
251
|
+
return resolvedState;
|
|
252
|
+
})
|
|
253
|
+
.finally(() => {
|
|
254
|
+
inflightResolve = undefined;
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
// Serve the stale state instantly while the refresh happens; only block if we have
|
|
258
|
+
// nothing yet.
|
|
259
|
+
return resolvedState ? Promise.resolve(resolvedState) : inflightResolve;
|
|
260
|
+
};
|
|
261
|
+
// ── Public entry ─────────────────────────────────────────────────────────────
|
|
262
|
+
// Called by dynamicModuleLoader for every story load. Returns the story function, or
|
|
263
|
+
// undefined to signal "use the bundled module" (no store, nothing published, runtime
|
|
264
|
+
// not exposed, or any error - availability always wins over federation).
|
|
265
|
+
const loadFederatedStory = (qpqConfig, qpqFunctionRuntime) => __awaiter(void 0, void 0, void 0, function* () {
|
|
266
|
+
const storeUrl = process.env.federatedCodeStoreUrl;
|
|
267
|
+
if (!storeUrl) {
|
|
268
|
+
return undefined;
|
|
269
|
+
}
|
|
270
|
+
try {
|
|
271
|
+
const storeState = yield resolveStore(qpqConfig, storeUrl);
|
|
272
|
+
if (!storeState.available) {
|
|
273
|
+
return undefined;
|
|
274
|
+
}
|
|
275
|
+
const federatedKey = (0, quidproquo_core_1.getFederatedKeyFromQpqFunctionRuntime)(qpqFunctionRuntime);
|
|
276
|
+
const exposePath = storeState.manifest.exposes[federatedKey];
|
|
277
|
+
if (!exposePath) {
|
|
278
|
+
console.warn(`federated code store has no module for [${federatedKey}] - using the bundled module`);
|
|
279
|
+
return undefined;
|
|
280
|
+
}
|
|
281
|
+
const remoteModule = yield (0, runtime_1.loadRemote)(`${storeState.runtimeName}/${exposePath}`);
|
|
282
|
+
const storyName = quidproquo_core_1.qpqCoreUtils.getStoryNameFromQpqFunctionRuntime(qpqFunctionRuntime);
|
|
283
|
+
const story = remoteModule === null || remoteModule === void 0 ? void 0 : remoteModule[storyName];
|
|
284
|
+
if (!story) {
|
|
285
|
+
throw new FederatedModuleLoadError_1.FederatedModuleLoadError(FederatedModuleLoadError_1.FederatedModuleLoadErrorCode.storyNotExported, `story [${storyName}] is not exported from federated module [${exposePath}]`);
|
|
286
|
+
}
|
|
287
|
+
return story;
|
|
288
|
+
}
|
|
289
|
+
catch (error) {
|
|
290
|
+
// Availability first: a broken store must never take the service down
|
|
291
|
+
console.warn('federated module load failed - using the bundled module', error);
|
|
292
|
+
return undefined;
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
exports.loadFederatedStory = loadFederatedStory;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const FEDERATED_SHARED_PACKAGE_NAMES: readonly ["quidproquo-core", "quidproquo-webserver"];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FEDERATED_SHARED_PACKAGE_NAMES = void 0;
|
|
4
|
+
// The framework packages the lambda host provides to the module-federation share
|
|
5
|
+
// scope, so a federated remote resolves the SAME module instances as the host
|
|
6
|
+
// (instanceof checks and module-level state stay coherent). Single source of truth
|
|
7
|
+
// for BOTH the host runtime (loadFederatedStory getHostSharedModules) and the
|
|
8
|
+
// remote build (quidproquo-deploy-webpack getWebpackConfigForQpqRemote) — the two
|
|
9
|
+
// lists must never drift, or the remote would silently bundle its own copy.
|
|
10
|
+
exports.FEDERATED_SHARED_PACKAGE_NAMES = ['quidproquo-core', 'quidproquo-webserver'];
|
|
@@ -15,9 +15,9 @@ const s3_request_presigner_1 = require("@aws-sdk/s3-request-presigner");
|
|
|
15
15
|
// import { createPresignedPost } from '@aws-sdk/s3-presigned-post';
|
|
16
16
|
const createAwsClient_1 = require("../createAwsClient");
|
|
17
17
|
// export const generatePresignedUploadFormUrl = async (
|
|
18
|
-
// bucketName: string,
|
|
19
|
-
// objectKey: string,
|
|
20
|
-
// region: string,
|
|
18
|
+
// bucketName: string,
|
|
19
|
+
// objectKey: string,
|
|
20
|
+
// region: string,
|
|
21
21
|
// expirationMs: number,
|
|
22
22
|
// contentType: string | undefined,
|
|
23
23
|
// maxSizeBytes?: number | undefined
|
|
@@ -56,7 +56,7 @@ const generatePresignedUploadUrl = (bucketName, objectKey, region, expirationMs,
|
|
|
56
56
|
Bucket: bucketName,
|
|
57
57
|
Key: objectKey,
|
|
58
58
|
ContentType: contentType,
|
|
59
|
-
Metadata: Object.assign(Object.assign({}, (correlationId && { 'correlation-id': correlationId })), { 'upload-timestamp': Date.now().toString() })
|
|
59
|
+
Metadata: Object.assign(Object.assign({}, (correlationId && { 'correlation-id': correlationId })), { 'upload-timestamp': Date.now().toString() }),
|
|
60
60
|
});
|
|
61
61
|
const url = yield (0, s3_request_presigner_1.getSignedUrl)(s3Client, putObjectCommand, {
|
|
62
62
|
expiresIn: expirationMs / 1000,
|
|
@@ -17,7 +17,9 @@ export declare const getCFExportNameApiKeyIdFromConfig: (apiKeyName: string, qpq
|
|
|
17
17
|
export declare const getCFExportNameSnsTopicArnFromConfig: (eventBusName: string, qpqConfig: QPQConfig, applicationOverride?: string) => string;
|
|
18
18
|
export declare const getCFExportNameDistributionIdArnFromConfig: (webEntryName: string, qpqConfig: QPQConfig, serviceOverride?: string, applicationOverride?: string) => string;
|
|
19
19
|
export declare const getCFExportNameWebsocketApiIdFromConfig: (websocketApiName: string, qpqConfig: QPQConfig) => string;
|
|
20
|
+
export declare const getWebsocketApiIdSsmParameterName: (websocketApiName: string, qpqConfig: QPQConfig) => string;
|
|
20
21
|
export declare const getEventBusSnsTopicArn: (eventBusName: string, qpqConfig: QPQConfig, module: string, environment: string, application: string, feature?: string) => string;
|
|
22
|
+
export declare const getAccountStackName: () => string;
|
|
21
23
|
export declare const getBaseStackName: (qpqConfig: QPQConfig) => string;
|
|
22
24
|
export declare const getInfStackName: (qpqConfig: QPQConfig) => string;
|
|
23
25
|
export declare const getWebStackName: (qpqConfig: QPQConfig) => string;
|