BOC v1.0: RS256 auth, Ledger integration, Prometheus metrics, CI/CD, backup
This commit is contained in:
+73
@@ -0,0 +1,73 @@
|
||||
import { MotionGlobalConfig } from 'motion-utils';
|
||||
import { stepsOrder } from './order.mjs';
|
||||
import { createRenderStep } from './render-step.mjs';
|
||||
|
||||
const maxElapsed = 40;
|
||||
function createRenderBatcher(scheduleNextBatch, allowKeepAlive) {
|
||||
let runNextFrame = false;
|
||||
let useDefaultElapsed = true;
|
||||
const state = {
|
||||
delta: 0.0,
|
||||
timestamp: 0.0,
|
||||
isProcessing: false,
|
||||
};
|
||||
const flagRunNextFrame = () => (runNextFrame = true);
|
||||
const steps = stepsOrder.reduce((acc, key) => {
|
||||
acc[key] = createRenderStep(flagRunNextFrame);
|
||||
return acc;
|
||||
}, {});
|
||||
const { setup, read, resolveKeyframes, preUpdate, update, preRender, render, postRender, } = steps;
|
||||
const processBatch = () => {
|
||||
const useManualTiming = MotionGlobalConfig.useManualTiming;
|
||||
const timestamp = useManualTiming
|
||||
? state.timestamp
|
||||
: performance.now();
|
||||
runNextFrame = false;
|
||||
if (!useManualTiming) {
|
||||
state.delta = useDefaultElapsed
|
||||
? 1000 / 60
|
||||
: Math.max(Math.min(timestamp - state.timestamp, maxElapsed), 1);
|
||||
}
|
||||
state.timestamp = timestamp;
|
||||
state.isProcessing = true;
|
||||
// Unrolled render loop for better per-frame performance
|
||||
setup.process(state);
|
||||
read.process(state);
|
||||
resolveKeyframes.process(state);
|
||||
preUpdate.process(state);
|
||||
update.process(state);
|
||||
preRender.process(state);
|
||||
render.process(state);
|
||||
postRender.process(state);
|
||||
state.isProcessing = false;
|
||||
if (runNextFrame && allowKeepAlive) {
|
||||
useDefaultElapsed = false;
|
||||
scheduleNextBatch(processBatch);
|
||||
}
|
||||
};
|
||||
const wake = () => {
|
||||
runNextFrame = true;
|
||||
useDefaultElapsed = true;
|
||||
if (!state.isProcessing) {
|
||||
scheduleNextBatch(processBatch);
|
||||
}
|
||||
};
|
||||
const schedule = stepsOrder.reduce((acc, key) => {
|
||||
const step = steps[key];
|
||||
acc[key] = (process, keepAlive = false, immediate = false) => {
|
||||
if (!runNextFrame)
|
||||
wake();
|
||||
return step.schedule(process, keepAlive, immediate);
|
||||
};
|
||||
return acc;
|
||||
}, {});
|
||||
const cancel = (process) => {
|
||||
for (let i = 0; i < stepsOrder.length; i++) {
|
||||
steps[stepsOrder[i]].cancel(process);
|
||||
}
|
||||
};
|
||||
return { schedule, cancel, state, steps };
|
||||
}
|
||||
|
||||
export { createRenderBatcher };
|
||||
//# sourceMappingURL=batcher.mjs.map
|
||||
+1
File diff suppressed because one or more lines are too long
+7
@@ -0,0 +1,7 @@
|
||||
import { noop } from 'motion-utils';
|
||||
import { createRenderBatcher } from './batcher.mjs';
|
||||
|
||||
const { schedule: frame, cancel: cancelFrame, state: frameData, steps: frameSteps, } = /* @__PURE__ */ createRenderBatcher(typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : noop, true);
|
||||
|
||||
export { cancelFrame, frame, frameData, frameSteps };
|
||||
//# sourceMappingURL=frame.mjs.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"frame.mjs","sources":["../../../src/frameloop/frame.ts"],"sourcesContent":["import { noop } from \"motion-utils\"\nimport { createRenderBatcher } from \"./batcher\"\n\nexport const {\n schedule: frame,\n cancel: cancelFrame,\n state: frameData,\n steps: frameSteps,\n} = /* @__PURE__ */ createRenderBatcher(\n typeof requestAnimationFrame !== \"undefined\" ? requestAnimationFrame : noop,\n true\n)\n"],"names":[],"mappings":";;;AAGO,MAAM,EACT,QAAQ,EAAE,KAAK,EACf,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,UAAU,GACpB,mBAAmB,mBAAmB,CACnC,OAAO,qBAAqB,KAAK,WAAW,GAAG,qBAAqB,GAAG,IAAI,EAC3E,IAAI;;;;"}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
import { stepsOrder } from './order.mjs';
|
||||
import { frame, cancelFrame } from './frame.mjs';
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*
|
||||
* Import as `frame` instead.
|
||||
*/
|
||||
const sync = frame;
|
||||
/**
|
||||
* @deprecated
|
||||
*
|
||||
* Use cancelFrame(callback) instead.
|
||||
*/
|
||||
const cancelSync = stepsOrder.reduce((acc, key) => {
|
||||
acc[key] = (process) => cancelFrame(process);
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
export { cancelSync, sync };
|
||||
//# sourceMappingURL=index-legacy.mjs.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index-legacy.mjs","sources":["../../../src/frameloop/index-legacy.ts"],"sourcesContent":["import { cancelFrame, frame } from \".\"\nimport { stepsOrder } from \"./order\"\nimport { Process } from \"./types\"\n\n/**\n * @deprecated\n *\n * Import as `frame` instead.\n */\nexport const sync = frame\n\n/**\n * @deprecated\n *\n * Use cancelFrame(callback) instead.\n */\nexport const cancelSync = stepsOrder.reduce((acc, key) => {\n acc[key] = (process: Process) => cancelFrame(process)\n return acc\n}, {} as Record<string, (process: Process) => void>)\n"],"names":[],"mappings":";;;AAIA;;;;AAIG;AACI,MAAM,IAAI,GAAG;AAEpB;;;;AAIG;AACI,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,KAAI;AACrD,IAAA,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAgB,KAAK,WAAW,CAAC,OAAO,CAAC;AACrD,IAAA,OAAO,GAAG;AACd,CAAC,EAAE,EAAgD;;;;"}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
import { createRenderBatcher } from './batcher.mjs';
|
||||
|
||||
const { schedule: microtask, cancel: cancelMicrotask } =
|
||||
/* @__PURE__ */ createRenderBatcher(queueMicrotask, false);
|
||||
|
||||
export { cancelMicrotask, microtask };
|
||||
//# sourceMappingURL=microtask.mjs.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"microtask.mjs","sources":["../../../src/frameloop/microtask.ts"],"sourcesContent":["import { createRenderBatcher } from \"./batcher\"\n\nexport const { schedule: microtask, cancel: cancelMicrotask } =\n /* @__PURE__ */ createRenderBatcher(queueMicrotask, false)\n"],"names":[],"mappings":";;AAEO,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE;AACzD,gBAAgB,mBAAmB,CAAC,cAAc,EAAE,KAAK;;;;"}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
const stepsOrder = [
|
||||
"setup", // Compute
|
||||
"read", // Read
|
||||
"resolveKeyframes", // Write/Read/Write/Read
|
||||
"preUpdate", // Compute
|
||||
"update", // Compute
|
||||
"preRender", // Compute
|
||||
"render", // Write
|
||||
"postRender", // Compute
|
||||
];
|
||||
|
||||
export { stepsOrder };
|
||||
//# sourceMappingURL=order.mjs.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"order.mjs","sources":["../../../src/frameloop/order.ts"],"sourcesContent":["import { StepId } from \"./types\"\n\nexport const stepsOrder: StepId[] = [\n \"setup\", // Compute\n \"read\", // Read\n \"resolveKeyframes\", // Write/Read/Write/Read\n \"preUpdate\", // Compute\n \"update\", // Compute\n \"preRender\", // Compute\n \"render\", // Write\n \"postRender\", // Compute\n] as const\n\nexport type StepNames = (typeof stepsOrder)[number]\n"],"names":[],"mappings":"AAEO,MAAM,UAAU,GAAa;AAChC,IAAA,OAAO;AACP,IAAA,MAAM;AACN,IAAA,kBAAkB;AAClB,IAAA,WAAW;AACX,IAAA,QAAQ;AACR,IAAA,WAAW;AACX,IAAA,QAAQ;AACR,IAAA,YAAY;;;;;"}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
function createRenderStep(runNextFrame) {
|
||||
/**
|
||||
* We create and reuse two queues, one to queue jobs for the current frame
|
||||
* and one for the next. We reuse to avoid triggering GC after x frames.
|
||||
*/
|
||||
let thisFrame = new Set();
|
||||
let nextFrame = new Set();
|
||||
/**
|
||||
* Track whether we're currently processing jobs in this step. This way
|
||||
* we can decide whether to schedule new jobs for this frame or next.
|
||||
*/
|
||||
let isProcessing = false;
|
||||
let flushNextFrame = false;
|
||||
/**
|
||||
* A set of processes which were marked keepAlive when scheduled.
|
||||
*/
|
||||
const toKeepAlive = new WeakSet();
|
||||
let latestFrameData = {
|
||||
delta: 0.0,
|
||||
timestamp: 0.0,
|
||||
isProcessing: false,
|
||||
};
|
||||
function triggerCallback(callback) {
|
||||
if (toKeepAlive.has(callback)) {
|
||||
step.schedule(callback);
|
||||
runNextFrame();
|
||||
}
|
||||
callback(latestFrameData);
|
||||
}
|
||||
const step = {
|
||||
/**
|
||||
* Schedule a process to run on the next frame.
|
||||
*/
|
||||
schedule: (callback, keepAlive = false, immediate = false) => {
|
||||
const addToCurrentFrame = immediate && isProcessing;
|
||||
const queue = addToCurrentFrame ? thisFrame : nextFrame;
|
||||
if (keepAlive)
|
||||
toKeepAlive.add(callback);
|
||||
queue.add(callback);
|
||||
return callback;
|
||||
},
|
||||
/**
|
||||
* Cancel the provided callback from running on the next frame.
|
||||
*/
|
||||
cancel: (callback) => {
|
||||
nextFrame.delete(callback);
|
||||
toKeepAlive.delete(callback);
|
||||
},
|
||||
/**
|
||||
* Execute all schedule callbacks.
|
||||
*/
|
||||
process: (frameData) => {
|
||||
latestFrameData = frameData;
|
||||
/**
|
||||
* If we're already processing we've probably been triggered by a flushSync
|
||||
* inside an existing process. Instead of executing, mark flushNextFrame
|
||||
* as true and ensure we flush the following frame at the end of this one.
|
||||
*/
|
||||
if (isProcessing) {
|
||||
flushNextFrame = true;
|
||||
return;
|
||||
}
|
||||
isProcessing = true;
|
||||
// Swap this frame and the next to avoid GC
|
||||
const prevFrame = thisFrame;
|
||||
thisFrame = nextFrame;
|
||||
nextFrame = prevFrame;
|
||||
// Execute this frame
|
||||
thisFrame.forEach(triggerCallback);
|
||||
// Clear the frame so no callbacks remain. This is to avoid
|
||||
// memory leaks should this render step not run for a while.
|
||||
thisFrame.clear();
|
||||
isProcessing = false;
|
||||
if (flushNextFrame) {
|
||||
flushNextFrame = false;
|
||||
step.process(frameData);
|
||||
}
|
||||
},
|
||||
};
|
||||
return step;
|
||||
}
|
||||
|
||||
export { createRenderStep };
|
||||
//# sourceMappingURL=render-step.mjs.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"render-step.mjs","sources":["../../../src/frameloop/render-step.ts"],"sourcesContent":["import { FrameData, Process, Step } from \"./types\"\n\nexport function createRenderStep(runNextFrame: () => void): Step {\n /**\n * We create and reuse two queues, one to queue jobs for the current frame\n * and one for the next. We reuse to avoid triggering GC after x frames.\n */\n let thisFrame = new Set<Process>()\n let nextFrame = new Set<Process>()\n\n /**\n * Track whether we're currently processing jobs in this step. This way\n * we can decide whether to schedule new jobs for this frame or next.\n */\n let isProcessing = false\n\n let flushNextFrame = false\n\n /**\n * A set of processes which were marked keepAlive when scheduled.\n */\n const toKeepAlive = new WeakSet<Process>()\n\n let latestFrameData: FrameData = {\n delta: 0.0,\n timestamp: 0.0,\n isProcessing: false,\n }\n\n function triggerCallback(callback: Process) {\n if (toKeepAlive.has(callback)) {\n step.schedule(callback)\n runNextFrame()\n }\n\n callback(latestFrameData)\n }\n\n const step: Step = {\n /**\n * Schedule a process to run on the next frame.\n */\n schedule: (callback, keepAlive = false, immediate = false) => {\n const addToCurrentFrame = immediate && isProcessing\n const queue = addToCurrentFrame ? thisFrame : nextFrame\n\n if (keepAlive) toKeepAlive.add(callback)\n\n queue.add(callback)\n\n return callback\n },\n\n /**\n * Cancel the provided callback from running on the next frame.\n */\n cancel: (callback) => {\n nextFrame.delete(callback)\n toKeepAlive.delete(callback)\n },\n\n /**\n * Execute all schedule callbacks.\n */\n process: (frameData) => {\n latestFrameData = frameData\n\n /**\n * If we're already processing we've probably been triggered by a flushSync\n * inside an existing process. Instead of executing, mark flushNextFrame\n * as true and ensure we flush the following frame at the end of this one.\n */\n if (isProcessing) {\n flushNextFrame = true\n return\n }\n\n isProcessing = true\n\n // Swap this frame and the next to avoid GC\n const prevFrame = thisFrame\n thisFrame = nextFrame\n nextFrame = prevFrame\n\n // Execute this frame\n thisFrame.forEach(triggerCallback)\n\n // Clear the frame so no callbacks remain. This is to avoid\n // memory leaks should this render step not run for a while.\n thisFrame.clear()\n\n isProcessing = false\n\n if (flushNextFrame) {\n flushNextFrame = false\n step.process(frameData)\n }\n },\n }\n\n return step\n}\n"],"names":[],"mappings":"AAEM,SAAU,gBAAgB,CAAC,YAAwB,EAAA;AACrD;;;AAGG;AACH,IAAA,IAAI,SAAS,GAAG,IAAI,GAAG,EAAW;AAClC,IAAA,IAAI,SAAS,GAAG,IAAI,GAAG,EAAW;AAElC;;;AAGG;IACH,IAAI,YAAY,GAAG,KAAK;IAExB,IAAI,cAAc,GAAG,KAAK;AAE1B;;AAEG;AACH,IAAA,MAAM,WAAW,GAAG,IAAI,OAAO,EAAW;AAE1C,IAAA,IAAI,eAAe,GAAc;AAC7B,QAAA,KAAK,EAAE,GAAG;AACV,QAAA,SAAS,EAAE,GAAG;AACd,QAAA,YAAY,EAAE,KAAK;KACtB;IAED,SAAS,eAAe,CAAC,QAAiB,EAAA;AACtC,QAAA,IAAI,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;AAC3B,YAAA,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;AACvB,YAAA,YAAY,EAAE;QAClB;QAEA,QAAQ,CAAC,eAAe,CAAC;IAC7B;AAEA,IAAA,MAAM,IAAI,GAAS;AACf;;AAEG;AACH,QAAA,QAAQ,EAAE,CAAC,QAAQ,EAAE,SAAS,GAAG,KAAK,EAAE,SAAS,GAAG,KAAK,KAAI;AACzD,YAAA,MAAM,iBAAiB,GAAG,SAAS,IAAI,YAAY;YACnD,MAAM,KAAK,GAAG,iBAAiB,GAAG,SAAS,GAAG,SAAS;AAEvD,YAAA,IAAI,SAAS;AAAE,gBAAA,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC;AAExC,YAAA,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;AAEnB,YAAA,OAAO,QAAQ;QACnB,CAAC;AAED;;AAEG;AACH,QAAA,MAAM,EAAE,CAAC,QAAQ,KAAI;AACjB,YAAA,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC;AAC1B,YAAA,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC;QAChC,CAAC;AAED;;AAEG;AACH,QAAA,OAAO,EAAE,CAAC,SAAS,KAAI;YACnB,eAAe,GAAG,SAAS;AAE3B;;;;AAIG;YACH,IAAI,YAAY,EAAE;gBACd,cAAc,GAAG,IAAI;gBACrB;YACJ;YAEA,YAAY,GAAG,IAAI;;YAGnB,MAAM,SAAS,GAAG,SAAS;YAC3B,SAAS,GAAG,SAAS;YACrB,SAAS,GAAG,SAAS;;AAGrB,YAAA,SAAS,CAAC,OAAO,CAAC,eAAe,CAAC;;;YAIlC,SAAS,CAAC,KAAK,EAAE;YAEjB,YAAY,GAAG,KAAK;YAEpB,IAAI,cAAc,EAAE;gBAChB,cAAc,GAAG,KAAK;AACtB,gBAAA,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;YAC3B;QACJ,CAAC;KACJ;AAED,IAAA,OAAO,IAAI;AACf;;;;"}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
import { MotionGlobalConfig } from 'motion-utils';
|
||||
import { frameData } from './frame.mjs';
|
||||
|
||||
let now;
|
||||
function clearTime() {
|
||||
now = undefined;
|
||||
}
|
||||
/**
|
||||
* An eventloop-synchronous alternative to performance.now().
|
||||
*
|
||||
* Ensures that time measurements remain consistent within a synchronous context.
|
||||
* Usually calling performance.now() twice within the same synchronous context
|
||||
* will return different values which isn't useful for animations when we're usually
|
||||
* trying to sync animations to the same frame.
|
||||
*/
|
||||
const time = {
|
||||
now: () => {
|
||||
if (now === undefined) {
|
||||
time.set(frameData.isProcessing || MotionGlobalConfig.useManualTiming
|
||||
? frameData.timestamp
|
||||
: performance.now());
|
||||
}
|
||||
return now;
|
||||
},
|
||||
set: (newTime) => {
|
||||
now = newTime;
|
||||
queueMicrotask(clearTime);
|
||||
},
|
||||
};
|
||||
|
||||
export { time };
|
||||
//# sourceMappingURL=sync-time.mjs.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"sync-time.mjs","sources":["../../../src/frameloop/sync-time.ts"],"sourcesContent":["import { MotionGlobalConfig } from \"motion-utils\"\nimport { frameData } from \"./frame\"\n\nlet now: number | undefined\n\nfunction clearTime() {\n now = undefined\n}\n\n/**\n * An eventloop-synchronous alternative to performance.now().\n *\n * Ensures that time measurements remain consistent within a synchronous context.\n * Usually calling performance.now() twice within the same synchronous context\n * will return different values which isn't useful for animations when we're usually\n * trying to sync animations to the same frame.\n */\nexport const time = {\n now: (): number => {\n if (now === undefined) {\n time.set(\n frameData.isProcessing || MotionGlobalConfig.useManualTiming\n ? frameData.timestamp\n : performance.now()\n )\n }\n\n return now!\n },\n set: (newTime: number) => {\n now = newTime\n queueMicrotask(clearTime)\n },\n}\n"],"names":[],"mappings":";;;AAGA,IAAI,GAAuB;AAE3B,SAAS,SAAS,GAAA;IACd,GAAG,GAAG,SAAS;AACnB;AAEA;;;;;;;AAOG;AACI,MAAM,IAAI,GAAG;IAChB,GAAG,EAAE,MAAa;AACd,QAAA,IAAI,GAAG,KAAK,SAAS,EAAE;YACnB,IAAI,CAAC,GAAG,CACJ,SAAS,CAAC,YAAY,IAAI,kBAAkB,CAAC;kBACvC,SAAS,CAAC;AACZ,kBAAE,WAAW,CAAC,GAAG,EAAE,CAC1B;QACL;AAEA,QAAA,OAAO,GAAI;IACf,CAAC;AACD,IAAA,GAAG,EAAE,CAAC,OAAe,KAAI;QACrB,GAAG,GAAG,OAAO;QACb,cAAc,CAAC,SAAS,CAAC;IAC7B,CAAC;;;;;"}
|
||||
Reference in New Issue
Block a user