@platforma-open/milaboratories.humanization-score.model 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,18 +1,18 @@
1
1
   WARN  Issue while reading "/home/runner/work/humanization-score/humanization-score/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
2
2
 
3
- > @platforma-open/milaboratories.humanization-score.model@0.2.0 build /home/runner/work/humanization-score/humanization-score/model
3
+ > @platforma-open/milaboratories.humanization-score.model@0.3.0 build /home/runner/work/humanization-score/humanization-score/model
4
4
  > ts-builder build --target block-model && block-tools build-model
5
5
 
6
6
  Building block-model project...
7
7
  ↳ cli.mjs -c /home/runner/work/humanization-score/humanization-score/node_modules/.pnpm/@milaboratories+ts-builder@1.5.0_@types+node@24.5.2_rollup@4.55.1_vue@3.5.26_typescript@5.6.3__yaml@2.8.2/node_modules/@milaboratories/ts-builder/dist/configs/rolldown.block-model.config.js
8
- [log] <DIR>/index.d.ts.map asset │ size: 0.23 kB
9
- [log] <DIR>/index.js.map asset │ size: 3.40 kB
10
- [log] <DIR>/index.js chunk │ size: 1.61 kB
11
- [log] <DIR>/index.d.ts chunk │ size: 55.55 kB
12
- [log] <DIR>/index.cjs.map asset │ size: 3.51 kB
13
- [log] <DIR>/index.cjs chunk │ size: 1.73 kB
14
- [log] <DIR>/bundle.js.map asset │ size: 692.77 kB
15
- [log] <DIR>/bundle.js chunk │ size: 351.38 kB
8
+ [log] <DIR>/index.d.ts.map asset │ size: 0.40 kB
9
+ [log] <DIR>/index.js.map asset │ size: 10.30 kB
10
+ [log] <DIR>/index.js chunk │ size: 4.23 kB
11
+ [log] <DIR>/index.d.ts chunk │ size: 58.33 kB
12
+ [log] <DIR>/index.cjs.map asset │ size: 10.42 kB
13
+ [log] <DIR>/index.cjs chunk │ size: 4.48 kB
14
+ [log] <DIR>/bundle.js.map asset │ size: 714.87 kB
15
+ [log] <DIR>/bundle.js chunk │ size: 363.08 kB
16
16
  [log]
17
- [success] rolldown v1.0.0-rc.18 Finished in 2.02 s
17
+ [success] rolldown v1.0.0-rc.18 Finished in 3.04 s
18
18
  Build completed successfully
@@ -1,5 +1,5 @@
1
1
   WARN  Issue while reading "/home/runner/work/humanization-score/humanization-score/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
2
2
 
3
- > @platforma-open/milaboratories.humanization-score.model@0.2.0 lint /home/runner/work/humanization-score/humanization-score/model
3
+ > @platforma-open/milaboratories.humanization-score.model@0.3.0 lint /home/runner/work/humanization-score/humanization-score/model
4
4
  > eslint .
5
5
 
@@ -1,6 +1,6 @@
1
1
   WARN  Issue while reading "/home/runner/work/humanization-score/humanization-score/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
2
2
 
3
- > @platforma-open/milaboratories.humanization-score.model@0.2.0 type-check /home/runner/work/humanization-score/humanization-score/model
3
+ > @platforma-open/milaboratories.humanization-score.model@0.3.0 type-check /home/runner/work/humanization-score/humanization-score/model
4
4
  > ts-builder type-check --target block-model
5
5
 
6
6
  ↳ tsc --noEmit --project ./tsconfig.json --customConditions ,
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @platforma-open/milaboratories.humanization-score.model
2
2
 
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 5c4b4f0: Initial release of the Humanization Score block.
8
+
9
+ Scores antibody sequences for humanness relative to natural human antibody
10
+ repertoires using the offline OASis/SwissProt databases bundled with the
11
+ `promb` Python runtime environment.
12
+
13
+ - **workflow**: Tengo templates that run per-clonotype humanness scoring over
14
+ the input dataset.
15
+ - **software**: Python scoring scripts (Parquet in/out) wrapping `promb`.
16
+ - **model**: block configuration, inputs/outputs, and result columns.
17
+ - **ui**: results UI with humanness score table, histogram, and sample boxplot
18
+ pages.
19
+
3
20
  ## 0.2.0
4
21
 
5
22
  Initial release.
package/dist/bundle.js CHANGED
@@ -4960,6 +4960,9 @@
4960
4960
  Sequence: "pl7.app/vdj/sequence"
4961
4961
  }
4962
4962
  };
4963
+ function isLabelColumn(column) {
4964
+ return column.axesSpec.length === 1 && column.name === PColumnName.Label;
4965
+ }
4963
4966
  /** Get column id and spec from a column */
4964
4967
  function getColumnIdAndSpec(column) {
4965
4968
  return {
@@ -8196,6 +8199,198 @@
8196
8199
  }
8197
8200
  };
8198
8201
  //#endregion
8202
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.77.15/node_modules/@platforma-sdk/model/dist/pframe_utils/axes.js
8203
+ /** Create id for column copy with added keys in axes domains */
8204
+ const colId = (id, domains, contextDomains) => {
8205
+ let wid = id.toString();
8206
+ domains?.forEach((domain) => {
8207
+ if (domain) for (const [k, v] of Object.entries(domain)) {
8208
+ wid += k;
8209
+ wid += v;
8210
+ }
8211
+ });
8212
+ contextDomains?.forEach((contextDomain) => {
8213
+ if (contextDomain) for (const [k, v] of Object.entries(contextDomain)) {
8214
+ wid += k;
8215
+ wid += v;
8216
+ }
8217
+ });
8218
+ return wid;
8219
+ };
8220
+ /** All combinations with 1 key from each list */
8221
+ function getKeysCombinations(idsLists) {
8222
+ if (!idsLists.length) return [];
8223
+ let result = [[]];
8224
+ idsLists.forEach((list) => {
8225
+ const nextResult = [];
8226
+ list.forEach((key) => {
8227
+ nextResult.push(...result.map((resultItem) => [...resultItem, key]));
8228
+ });
8229
+ result = nextResult;
8230
+ });
8231
+ return result;
8232
+ }
8233
+ function getAvailableWithLinkersAxes(linkerColumns, blockAxes) {
8234
+ const availableAxes = LinkerMap.fromColumns(linkerColumns.map(getColumnIdAndSpec)).getReachableByLinkersAxesFromAxesNormalized([...blockAxes.values()], (linkerKeyId, sourceAxisId) => matchAxisId(sourceAxisId, linkerKeyId));
8235
+ return new Map(availableAxes.map((axisSpec) => {
8236
+ return [canonicalizeJson(getAxisId(axisSpec)), axisSpec];
8237
+ }));
8238
+ }
8239
+ /** Add columns with fully compatible axes created from partial compatible ones */
8240
+ function enrichCompatible(blockAxes, columns) {
8241
+ return columns.flatMap((column) => getAdditionalColumnsForColumn(blockAxes, column));
8242
+ }
8243
+ function getAdditionalColumnsForColumn(blockAxes, column) {
8244
+ const columnAxesIds = column.spec.axesSpec.map(getAxisId);
8245
+ if (columnAxesIds.every((id) => blockAxes.has(canonicalizeJson(id)))) return [column];
8246
+ const secondaryIdsVariants = getKeysCombinations(columnAxesIds.map((id) => {
8247
+ const result = [];
8248
+ for (const [_, mainId] of blockAxes) if (matchAxisId(mainId, id) && !matchAxisId(id, mainId)) result.push(mainId);
8249
+ return result;
8250
+ }));
8251
+ const allAddedDomainValues = /* @__PURE__ */ new Set();
8252
+ const addedNotToAllVariantsDomainValues = /* @__PURE__ */ new Set();
8253
+ const addedByVariantsDomainValues = secondaryIdsVariants.map((idsList) => {
8254
+ const addedSet = /* @__PURE__ */ new Set();
8255
+ idsList.map((axisId, idx) => {
8256
+ const d1 = column.spec.axesSpec[idx].domain;
8257
+ const d2 = axisId.domain;
8258
+ Object.entries(d2 ?? {}).forEach(([key, value]) => {
8259
+ if (d1?.[key] === void 0) {
8260
+ const item = JSON.stringify([key, value]);
8261
+ addedSet.add(item);
8262
+ allAddedDomainValues.add(item);
8263
+ }
8264
+ });
8265
+ const cd1 = column.spec.axesSpec[idx].contextDomain;
8266
+ const cd2 = axisId.contextDomain;
8267
+ Object.entries(cd2 ?? {}).forEach(([key, value]) => {
8268
+ if (cd1?.[key] === void 0) {
8269
+ const item = JSON.stringify(["ctx:" + key, value]);
8270
+ addedSet.add(item);
8271
+ allAddedDomainValues.add(item);
8272
+ }
8273
+ });
8274
+ return {
8275
+ ...axisId,
8276
+ annotations: column.spec.axesSpec[idx].annotations
8277
+ };
8278
+ });
8279
+ return addedSet;
8280
+ });
8281
+ [...allAddedDomainValues].forEach((addedPart) => {
8282
+ if (addedByVariantsDomainValues.some((s) => !s.has(addedPart))) addedNotToAllVariantsDomainValues.add(addedPart);
8283
+ });
8284
+ return [column, ...secondaryIdsVariants.map((idsList, idx) => {
8285
+ const id = colId(column.id, idsList.map((id) => id.domain), idsList.map((id) => id.contextDomain));
8286
+ const label = readAnnotation(column.spec, Annotation.Label) ?? "";
8287
+ const labelDomainPart = [...addedByVariantsDomainValues[idx]].filter((str) => addedNotToAllVariantsDomainValues.has(str)).sort().map((v) => JSON.parse(v)?.[1]).join(" / ");
8288
+ const annotations = {
8289
+ ...column.spec.annotations,
8290
+ [Annotation.Graph.IsVirtual]: stringifyJson(true)
8291
+ };
8292
+ if (label || labelDomainPart) annotations[Annotation.Label] = label && labelDomainPart ? label + " / " + labelDomainPart : label + labelDomainPart;
8293
+ return {
8294
+ ...column,
8295
+ id,
8296
+ spec: {
8297
+ ...column.spec,
8298
+ axesSpec: idsList.map((axisId, idx) => ({
8299
+ ...axisId,
8300
+ annotations: column.spec.axesSpec[idx].annotations
8301
+ })),
8302
+ annotations
8303
+ }
8304
+ };
8305
+ })];
8306
+ }
8307
+ //#endregion
8308
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.77.15/node_modules/@platforma-sdk/model/dist/pframe_utils/columns.js
8309
+ function getAllRelatedColumns(ctx, predicate) {
8310
+ const columns = new PColumnCollection();
8311
+ columns.addColumnProvider(ctx.resultPool);
8312
+ const allColumns = columns.getColumns(predicate, {
8313
+ dontWaitAllData: true,
8314
+ overrideLabelAnnotation: false
8315
+ }) ?? [];
8316
+ return enrichCompatible(new Map(allColumns.flatMap((column) => getNormalizedAxesList(column.spec.axesSpec)).map((axisSpec) => {
8317
+ return [canonicalizeJson(getAxisId(axisSpec)), axisSpec];
8318
+ })), allColumns);
8319
+ }
8320
+ function getRelatedColumns(ctx, { columns: rootColumns, predicate }) {
8321
+ const columns = new PColumnCollection();
8322
+ columns.addColumnProvider(ctx.resultPool);
8323
+ columns.addColumns(rootColumns);
8324
+ const blockAxes = /* @__PURE__ */ new Map();
8325
+ const allAxes = /* @__PURE__ */ new Map();
8326
+ for (const c of rootColumns) for (const spec of getNormalizedAxesList(c.spec.axesSpec)) {
8327
+ const aid = getAxisId(spec);
8328
+ blockAxes.set(canonicalizeJson(aid), spec);
8329
+ allAxes.set(canonicalizeJson(aid), spec);
8330
+ }
8331
+ const availableWithLinkersAxes = getAvailableWithLinkersAxes(columns.getColumns((spec) => predicate(spec) && isLinkerColumn(spec), { dontWaitAllData: true }) ?? [], blockAxes);
8332
+ for (const item of availableWithLinkersAxes) {
8333
+ blockAxes.set(...item);
8334
+ allAxes.set(...item);
8335
+ }
8336
+ const blockAxesArr = Array.from(blockAxes.values());
8337
+ let compatibleWithoutLabels = (columns.getColumns((spec) => predicate(spec) && spec.axesSpec.some((axisSpec) => {
8338
+ const axisId = getAxisId(axisSpec);
8339
+ return blockAxesArr.some((selectorAxisSpec) => matchAxisId(getAxisId(selectorAxisSpec), axisId));
8340
+ }), {
8341
+ dontWaitAllData: true,
8342
+ overrideLabelAnnotation: false
8343
+ }) ?? []).filter((column) => !isLabelColumn(column.spec));
8344
+ for (const c of compatibleWithoutLabels) for (const spec of getNormalizedAxesList(c.spec.axesSpec)) {
8345
+ const aid = getAxisId(spec);
8346
+ allAxes.set(canonicalizeJson(aid), spec);
8347
+ }
8348
+ const allAxesArr = Array.from(allAxes.values());
8349
+ compatibleWithoutLabels = (columns.getColumns((spec) => predicate(spec) && spec.axesSpec.every((axisSpec) => {
8350
+ const axisId = getAxisId(axisSpec);
8351
+ return allAxesArr.some((selectorAxisSpec) => matchAxisId(getAxisId(selectorAxisSpec), axisId));
8352
+ }), {
8353
+ dontWaitAllData: true,
8354
+ overrideLabelAnnotation: false
8355
+ }) ?? []).filter((column) => !isLabelColumn(column.spec));
8356
+ const compatibleLabels = (columns.getColumns((spec) => predicate(spec) && spec.axesSpec.some((axisSpec) => {
8357
+ const axisId = getAxisId(axisSpec);
8358
+ return allAxesArr.some((selectorAxisSpec) => matchAxisId(getAxisId(selectorAxisSpec), axisId));
8359
+ }), {
8360
+ dontWaitAllData: true,
8361
+ overrideLabelAnnotation: false
8362
+ }) ?? []).filter((column) => isLabelColumn(column.spec));
8363
+ return enrichCompatible(blockAxes, [...compatibleWithoutLabels, ...compatibleLabels]);
8364
+ }
8365
+ //#endregion
8366
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.77.15/node_modules/@platforma-sdk/model/dist/components/PFrameForGraphs.js
8367
+ function isHiddenFromGraphColumn(column) {
8368
+ return !!readAnnotationJson(column, Annotation.HideDataFromGraphs);
8369
+ }
8370
+ function isHiddenFromUIColumn(column) {
8371
+ return !!readAnnotationJson(column, Annotation.HideDataFromUi);
8372
+ }
8373
+ /**
8374
+ The aim of createPFrameForGraphs: to create pframe with block’s columns and all compatible columns from result pool
8375
+ (including linker columns and all label columns).
8376
+ Block’s columns are added to pframe as is.
8377
+ Other columns are added basing on set of axes of block’s columns, considering available with linker columns.
8378
+ Compatible columns must have at least one axis from block’s axes set. This axis of the compatible column from
8379
+ result pool must satisfy matchAxisId (it can have less domain keys than in block’s axis, but without conflicting values
8380
+ among existing ones).
8381
+ In requests to pframe (calculateTableData) columns must have strictly the same axes. For compatibility in case
8382
+ of partially matched axis we add to pframe a copy of this column with modified axis (with filled missed domains)
8383
+ and modified label (with added domain values in case if more than one copy with different domains exist).
8384
+ */
8385
+ function createPFrameForGraphs(ctx, blockColumns) {
8386
+ const suitableSpec = (spec) => !isHiddenFromUIColumn(spec) && !isHiddenFromGraphColumn(spec);
8387
+ if (!blockColumns) return ctx.createPFrame(getAllRelatedColumns(ctx, suitableSpec));
8388
+ return ctx.createPFrame(getRelatedColumns(ctx, {
8389
+ columns: blockColumns,
8390
+ predicate: suitableSpec
8391
+ }));
8392
+ }
8393
+ //#endregion
8199
8394
  //#region ../node_modules/.pnpm/@platforma-sdk+model@1.77.15/node_modules/@platforma-sdk/model/dist/columns/column_selector.js
8200
8395
  function normalizeStringMatchers(input) {
8201
8396
  if (typeof input === "string") return [{
@@ -10170,29 +10365,45 @@
10170
10365
  });
10171
10366
  //#endregion
10172
10367
  //#region src/index.ts
10368
+ const HUMANNESS_SCORE_COLUMN = "pl7.app/humannessScore";
10369
+ const defaultGraphStateHistogram = () => ({
10370
+ title: "Humanness Score Distribution",
10371
+ template: "bins",
10372
+ currentTab: null,
10373
+ axesSettings: { other: { binsCount: 20 } }
10374
+ });
10375
+ const defaultGraphStateBoxplot = () => ({
10376
+ title: "Humanness by Sample",
10377
+ template: "box",
10378
+ currentTab: null
10379
+ });
10380
+ const inputSelectors = [{
10381
+ axes: [{ name: "pl7.app/sampleId" }, { name: "pl7.app/vdj/clonotypeKey" }],
10382
+ annotations: { "pl7.app/isAnchor": "true" }
10383
+ }, {
10384
+ axes: [{ name: "pl7.app/sampleId" }, { name: "pl7.app/vdj/scClonotypeKey" }],
10385
+ annotations: { "pl7.app/isAnchor": "true" }
10386
+ }];
10173
10387
  const dataModel = new DataModelBuilder().from("v1").upgradeLegacy(({ args, uiState }) => ({
10174
10388
  ...args,
10175
- tableState: uiState.tableState
10389
+ tableState: uiState.tableState,
10390
+ graphStateHistogram: uiState.graphStateHistogram ?? defaultGraphStateHistogram(),
10391
+ graphStateBoxplot: uiState.graphStateBoxplot ?? defaultGraphStateBoxplot()
10176
10392
  })).init(() => ({
10177
10393
  customBlockLabel: "",
10178
- tableState: createPlDataTableStateV2()
10394
+ tableState: createPlDataTableStateV2(),
10395
+ graphStateHistogram: defaultGraphStateHistogram(),
10396
+ graphStateBoxplot: defaultGraphStateBoxplot()
10179
10397
  }));
10180
- //#endregion
10181
- exports.platforma = BlockModelV3.create(dataModel).args((data) => {
10398
+ const platforma$1 = BlockModelV3.create(dataModel).args((data) => {
10182
10399
  if (!data.inputAnchor) throw new Error("Input anchor is required");
10183
10400
  return {
10184
- customBlockLabel: data.customBlockLabel || "Humanness Score",
10401
+ customBlockLabel: data.customBlockLabel || "",
10185
10402
  inputAnchor: data.inputAnchor,
10186
10403
  mem: data.mem
10187
10404
  };
10188
- }).output("inputOptions", (ctx) => ctx.resultPool.getOptions([{
10189
- axes: [{ name: "pl7.app/sampleId" }, { name: "pl7.app/vdj/clonotypeKey" }],
10190
- annotations: { "pl7.app/isAnchor": "true" }
10191
- }, {
10192
- axes: [{ name: "pl7.app/sampleId" }, { name: "pl7.app/vdj/scClonotypeKey" }],
10193
- annotations: { "pl7.app/isAnchor": "true" }
10194
- }])).outputWithStatus("pt", (ctx) => {
10195
- const pCols = ctx.outputs?.resolve("outputLiabilities")?.getPColumns();
10405
+ }).output("inputOptions", (ctx) => ctx.resultPool.getOptions(inputSelectors)).outputWithStatus("pt", (ctx) => {
10406
+ const pCols = ctx.outputs?.resolve("outputHumanness")?.getPColumns();
10196
10407
  if (pCols === void 0) return;
10197
10408
  return createPlDataTableV3(ctx, {
10198
10409
  tableState: ctx.data.tableState,
@@ -10201,11 +10412,85 @@
10201
10412
  isPrimary: true
10202
10413
  }))
10203
10414
  });
10204
- }).output("isRunning", (ctx) => ctx.outputs?.getIsReadyOrError() === false).title(() => "Humanness Score").subtitle((ctx) => ctx.data.customBlockLabel || "Humanness Score").sections((_) => [{
10205
- type: "link",
10206
- href: "/",
10207
- label: "Table"
10208
- }]).done();
10415
+ }).outputWithStatus("histogramPf", (ctx) => {
10416
+ const pCols = ctx.outputs?.resolve("outputHumanness")?.getPColumns();
10417
+ if (pCols === void 0) return void 0;
10418
+ return createPFrameForGraphs(ctx, pCols);
10419
+ }).output("histogramPfPcols", (ctx) => {
10420
+ const pCols = ctx.outputs?.resolve("outputHumanness")?.getPColumns();
10421
+ if (pCols === void 0 || pCols.length === 0) return void 0;
10422
+ return pCols.map((c) => ({
10423
+ columnId: c.id,
10424
+ spec: c.spec
10425
+ }));
10426
+ }).outputWithStatus("perSamplePf", (ctx) => {
10427
+ const humanness = ctx.outputs?.resolve("outputHumanness")?.getPColumns();
10428
+ if (humanness === void 0) return void 0;
10429
+ const ref = ctx.data.inputAnchor;
10430
+ if (ref === void 0) return void 0;
10431
+ const abundance = ctx.resultPool.getAnchoredPColumns({ main: ref }, [{
10432
+ axes: [{
10433
+ anchor: "main",
10434
+ idx: 0
10435
+ }, {
10436
+ anchor: "main",
10437
+ idx: 1
10438
+ }],
10439
+ annotations: {
10440
+ "pl7.app/isAbundance": "true",
10441
+ "pl7.app/abundance/normalized": "false",
10442
+ "pl7.app/abundance/isPrimary": "true"
10443
+ }
10444
+ }]);
10445
+ return createPFrameForGraphs(ctx, [...humanness, ...abundance ?? []]);
10446
+ }).output("perSamplePfPcols", (ctx) => {
10447
+ const humanness = ctx.outputs?.resolve("outputHumanness")?.getPColumns();
10448
+ if (humanness === void 0 || humanness.length === 0) return void 0;
10449
+ const ref = ctx.data.inputAnchor;
10450
+ if (ref === void 0) return void 0;
10451
+ const abundance = ctx.resultPool.getAnchoredPColumns({ main: ref }, [{
10452
+ axes: [{
10453
+ anchor: "main",
10454
+ idx: 0
10455
+ }, {
10456
+ anchor: "main",
10457
+ idx: 1
10458
+ }],
10459
+ annotations: {
10460
+ "pl7.app/isAbundance": "true",
10461
+ "pl7.app/abundance/normalized": "false",
10462
+ "pl7.app/abundance/isPrimary": "true"
10463
+ }
10464
+ }]);
10465
+ return [...humanness, ...abundance ?? []].map((c) => ({
10466
+ columnId: c.id,
10467
+ spec: c.spec
10468
+ }));
10469
+ }).output("isRunning", (ctx) => ctx.outputs?.getIsReadyOrError() === false).title(() => "Humanization Score").subtitle((ctx) => {
10470
+ if (ctx.data.customBlockLabel) return ctx.data.customBlockLabel;
10471
+ return "Humanization Score";
10472
+ }).sections((_) => [
10473
+ {
10474
+ type: "link",
10475
+ href: "/",
10476
+ label: "Table"
10477
+ },
10478
+ {
10479
+ type: "link",
10480
+ href: "/histogram",
10481
+ label: "Score Distribution"
10482
+ },
10483
+ {
10484
+ type: "link",
10485
+ href: "/by-sample",
10486
+ label: "By Sample"
10487
+ }
10488
+ ]).done();
10489
+ //#endregion
10490
+ exports.HUMANNESS_SCORE_COLUMN = HUMANNESS_SCORE_COLUMN;
10491
+ exports.defaultGraphStateBoxplot = defaultGraphStateBoxplot;
10492
+ exports.defaultGraphStateHistogram = defaultGraphStateHistogram;
10493
+ exports.platforma = platforma$1;
10209
10494
  });
10210
10495
 
10211
10496
  //# sourceMappingURL=bundle.js.map