openlearn-next 0.7.12 → 0.7.13
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/dist/assets/{ActivityWorkspaceWidget-TtBuNORs.js → ActivityWorkspaceWidget-9DeXkxGk.js} +1 -1
- package/dist/assets/{AdminDirectoryView-D03WOMc-.js → AdminDirectoryView-5gupeGAR.js} +1 -1
- package/dist/assets/{AssessmentCenter-MUvoJySb.js → AssessmentCenter-CPaqy0Xa.js} +1 -1
- package/dist/assets/{AssignmentFilePreview-dVhnTYmq.js → AssignmentFilePreview-7fHtUuUL.js} +2 -2
- package/dist/assets/{BatchPickerModal-QALdhrX6.js → BatchPickerModal-0yIe1DXi.js} +1 -1
- package/dist/assets/{ClassesView-CKwlRz-A.js → ClassesView-CGpoW0IC.js} +1 -1
- package/dist/assets/{ClassroomCountdownWidget-DyWyForY.js → ClassroomCountdownWidget-B_5--dn_.js} +1 -1
- package/dist/assets/{CloudDriveModal-C8UAn3MO.js → CloudDriveModal-4Ts5Duh5.js} +1 -1
- package/dist/assets/{ComputerLabView-E5b3XTkk.js → ComputerLabView-DAEaKTBj.js} +1 -1
- package/dist/assets/{CourseManagement-3jSlq7lV.js → CourseManagement-CxIBH7lA.js} +1 -1
- package/dist/assets/{CourseWizardModal-BAkW5VJX.js → CourseWizardModal-R0xpa_Aw.js} +1 -1
- package/dist/assets/{CoursewareHubPanel-BkjcusjZ.js → CoursewareHubPanel-CpHptmSa.js} +1 -1
- package/dist/assets/{Dashboard-Ha2fZAqD.js → Dashboard-DeBfP_Nc.js} +1 -1
- package/dist/assets/{ExportWeightModal-D2Y13384.js → ExportWeightModal-DlnCOBlL.js} +1 -1
- package/dist/assets/{HelpTour-DBq2otcV.js → HelpTour-Cztpqw_J.js} +1 -1
- package/dist/assets/{HelpView-BVLRnMxl.js → HelpView-LPLAY9bq.js} +3 -3
- package/dist/assets/{ImportLessonsModal-CQlq4b81.js → ImportLessonsModal-BopEHmU_.js} +1 -1
- package/dist/assets/{ImportModal-Ct0I5cAL.js → ImportModal-CYU3aMYY.js} +1 -1
- package/dist/assets/{InteractiveCoursewareViewer-DGKh1gO8.js → InteractiveCoursewareViewer-CGc3P4HF.js} +1 -1
- package/dist/assets/InteractiveWhiteboard-DiyHrIGn.js +19 -0
- package/dist/assets/{LazyCourseware-zONqinCM.js → LazyCourseware-Bj1jm0nC.js} +2 -2
- package/dist/assets/LazyWhiteboard-NPD1EoyO.js +2 -0
- package/dist/assets/LessonEditorView-DqreBtFx.js +1 -0
- package/dist/assets/{LiveClassroomView-TaHtHWkY.js → LiveClassroomView-eTc6Fb9g.js} +11 -10
- package/dist/assets/{NotificationDetailModal-BF_-pn0c.js → NotificationDetailModal-B7G7ra9a.js} +1 -1
- package/dist/assets/{PluginView-sVMPXae9.js → PluginView-DP6s-L70.js} +1 -1
- package/dist/assets/{ProcessLogsModal-D97xLgnL.js → ProcessLogsModal-Dq5C4s7j.js} +1 -1
- package/dist/assets/{QuizGeneratorModal-CNY8ISjR.js → QuizGeneratorModal-CoX9f8Wp.js} +1 -1
- package/dist/assets/RevealPresentationWrapper-wwlcfNWB.js +48 -0
- package/dist/assets/{StudentAssignmentEvalPanel-CUmM5DbT.js → StudentAssignmentEvalPanel-DHb-asHQ.js} +1 -1
- package/dist/assets/{StudentAssignmentView-B-1MtwKj.js → StudentAssignmentView-AJpjQK3f.js} +1 -1
- package/dist/assets/{StudentLessonView-CqrcvVND.js → StudentLessonView-Djd1T1QF.js} +1 -1
- package/dist/assets/{StudentView-Bi9kgSrN.js → StudentView-D41z7GY5.js} +2 -2
- package/dist/assets/{SystemResourceLibraryModal-DDALKrJC.js → SystemResourceLibraryModal-CxmQh1HA.js} +1 -1
- package/dist/assets/TeacherView-DqSWaNuI.js +2 -0
- package/dist/assets/{TimetableView-BOLB-kZC.js → TimetableView-DrFs_xgc.js} +1 -1
- package/dist/assets/{UTIF-BtQhea94.js → UTIF-u3Ct70K4.js} +1 -1
- package/dist/assets/{index-Bc9003lB.js → index-7CK1B0tE.js} +28 -28
- package/dist/assets/index-BaGZmpr6.css +1 -0
- package/dist/assets/{index.es-CijVATXs.js → index.es-CcQ2kcDj.js} +1 -1
- package/dist/assets/{pluginParsers-DD3QL1Xl.js → pluginParsers-BN3lQ7PJ.js} +1 -1
- package/dist/assets/{student-workspace-C4UgD58C.js → student-workspace-DkTkcAGK.js} +1 -1
- package/dist/assets/{vendor-icons-CaXLq01o.js → vendor-icons-CqLdl4B_.js} +1 -1
- package/dist/assets/{vendor-pdf-DVWGghIL.js → vendor-pdf-BMEc_Clb.js} +3 -3
- package/dist/assets/{vendor-pptx-BqU7v5zS.js → vendor-pptx-C0qaOH5T.js} +178 -178
- package/dist/index.html +3 -3
- package/dist/server.cjs +732 -1109
- package/package.json +2 -1
- package/dist/assets/InteractiveWhiteboard-BbZlYpRu.js +0 -65
- package/dist/assets/LazyWhiteboard-BV98LEZ8.js +0 -2
- package/dist/assets/LessonEditorView-LXRkKxdY.js +0 -1
- package/dist/assets/TeacherView-C5JmoKHk.js +0 -2
- package/dist/assets/index-D4aq9poS.css +0 -1
- package/dist/assets/vendor-reveal-DcQQzuI9.css +0 -1
package/dist/server.cjs
CHANGED
|
@@ -21290,7 +21290,7 @@ var import_node_fs11 = __toESM(require("node:fs"), 1);
|
|
|
21290
21290
|
var import_node_path13 = __toESM(require("node:path"), 1);
|
|
21291
21291
|
var import_node_url5 = require("node:url");
|
|
21292
21292
|
var import_meta7 = {};
|
|
21293
|
-
var FALLBACK_VERSION = "0.7.
|
|
21293
|
+
var FALLBACK_VERSION = "0.7.13";
|
|
21294
21294
|
function readPlatformVersion() {
|
|
21295
21295
|
const bases = [];
|
|
21296
21296
|
if (typeof __dirname !== "undefined") bases.push(__dirname);
|
|
@@ -29983,924 +29983,6 @@ var ServiceRegistryKernel = class {
|
|
|
29983
29983
|
}
|
|
29984
29984
|
};
|
|
29985
29985
|
|
|
29986
|
-
// packages/core/bootstrap/composition/composition-validator.ts
|
|
29987
|
-
var CompositionValidator = class {
|
|
29988
|
-
static validate(options, pipeline, modules) {
|
|
29989
|
-
const errors = [];
|
|
29990
|
-
const warnings = [];
|
|
29991
|
-
if (options.config && options.config.port !== void 0) {
|
|
29992
|
-
if (options.config.port <= 0 || options.config.port > 65535) {
|
|
29993
|
-
errors.push({
|
|
29994
|
-
code: "INVALID_PORT",
|
|
29995
|
-
message: `Port must be a valid number between 1 and 65535. Received: ${options.config.port}`,
|
|
29996
|
-
target: "config.port"
|
|
29997
|
-
});
|
|
29998
|
-
}
|
|
29999
|
-
}
|
|
30000
|
-
if (!pipeline || pipeline.stages.length === 0) {
|
|
30001
|
-
errors.push({
|
|
30002
|
-
code: "EMPTY_PIPELINE",
|
|
30003
|
-
message: "Bootstrap pipeline is missing or contains zero stages.",
|
|
30004
|
-
target: "pipeline"
|
|
30005
|
-
});
|
|
30006
|
-
}
|
|
30007
|
-
const moduleIds = /* @__PURE__ */ new Set();
|
|
30008
|
-
for (const mod of modules) {
|
|
30009
|
-
if (!mod.id) {
|
|
30010
|
-
errors.push({
|
|
30011
|
-
code: "INVALID_MODULE",
|
|
30012
|
-
message: `Module '${mod.name}' has no unique ID.`,
|
|
30013
|
-
target: "module.id"
|
|
30014
|
-
});
|
|
30015
|
-
} else if (moduleIds.has(mod.id)) {
|
|
30016
|
-
errors.push({
|
|
30017
|
-
code: "DUPLICATE_MODULE",
|
|
30018
|
-
message: `Duplicate composition module detected: '${mod.id}'.`,
|
|
30019
|
-
target: "module.id"
|
|
30020
|
-
});
|
|
30021
|
-
} else {
|
|
30022
|
-
moduleIds.add(mod.id);
|
|
30023
|
-
}
|
|
30024
|
-
}
|
|
30025
|
-
return {
|
|
30026
|
-
isValid: errors.length === 0,
|
|
30027
|
-
errors: Object.freeze(errors),
|
|
30028
|
-
warnings: Object.freeze(warnings)
|
|
30029
|
-
};
|
|
30030
|
-
}
|
|
30031
|
-
};
|
|
30032
|
-
|
|
30033
|
-
// packages/core/bootstrap/builder/builder-validation-engine.ts
|
|
30034
|
-
var BuilderValidationEngine = class {
|
|
30035
|
-
static validate(config, environment, stages) {
|
|
30036
|
-
const errors = [];
|
|
30037
|
-
const warnings = [];
|
|
30038
|
-
if (!["development", "production", "test"].includes(environment)) {
|
|
30039
|
-
errors.push({
|
|
30040
|
-
code: "INVALID_ENVIRONMENT",
|
|
30041
|
-
message: `Environment must be one of 'development', 'production', 'test'. Received: '${environment}'`,
|
|
30042
|
-
field: "environment"
|
|
30043
|
-
});
|
|
30044
|
-
}
|
|
30045
|
-
if (!config.port || config.port <= 0 || config.port > 65535) {
|
|
30046
|
-
errors.push({
|
|
30047
|
-
code: "INVALID_PORT",
|
|
30048
|
-
message: `Port must be a valid number between 1 and 65535. Received: ${config.port}`,
|
|
30049
|
-
field: "port"
|
|
30050
|
-
});
|
|
30051
|
-
}
|
|
30052
|
-
if (!stages || stages.length === 0) {
|
|
30053
|
-
errors.push({
|
|
30054
|
-
code: "MISSING_STAGES",
|
|
30055
|
-
message: "Bootstrap pipeline contains no registered stages.",
|
|
30056
|
-
field: "stages"
|
|
30057
|
-
});
|
|
30058
|
-
} else {
|
|
30059
|
-
const stageIds = /* @__PURE__ */ new Set();
|
|
30060
|
-
for (const stage of stages) {
|
|
30061
|
-
if (!stage.id) {
|
|
30062
|
-
errors.push({
|
|
30063
|
-
code: "INVALID_STAGE",
|
|
30064
|
-
message: `Stage '${stage.name}' has no unique ID.`
|
|
30065
|
-
});
|
|
30066
|
-
} else if (stageIds.has(stage.id)) {
|
|
30067
|
-
errors.push({
|
|
30068
|
-
code: "DUPLICATE_STAGE",
|
|
30069
|
-
message: `Duplicate stage registration detected for stage ID '${stage.id}'.`,
|
|
30070
|
-
field: "stage.id"
|
|
30071
|
-
});
|
|
30072
|
-
} else {
|
|
30073
|
-
stageIds.add(stage.id);
|
|
30074
|
-
}
|
|
30075
|
-
}
|
|
30076
|
-
}
|
|
30077
|
-
return {
|
|
30078
|
-
isValid: errors.length === 0,
|
|
30079
|
-
errors: Object.freeze(errors),
|
|
30080
|
-
warnings: Object.freeze(warnings)
|
|
30081
|
-
};
|
|
30082
|
-
}
|
|
30083
|
-
};
|
|
30084
|
-
|
|
30085
|
-
// packages/core/bootstrap/types/index.ts
|
|
30086
|
-
var PlatformBootstrapError = class extends Error {
|
|
30087
|
-
constructor(message, stage, cause) {
|
|
30088
|
-
super(`[PlatformBootstrapError${stage ? `:${stage}` : ""}] ${message}`);
|
|
30089
|
-
this.stage = stage;
|
|
30090
|
-
this.cause = cause;
|
|
30091
|
-
this.name = "PlatformBootstrapError";
|
|
30092
|
-
}
|
|
30093
|
-
};
|
|
30094
|
-
var ConfigurationError = class extends PlatformBootstrapError {
|
|
30095
|
-
constructor(message, cause) {
|
|
30096
|
-
super(message, "Configuring" /* Configuring */, cause);
|
|
30097
|
-
this.name = "ConfigurationError";
|
|
30098
|
-
}
|
|
30099
|
-
};
|
|
30100
|
-
var StartupTimeoutError = class extends PlatformBootstrapError {
|
|
30101
|
-
constructor(message, stage, cause) {
|
|
30102
|
-
super(message, stage, cause);
|
|
30103
|
-
this.name = "StartupTimeoutError";
|
|
30104
|
-
}
|
|
30105
|
-
};
|
|
30106
|
-
var PLATFORM_VERSION2 = PLATFORM_VERSION;
|
|
30107
|
-
var BOOTSTRAP_STAGE_NAMES = Object.freeze([
|
|
30108
|
-
"Created" /* Created */,
|
|
30109
|
-
"Configuring" /* Configuring */,
|
|
30110
|
-
"Registering" /* Registering */,
|
|
30111
|
-
"Initializing" /* Initializing */,
|
|
30112
|
-
"Activating" /* Activating */,
|
|
30113
|
-
"Ready" /* Ready */,
|
|
30114
|
-
"ShuttingDown" /* ShuttingDown */,
|
|
30115
|
-
"Disposed" /* Disposed */
|
|
30116
|
-
]);
|
|
30117
|
-
var DEFAULT_BOOTSTRAP_CONFIG = Object.freeze({
|
|
30118
|
-
environment: "development",
|
|
30119
|
-
mode: "standalone",
|
|
30120
|
-
port: 9e3,
|
|
30121
|
-
debug: false,
|
|
30122
|
-
pluginsDir: "./plugins",
|
|
30123
|
-
dbPath: "./packages/core/db/educational_os.db"
|
|
30124
|
-
});
|
|
30125
|
-
|
|
30126
|
-
// packages/core/bootstrap/pipeline/pipeline-executor.ts
|
|
30127
|
-
var PipelineExecutor = class {
|
|
30128
|
-
constructor() {
|
|
30129
|
-
this.listeners = /* @__PURE__ */ new Set();
|
|
30130
|
-
}
|
|
30131
|
-
addListener(listener) {
|
|
30132
|
-
this.listeners.add(listener);
|
|
30133
|
-
return () => {
|
|
30134
|
-
this.listeners.delete(listener);
|
|
30135
|
-
};
|
|
30136
|
-
}
|
|
30137
|
-
emit(event) {
|
|
30138
|
-
for (const listener of Array.from(this.listeners)) {
|
|
30139
|
-
try {
|
|
30140
|
-
listener(event);
|
|
30141
|
-
} catch (err) {
|
|
30142
|
-
console.error("[PipelineExecutor] Listener error:", err);
|
|
30143
|
-
}
|
|
30144
|
-
}
|
|
30145
|
-
}
|
|
30146
|
-
async execute(stages, context) {
|
|
30147
|
-
const startTime = Date.now();
|
|
30148
|
-
const results = [];
|
|
30149
|
-
const executedStages = [];
|
|
30150
|
-
this.emit({ type: "PipelineStarted", timestamp: startTime });
|
|
30151
|
-
console.log("[Platform] Starting Bootstrap Pipeline execution...");
|
|
30152
|
-
for (const stage of stages) {
|
|
30153
|
-
if (context.isCancelled) {
|
|
30154
|
-
console.warn(`[Platform] Pipeline cancelled before stage ${stage.name}`);
|
|
30155
|
-
const totalDurationMs2 = Date.now() - startTime;
|
|
30156
|
-
return {
|
|
30157
|
-
totalDurationMs: totalDurationMs2,
|
|
30158
|
-
status: "Aborted",
|
|
30159
|
-
stageResults: Object.freeze(results)
|
|
30160
|
-
};
|
|
30161
|
-
}
|
|
30162
|
-
console.log(`[Platform] Entering ${stage.name}`);
|
|
30163
|
-
this.emit({
|
|
30164
|
-
type: "StageStarted",
|
|
30165
|
-
timestamp: Date.now(),
|
|
30166
|
-
stageId: stage.id,
|
|
30167
|
-
stageName: String(stage.name)
|
|
30168
|
-
});
|
|
30169
|
-
const stageStart = Date.now();
|
|
30170
|
-
try {
|
|
30171
|
-
if (stage.timeoutMs && stage.timeoutMs > 0) {
|
|
30172
|
-
await this.executeWithTimeout(stage, context, stage.timeoutMs);
|
|
30173
|
-
} else {
|
|
30174
|
-
await stage.execute(context);
|
|
30175
|
-
}
|
|
30176
|
-
const durationMs = Date.now() - stageStart;
|
|
30177
|
-
console.log(`[Platform] Completed ${stage.name} (${durationMs} ms)`);
|
|
30178
|
-
results.push({
|
|
30179
|
-
stageId: stage.id,
|
|
30180
|
-
stageName: String(stage.name),
|
|
30181
|
-
durationMs,
|
|
30182
|
-
status: "Success"
|
|
30183
|
-
});
|
|
30184
|
-
executedStages.push(stage);
|
|
30185
|
-
this.emit({
|
|
30186
|
-
type: "StageCompleted",
|
|
30187
|
-
timestamp: Date.now(),
|
|
30188
|
-
stageId: stage.id,
|
|
30189
|
-
stageName: String(stage.name),
|
|
30190
|
-
durationMs
|
|
30191
|
-
});
|
|
30192
|
-
} catch (err) {
|
|
30193
|
-
const error = err instanceof Error ? err : new Error(String(err));
|
|
30194
|
-
const durationMs = Date.now() - stageStart;
|
|
30195
|
-
console.error(`[Platform] Failed ${stage.name} (${durationMs} ms): ${error.message}`);
|
|
30196
|
-
results.push({
|
|
30197
|
-
stageId: stage.id,
|
|
30198
|
-
stageName: String(stage.name),
|
|
30199
|
-
durationMs,
|
|
30200
|
-
status: "Failed",
|
|
30201
|
-
error
|
|
30202
|
-
});
|
|
30203
|
-
this.emit({
|
|
30204
|
-
type: "StageFailed",
|
|
30205
|
-
timestamp: Date.now(),
|
|
30206
|
-
stageId: stage.id,
|
|
30207
|
-
stageName: String(stage.name),
|
|
30208
|
-
durationMs,
|
|
30209
|
-
error
|
|
30210
|
-
});
|
|
30211
|
-
await this.rollbackExecutedStages(executedStages, context);
|
|
30212
|
-
const totalDurationMs2 = Date.now() - startTime;
|
|
30213
|
-
const pipelineResult = {
|
|
30214
|
-
totalDurationMs: totalDurationMs2,
|
|
30215
|
-
status: "Failed",
|
|
30216
|
-
stageResults: Object.freeze(results),
|
|
30217
|
-
failedStage: stage.id,
|
|
30218
|
-
error
|
|
30219
|
-
};
|
|
30220
|
-
this.emit({
|
|
30221
|
-
type: "PipelineCompleted",
|
|
30222
|
-
timestamp: Date.now(),
|
|
30223
|
-
durationMs: totalDurationMs2,
|
|
30224
|
-
error
|
|
30225
|
-
});
|
|
30226
|
-
return pipelineResult;
|
|
30227
|
-
}
|
|
30228
|
-
}
|
|
30229
|
-
const totalDurationMs = Date.now() - startTime;
|
|
30230
|
-
console.log(`[Platform] Ready. Total startup duration: ${totalDurationMs} ms.`);
|
|
30231
|
-
const finalResult = {
|
|
30232
|
-
totalDurationMs,
|
|
30233
|
-
status: "Success",
|
|
30234
|
-
stageResults: Object.freeze(results)
|
|
30235
|
-
};
|
|
30236
|
-
this.emit({
|
|
30237
|
-
type: "PipelineCompleted",
|
|
30238
|
-
timestamp: Date.now(),
|
|
30239
|
-
durationMs: totalDurationMs
|
|
30240
|
-
});
|
|
30241
|
-
return finalResult;
|
|
30242
|
-
}
|
|
30243
|
-
async executeWithTimeout(stage, context, timeoutMs) {
|
|
30244
|
-
let timer;
|
|
30245
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
30246
|
-
timer = setTimeout(() => {
|
|
30247
|
-
reject(new StartupTimeoutError(`Stage execution timed out after ${timeoutMs} ms`));
|
|
30248
|
-
}, timeoutMs);
|
|
30249
|
-
});
|
|
30250
|
-
try {
|
|
30251
|
-
await Promise.race([stage.execute(context), timeoutPromise]);
|
|
30252
|
-
} finally {
|
|
30253
|
-
if (timer) {
|
|
30254
|
-
clearTimeout(timer);
|
|
30255
|
-
}
|
|
30256
|
-
}
|
|
30257
|
-
}
|
|
30258
|
-
async rollbackExecutedStages(executedStages, context) {
|
|
30259
|
-
console.log("[Platform] Triggering stage rollbacks...");
|
|
30260
|
-
for (let i = executedStages.length - 1; i >= 0; i--) {
|
|
30261
|
-
const stage = executedStages[i];
|
|
30262
|
-
if (stage.rollback) {
|
|
30263
|
-
try {
|
|
30264
|
-
console.log(`[Platform] Rolling back ${stage.name}`);
|
|
30265
|
-
await stage.rollback(context);
|
|
30266
|
-
} catch (rbErr) {
|
|
30267
|
-
console.error(`[Platform] Error during rollback of ${stage.name}:`, rbErr);
|
|
30268
|
-
}
|
|
30269
|
-
}
|
|
30270
|
-
}
|
|
30271
|
-
}
|
|
30272
|
-
};
|
|
30273
|
-
|
|
30274
|
-
// packages/core/bootstrap/pipeline/stages/standard-stages.ts
|
|
30275
|
-
var StartupStageImpl = class {
|
|
30276
|
-
constructor() {
|
|
30277
|
-
this.id = "stage_startup";
|
|
30278
|
-
this.name = "Created" /* Created */;
|
|
30279
|
-
this.description = "Environment & configuration validation";
|
|
30280
|
-
}
|
|
30281
|
-
async execute(context) {
|
|
30282
|
-
context.setStage("Configuring" /* Configuring */);
|
|
30283
|
-
}
|
|
30284
|
-
};
|
|
30285
|
-
var RegistrationStageImpl = class {
|
|
30286
|
-
constructor() {
|
|
30287
|
-
this.id = "stage_registration";
|
|
30288
|
-
this.name = "Registering" /* Registering */;
|
|
30289
|
-
this.description = "Core Service Contracts & DI Tokens registration";
|
|
30290
|
-
}
|
|
30291
|
-
async execute(context) {
|
|
30292
|
-
context.setStage("Registering" /* Registering */);
|
|
30293
|
-
}
|
|
30294
|
-
};
|
|
30295
|
-
var InitializationStageImpl = class {
|
|
30296
|
-
constructor() {
|
|
30297
|
-
this.id = "stage_initialization";
|
|
30298
|
-
this.name = "Initializing" /* Initializing */;
|
|
30299
|
-
this.description = "Subsystem Kernels initialization";
|
|
30300
|
-
}
|
|
30301
|
-
async execute(context) {
|
|
30302
|
-
context.setStage("Initializing" /* Initializing */);
|
|
30303
|
-
}
|
|
30304
|
-
};
|
|
30305
|
-
var ActivationStageImpl = class {
|
|
30306
|
-
constructor() {
|
|
30307
|
-
this.id = "stage_activation";
|
|
30308
|
-
this.name = "Activating" /* Activating */;
|
|
30309
|
-
this.description = "Plugin Host discovery & ESM plugins activation";
|
|
30310
|
-
}
|
|
30311
|
-
async execute(context) {
|
|
30312
|
-
context.setStage("Activating" /* Activating */);
|
|
30313
|
-
}
|
|
30314
|
-
};
|
|
30315
|
-
var ReadyStageImpl = class {
|
|
30316
|
-
constructor() {
|
|
30317
|
-
this.id = "stage_ready";
|
|
30318
|
-
this.name = "Ready" /* Ready */;
|
|
30319
|
-
this.description = "HTTP & Socket.IO server readiness";
|
|
30320
|
-
}
|
|
30321
|
-
async execute(context) {
|
|
30322
|
-
context.setStage("Ready" /* Ready */);
|
|
30323
|
-
}
|
|
30324
|
-
};
|
|
30325
|
-
|
|
30326
|
-
// packages/core/bootstrap/pipeline/bootstrap-pipeline.ts
|
|
30327
|
-
var BootstrapPipeline = class {
|
|
30328
|
-
constructor(stages) {
|
|
30329
|
-
this._stages = [];
|
|
30330
|
-
this.executor = new PipelineExecutor();
|
|
30331
|
-
if (stages && stages.length > 0) {
|
|
30332
|
-
this._stages = [...stages];
|
|
30333
|
-
} else {
|
|
30334
|
-
this._stages = [
|
|
30335
|
-
new StartupStageImpl(),
|
|
30336
|
-
new RegistrationStageImpl(),
|
|
30337
|
-
new InitializationStageImpl(),
|
|
30338
|
-
new ActivationStageImpl(),
|
|
30339
|
-
new ReadyStageImpl()
|
|
30340
|
-
];
|
|
30341
|
-
}
|
|
30342
|
-
}
|
|
30343
|
-
get stages() {
|
|
30344
|
-
return Object.freeze(this._stages);
|
|
30345
|
-
}
|
|
30346
|
-
addStage(stage) {
|
|
30347
|
-
this._stages.push(stage);
|
|
30348
|
-
return this;
|
|
30349
|
-
}
|
|
30350
|
-
addListener(listener) {
|
|
30351
|
-
return this.executor.addListener(listener);
|
|
30352
|
-
}
|
|
30353
|
-
async run(context) {
|
|
30354
|
-
const result = await this.execute(context);
|
|
30355
|
-
if (result.status === "Failed") {
|
|
30356
|
-
throw result.error || new Error(`Bootstrap Pipeline failed at stage: ${result.failedStage}`);
|
|
30357
|
-
}
|
|
30358
|
-
}
|
|
30359
|
-
async execute(context) {
|
|
30360
|
-
return this.executor.execute(this._stages, context);
|
|
30361
|
-
}
|
|
30362
|
-
};
|
|
30363
|
-
|
|
30364
|
-
// packages/core/bootstrap/builder/platform-builder.ts
|
|
30365
|
-
var DefaultPlatformLogger = class {
|
|
30366
|
-
info(message, ...args) {
|
|
30367
|
-
console.log(`[PlatformBuilder:INFO] ${message}`, ...args);
|
|
30368
|
-
}
|
|
30369
|
-
warn(message, ...args) {
|
|
30370
|
-
console.warn(`[PlatformBuilder:WARN] ${message}`, ...args);
|
|
30371
|
-
}
|
|
30372
|
-
error(message, ...args) {
|
|
30373
|
-
console.error(`[PlatformBuilder:ERROR] ${message}`, ...args);
|
|
30374
|
-
}
|
|
30375
|
-
debug(message, ...args) {
|
|
30376
|
-
console.debug(`[PlatformBuilder:DEBUG] ${message}`, ...args);
|
|
30377
|
-
}
|
|
30378
|
-
};
|
|
30379
|
-
var PlatformBuilder = class _PlatformBuilder {
|
|
30380
|
-
constructor(options) {
|
|
30381
|
-
this._state = "Created";
|
|
30382
|
-
this._config = { ...DEFAULT_BOOTSTRAP_CONFIG };
|
|
30383
|
-
this._logger = new DefaultPlatformLogger();
|
|
30384
|
-
this._environment = "development";
|
|
30385
|
-
this._metadata = /* @__PURE__ */ new Map();
|
|
30386
|
-
this._services = /* @__PURE__ */ new Map();
|
|
30387
|
-
this._capabilities = /* @__PURE__ */ new Map();
|
|
30388
|
-
this._extensions = /* @__PURE__ */ new Map();
|
|
30389
|
-
this._pipeline = new BootstrapPipeline();
|
|
30390
|
-
this._state = "Created";
|
|
30391
|
-
this._logger.info("Builder Started");
|
|
30392
|
-
if (options) {
|
|
30393
|
-
if (options.config) this.withConfiguration(options.config);
|
|
30394
|
-
if (options.logger) this.withLogger(options.logger);
|
|
30395
|
-
if (options.environment) this.withEnvironment(options.environment);
|
|
30396
|
-
if (options.metadata) {
|
|
30397
|
-
for (const [k, v] of Object.entries(options.metadata)) {
|
|
30398
|
-
this.withMetadata(k, v);
|
|
30399
|
-
}
|
|
30400
|
-
}
|
|
30401
|
-
}
|
|
30402
|
-
}
|
|
30403
|
-
static create(options) {
|
|
30404
|
-
return new _PlatformBuilder(options);
|
|
30405
|
-
}
|
|
30406
|
-
get state() {
|
|
30407
|
-
return this._state;
|
|
30408
|
-
}
|
|
30409
|
-
transitionTo(newState) {
|
|
30410
|
-
if (this._state === "Disposed") {
|
|
30411
|
-
throw new Error("PlatformBuilder has been disposed and cannot accept further transitions.");
|
|
30412
|
-
}
|
|
30413
|
-
if (this._state === "Built" && newState !== "Disposed") {
|
|
30414
|
-
throw new Error(`Invalid state transition from Built to ${newState}. Builder is already built.`);
|
|
30415
|
-
}
|
|
30416
|
-
this._state = newState;
|
|
30417
|
-
}
|
|
30418
|
-
withConfiguration(config) {
|
|
30419
|
-
this.transitionTo("Configuring");
|
|
30420
|
-
this._config = { ...this._config, ...config };
|
|
30421
|
-
if (config.environment) {
|
|
30422
|
-
this._environment = config.environment;
|
|
30423
|
-
}
|
|
30424
|
-
this._logger.info("Configuration Loaded");
|
|
30425
|
-
return this;
|
|
30426
|
-
}
|
|
30427
|
-
withLogger(logger2) {
|
|
30428
|
-
this.transitionTo("Configuring");
|
|
30429
|
-
this._logger = logger2;
|
|
30430
|
-
return this;
|
|
30431
|
-
}
|
|
30432
|
-
withEnvironment(env) {
|
|
30433
|
-
this.transitionTo("Configuring");
|
|
30434
|
-
this._environment = env;
|
|
30435
|
-
this._config = { ...this._config, environment: env };
|
|
30436
|
-
return this;
|
|
30437
|
-
}
|
|
30438
|
-
withMetadata(key, value) {
|
|
30439
|
-
this.transitionTo("Configuring");
|
|
30440
|
-
this._metadata.set(key, value);
|
|
30441
|
-
return this;
|
|
30442
|
-
}
|
|
30443
|
-
addBootstrapStage(stage) {
|
|
30444
|
-
this.transitionTo("Configuring");
|
|
30445
|
-
this._pipeline.addStage(stage);
|
|
30446
|
-
return this;
|
|
30447
|
-
}
|
|
30448
|
-
addService(serviceId, instance) {
|
|
30449
|
-
this.transitionTo("Configuring");
|
|
30450
|
-
this._services.set(serviceId, instance);
|
|
30451
|
-
return this;
|
|
30452
|
-
}
|
|
30453
|
-
addCapability(capabilityId, descriptor) {
|
|
30454
|
-
this.transitionTo("Configuring");
|
|
30455
|
-
this._capabilities.set(capabilityId, descriptor);
|
|
30456
|
-
return this;
|
|
30457
|
-
}
|
|
30458
|
-
addExtension(extensionId, extensionSpec) {
|
|
30459
|
-
this.transitionTo("Configuring");
|
|
30460
|
-
this._extensions.set(extensionId, extensionSpec);
|
|
30461
|
-
return this;
|
|
30462
|
-
}
|
|
30463
|
-
buildResult() {
|
|
30464
|
-
const buildStart = Date.now();
|
|
30465
|
-
this.transitionTo("Validating");
|
|
30466
|
-
this._logger.info("Validation Started");
|
|
30467
|
-
const validation = BuilderValidationEngine.validate(this._config, this._environment, this._pipeline.stages);
|
|
30468
|
-
this._logger.info("Validation Completed");
|
|
30469
|
-
if (!validation.isValid) {
|
|
30470
|
-
this._logger.error(`Validation Failed with ${validation.errors.length} errors.`);
|
|
30471
|
-
throw new ConfigurationError(
|
|
30472
|
-
`PlatformBuilder validation failed: ${validation.errors.map((e) => e.message).join("; ")}`
|
|
30473
|
-
);
|
|
30474
|
-
}
|
|
30475
|
-
this.transitionTo("Building");
|
|
30476
|
-
this._logger.info("Build Started");
|
|
30477
|
-
const platformContext = {
|
|
30478
|
-
platformId: `plt_${globalThis.crypto.randomUUID()}`,
|
|
30479
|
-
version: PLATFORM_VERSION2,
|
|
30480
|
-
namespace: "openlearn.core",
|
|
30481
|
-
mode: this._config.mode,
|
|
30482
|
-
environment: {
|
|
30483
|
-
type: this._environment,
|
|
30484
|
-
isDevelopment: this._environment === "development",
|
|
30485
|
-
isProduction: this._environment === "production",
|
|
30486
|
-
isTest: this._environment === "test",
|
|
30487
|
-
isPluginSandbox: false
|
|
30488
|
-
},
|
|
30489
|
-
config: this._config,
|
|
30490
|
-
featureFlags: {
|
|
30491
|
-
isEnabled: () => true,
|
|
30492
|
-
getFlag: (_, def) => def,
|
|
30493
|
-
getAllFlags: () => ({})
|
|
30494
|
-
},
|
|
30495
|
-
runtimeMetadata: {
|
|
30496
|
-
os: process.platform,
|
|
30497
|
-
nodeVersion: process.version,
|
|
30498
|
-
arch: process.arch,
|
|
30499
|
-
processId: process.pid,
|
|
30500
|
-
memoryUsage: process.memoryUsage(),
|
|
30501
|
-
buildVersion: PLATFORM_VERSION2
|
|
30502
|
-
},
|
|
30503
|
-
bootstrapState: "Bootstrapping",
|
|
30504
|
-
logger: this._logger,
|
|
30505
|
-
diagnostics: {
|
|
30506
|
-
getMetrics: () => ({ uptime: 0 }),
|
|
30507
|
-
getSystemStatus: () => ({ isHealthy: true, activeServicesCount: this._services.size, uptimeSeconds: 0 })
|
|
30508
|
-
},
|
|
30509
|
-
serviceLocator: {
|
|
30510
|
-
hasService: (id) => this._services.has(id),
|
|
30511
|
-
getService: (id) => this._services.get(id)
|
|
30512
|
-
},
|
|
30513
|
-
capabilityCatalog: {
|
|
30514
|
-
hasCapability: (id) => this._capabilities.has(id),
|
|
30515
|
-
getCapability: (id) => this._capabilities.get(id)
|
|
30516
|
-
},
|
|
30517
|
-
extensionCatalog: {
|
|
30518
|
-
hasExtension: (id) => this._extensions.has(id),
|
|
30519
|
-
getExtension: (id) => this._extensions.get(id)
|
|
30520
|
-
},
|
|
30521
|
-
eventDispatcher: {
|
|
30522
|
-
dispatch: async () => {
|
|
30523
|
-
}
|
|
30524
|
-
},
|
|
30525
|
-
shutdownToken: {
|
|
30526
|
-
isRequested: false,
|
|
30527
|
-
onShutdown: () => {
|
|
30528
|
-
}
|
|
30529
|
-
}
|
|
30530
|
-
};
|
|
30531
|
-
const buildDurationMs = Date.now() - buildStart;
|
|
30532
|
-
this.transitionTo("Built");
|
|
30533
|
-
this._logger.info(`Build Completed in ${buildDurationMs} ms`);
|
|
30534
|
-
const result = {
|
|
30535
|
-
platformContext,
|
|
30536
|
-
pipeline: this._pipeline,
|
|
30537
|
-
buildDurationMs,
|
|
30538
|
-
validation,
|
|
30539
|
-
metadata: Object.fromEntries(this._metadata.entries()),
|
|
30540
|
-
builderVersion: PLATFORM_VERSION2
|
|
30541
|
-
};
|
|
30542
|
-
return result;
|
|
30543
|
-
}
|
|
30544
|
-
async build() {
|
|
30545
|
-
const res = this.buildResult();
|
|
30546
|
-
return {
|
|
30547
|
-
currentStage: "Created" /* Created */,
|
|
30548
|
-
context: res.platformContext,
|
|
30549
|
-
pipeline: res.pipeline,
|
|
30550
|
-
start: async () => {
|
|
30551
|
-
},
|
|
30552
|
-
shutdown: async () => {
|
|
30553
|
-
},
|
|
30554
|
-
dispose: async () => {
|
|
30555
|
-
}
|
|
30556
|
-
};
|
|
30557
|
-
}
|
|
30558
|
-
async start() {
|
|
30559
|
-
const kernel = await this.build();
|
|
30560
|
-
await kernel.start();
|
|
30561
|
-
return kernel;
|
|
30562
|
-
}
|
|
30563
|
-
async shutdown() {
|
|
30564
|
-
this.transitionTo("Disposed");
|
|
30565
|
-
}
|
|
30566
|
-
dispose() {
|
|
30567
|
-
this._state = "Disposed";
|
|
30568
|
-
this._services.clear();
|
|
30569
|
-
this._capabilities.clear();
|
|
30570
|
-
this._extensions.clear();
|
|
30571
|
-
this._metadata.clear();
|
|
30572
|
-
}
|
|
30573
|
-
};
|
|
30574
|
-
|
|
30575
|
-
// packages/core/bootstrap/composition/platform-composition-root.ts
|
|
30576
|
-
var PlatformCompositionRoot = class _PlatformCompositionRoot {
|
|
30577
|
-
constructor() {
|
|
30578
|
-
this._state = "Created";
|
|
30579
|
-
this._modules = [];
|
|
30580
|
-
this._state = "Created";
|
|
30581
|
-
}
|
|
30582
|
-
static create() {
|
|
30583
|
-
return new _PlatformCompositionRoot();
|
|
30584
|
-
}
|
|
30585
|
-
get state() {
|
|
30586
|
-
return this._state;
|
|
30587
|
-
}
|
|
30588
|
-
registerModule(module2) {
|
|
30589
|
-
if (this._state === "Disposed" || this._state === "Composed") {
|
|
30590
|
-
throw new Error(`Cannot register composition module in state: ${this._state}`);
|
|
30591
|
-
}
|
|
30592
|
-
this._modules.push(module2);
|
|
30593
|
-
return this;
|
|
30594
|
-
}
|
|
30595
|
-
compose(options) {
|
|
30596
|
-
const startTime = Date.now();
|
|
30597
|
-
this._state = "Validating";
|
|
30598
|
-
const opts = options || {};
|
|
30599
|
-
const builder = PlatformBuilder.create();
|
|
30600
|
-
if (opts.config) builder.withConfiguration(opts.config);
|
|
30601
|
-
if (opts.logger) builder.withLogger(opts.logger);
|
|
30602
|
-
if (opts.environment) builder.withEnvironment(opts.environment);
|
|
30603
|
-
const builderResult = builder.buildResult();
|
|
30604
|
-
const validation = CompositionValidator.validate(opts, builderResult.pipeline, this._modules);
|
|
30605
|
-
if (!validation.isValid) {
|
|
30606
|
-
throw new ConfigurationError(
|
|
30607
|
-
`CompositionRoot validation failed: ${validation.errors.map((e) => e.message).join("; ")}`
|
|
30608
|
-
);
|
|
30609
|
-
}
|
|
30610
|
-
this._state = "Composing";
|
|
30611
|
-
for (const mod of this._modules) {
|
|
30612
|
-
mod.compose(opts);
|
|
30613
|
-
}
|
|
30614
|
-
const durationMs = Date.now() - startTime;
|
|
30615
|
-
this._state = "Composed";
|
|
30616
|
-
return {
|
|
30617
|
-
context: builderResult.platformContext,
|
|
30618
|
-
pipeline: builderResult.pipeline,
|
|
30619
|
-
durationMs,
|
|
30620
|
-
validation
|
|
30621
|
-
};
|
|
30622
|
-
}
|
|
30623
|
-
dispose() {
|
|
30624
|
-
this._state = "Disposed";
|
|
30625
|
-
this._modules = [];
|
|
30626
|
-
}
|
|
30627
|
-
};
|
|
30628
|
-
|
|
30629
|
-
// packages/core/bootstrap/permission/permission-registry.ts
|
|
30630
|
-
var PermissionRegistry = class {
|
|
30631
|
-
constructor() {
|
|
30632
|
-
this.descriptors = /* @__PURE__ */ new Map();
|
|
30633
|
-
}
|
|
30634
|
-
register(descriptor) {
|
|
30635
|
-
if (!descriptor || !descriptor.id) {
|
|
30636
|
-
throw new Error("PermissionRegistry Error: PermissionDescriptor must have a valid ID.");
|
|
30637
|
-
}
|
|
30638
|
-
if (this.descriptors.has(descriptor.id)) {
|
|
30639
|
-
throw new Error(`PermissionRegistry Collision: Permission '${descriptor.id}' is already registered.`);
|
|
30640
|
-
}
|
|
30641
|
-
this.descriptors.set(descriptor.id, Object.freeze({ ...descriptor }));
|
|
30642
|
-
}
|
|
30643
|
-
unregister(permissionId) {
|
|
30644
|
-
return this.descriptors.delete(permissionId);
|
|
30645
|
-
}
|
|
30646
|
-
get(permissionId) {
|
|
30647
|
-
return this.descriptors.get(permissionId);
|
|
30648
|
-
}
|
|
30649
|
-
exists(permissionId) {
|
|
30650
|
-
return this.descriptors.has(permissionId);
|
|
30651
|
-
}
|
|
30652
|
-
list() {
|
|
30653
|
-
return Object.freeze(Array.from(this.descriptors.values()));
|
|
30654
|
-
}
|
|
30655
|
-
clear() {
|
|
30656
|
-
this.descriptors.clear();
|
|
30657
|
-
}
|
|
30658
|
-
};
|
|
30659
|
-
|
|
30660
|
-
// packages/core/bootstrap/permission/permission-evaluator.ts
|
|
30661
|
-
var PermissionEvaluator = class {
|
|
30662
|
-
static async evaluate(subject, permission, explicitGrants, descriptor, providers) {
|
|
30663
|
-
const evaluatedAt = Date.now();
|
|
30664
|
-
const grantKey = `${subject}::${permission}`;
|
|
30665
|
-
if (explicitGrants.has(grantKey)) {
|
|
30666
|
-
const policy = explicitGrants.get(grantKey);
|
|
30667
|
-
if (policy === "Allow") {
|
|
30668
|
-
return { allowed: true, policy: "Allow", reason: "Explicitly granted to subject", evaluatedAt };
|
|
30669
|
-
}
|
|
30670
|
-
if (policy === "Deny") {
|
|
30671
|
-
return { allowed: false, policy: "Deny", reason: "Explicitly denied to subject", evaluatedAt };
|
|
30672
|
-
}
|
|
30673
|
-
}
|
|
30674
|
-
if (providers && providers.length > 0) {
|
|
30675
|
-
for (const provider of providers) {
|
|
30676
|
-
const policy = await provider.getPolicy(subject, permission);
|
|
30677
|
-
if (policy === "Allow") {
|
|
30678
|
-
return { allowed: true, policy: "Allow", reason: `Granted by provider '${provider.id}'`, evaluatedAt };
|
|
30679
|
-
}
|
|
30680
|
-
if (policy === "Deny") {
|
|
30681
|
-
return { allowed: false, policy: "Deny", reason: `Denied by provider '${provider.id}'`, evaluatedAt };
|
|
30682
|
-
}
|
|
30683
|
-
}
|
|
30684
|
-
}
|
|
30685
|
-
if (descriptor && descriptor.defaultPolicy) {
|
|
30686
|
-
const defaultPol = descriptor.defaultPolicy;
|
|
30687
|
-
if (defaultPol === "Allow") {
|
|
30688
|
-
return { allowed: true, policy: "Allow", reason: "Allowed by descriptor default policy", evaluatedAt };
|
|
30689
|
-
}
|
|
30690
|
-
if (defaultPol === "Deny") {
|
|
30691
|
-
return { allowed: false, policy: "Deny", reason: "Denied by descriptor default policy", evaluatedAt };
|
|
30692
|
-
}
|
|
30693
|
-
}
|
|
30694
|
-
return {
|
|
30695
|
-
allowed: false,
|
|
30696
|
-
policy: "Default",
|
|
30697
|
-
reason: "No explicit allow policy resolved; default deny",
|
|
30698
|
-
evaluatedAt
|
|
30699
|
-
};
|
|
30700
|
-
}
|
|
30701
|
-
};
|
|
30702
|
-
|
|
30703
|
-
// packages/core/bootstrap/permission/permission-manager.ts
|
|
30704
|
-
var PermissionManager = class {
|
|
30705
|
-
constructor() {
|
|
30706
|
-
this.registry = new PermissionRegistry();
|
|
30707
|
-
this.grants = /* @__PURE__ */ new Map();
|
|
30708
|
-
this.providers = [];
|
|
30709
|
-
}
|
|
30710
|
-
register(descriptor) {
|
|
30711
|
-
this.registry.register(descriptor);
|
|
30712
|
-
}
|
|
30713
|
-
unregister(permissionId) {
|
|
30714
|
-
return this.registry.unregister(permissionId);
|
|
30715
|
-
}
|
|
30716
|
-
grant(subject, permissionId, policy = "Allow") {
|
|
30717
|
-
const key = `${subject}::${permissionId}`;
|
|
30718
|
-
this.grants.set(key, policy);
|
|
30719
|
-
}
|
|
30720
|
-
revoke(subject, permissionId) {
|
|
30721
|
-
const key = `${subject}::${permissionId}`;
|
|
30722
|
-
this.grants.delete(key);
|
|
30723
|
-
}
|
|
30724
|
-
addProvider(provider) {
|
|
30725
|
-
if (!this.providers.some((p) => p.id === provider.id)) {
|
|
30726
|
-
this.providers.push(provider);
|
|
30727
|
-
}
|
|
30728
|
-
}
|
|
30729
|
-
removeProvider(providerId) {
|
|
30730
|
-
this.providers = this.providers.filter((p) => p.id !== providerId);
|
|
30731
|
-
}
|
|
30732
|
-
exists(permissionId) {
|
|
30733
|
-
return this.registry.exists(permissionId);
|
|
30734
|
-
}
|
|
30735
|
-
list() {
|
|
30736
|
-
return this.registry.list();
|
|
30737
|
-
}
|
|
30738
|
-
async check(subject, target, permissionId, metadata) {
|
|
30739
|
-
const timestamp = Date.now();
|
|
30740
|
-
const descriptor = this.registry.get(permissionId);
|
|
30741
|
-
const result = await PermissionEvaluator.evaluate(subject, permissionId, this.grants, descriptor, this.providers);
|
|
30742
|
-
const context = {
|
|
30743
|
-
subject,
|
|
30744
|
-
target,
|
|
30745
|
-
permission: permissionId,
|
|
30746
|
-
metadata,
|
|
30747
|
-
timestamp,
|
|
30748
|
-
result
|
|
30749
|
-
};
|
|
30750
|
-
return context;
|
|
30751
|
-
}
|
|
30752
|
-
async require(subject, target, permissionId, metadata) {
|
|
30753
|
-
const context = await this.check(subject, target, permissionId, metadata);
|
|
30754
|
-
if (!context.result || !context.result.allowed) {
|
|
30755
|
-
const reason = context.result?.reason || "Permission Denied";
|
|
30756
|
-
throw new Error(
|
|
30757
|
-
`Infrastructure Permission Exception: Subject '${subject}' is denied '${permissionId}' on target '${target}'. Reason: ${reason}`
|
|
30758
|
-
);
|
|
30759
|
-
}
|
|
30760
|
-
return context;
|
|
30761
|
-
}
|
|
30762
|
-
clear() {
|
|
30763
|
-
this.registry.clear();
|
|
30764
|
-
this.grants.clear();
|
|
30765
|
-
this.providers = [];
|
|
30766
|
-
}
|
|
30767
|
-
};
|
|
30768
|
-
|
|
30769
|
-
// packages/core/bootstrap/composition/plugin-composition-module.ts
|
|
30770
|
-
var _sharedPlatformRegistry;
|
|
30771
|
-
function getPlatformServiceRegistry() {
|
|
30772
|
-
if (!_sharedPlatformRegistry) {
|
|
30773
|
-
_sharedPlatformRegistry = new PlatformServiceRegistry();
|
|
30774
|
-
}
|
|
30775
|
-
return _sharedPlatformRegistry;
|
|
30776
|
-
}
|
|
30777
|
-
var PluginCompositionModule = class {
|
|
30778
|
-
constructor() {
|
|
30779
|
-
this.id = "mod_plugin_composition";
|
|
30780
|
-
this.name = "PluginCompositionModule";
|
|
30781
|
-
}
|
|
30782
|
-
compose(options) {
|
|
30783
|
-
const serviceRegistry = getPlatformServiceRegistry();
|
|
30784
|
-
const registerOrReplace = (config) => {
|
|
30785
|
-
const { id, instance } = config;
|
|
30786
|
-
if (serviceRegistry.has(id)) {
|
|
30787
|
-
serviceRegistry.replace(id, instance);
|
|
30788
|
-
} else {
|
|
30789
|
-
serviceRegistry.register({ id }, instance);
|
|
30790
|
-
}
|
|
30791
|
-
};
|
|
30792
|
-
const capabilityRegistry = new CapabilityRegistry();
|
|
30793
|
-
const permissionManager = new PermissionManager();
|
|
30794
|
-
const eventBus = new EventBus();
|
|
30795
|
-
const realPluginHost = options?.infrastructureRefs?.get("pluginHost") ?? {
|
|
30796
|
-
name: "PluginHostService",
|
|
30797
|
-
isReady: true,
|
|
30798
|
-
pluginsCount: 0
|
|
30799
|
-
};
|
|
30800
|
-
const realContributionRegistry = options?.infrastructureRefs?.get("contributionRegistry") ?? {
|
|
30801
|
-
name: "ContributionRegistry",
|
|
30802
|
-
slotsCount: 0
|
|
30803
|
-
};
|
|
30804
|
-
const realRuntimeComposition = options?.infrastructureRefs?.get("runtimeComposition") ?? {
|
|
30805
|
-
name: "PluginRuntimeComposition",
|
|
30806
|
-
isStarted: true
|
|
30807
|
-
};
|
|
30808
|
-
const realLifecycleManager = options?.infrastructureRefs?.get("lifecycleManager") ?? {
|
|
30809
|
-
name: "PluginLifecycleManager",
|
|
30810
|
-
version: PLATFORM_VERSION
|
|
30811
|
-
};
|
|
30812
|
-
const realCapabilityGateway = options?.infrastructureRefs?.get("capabilityGateway") ?? {
|
|
30813
|
-
name: "PluginCapabilityGateway",
|
|
30814
|
-
version: PLATFORM_VERSION
|
|
30815
|
-
};
|
|
30816
|
-
const realExtensionRegistry = options?.infrastructureRefs?.get("extensionRegistry") ?? {
|
|
30817
|
-
name: "UnifiedExtensionRegistry",
|
|
30818
|
-
version: PLATFORM_VERSION
|
|
30819
|
-
};
|
|
30820
|
-
const realDistributionManager = options?.infrastructureRefs?.get("distributionManager") ?? {
|
|
30821
|
-
name: "PluginDistributionManager",
|
|
30822
|
-
version: PLATFORM_VERSION
|
|
30823
|
-
};
|
|
30824
|
-
registerOrReplace({
|
|
30825
|
-
id: "srv_plugin_host",
|
|
30826
|
-
lifetime: "Singleton",
|
|
30827
|
-
description: "OpenLearn Plugin Host Service Engine",
|
|
30828
|
-
instance: realPluginHost
|
|
30829
|
-
});
|
|
30830
|
-
registerOrReplace({
|
|
30831
|
-
id: "srv_plugin_contribution_registry",
|
|
30832
|
-
lifetime: "Singleton",
|
|
30833
|
-
description: "Plugin UI & Slot Contribution Registry",
|
|
30834
|
-
instance: realContributionRegistry
|
|
30835
|
-
});
|
|
30836
|
-
registerOrReplace({
|
|
30837
|
-
id: "srv_plugin_runtime_composition",
|
|
30838
|
-
lifetime: "Singleton",
|
|
30839
|
-
description: "OpenLearn Plugin Runtime Composition Facade",
|
|
30840
|
-
instance: realRuntimeComposition
|
|
30841
|
-
});
|
|
30842
|
-
registerOrReplace({
|
|
30843
|
-
id: "srv_plugin_lifecycle_manager",
|
|
30844
|
-
lifetime: "Singleton",
|
|
30845
|
-
description: "OpenLearn Unified Plugin Lifecycle Manager",
|
|
30846
|
-
instance: realLifecycleManager
|
|
30847
|
-
});
|
|
30848
|
-
registerOrReplace({
|
|
30849
|
-
id: "srv_plugin_capability_gateway",
|
|
30850
|
-
lifetime: "Singleton",
|
|
30851
|
-
description: "OpenLearn Unified Plugin Capability Gateway",
|
|
30852
|
-
instance: realCapabilityGateway
|
|
30853
|
-
});
|
|
30854
|
-
registerOrReplace({
|
|
30855
|
-
id: "srv_unified_extension_registry",
|
|
30856
|
-
lifetime: "Singleton",
|
|
30857
|
-
description: "OpenLearn Unified Extension Registry Foundation",
|
|
30858
|
-
instance: realExtensionRegistry
|
|
30859
|
-
});
|
|
30860
|
-
registerOrReplace({
|
|
30861
|
-
id: "srv_plugin_distribution_manager",
|
|
30862
|
-
lifetime: "Singleton",
|
|
30863
|
-
description: "OpenLearn Plugin Distribution Manager Foundation",
|
|
30864
|
-
instance: realDistributionManager
|
|
30865
|
-
});
|
|
30866
|
-
permissionManager.register({
|
|
30867
|
-
id: "perm_plugin_execute",
|
|
30868
|
-
name: "Plugin Execution Permission",
|
|
30869
|
-
category: "Infrastructure",
|
|
30870
|
-
description: "Allows plugin sandbox execution within Platform",
|
|
30871
|
-
defaultPolicy: "Allow"
|
|
30872
|
-
});
|
|
30873
|
-
permissionManager.register({
|
|
30874
|
-
id: "perm_plugin_install",
|
|
30875
|
-
name: "Plugin Installation Permission",
|
|
30876
|
-
category: "Infrastructure",
|
|
30877
|
-
description: "Allows installing new plugin packages into storage",
|
|
30878
|
-
defaultPolicy: "Allow"
|
|
30879
|
-
});
|
|
30880
|
-
eventBus.publish({
|
|
30881
|
-
id: `evt_${globalThis.crypto.randomUUID()}`,
|
|
30882
|
-
type: "PluginHostInitialized",
|
|
30883
|
-
source: "PluginCompositionModule",
|
|
30884
|
-
payload: { timestamp: Date.now(), status: "Ready" },
|
|
30885
|
-
timestamp: Date.now()
|
|
30886
|
-
});
|
|
30887
|
-
eventBus.publish({
|
|
30888
|
-
id: `evt_${globalThis.crypto.randomUUID()}`,
|
|
30889
|
-
type: "PluginLoaded",
|
|
30890
|
-
source: "PluginCompositionModule",
|
|
30891
|
-
payload: { timestamp: Date.now(), pluginsLoaded: 0 },
|
|
30892
|
-
timestamp: Date.now()
|
|
30893
|
-
});
|
|
30894
|
-
eventBus.publish({
|
|
30895
|
-
id: `evt_${globalThis.crypto.randomUUID()}`,
|
|
30896
|
-
type: "PluginActivated",
|
|
30897
|
-
source: "PluginCompositionModule",
|
|
30898
|
-
payload: { timestamp: Date.now(), activePlugins: [] },
|
|
30899
|
-
timestamp: Date.now()
|
|
30900
|
-
});
|
|
30901
|
-
}
|
|
30902
|
-
};
|
|
30903
|
-
|
|
30904
29986
|
// packages/core/kernel/index.ts
|
|
30905
29987
|
var import_path12 = __toESM(require("path"), 1);
|
|
30906
29988
|
var Kernel = class {
|
|
@@ -30967,20 +30049,6 @@ var Kernel = class {
|
|
|
30967
30049
|
this.unifiedExtensionRegistry = new UnifiedExtensionRegistry();
|
|
30968
30050
|
this.capabilityRegistry = capabilityRegistry;
|
|
30969
30051
|
this.pluginCapabilityGateway = new PluginCapabilityGateway(capabilityRegistry);
|
|
30970
|
-
const infrastructureRefs = /* @__PURE__ */ new Map([
|
|
30971
|
-
["pluginHost", this.pluginHost],
|
|
30972
|
-
["contributionRegistry", this.pluginHost.getContributionRegistry()],
|
|
30973
|
-
["runtimeComposition", this.pluginRuntimeComposition],
|
|
30974
|
-
["lifecycleManager", this.pluginLifecycleManager],
|
|
30975
|
-
["capabilityGateway", this.pluginCapabilityGateway],
|
|
30976
|
-
["extensionRegistry", this.unifiedExtensionRegistry],
|
|
30977
|
-
["distributionManager", this.pluginDistributionManager]
|
|
30978
|
-
]);
|
|
30979
|
-
try {
|
|
30980
|
-
PlatformCompositionRoot.create().registerModule(new PluginCompositionModule()).compose({ infrastructureRefs });
|
|
30981
|
-
} catch (e) {
|
|
30982
|
-
console.warn("[P7-A2] Plugin composition failed (non-fatal):", e.message);
|
|
30983
|
-
}
|
|
30984
30052
|
this.serviceRegistry.register(IEventBusServiceToken3, this.eventBus);
|
|
30985
30053
|
this.serviceRegistry.register(ICapabilityServiceToken, this.capabilityGuard);
|
|
30986
30054
|
this.serviceRegistry.register(IStorageServiceToken, this.storageService);
|
|
@@ -34823,7 +33891,7 @@ function sendSafeError(res, err, status = 500, fallbackMessage = "Internal serve
|
|
|
34823
33891
|
}
|
|
34824
33892
|
const isProd = process.env.NODE_ENV === "production";
|
|
34825
33893
|
const exposedMessage = isProd && effectiveStatus >= 500 ? fallbackMessage : message;
|
|
34826
|
-
const rawCode = err && typeof err === "object" && typeof err.code === "string" ? err.code : void 0;
|
|
33894
|
+
const rawCode = err && typeof err === "object" && typeof err.code === "string" ? err.code : err && typeof err === "object" && err.type === "entity.too.large" ? "PAYLOAD_TOO_LARGE" : void 0;
|
|
34827
33895
|
const errorCode = effectiveStatus >= 400 && effectiveStatus < 500 && rawCode ? rawCode : void 0;
|
|
34828
33896
|
return res.status(effectiveStatus).json({ success: false, ...errorCode ? { code: errorCode } : {}, error: exposedMessage });
|
|
34829
33897
|
}
|
|
@@ -36281,15 +35349,28 @@ var LARGE_UPLOAD_ENDPOINTS = [
|
|
|
36281
35349
|
"/api/upload",
|
|
36282
35350
|
"/api/courseware/upload",
|
|
36283
35351
|
"/api/courseware/inline",
|
|
36284
|
-
"/api/plugins/upload-zip"
|
|
35352
|
+
"/api/plugins/upload-zip",
|
|
35353
|
+
"/api/resources"
|
|
36285
35354
|
];
|
|
36286
35355
|
var LARGE_UPLOAD_LIMIT = "110mb";
|
|
35356
|
+
var MEDIUM_UPLOAD_ENDPOINTS = [
|
|
35357
|
+
"/api/auth/avatar",
|
|
35358
|
+
"/api/timetable/ocr",
|
|
35359
|
+
"/api/site-settings",
|
|
35360
|
+
"/api/agent/chat"
|
|
35361
|
+
];
|
|
35362
|
+
var MEDIUM_UPLOAD_LIMIT = "30mb";
|
|
36287
35363
|
function mountLargeBodyParsers(app) {
|
|
36288
35364
|
app.use(
|
|
36289
35365
|
LARGE_UPLOAD_ENDPOINTS,
|
|
36290
35366
|
import_express2.default.json({ limit: LARGE_UPLOAD_LIMIT }),
|
|
36291
35367
|
import_express2.default.urlencoded({ limit: LARGE_UPLOAD_LIMIT, extended: true })
|
|
36292
35368
|
);
|
|
35369
|
+
app.use(
|
|
35370
|
+
MEDIUM_UPLOAD_ENDPOINTS,
|
|
35371
|
+
import_express2.default.json({ limit: MEDIUM_UPLOAD_LIMIT }),
|
|
35372
|
+
import_express2.default.urlencoded({ limit: MEDIUM_UPLOAD_LIMIT, extended: true })
|
|
35373
|
+
);
|
|
36293
35374
|
app.use(
|
|
36294
35375
|
COURSE_PACKAGE_IMPORT_PATH,
|
|
36295
35376
|
import_express2.default.json({ limit: COURSE_PACKAGE_IMPORT_BODY_LIMIT_BYTES }),
|
|
@@ -36326,211 +35407,753 @@ function call(op, args) {
|
|
|
36326
35407
|
pending.set(callId, { resolve: resolve, reject: reject });
|
|
36327
35408
|
post({ type: 'call', callId: callId, op: op, args: args });
|
|
36328
35409
|
});
|
|
36329
|
-
}
|
|
36330
|
-
function makeCtx(pluginId, manifest) {
|
|
36331
|
-
return {
|
|
36332
|
-
pluginId: pluginId,
|
|
36333
|
-
manifest: manifest,
|
|
36334
|
-
services: {
|
|
36335
|
-
frontendApi: {
|
|
36336
|
-
get: function (path) { return call('api.get', [path]); },
|
|
36337
|
-
post: function (path, body) { return call('api.post', [path, body]); },
|
|
36338
|
-
del: function (path) { return call('api.del', [path]); }
|
|
36339
|
-
},
|
|
36340
|
-
storageService: {
|
|
36341
|
-
get: function (key) { return call('storage.get', [key]); },
|
|
36342
|
-
set: function (key, value) { return call('storage.set', [key, value]); },
|
|
36343
|
-
delete: function (key) { return call('storage.delete', [key]); }
|
|
35410
|
+
}
|
|
35411
|
+
function makeCtx(pluginId, manifest) {
|
|
35412
|
+
return {
|
|
35413
|
+
pluginId: pluginId,
|
|
35414
|
+
manifest: manifest,
|
|
35415
|
+
services: {
|
|
35416
|
+
frontendApi: {
|
|
35417
|
+
get: function (path) { return call('api.get', [path]); },
|
|
35418
|
+
post: function (path, body) { return call('api.post', [path, body]); },
|
|
35419
|
+
del: function (path) { return call('api.del', [path]); }
|
|
35420
|
+
},
|
|
35421
|
+
storageService: {
|
|
35422
|
+
get: function (key) { return call('storage.get', [key]); },
|
|
35423
|
+
set: function (key, value) { return call('storage.set', [key, value]); },
|
|
35424
|
+
delete: function (key) { return call('storage.delete', [key]); }
|
|
35425
|
+
}
|
|
35426
|
+
},
|
|
35427
|
+
ui: {
|
|
35428
|
+
registerExtensionPoint: function (slot, config) { return call('ui.register', [slot, config]); },
|
|
35429
|
+
showToast: function (message) { return call('ui.toast', [message]); }
|
|
35430
|
+
},
|
|
35431
|
+
invokeCommand: function (type, payload) { return call('command.invoke', [type, payload]); },
|
|
35432
|
+
context: { get: function () { return call('context.get', []); } }
|
|
35433
|
+
};
|
|
35434
|
+
}
|
|
35435
|
+
window.addEventListener('message', async function (event) {
|
|
35436
|
+
const data = event.data;
|
|
35437
|
+
if (!data || data.channel !== CHANNEL || event.source !== parent) return;
|
|
35438
|
+
if (data.type === 'reply') {
|
|
35439
|
+
const waiter = pending.get(data.callId);
|
|
35440
|
+
if (!waiter) return;
|
|
35441
|
+
pending.delete(data.callId);
|
|
35442
|
+
if (data.ok) waiter.resolve(data.value);
|
|
35443
|
+
else waiter.reject(new Error(data.error || 'bridge call failed'));
|
|
35444
|
+
return;
|
|
35445
|
+
}
|
|
35446
|
+
if (data.type === 'deactivate') {
|
|
35447
|
+
try {
|
|
35448
|
+
if (activePlugin && typeof activePlugin.deactivate === 'function') {
|
|
35449
|
+
await activePlugin.deactivate();
|
|
35450
|
+
}
|
|
35451
|
+
} catch (_) {}
|
|
35452
|
+
activePlugin = null;
|
|
35453
|
+
pending.clear();
|
|
35454
|
+
post({ type: 'deactivated', id: data.id });
|
|
35455
|
+
return;
|
|
35456
|
+
}
|
|
35457
|
+
if (data.type !== 'load') return;
|
|
35458
|
+
targetOrigin = event.origin && event.origin !== 'null' ? event.origin : '*';
|
|
35459
|
+
try {
|
|
35460
|
+
const blob = new Blob([data.source], { type: 'text/javascript' });
|
|
35461
|
+
const url = URL.createObjectURL(blob);
|
|
35462
|
+
let mod;
|
|
35463
|
+
try { mod = await import(url); } finally { URL.revokeObjectURL(url); }
|
|
35464
|
+
const plugin = mod.default || mod;
|
|
35465
|
+
if (typeof plugin.activate !== 'function') throw new Error('missing activate function');
|
|
35466
|
+
activePlugin = plugin;
|
|
35467
|
+
await Promise.race([
|
|
35468
|
+
plugin.activate(makeCtx(data.pluginId, data.manifest)),
|
|
35469
|
+
new Promise(function (_, reject) { setTimeout(function () { reject(new Error('Activation timeout (5000ms)')); }, 5000); })
|
|
35470
|
+
]);
|
|
35471
|
+
post({ type: 'activated', id: data.id });
|
|
35472
|
+
} catch (error) {
|
|
35473
|
+
post({ type: 'activate-error', id: data.id, error: error && error.message ? error.message : String(error) });
|
|
35474
|
+
}
|
|
35475
|
+
});
|
|
35476
|
+
post({ type: 'ready' });
|
|
35477
|
+
</script>
|
|
35478
|
+
</body></html>`;
|
|
35479
|
+
|
|
35480
|
+
// server/utils/plugin-view-bridge.ts
|
|
35481
|
+
var PLUGIN_VIEW_CSP = "sandbox allow-scripts allow-forms allow-downloads; frame-ancestors 'self'; default-src 'self' 'unsafe-inline' data: blob: https:; script-src 'self' 'unsafe-inline' 'unsafe-eval' data: blob: https:; script-src-attr 'unsafe-inline'; style-src 'self' 'unsafe-inline' data: blob: https:; style-src-attr 'unsafe-inline'; connect-src 'self' blob: data: https:;";
|
|
35482
|
+
var PLUGIN_VIEW_BRIDGE_JS = `(function () {
|
|
35483
|
+
'use strict';
|
|
35484
|
+
const CHANNEL = 'ol-plugin-view';
|
|
35485
|
+
let targetOrigin = '*';
|
|
35486
|
+
const pending = new Map();
|
|
35487
|
+
const initCallbacks = [];
|
|
35488
|
+
const contextUpdateCallbacks = [];
|
|
35489
|
+
let currentContext = null;
|
|
35490
|
+
|
|
35491
|
+
function post(msg) {
|
|
35492
|
+
if (window.parent && window.parent !== window) {
|
|
35493
|
+
window.parent.postMessage(Object.assign({ channel: CHANNEL }, msg), targetOrigin);
|
|
35494
|
+
}
|
|
35495
|
+
}
|
|
35496
|
+
|
|
35497
|
+
function call(op, args) {
|
|
35498
|
+
const callId = Math.random().toString(16).slice(2) + Date.now().toString(16);
|
|
35499
|
+
return new Promise(function (resolve, reject) {
|
|
35500
|
+
pending.set(callId, { resolve: resolve, reject: reject });
|
|
35501
|
+
post({ type: 'call', callId: callId, op: op, args: args || [] });
|
|
35502
|
+
});
|
|
35503
|
+
}
|
|
35504
|
+
|
|
35505
|
+
window.addEventListener('message', function (event) {
|
|
35506
|
+
const data = event.data;
|
|
35507
|
+
if (!data || data.channel !== CHANNEL) return;
|
|
35508
|
+
if (event.source !== window.parent) return;
|
|
35509
|
+
|
|
35510
|
+
if (data.type === 'init') {
|
|
35511
|
+
currentContext = data.payload || {};
|
|
35512
|
+
targetOrigin = event.origin && event.origin !== 'null' ? event.origin : '*';
|
|
35513
|
+
for (let i = 0; i < initCallbacks.length; i++) {
|
|
35514
|
+
try {
|
|
35515
|
+
initCallbacks[i](currentContext);
|
|
35516
|
+
} catch (e) {
|
|
35517
|
+
console.error('[OpenLearnPluginBridge] init callback error:', e);
|
|
35518
|
+
}
|
|
35519
|
+
}
|
|
35520
|
+
return;
|
|
35521
|
+
}
|
|
35522
|
+
|
|
35523
|
+
if (data.type === 'context-update') {
|
|
35524
|
+
currentContext = Object.assign({}, currentContext, data.payload || {});
|
|
35525
|
+
for (let i = 0; i < contextUpdateCallbacks.length; i++) {
|
|
35526
|
+
try {
|
|
35527
|
+
contextUpdateCallbacks[i](currentContext);
|
|
35528
|
+
} catch (e) {
|
|
35529
|
+
console.error('[OpenLearnPluginBridge] contextUpdate callback error:', e);
|
|
35530
|
+
}
|
|
35531
|
+
}
|
|
35532
|
+
return;
|
|
35533
|
+
}
|
|
35534
|
+
|
|
35535
|
+
if (data.type === 'reply') {
|
|
35536
|
+
const waiter = pending.get(data.callId);
|
|
35537
|
+
if (!waiter) return;
|
|
35538
|
+
pending.delete(data.callId);
|
|
35539
|
+
if (data.ok) {
|
|
35540
|
+
waiter.resolve(data.value);
|
|
35541
|
+
} else {
|
|
35542
|
+
waiter.reject(new Error(data.error || 'bridge call failed'));
|
|
35543
|
+
}
|
|
35544
|
+
return;
|
|
35545
|
+
}
|
|
35546
|
+
});
|
|
35547
|
+
|
|
35548
|
+
const bridge = {
|
|
35549
|
+
CHANNEL: CHANNEL,
|
|
35550
|
+
onInit: function (callback) {
|
|
35551
|
+
if (typeof callback === 'function') {
|
|
35552
|
+
if (currentContext) {
|
|
35553
|
+
try {
|
|
35554
|
+
callback(currentContext);
|
|
35555
|
+
} catch (e) {
|
|
35556
|
+
console.error('[OpenLearnPluginBridge] onInit callback error:', e);
|
|
35557
|
+
}
|
|
35558
|
+
}
|
|
35559
|
+
initCallbacks.push(callback);
|
|
35560
|
+
}
|
|
35561
|
+
return bridge;
|
|
35562
|
+
},
|
|
35563
|
+
onContextUpdate: function (callback) {
|
|
35564
|
+
if (typeof callback === 'function') {
|
|
35565
|
+
contextUpdateCallbacks.push(callback);
|
|
36344
35566
|
}
|
|
35567
|
+
return bridge;
|
|
35568
|
+
},
|
|
35569
|
+
getContext: function () {
|
|
35570
|
+
return currentContext;
|
|
36345
35571
|
},
|
|
36346
35572
|
ui: {
|
|
36347
|
-
|
|
36348
|
-
|
|
35573
|
+
toast: function (message, type) {
|
|
35574
|
+
return call('ui.toast', [message, type || 'info']);
|
|
35575
|
+
},
|
|
35576
|
+
showToast: function (message, type) {
|
|
35577
|
+
return call('ui.toast', [message, type || 'info']);
|
|
35578
|
+
},
|
|
35579
|
+
resize: function (height) {
|
|
35580
|
+
post({ type: 'resize', height: Number(height) || 0 });
|
|
35581
|
+
},
|
|
35582
|
+
},
|
|
35583
|
+
invokeCommand: function (type, payload) {
|
|
35584
|
+
return call('command.invoke', [type, payload]);
|
|
35585
|
+
},
|
|
35586
|
+
api: {
|
|
35587
|
+
get: function (path) {
|
|
35588
|
+
return call('api.get', [path]);
|
|
35589
|
+
},
|
|
35590
|
+
post: function (path, body) {
|
|
35591
|
+
return call('api.post', [path, body]);
|
|
35592
|
+
},
|
|
35593
|
+
del: function (path) {
|
|
35594
|
+
return call('api.del', [path]);
|
|
35595
|
+
},
|
|
35596
|
+
},
|
|
35597
|
+
storage: {
|
|
35598
|
+
get: function (key) {
|
|
35599
|
+
return call('storage.get', [key]);
|
|
35600
|
+
},
|
|
35601
|
+
set: function (key, value) {
|
|
35602
|
+
return call('storage.set', [key, value]);
|
|
35603
|
+
},
|
|
35604
|
+
delete: function (key) {
|
|
35605
|
+
return call('storage.delete', [key]);
|
|
35606
|
+
},
|
|
36349
35607
|
},
|
|
36350
|
-
invokeCommand: function (type, payload) { return call('command.invoke', [type, payload]); },
|
|
36351
|
-
context: { get: function () { return call('context.get', []); } }
|
|
36352
35608
|
};
|
|
36353
|
-
|
|
36354
|
-
window.
|
|
36355
|
-
|
|
36356
|
-
|
|
36357
|
-
|
|
36358
|
-
|
|
36359
|
-
|
|
36360
|
-
|
|
36361
|
-
|
|
36362
|
-
|
|
36363
|
-
|
|
35609
|
+
|
|
35610
|
+
window.OpenLearnPluginBridge = bridge;
|
|
35611
|
+
// \u901A\u77E5\u5BBF\u4E3B\u89C6\u56FE\u6C99\u7BB1 iframe \u5DF2\u5C31\u7EEA
|
|
35612
|
+
post({ type: 'ready' });
|
|
35613
|
+
})();
|
|
35614
|
+
`;
|
|
35615
|
+
|
|
35616
|
+
// packages/core/bootstrap/types/index.ts
|
|
35617
|
+
var PlatformBootstrapError = class extends Error {
|
|
35618
|
+
constructor(message, stage, cause) {
|
|
35619
|
+
super(`[PlatformBootstrapError${stage ? `:${stage}` : ""}] ${message}`);
|
|
35620
|
+
this.stage = stage;
|
|
35621
|
+
this.cause = cause;
|
|
35622
|
+
this.name = "PlatformBootstrapError";
|
|
35623
|
+
}
|
|
35624
|
+
};
|
|
35625
|
+
var ConfigurationError = class extends PlatformBootstrapError {
|
|
35626
|
+
constructor(message, cause) {
|
|
35627
|
+
super(message, "Configuring" /* Configuring */, cause);
|
|
35628
|
+
this.name = "ConfigurationError";
|
|
35629
|
+
}
|
|
35630
|
+
};
|
|
35631
|
+
var StartupTimeoutError = class extends PlatformBootstrapError {
|
|
35632
|
+
constructor(message, stage, cause) {
|
|
35633
|
+
super(message, stage, cause);
|
|
35634
|
+
this.name = "StartupTimeoutError";
|
|
35635
|
+
}
|
|
35636
|
+
};
|
|
35637
|
+
var PLATFORM_VERSION2 = PLATFORM_VERSION;
|
|
35638
|
+
var BOOTSTRAP_STAGE_NAMES = Object.freeze([
|
|
35639
|
+
"Created" /* Created */,
|
|
35640
|
+
"Configuring" /* Configuring */,
|
|
35641
|
+
"Registering" /* Registering */,
|
|
35642
|
+
"Initializing" /* Initializing */,
|
|
35643
|
+
"Activating" /* Activating */,
|
|
35644
|
+
"Ready" /* Ready */,
|
|
35645
|
+
"ShuttingDown" /* ShuttingDown */,
|
|
35646
|
+
"Disposed" /* Disposed */
|
|
35647
|
+
]);
|
|
35648
|
+
var DEFAULT_BOOTSTRAP_CONFIG = Object.freeze({
|
|
35649
|
+
environment: "development",
|
|
35650
|
+
mode: "standalone",
|
|
35651
|
+
port: 9e3,
|
|
35652
|
+
debug: false,
|
|
35653
|
+
pluginsDir: "./plugins",
|
|
35654
|
+
dbPath: "./packages/core/db/educational_os.db"
|
|
35655
|
+
});
|
|
35656
|
+
|
|
35657
|
+
// packages/core/bootstrap/pipeline/pipeline-executor.ts
|
|
35658
|
+
var PipelineExecutor = class {
|
|
35659
|
+
constructor() {
|
|
35660
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
35661
|
+
}
|
|
35662
|
+
addListener(listener) {
|
|
35663
|
+
this.listeners.add(listener);
|
|
35664
|
+
return () => {
|
|
35665
|
+
this.listeners.delete(listener);
|
|
35666
|
+
};
|
|
35667
|
+
}
|
|
35668
|
+
emit(event) {
|
|
35669
|
+
for (const listener of Array.from(this.listeners)) {
|
|
35670
|
+
try {
|
|
35671
|
+
listener(event);
|
|
35672
|
+
} catch (err) {
|
|
35673
|
+
console.error("[PipelineExecutor] Listener error:", err);
|
|
35674
|
+
}
|
|
35675
|
+
}
|
|
35676
|
+
}
|
|
35677
|
+
async execute(stages, context) {
|
|
35678
|
+
const startTime = Date.now();
|
|
35679
|
+
const results = [];
|
|
35680
|
+
const executedStages = [];
|
|
35681
|
+
this.emit({ type: "PipelineStarted", timestamp: startTime });
|
|
35682
|
+
console.log("[Platform] Starting Bootstrap Pipeline execution...");
|
|
35683
|
+
for (const stage of stages) {
|
|
35684
|
+
if (context.isCancelled) {
|
|
35685
|
+
console.warn(`[Platform] Pipeline cancelled before stage ${stage.name}`);
|
|
35686
|
+
const totalDurationMs2 = Date.now() - startTime;
|
|
35687
|
+
return {
|
|
35688
|
+
totalDurationMs: totalDurationMs2,
|
|
35689
|
+
status: "Aborted",
|
|
35690
|
+
stageResults: Object.freeze(results)
|
|
35691
|
+
};
|
|
35692
|
+
}
|
|
35693
|
+
console.log(`[Platform] Entering ${stage.name}`);
|
|
35694
|
+
this.emit({
|
|
35695
|
+
type: "StageStarted",
|
|
35696
|
+
timestamp: Date.now(),
|
|
35697
|
+
stageId: stage.id,
|
|
35698
|
+
stageName: String(stage.name)
|
|
35699
|
+
});
|
|
35700
|
+
const stageStart = Date.now();
|
|
35701
|
+
try {
|
|
35702
|
+
if (stage.timeoutMs && stage.timeoutMs > 0) {
|
|
35703
|
+
await this.executeWithTimeout(stage, context, stage.timeoutMs);
|
|
35704
|
+
} else {
|
|
35705
|
+
await stage.execute(context);
|
|
35706
|
+
}
|
|
35707
|
+
const durationMs = Date.now() - stageStart;
|
|
35708
|
+
console.log(`[Platform] Completed ${stage.name} (${durationMs} ms)`);
|
|
35709
|
+
results.push({
|
|
35710
|
+
stageId: stage.id,
|
|
35711
|
+
stageName: String(stage.name),
|
|
35712
|
+
durationMs,
|
|
35713
|
+
status: "Success"
|
|
35714
|
+
});
|
|
35715
|
+
executedStages.push(stage);
|
|
35716
|
+
this.emit({
|
|
35717
|
+
type: "StageCompleted",
|
|
35718
|
+
timestamp: Date.now(),
|
|
35719
|
+
stageId: stage.id,
|
|
35720
|
+
stageName: String(stage.name),
|
|
35721
|
+
durationMs
|
|
35722
|
+
});
|
|
35723
|
+
} catch (err) {
|
|
35724
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
35725
|
+
const durationMs = Date.now() - stageStart;
|
|
35726
|
+
console.error(`[Platform] Failed ${stage.name} (${durationMs} ms): ${error.message}`);
|
|
35727
|
+
results.push({
|
|
35728
|
+
stageId: stage.id,
|
|
35729
|
+
stageName: String(stage.name),
|
|
35730
|
+
durationMs,
|
|
35731
|
+
status: "Failed",
|
|
35732
|
+
error
|
|
35733
|
+
});
|
|
35734
|
+
this.emit({
|
|
35735
|
+
type: "StageFailed",
|
|
35736
|
+
timestamp: Date.now(),
|
|
35737
|
+
stageId: stage.id,
|
|
35738
|
+
stageName: String(stage.name),
|
|
35739
|
+
durationMs,
|
|
35740
|
+
error
|
|
35741
|
+
});
|
|
35742
|
+
await this.rollbackExecutedStages(executedStages, context);
|
|
35743
|
+
const totalDurationMs2 = Date.now() - startTime;
|
|
35744
|
+
const pipelineResult = {
|
|
35745
|
+
totalDurationMs: totalDurationMs2,
|
|
35746
|
+
status: "Failed",
|
|
35747
|
+
stageResults: Object.freeze(results),
|
|
35748
|
+
failedStage: stage.id,
|
|
35749
|
+
error
|
|
35750
|
+
};
|
|
35751
|
+
this.emit({
|
|
35752
|
+
type: "PipelineCompleted",
|
|
35753
|
+
timestamp: Date.now(),
|
|
35754
|
+
durationMs: totalDurationMs2,
|
|
35755
|
+
error
|
|
35756
|
+
});
|
|
35757
|
+
return pipelineResult;
|
|
35758
|
+
}
|
|
35759
|
+
}
|
|
35760
|
+
const totalDurationMs = Date.now() - startTime;
|
|
35761
|
+
console.log(`[Platform] Ready. Total startup duration: ${totalDurationMs} ms.`);
|
|
35762
|
+
const finalResult = {
|
|
35763
|
+
totalDurationMs,
|
|
35764
|
+
status: "Success",
|
|
35765
|
+
stageResults: Object.freeze(results)
|
|
35766
|
+
};
|
|
35767
|
+
this.emit({
|
|
35768
|
+
type: "PipelineCompleted",
|
|
35769
|
+
timestamp: Date.now(),
|
|
35770
|
+
durationMs: totalDurationMs
|
|
35771
|
+
});
|
|
35772
|
+
return finalResult;
|
|
36364
35773
|
}
|
|
36365
|
-
|
|
35774
|
+
async executeWithTimeout(stage, context, timeoutMs) {
|
|
35775
|
+
let timer;
|
|
35776
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
35777
|
+
timer = setTimeout(() => {
|
|
35778
|
+
reject(new StartupTimeoutError(`Stage execution timed out after ${timeoutMs} ms`));
|
|
35779
|
+
}, timeoutMs);
|
|
35780
|
+
});
|
|
36366
35781
|
try {
|
|
36367
|
-
|
|
36368
|
-
|
|
35782
|
+
await Promise.race([stage.execute(context), timeoutPromise]);
|
|
35783
|
+
} finally {
|
|
35784
|
+
if (timer) {
|
|
35785
|
+
clearTimeout(timer);
|
|
36369
35786
|
}
|
|
36370
|
-
}
|
|
36371
|
-
activePlugin = null;
|
|
36372
|
-
pending.clear();
|
|
36373
|
-
post({ type: 'deactivated', id: data.id });
|
|
36374
|
-
return;
|
|
35787
|
+
}
|
|
36375
35788
|
}
|
|
36376
|
-
|
|
36377
|
-
|
|
36378
|
-
|
|
36379
|
-
|
|
36380
|
-
|
|
36381
|
-
|
|
36382
|
-
|
|
36383
|
-
|
|
36384
|
-
|
|
36385
|
-
|
|
36386
|
-
|
|
36387
|
-
|
|
36388
|
-
|
|
36389
|
-
]);
|
|
36390
|
-
post({ type: 'activated', id: data.id });
|
|
36391
|
-
} catch (error) {
|
|
36392
|
-
post({ type: 'activate-error', id: data.id, error: error && error.message ? error.message : String(error) });
|
|
35789
|
+
async rollbackExecutedStages(executedStages, context) {
|
|
35790
|
+
console.log("[Platform] Triggering stage rollbacks...");
|
|
35791
|
+
for (let i = executedStages.length - 1; i >= 0; i--) {
|
|
35792
|
+
const stage = executedStages[i];
|
|
35793
|
+
if (stage.rollback) {
|
|
35794
|
+
try {
|
|
35795
|
+
console.log(`[Platform] Rolling back ${stage.name}`);
|
|
35796
|
+
await stage.rollback(context);
|
|
35797
|
+
} catch (rbErr) {
|
|
35798
|
+
console.error(`[Platform] Error during rollback of ${stage.name}:`, rbErr);
|
|
35799
|
+
}
|
|
35800
|
+
}
|
|
35801
|
+
}
|
|
36393
35802
|
}
|
|
36394
|
-
}
|
|
36395
|
-
post({ type: 'ready' });
|
|
36396
|
-
</script>
|
|
36397
|
-
</body></html>`;
|
|
35803
|
+
};
|
|
36398
35804
|
|
|
36399
|
-
//
|
|
36400
|
-
var
|
|
36401
|
-
|
|
36402
|
-
|
|
36403
|
-
|
|
36404
|
-
|
|
36405
|
-
|
|
36406
|
-
|
|
36407
|
-
|
|
36408
|
-
|
|
35805
|
+
// packages/core/bootstrap/pipeline/stages/standard-stages.ts
|
|
35806
|
+
var StartupStageImpl = class {
|
|
35807
|
+
constructor() {
|
|
35808
|
+
this.id = "stage_startup";
|
|
35809
|
+
this.name = "Created" /* Created */;
|
|
35810
|
+
this.description = "Environment & configuration validation";
|
|
35811
|
+
}
|
|
35812
|
+
async execute(context) {
|
|
35813
|
+
context.setStage("Configuring" /* Configuring */);
|
|
35814
|
+
}
|
|
35815
|
+
};
|
|
35816
|
+
var RegistrationStageImpl = class {
|
|
35817
|
+
constructor() {
|
|
35818
|
+
this.id = "stage_registration";
|
|
35819
|
+
this.name = "Registering" /* Registering */;
|
|
35820
|
+
this.description = "Core Service Contracts & DI Tokens registration";
|
|
35821
|
+
}
|
|
35822
|
+
async execute(context) {
|
|
35823
|
+
context.setStage("Registering" /* Registering */);
|
|
35824
|
+
}
|
|
35825
|
+
};
|
|
35826
|
+
var InitializationStageImpl = class {
|
|
35827
|
+
constructor() {
|
|
35828
|
+
this.id = "stage_initialization";
|
|
35829
|
+
this.name = "Initializing" /* Initializing */;
|
|
35830
|
+
this.description = "Subsystem Kernels initialization";
|
|
35831
|
+
}
|
|
35832
|
+
async execute(context) {
|
|
35833
|
+
context.setStage("Initializing" /* Initializing */);
|
|
35834
|
+
}
|
|
35835
|
+
};
|
|
35836
|
+
var ActivationStageImpl = class {
|
|
35837
|
+
constructor() {
|
|
35838
|
+
this.id = "stage_activation";
|
|
35839
|
+
this.name = "Activating" /* Activating */;
|
|
35840
|
+
this.description = "Plugin Host discovery & ESM plugins activation";
|
|
35841
|
+
}
|
|
35842
|
+
async execute(context) {
|
|
35843
|
+
context.setStage("Activating" /* Activating */);
|
|
35844
|
+
}
|
|
35845
|
+
};
|
|
35846
|
+
var ReadyStageImpl = class {
|
|
35847
|
+
constructor() {
|
|
35848
|
+
this.id = "stage_ready";
|
|
35849
|
+
this.name = "Ready" /* Ready */;
|
|
35850
|
+
this.description = "HTTP & Socket.IO server readiness";
|
|
35851
|
+
}
|
|
35852
|
+
async execute(context) {
|
|
35853
|
+
context.setStage("Ready" /* Ready */);
|
|
35854
|
+
}
|
|
35855
|
+
};
|
|
36409
35856
|
|
|
36410
|
-
|
|
36411
|
-
|
|
36412
|
-
|
|
35857
|
+
// packages/core/bootstrap/pipeline/bootstrap-pipeline.ts
|
|
35858
|
+
var BootstrapPipeline = class {
|
|
35859
|
+
constructor(stages) {
|
|
35860
|
+
this._stages = [];
|
|
35861
|
+
this.executor = new PipelineExecutor();
|
|
35862
|
+
if (stages && stages.length > 0) {
|
|
35863
|
+
this._stages = [...stages];
|
|
35864
|
+
} else {
|
|
35865
|
+
this._stages = [
|
|
35866
|
+
new StartupStageImpl(),
|
|
35867
|
+
new RegistrationStageImpl(),
|
|
35868
|
+
new InitializationStageImpl(),
|
|
35869
|
+
new ActivationStageImpl(),
|
|
35870
|
+
new ReadyStageImpl()
|
|
35871
|
+
];
|
|
36413
35872
|
}
|
|
36414
35873
|
}
|
|
36415
|
-
|
|
36416
|
-
|
|
36417
|
-
|
|
36418
|
-
|
|
36419
|
-
|
|
36420
|
-
|
|
36421
|
-
|
|
35874
|
+
get stages() {
|
|
35875
|
+
return Object.freeze(this._stages);
|
|
35876
|
+
}
|
|
35877
|
+
addStage(stage) {
|
|
35878
|
+
this._stages.push(stage);
|
|
35879
|
+
return this;
|
|
35880
|
+
}
|
|
35881
|
+
addListener(listener) {
|
|
35882
|
+
return this.executor.addListener(listener);
|
|
36422
35883
|
}
|
|
35884
|
+
async run(context) {
|
|
35885
|
+
const result = await this.execute(context);
|
|
35886
|
+
if (result.status === "Failed") {
|
|
35887
|
+
throw result.error || new Error(`Bootstrap Pipeline failed at stage: ${result.failedStage}`);
|
|
35888
|
+
}
|
|
35889
|
+
}
|
|
35890
|
+
async execute(context) {
|
|
35891
|
+
return this.executor.execute(this._stages, context);
|
|
35892
|
+
}
|
|
35893
|
+
};
|
|
36423
35894
|
|
|
36424
|
-
|
|
36425
|
-
|
|
36426
|
-
|
|
36427
|
-
|
|
35895
|
+
// packages/core/bootstrap/builder/builder-validation-engine.ts
|
|
35896
|
+
var BuilderValidationEngine = class {
|
|
35897
|
+
static validate(config, environment, stages) {
|
|
35898
|
+
const errors = [];
|
|
35899
|
+
const warnings = [];
|
|
35900
|
+
if (!["development", "production", "test"].includes(environment)) {
|
|
35901
|
+
errors.push({
|
|
35902
|
+
code: "INVALID_ENVIRONMENT",
|
|
35903
|
+
message: `Environment must be one of 'development', 'production', 'test'. Received: '${environment}'`,
|
|
35904
|
+
field: "environment"
|
|
35905
|
+
});
|
|
35906
|
+
}
|
|
35907
|
+
if (!config.port || config.port <= 0 || config.port > 65535) {
|
|
35908
|
+
errors.push({
|
|
35909
|
+
code: "INVALID_PORT",
|
|
35910
|
+
message: `Port must be a valid number between 1 and 65535. Received: ${config.port}`,
|
|
35911
|
+
field: "port"
|
|
35912
|
+
});
|
|
35913
|
+
}
|
|
35914
|
+
if (!stages || stages.length === 0) {
|
|
35915
|
+
errors.push({
|
|
35916
|
+
code: "MISSING_STAGES",
|
|
35917
|
+
message: "Bootstrap pipeline contains no registered stages.",
|
|
35918
|
+
field: "stages"
|
|
35919
|
+
});
|
|
35920
|
+
} else {
|
|
35921
|
+
const stageIds = /* @__PURE__ */ new Set();
|
|
35922
|
+
for (const stage of stages) {
|
|
35923
|
+
if (!stage.id) {
|
|
35924
|
+
errors.push({
|
|
35925
|
+
code: "INVALID_STAGE",
|
|
35926
|
+
message: `Stage '${stage.name}' has no unique ID.`
|
|
35927
|
+
});
|
|
35928
|
+
} else if (stageIds.has(stage.id)) {
|
|
35929
|
+
errors.push({
|
|
35930
|
+
code: "DUPLICATE_STAGE",
|
|
35931
|
+
message: `Duplicate stage registration detected for stage ID '${stage.id}'.`,
|
|
35932
|
+
field: "stage.id"
|
|
35933
|
+
});
|
|
35934
|
+
} else {
|
|
35935
|
+
stageIds.add(stage.id);
|
|
35936
|
+
}
|
|
35937
|
+
}
|
|
35938
|
+
}
|
|
35939
|
+
return {
|
|
35940
|
+
isValid: errors.length === 0,
|
|
35941
|
+
errors: Object.freeze(errors),
|
|
35942
|
+
warnings: Object.freeze(warnings)
|
|
35943
|
+
};
|
|
35944
|
+
}
|
|
35945
|
+
};
|
|
36428
35946
|
|
|
36429
|
-
|
|
36430
|
-
|
|
36431
|
-
|
|
36432
|
-
|
|
36433
|
-
|
|
36434
|
-
|
|
36435
|
-
|
|
36436
|
-
|
|
35947
|
+
// packages/core/bootstrap/builder/platform-builder.ts
|
|
35948
|
+
var DefaultPlatformLogger = class {
|
|
35949
|
+
info(message, ...args) {
|
|
35950
|
+
console.log(`[PlatformBuilder:INFO] ${message}`, ...args);
|
|
35951
|
+
}
|
|
35952
|
+
warn(message, ...args) {
|
|
35953
|
+
console.warn(`[PlatformBuilder:WARN] ${message}`, ...args);
|
|
35954
|
+
}
|
|
35955
|
+
error(message, ...args) {
|
|
35956
|
+
console.error(`[PlatformBuilder:ERROR] ${message}`, ...args);
|
|
35957
|
+
}
|
|
35958
|
+
debug(message, ...args) {
|
|
35959
|
+
console.debug(`[PlatformBuilder:DEBUG] ${message}`, ...args);
|
|
35960
|
+
}
|
|
35961
|
+
};
|
|
35962
|
+
var PlatformBuilder = class _PlatformBuilder {
|
|
35963
|
+
constructor(options) {
|
|
35964
|
+
this._state = "Created";
|
|
35965
|
+
this._config = { ...DEFAULT_BOOTSTRAP_CONFIG };
|
|
35966
|
+
this._logger = new DefaultPlatformLogger();
|
|
35967
|
+
this._environment = "development";
|
|
35968
|
+
this._metadata = /* @__PURE__ */ new Map();
|
|
35969
|
+
this._services = /* @__PURE__ */ new Map();
|
|
35970
|
+
this._capabilities = /* @__PURE__ */ new Map();
|
|
35971
|
+
this._extensions = /* @__PURE__ */ new Map();
|
|
35972
|
+
this._pipeline = new BootstrapPipeline();
|
|
35973
|
+
this._state = "Created";
|
|
35974
|
+
this._logger.info("Builder Started");
|
|
35975
|
+
if (options) {
|
|
35976
|
+
if (options.config) this.withConfiguration(options.config);
|
|
35977
|
+
if (options.logger) this.withLogger(options.logger);
|
|
35978
|
+
if (options.environment) this.withEnvironment(options.environment);
|
|
35979
|
+
if (options.metadata) {
|
|
35980
|
+
for (const [k, v] of Object.entries(options.metadata)) {
|
|
35981
|
+
this.withMetadata(k, v);
|
|
36437
35982
|
}
|
|
36438
35983
|
}
|
|
36439
|
-
return;
|
|
36440
35984
|
}
|
|
36441
|
-
|
|
36442
|
-
|
|
36443
|
-
|
|
36444
|
-
|
|
36445
|
-
|
|
36446
|
-
|
|
36447
|
-
|
|
36448
|
-
|
|
36449
|
-
|
|
36450
|
-
|
|
36451
|
-
return;
|
|
35985
|
+
}
|
|
35986
|
+
static create(options) {
|
|
35987
|
+
return new _PlatformBuilder(options);
|
|
35988
|
+
}
|
|
35989
|
+
get state() {
|
|
35990
|
+
return this._state;
|
|
35991
|
+
}
|
|
35992
|
+
transitionTo(newState) {
|
|
35993
|
+
if (this._state === "Disposed") {
|
|
35994
|
+
throw new Error("PlatformBuilder has been disposed and cannot accept further transitions.");
|
|
36452
35995
|
}
|
|
36453
|
-
|
|
36454
|
-
|
|
36455
|
-
const waiter = pending.get(data.callId);
|
|
36456
|
-
if (!waiter) return;
|
|
36457
|
-
pending.delete(data.callId);
|
|
36458
|
-
if (data.ok) {
|
|
36459
|
-
waiter.resolve(data.value);
|
|
36460
|
-
} else {
|
|
36461
|
-
waiter.reject(new Error(data.error || 'bridge call failed'));
|
|
36462
|
-
}
|
|
36463
|
-
return;
|
|
35996
|
+
if (this._state === "Built" && newState !== "Disposed") {
|
|
35997
|
+
throw new Error(`Invalid state transition from Built to ${newState}. Builder is already built.`);
|
|
36464
35998
|
}
|
|
36465
|
-
|
|
36466
|
-
|
|
36467
|
-
|
|
36468
|
-
|
|
36469
|
-
|
|
36470
|
-
|
|
36471
|
-
|
|
36472
|
-
|
|
36473
|
-
|
|
36474
|
-
|
|
36475
|
-
|
|
36476
|
-
|
|
36477
|
-
|
|
36478
|
-
|
|
36479
|
-
|
|
36480
|
-
|
|
36481
|
-
|
|
36482
|
-
|
|
36483
|
-
|
|
36484
|
-
|
|
36485
|
-
|
|
36486
|
-
|
|
36487
|
-
|
|
36488
|
-
|
|
36489
|
-
|
|
36490
|
-
|
|
36491
|
-
|
|
36492
|
-
|
|
36493
|
-
|
|
35999
|
+
this._state = newState;
|
|
36000
|
+
}
|
|
36001
|
+
withConfiguration(config) {
|
|
36002
|
+
this.transitionTo("Configuring");
|
|
36003
|
+
this._config = { ...this._config, ...config };
|
|
36004
|
+
if (config.environment) {
|
|
36005
|
+
this._environment = config.environment;
|
|
36006
|
+
}
|
|
36007
|
+
this._logger.info("Configuration Loaded");
|
|
36008
|
+
return this;
|
|
36009
|
+
}
|
|
36010
|
+
withLogger(logger2) {
|
|
36011
|
+
this.transitionTo("Configuring");
|
|
36012
|
+
this._logger = logger2;
|
|
36013
|
+
return this;
|
|
36014
|
+
}
|
|
36015
|
+
withEnvironment(env) {
|
|
36016
|
+
this.transitionTo("Configuring");
|
|
36017
|
+
this._environment = env;
|
|
36018
|
+
this._config = { ...this._config, environment: env };
|
|
36019
|
+
return this;
|
|
36020
|
+
}
|
|
36021
|
+
withMetadata(key, value) {
|
|
36022
|
+
this.transitionTo("Configuring");
|
|
36023
|
+
this._metadata.set(key, value);
|
|
36024
|
+
return this;
|
|
36025
|
+
}
|
|
36026
|
+
addBootstrapStage(stage) {
|
|
36027
|
+
this.transitionTo("Configuring");
|
|
36028
|
+
this._pipeline.addStage(stage);
|
|
36029
|
+
return this;
|
|
36030
|
+
}
|
|
36031
|
+
addService(serviceId, instance) {
|
|
36032
|
+
this.transitionTo("Configuring");
|
|
36033
|
+
this._services.set(serviceId, instance);
|
|
36034
|
+
return this;
|
|
36035
|
+
}
|
|
36036
|
+
addCapability(capabilityId, descriptor) {
|
|
36037
|
+
this.transitionTo("Configuring");
|
|
36038
|
+
this._capabilities.set(capabilityId, descriptor);
|
|
36039
|
+
return this;
|
|
36040
|
+
}
|
|
36041
|
+
addExtension(extensionId, extensionSpec) {
|
|
36042
|
+
this.transitionTo("Configuring");
|
|
36043
|
+
this._extensions.set(extensionId, extensionSpec);
|
|
36044
|
+
return this;
|
|
36045
|
+
}
|
|
36046
|
+
buildResult() {
|
|
36047
|
+
const buildStart = Date.now();
|
|
36048
|
+
this.transitionTo("Validating");
|
|
36049
|
+
this._logger.info("Validation Started");
|
|
36050
|
+
const validation = BuilderValidationEngine.validate(this._config, this._environment, this._pipeline.stages);
|
|
36051
|
+
this._logger.info("Validation Completed");
|
|
36052
|
+
if (!validation.isValid) {
|
|
36053
|
+
this._logger.error(`Validation Failed with ${validation.errors.length} errors.`);
|
|
36054
|
+
throw new ConfigurationError(
|
|
36055
|
+
`PlatformBuilder validation failed: ${validation.errors.map((e) => e.message).join("; ")}`
|
|
36056
|
+
);
|
|
36057
|
+
}
|
|
36058
|
+
this.transitionTo("Building");
|
|
36059
|
+
this._logger.info("Build Started");
|
|
36060
|
+
const platformContext = {
|
|
36061
|
+
platformId: `plt_${globalThis.crypto.randomUUID()}`,
|
|
36062
|
+
version: PLATFORM_VERSION2,
|
|
36063
|
+
namespace: "openlearn.core",
|
|
36064
|
+
mode: this._config.mode,
|
|
36065
|
+
environment: {
|
|
36066
|
+
type: this._environment,
|
|
36067
|
+
isDevelopment: this._environment === "development",
|
|
36068
|
+
isProduction: this._environment === "production",
|
|
36069
|
+
isTest: this._environment === "test",
|
|
36070
|
+
isPluginSandbox: false
|
|
36494
36071
|
},
|
|
36495
|
-
|
|
36496
|
-
|
|
36072
|
+
config: this._config,
|
|
36073
|
+
featureFlags: {
|
|
36074
|
+
isEnabled: () => true,
|
|
36075
|
+
getFlag: (_, def) => def,
|
|
36076
|
+
getAllFlags: () => ({})
|
|
36497
36077
|
},
|
|
36498
|
-
|
|
36499
|
-
|
|
36078
|
+
runtimeMetadata: {
|
|
36079
|
+
os: process.platform,
|
|
36080
|
+
nodeVersion: process.version,
|
|
36081
|
+
arch: process.arch,
|
|
36082
|
+
processId: process.pid,
|
|
36083
|
+
memoryUsage: process.memoryUsage(),
|
|
36084
|
+
buildVersion: PLATFORM_VERSION2
|
|
36500
36085
|
},
|
|
36501
|
-
|
|
36502
|
-
|
|
36503
|
-
|
|
36504
|
-
|
|
36505
|
-
|
|
36506
|
-
get: function (path) {
|
|
36507
|
-
return call('api.get', [path]);
|
|
36086
|
+
bootstrapState: "Bootstrapping",
|
|
36087
|
+
logger: this._logger,
|
|
36088
|
+
diagnostics: {
|
|
36089
|
+
getMetrics: () => ({ uptime: 0 }),
|
|
36090
|
+
getSystemStatus: () => ({ isHealthy: true, activeServicesCount: this._services.size, uptimeSeconds: 0 })
|
|
36508
36091
|
},
|
|
36509
|
-
|
|
36510
|
-
|
|
36092
|
+
serviceLocator: {
|
|
36093
|
+
hasService: (id) => this._services.has(id),
|
|
36094
|
+
getService: (id) => this._services.get(id)
|
|
36511
36095
|
},
|
|
36512
|
-
|
|
36513
|
-
|
|
36096
|
+
capabilityCatalog: {
|
|
36097
|
+
hasCapability: (id) => this._capabilities.has(id),
|
|
36098
|
+
getCapability: (id) => this._capabilities.get(id)
|
|
36514
36099
|
},
|
|
36515
|
-
|
|
36516
|
-
|
|
36517
|
-
|
|
36518
|
-
return call('storage.get', [key]);
|
|
36100
|
+
extensionCatalog: {
|
|
36101
|
+
hasExtension: (id) => this._extensions.has(id),
|
|
36102
|
+
getExtension: (id) => this._extensions.get(id)
|
|
36519
36103
|
},
|
|
36520
|
-
|
|
36521
|
-
|
|
36104
|
+
eventDispatcher: {
|
|
36105
|
+
dispatch: async () => {
|
|
36106
|
+
}
|
|
36522
36107
|
},
|
|
36523
|
-
|
|
36524
|
-
|
|
36108
|
+
shutdownToken: {
|
|
36109
|
+
isRequested: false,
|
|
36110
|
+
onShutdown: () => {
|
|
36111
|
+
}
|
|
36112
|
+
}
|
|
36113
|
+
};
|
|
36114
|
+
const buildDurationMs = Date.now() - buildStart;
|
|
36115
|
+
this.transitionTo("Built");
|
|
36116
|
+
this._logger.info(`Build Completed in ${buildDurationMs} ms`);
|
|
36117
|
+
const result = {
|
|
36118
|
+
platformContext,
|
|
36119
|
+
pipeline: this._pipeline,
|
|
36120
|
+
buildDurationMs,
|
|
36121
|
+
validation,
|
|
36122
|
+
metadata: Object.fromEntries(this._metadata.entries()),
|
|
36123
|
+
builderVersion: PLATFORM_VERSION2
|
|
36124
|
+
};
|
|
36125
|
+
return result;
|
|
36126
|
+
}
|
|
36127
|
+
async build() {
|
|
36128
|
+
const res = this.buildResult();
|
|
36129
|
+
return {
|
|
36130
|
+
currentStage: "Created" /* Created */,
|
|
36131
|
+
context: res.platformContext,
|
|
36132
|
+
pipeline: res.pipeline,
|
|
36133
|
+
start: async () => {
|
|
36525
36134
|
},
|
|
36526
|
-
|
|
36527
|
-
|
|
36528
|
-
|
|
36529
|
-
|
|
36530
|
-
|
|
36531
|
-
|
|
36532
|
-
|
|
36533
|
-
|
|
36135
|
+
shutdown: async () => {
|
|
36136
|
+
},
|
|
36137
|
+
dispose: async () => {
|
|
36138
|
+
}
|
|
36139
|
+
};
|
|
36140
|
+
}
|
|
36141
|
+
async start() {
|
|
36142
|
+
const kernel = await this.build();
|
|
36143
|
+
await kernel.start();
|
|
36144
|
+
return kernel;
|
|
36145
|
+
}
|
|
36146
|
+
async shutdown() {
|
|
36147
|
+
this.transitionTo("Disposed");
|
|
36148
|
+
}
|
|
36149
|
+
dispose() {
|
|
36150
|
+
this._state = "Disposed";
|
|
36151
|
+
this._services.clear();
|
|
36152
|
+
this._capabilities.clear();
|
|
36153
|
+
this._extensions.clear();
|
|
36154
|
+
this._metadata.clear();
|
|
36155
|
+
}
|
|
36156
|
+
};
|
|
36534
36157
|
|
|
36535
36158
|
// packages/core/bootstrap/adapter/bootstrap-registration.ts
|
|
36536
36159
|
var BootstrapRegistration = class {
|