@sealpixel/core 1.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/README.md +3 -0
  2. package/dist/assets.d.ts +37 -0
  3. package/dist/assets.d.ts.map +1 -0
  4. package/dist/assets.js +96 -0
  5. package/dist/assets.js.map +1 -0
  6. package/dist/canonical-json.d.ts +11 -0
  7. package/dist/canonical-json.d.ts.map +1 -0
  8. package/dist/canonical-json.js +48 -0
  9. package/dist/canonical-json.js.map +1 -0
  10. package/dist/compile.d.ts +30 -0
  11. package/dist/compile.d.ts.map +1 -0
  12. package/dist/compile.js +64 -0
  13. package/dist/compile.js.map +1 -0
  14. package/dist/embedded.d.ts +13 -0
  15. package/dist/embedded.d.ts.map +1 -0
  16. package/dist/embedded.js +145 -0
  17. package/dist/embedded.js.map +1 -0
  18. package/dist/errors.d.ts +9 -0
  19. package/dist/errors.d.ts.map +1 -0
  20. package/dist/errors.js +19 -0
  21. package/dist/errors.js.map +1 -0
  22. package/dist/external-kernel.d.ts +13 -0
  23. package/dist/external-kernel.d.ts.map +1 -0
  24. package/dist/external-kernel.js +68 -0
  25. package/dist/external-kernel.js.map +1 -0
  26. package/dist/generated/geometry.d.ts +33 -0
  27. package/dist/generated/geometry.d.ts.map +1 -0
  28. package/dist/generated/geometry.js +3 -0
  29. package/dist/generated/geometry.js.map +1 -0
  30. package/dist/generated/output.d.ts +40 -0
  31. package/dist/generated/output.d.ts.map +1 -0
  32. package/dist/generated/output.js +3 -0
  33. package/dist/generated/output.js.map +1 -0
  34. package/dist/generated/plan.d.ts +292 -0
  35. package/dist/generated/plan.d.ts.map +1 -0
  36. package/dist/generated/plan.js +3 -0
  37. package/dist/generated/plan.js.map +1 -0
  38. package/dist/history.d.ts +16 -0
  39. package/dist/history.d.ts.map +1 -0
  40. package/dist/history.js +38 -0
  41. package/dist/history.js.map +1 -0
  42. package/dist/image-size.d.ts +12 -0
  43. package/dist/image-size.d.ts.map +1 -0
  44. package/dist/image-size.js +86 -0
  45. package/dist/image-size.js.map +1 -0
  46. package/dist/index.d.ts +24 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +22 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/inline-renderer.d.ts +28 -0
  51. package/dist/inline-renderer.d.ts.map +1 -0
  52. package/dist/inline-renderer.js +48 -0
  53. package/dist/inline-renderer.js.map +1 -0
  54. package/dist/options.d.ts +13 -0
  55. package/dist/options.d.ts.map +1 -0
  56. package/dist/options.js +35 -0
  57. package/dist/options.js.map +1 -0
  58. package/dist/plan.d.ts +16 -0
  59. package/dist/plan.d.ts.map +1 -0
  60. package/dist/plan.js +15 -0
  61. package/dist/plan.js.map +1 -0
  62. package/dist/plugin.d.ts +200 -0
  63. package/dist/plugin.d.ts.map +1 -0
  64. package/dist/plugin.js +2 -0
  65. package/dist/plugin.js.map +1 -0
  66. package/dist/registry.d.ts +58 -0
  67. package/dist/registry.d.ts.map +1 -0
  68. package/dist/registry.js +187 -0
  69. package/dist/registry.js.map +1 -0
  70. package/dist/render.d.ts +25 -0
  71. package/dist/render.d.ts.map +1 -0
  72. package/dist/render.js +164 -0
  73. package/dist/render.js.map +1 -0
  74. package/dist/renderer-core.d.ts +82 -0
  75. package/dist/renderer-core.d.ts.map +1 -0
  76. package/dist/renderer-core.js +228 -0
  77. package/dist/renderer-core.js.map +1 -0
  78. package/dist/renderer.d.ts +29 -0
  79. package/dist/renderer.d.ts.map +1 -0
  80. package/dist/renderer.js +2 -0
  81. package/dist/renderer.js.map +1 -0
  82. package/dist/session.d.ts +188 -0
  83. package/dist/session.d.ts.map +1 -0
  84. package/dist/session.js +513 -0
  85. package/dist/session.js.map +1 -0
  86. package/dist/types.d.ts +114 -0
  87. package/dist/types.d.ts.map +1 -0
  88. package/dist/types.js +2 -0
  89. package/dist/types.js.map +1 -0
  90. package/dist/worker-protocol.d.ts +100 -0
  91. package/dist/worker-protocol.d.ts.map +1 -0
  92. package/dist/worker-protocol.js +30 -0
  93. package/dist/worker-protocol.js.map +1 -0
  94. package/dist/worker-renderer.d.ts +35 -0
  95. package/dist/worker-renderer.d.ts.map +1 -0
  96. package/dist/worker-renderer.js +85 -0
  97. package/dist/worker-renderer.js.map +1 -0
  98. package/dist/worker.d.ts +23 -0
  99. package/dist/worker.d.ts.map +1 -0
  100. package/dist/worker.js +81 -0
  101. package/dist/worker.js.map +1 -0
  102. package/package.json +45 -0
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # @sealpixel/core
2
+
3
+ Headless core of the Sealpixel image editor: edit log types, `render()`, and (from M2) the `EditorSession`. Runtime-agnostic; the same code runs in browsers, workers, Node, Deno and Bun on top of `@sealpixel/wasm`.
@@ -0,0 +1,37 @@
1
+ import type { SealpixelWasm } from '@sealpixel/wasm';
2
+ import type { AssetDeclaration } from './plugin.js';
3
+ /** Supplies asset bytes by id. Implementations verify the declared hash. */
4
+ export interface AssetResolver {
5
+ resolve(id: string): Promise<Uint8Array>;
6
+ /** Declared assets, used to pre-load and to verify hashes. */
7
+ declarations(): readonly AssetDeclaration[];
8
+ }
9
+ export interface AssetResolverOptions {
10
+ assets: readonly AssetDeclaration[];
11
+ /** Resolves relative `url`s. Defaults to the document location in browsers. */
12
+ baseUrl?: string | URL;
13
+ fetch?: typeof fetch;
14
+ /** Computes sha256 for verification. Defaults to WebCrypto. */
15
+ sha256?: (bytes: Uint8Array) => Promise<string> | string;
16
+ }
17
+ /**
18
+ * Fetch-based resolver. Every asset must be declared with a hash; bytes whose
19
+ * hash differs are rejected, so client and server render the same glyphs.
20
+ */
21
+ export declare function createAssetResolver(options: AssetResolverOptions): AssetResolver;
22
+ /** Resolver over in-memory bytes (tests, servers with preloaded assets). */
23
+ export declare function staticAssetResolver(entries: readonly {
24
+ declaration: AssetDeclaration;
25
+ bytes: Uint8Array;
26
+ }[], sha256?: (bytes: Uint8Array) => Promise<string> | string): AssetResolver;
27
+ export declare function webCryptoSha256(bytes: Uint8Array): Promise<string>;
28
+ /** Id of the asset a `MISSING_ASSET` error refers to, if the error carries it. */
29
+ export declare function missingAssetId(error: unknown): string | null;
30
+ /**
31
+ * Runs `fn`, and whenever it fails with `MISSING_ASSET`, resolves that asset,
32
+ * stores it with `put`, and retries. Gives up after `limit` distinct assets.
33
+ */
34
+ export declare function withAssets<T>(fn: () => Promise<T>, resolver: AssetResolver | undefined, put: (id: string, bytes: Uint8Array) => Promise<void> | void, limit?: number): Promise<T>;
35
+ /** Uses a loaded core to hash, so the value equals the core's own sha256. */
36
+ export declare function wasmSha256(wasm: SealpixelWasm): (bytes: Uint8Array) => string;
37
+ //# sourceMappingURL=assets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../src/assets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,4EAA4E;AAC5E,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACzC,8DAA8D;IAC9D,YAAY,IAAI,SAAS,gBAAgB,EAAE,CAAC;CAC7C;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACpC,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;IACvB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,+DAA+D;IAC/D,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;CAC1D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,aAAa,CAgChF;AAED,4EAA4E;AAC5E,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,SAAS;IAAE,WAAW,EAAE,gBAAgB,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,EAAE,EACxE,MAAM,GAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAwB,GACxE,aAAa,CAUf;AAkBD,wBAAsB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAGxE;AAED,kFAAkF;AAClF,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAM5D;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAAC,CAAC,EAChC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,QAAQ,EAAE,aAAa,GAAG,SAAS,EACnC,GAAG,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,EAC5D,KAAK,SAAK,GACT,OAAO,CAAC,CAAC,CAAC,CAaZ;AAED,6EAA6E;AAC7E,wBAAgB,UAAU,CAAC,IAAI,EAAE,aAAa,GAAG,CAAC,KAAK,EAAE,UAAU,KAAK,MAAM,CAE7E"}
package/dist/assets.js ADDED
@@ -0,0 +1,96 @@
1
+ import { SealpixelError } from './errors.js';
2
+ /**
3
+ * Fetch-based resolver. Every asset must be declared with a hash; bytes whose
4
+ * hash differs are rejected, so client and server render the same glyphs.
5
+ */
6
+ export function createAssetResolver(options) {
7
+ const byId = new Map(options.assets.map((a) => [a.id, a]));
8
+ const cache = new Map();
9
+ const doFetch = options.fetch ?? fetch;
10
+ const sha = options.sha256 ?? webCryptoSha256;
11
+ return {
12
+ declarations: () => options.assets,
13
+ resolve(id) {
14
+ const cached = cache.get(id);
15
+ if (cached)
16
+ return cached;
17
+ const decl = byId.get(id);
18
+ if (!decl)
19
+ return Promise.reject(new SealpixelError('MISSING_ASSET', `asset "${id}" is not declared`));
20
+ const pending = (async () => {
21
+ if (!decl.url)
22
+ throw new SealpixelError('MISSING_ASSET', `asset "${id}" has no url`);
23
+ const url = options.baseUrl ? new URL(decl.url, options.baseUrl).toString() : decl.url;
24
+ const res = await doFetch(url);
25
+ if (!res.ok)
26
+ throw new SealpixelError('MISSING_ASSET', `asset "${id}": HTTP ${res.status} from ${url}`);
27
+ const bytes = new Uint8Array(await res.arrayBuffer());
28
+ return verify(id, decl, bytes, sha);
29
+ })().catch((error) => {
30
+ cache.delete(id);
31
+ throw error;
32
+ });
33
+ cache.set(id, pending);
34
+ return pending;
35
+ },
36
+ };
37
+ }
38
+ /** Resolver over in-memory bytes (tests, servers with preloaded assets). */
39
+ export function staticAssetResolver(entries, sha256 = webCryptoSha256) {
40
+ const map = new Map(entries.map((e) => [e.declaration.id, e]));
41
+ return {
42
+ declarations: () => entries.map((e) => e.declaration),
43
+ async resolve(id) {
44
+ const e = map.get(id);
45
+ if (!e)
46
+ throw new SealpixelError('MISSING_ASSET', `asset "${id}" is not declared`);
47
+ return verify(id, e.declaration, e.bytes, sha256);
48
+ },
49
+ };
50
+ }
51
+ async function verify(id, decl, bytes, sha256) {
52
+ const actual = await sha256(bytes);
53
+ if (actual !== decl.hash) {
54
+ throw new SealpixelError('MISSING_ASSET', `asset "${id}" hash mismatch: expected ${decl.hash}, got ${actual}`);
55
+ }
56
+ return bytes;
57
+ }
58
+ export async function webCryptoSha256(bytes) {
59
+ const digest = await crypto.subtle.digest('SHA-256', bytes);
60
+ return Array.from(new Uint8Array(digest), (b) => b.toString(16).padStart(2, '0')).join('');
61
+ }
62
+ /** Id of the asset a `MISSING_ASSET` error refers to, if the error carries it. */
63
+ export function missingAssetId(error) {
64
+ if (!(error instanceof Error) || error.name !== 'MISSING_ASSET')
65
+ return null;
66
+ const details = error.details;
67
+ if (details && typeof details.assetId === 'string')
68
+ return details.assetId;
69
+ const m = /asset "([^"]+)"/.exec(error.message);
70
+ return m?.[1] ?? null;
71
+ }
72
+ /**
73
+ * Runs `fn`, and whenever it fails with `MISSING_ASSET`, resolves that asset,
74
+ * stores it with `put`, and retries. Gives up after `limit` distinct assets.
75
+ */
76
+ export async function withAssets(fn, resolver, put, limit = 16) {
77
+ const loaded = new Set();
78
+ for (;;) {
79
+ try {
80
+ return await fn();
81
+ }
82
+ catch (error) {
83
+ const id = missingAssetId(error);
84
+ if (!id || !resolver || loaded.has(id) || loaded.size >= limit)
85
+ throw error;
86
+ const bytes = await resolver.resolve(id);
87
+ await put(id, bytes);
88
+ loaded.add(id);
89
+ }
90
+ }
91
+ }
92
+ /** Uses a loaded core to hash, so the value equals the core's own sha256. */
93
+ export function wasmSha256(wasm) {
94
+ return (bytes) => wasm.sha256Hex(bytes);
95
+ }
96
+ //# sourceMappingURL=assets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assets.js","sourceRoot":"","sources":["../src/assets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Deterministic JSON serialisation: object keys sorted, no whitespace,
3
+ * `undefined` properties dropped. Used for hashes and server job keys so the
4
+ * same logical value always yields the same string on every runtime.
5
+ *
6
+ * Throws on values JSON cannot represent (functions, symbols, bigint, cycles)
7
+ * and on non-finite numbers, which `JSON.stringify` would silently turn into
8
+ * `null`.
9
+ */
10
+ export declare function canonicalJson(value: unknown): string;
11
+ //# sourceMappingURL=canonical-json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical-json.d.ts","sourceRoot":"","sources":["../src/canonical-json.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEpD"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Deterministic JSON serialisation: object keys sorted, no whitespace,
3
+ * `undefined` properties dropped. Used for hashes and server job keys so the
4
+ * same logical value always yields the same string on every runtime.
5
+ *
6
+ * Throws on values JSON cannot represent (functions, symbols, bigint, cycles)
7
+ * and on non-finite numbers, which `JSON.stringify` would silently turn into
8
+ * `null`.
9
+ */
10
+ export function canonicalJson(value) {
11
+ return serialize(value, new Set());
12
+ }
13
+ function serialize(value, seen) {
14
+ if (value === null)
15
+ return 'null';
16
+ switch (typeof value) {
17
+ case 'string':
18
+ return JSON.stringify(value);
19
+ case 'boolean':
20
+ return value ? 'true' : 'false';
21
+ case 'number':
22
+ if (!Number.isFinite(value))
23
+ throw new TypeError(`canonicalJson: non-finite number ${value}`);
24
+ return Object.is(value, -0) ? '0' : JSON.stringify(value);
25
+ case 'object':
26
+ break;
27
+ default:
28
+ throw new TypeError(`canonicalJson: cannot serialise ${typeof value}`);
29
+ }
30
+ const obj = value;
31
+ if (seen.has(obj))
32
+ throw new TypeError('canonicalJson: circular structure');
33
+ seen.add(obj);
34
+ try {
35
+ if (Array.isArray(obj)) {
36
+ return `[${obj.map((item) => (item === undefined ? 'null' : serialize(item, seen))).join(',')}]`;
37
+ }
38
+ const keys = Object.keys(obj)
39
+ .filter((key) => obj[key] !== undefined)
40
+ .sort();
41
+ const parts = keys.map((key) => `${JSON.stringify(key)}:${serialize(obj[key], seen)}`);
42
+ return `{${parts.join(',')}}`;
43
+ }
44
+ finally {
45
+ seen.delete(obj);
46
+ }
47
+ }
48
+ //# sourceMappingURL=canonical-json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical-json.js","sourceRoot":"","sources":["../src/canonical-json.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,OAAO,SAAS,CAAC,KAAK,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,SAAS,CAAC,KAAc,EAAE,IAAiB;IAClD,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC;IAClC,QAAQ,OAAO,KAAK,EAAE,CAAC;QACrB,KAAK,QAAQ;YACX,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC/B,KAAK,SAAS;YACZ,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;QAClC,KAAK,QAAQ;YACX,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,MAAM,IAAI,SAAS,CAAC,oCAAoC,KAAK,EAAE,CAAC,CAAC;YAC9F,OAAO,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC5D,KAAK,QAAQ;YACX,MAAM;QACR;YACE,MAAM,IAAI,SAAS,CAAC,mCAAmC,OAAO,KAAK,EAAE,CAAC,CAAC;IAC3E,CAAC;IACD,MAAM,GAAG,GAAG,KAAe,CAAC;IAC5B,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,mCAAmC,CAAC,CAAC;IAC5E,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACd,IAAI,CAAC;QACH,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QACnG,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;aAC1B,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAE,GAA+B,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC;aACpE,IAAI,EAAE,CAAC;QACV,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CACpB,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,SAAS,CAAE,GAA+B,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,CAC5F,CAAC;QACF,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IAChC,CAAC;YAAS,CAAC;QACT,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC"}
@@ -0,0 +1,30 @@
1
+ import type { Stage } from './plan.js';
2
+ import type { AnyPlugin, Document, PlanContext, StageParams } from './plugin.js';
3
+ import type { Registry } from './registry.js';
4
+ import type { EditLog } from './types.js';
5
+ /**
6
+ * Folds `ops[0..upTo)` into the derived document. Pure. Ops with unknown
7
+ * types (only present when parsed with `tolerateUnknown`) are skipped.
8
+ */
9
+ export declare function compile(log: EditLog, registry: Registry, upTo?: number): Document;
10
+ /** A stage in the full pipeline, before it is split into core and external segments. */
11
+ export type PipelineStage = {
12
+ kind: 'core';
13
+ name: Stage['kind'];
14
+ order: number;
15
+ params: StageParams;
16
+ } | {
17
+ kind: 'js' | 'wasm';
18
+ name: string;
19
+ order: number;
20
+ plugin: AnyPlugin;
21
+ params: StageParams;
22
+ };
23
+ /**
24
+ * Asks every plugin for its stage parameters and produces the ordered stage
25
+ * list. Core stages with the same name are shallow-merged in plugin order.
26
+ */
27
+ export declare function toPipeline(doc: Document, registry: Registry, ctx: PlanContext): PipelineStage[];
28
+ /** Converts a run of core pipeline stages into Rust `Stage` values. */
29
+ export declare function toCoreStages(stages: readonly PipelineStage[]): Stage[];
30
+ //# sourceMappingURL=compile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../src/compile.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACjF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C;;;GAGG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,GAAE,MAAuB,GAAG,QAAQ,CAUjG;AAED,wFAAwF;AACxF,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GACzE;IAAE,IAAI,EAAE,IAAI,GAAG,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,CAAC;AAEjG;;;GAGG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,WAAW,GAAG,aAAa,EAAE,CA8B/F;AAED,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,GAAG,KAAK,EAAE,CAOtE"}
@@ -0,0 +1,64 @@
1
+ import { SealpixelError } from './errors.js';
2
+ /**
3
+ * Folds `ops[0..upTo)` into the derived document. Pure. Ops with unknown
4
+ * types (only present when parsed with `tolerateUnknown`) are skipped.
5
+ */
6
+ export function compile(log, registry, upTo = log.ops.length) {
7
+ const doc = registry.initialDocument();
8
+ const end = Math.max(0, Math.min(upTo, log.ops.length));
9
+ for (let i = 0; i < end; i++) {
10
+ const op = log.ops[i];
11
+ const entry = registry.byOpType.get(op.type);
12
+ if (!entry)
13
+ continue;
14
+ doc[entry.plugin.id] = entry.def.reduce(doc[entry.plugin.id], op);
15
+ }
16
+ return doc;
17
+ }
18
+ /**
19
+ * Asks every plugin for its stage parameters and produces the ordered stage
20
+ * list. Core stages with the same name are shallow-merged in plugin order.
21
+ */
22
+ export function toPipeline(doc, registry, ctx) {
23
+ const stages = [];
24
+ const coreByName = new Map();
25
+ for (const plugin of registry.plugins) {
26
+ const params = plugin.toPlan(doc[plugin.id], {
27
+ ...ctx,
28
+ options: plugin.options,
29
+ });
30
+ if (params === null)
31
+ continue;
32
+ if (plugin.kernel.kind === 'core') {
33
+ const name = plugin.stage.name;
34
+ const existing = coreByName.get(name);
35
+ if (existing) {
36
+ existing.params = { ...existing.params, ...params };
37
+ continue;
38
+ }
39
+ const stage = { kind: 'core', name, order: plugin.stage.order, params };
40
+ coreByName.set(name, stage);
41
+ stages.push(stage);
42
+ }
43
+ else {
44
+ stages.push({
45
+ kind: plugin.kernel.kind,
46
+ name: plugin.stage.name,
47
+ order: plugin.stage.order,
48
+ plugin,
49
+ params,
50
+ });
51
+ }
52
+ }
53
+ return stages.sort((a, b) => a.order - b.order);
54
+ }
55
+ /** Converts a run of core pipeline stages into Rust `Stage` values. */
56
+ export function toCoreStages(stages) {
57
+ return stages.map((s) => {
58
+ if (s.kind !== 'core') {
59
+ throw new SealpixelError('INVALID_EDIT_LOG', `stage "${s.name}" is not a core stage`);
60
+ }
61
+ return { kind: s.name, ...s.params };
62
+ });
63
+ }
64
+ //# sourceMappingURL=compile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile.js","sourceRoot":"","sources":["../src/compile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { Registry } from './registry.js';
2
+ import type { History } from './types.js';
3
+ export declare const PNG_KEYWORD = "sealpixel:editlog";
4
+ /** Keyword written by releases before the rename (Pincel). Read, never written. */
5
+ export declare const PNG_KEYWORD_LEGACY = "pincel:editlog";
6
+ /** The raw embedded text, or null when the file carries none. */
7
+ export declare function readEmbeddedEditLog(bytes: Uint8Array): string | null;
8
+ /**
9
+ * Parses and validates an embedded `{ log, index }` state through `registry`.
10
+ * Returns null when nothing is embedded.
11
+ */
12
+ export declare function readEmbeddedState(bytes: Uint8Array, registry: Registry): History | null;
13
+ //# sourceMappingURL=embedded.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedded.d.ts","sourceRoot":"","sources":["../src/embedded.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAW,OAAO,EAAE,MAAM,YAAY,CAAC;AAEnD,eAAO,MAAM,WAAW,sBAAsB,CAAC;AAC/C,mFAAmF;AACnF,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AAKnD,iEAAiE;AACjE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAOpE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,GAAG,IAAI,CAavF"}
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Reads the edit log Sealpixel embeds in exported files (PNG iTXt, JPEG APP1
3
+ * XMP, WebP XMP chunk). A header scan only: no pixel decoding, no wasm.
4
+ * Mirrors `sealpixel_core::codec::embedded`.
5
+ */
6
+ import { SealpixelError } from './errors.js';
7
+ export const PNG_KEYWORD = 'sealpixel:editlog';
8
+ /** Keyword written by releases before the rename (Pincel). Read, never written. */
9
+ export const PNG_KEYWORD_LEGACY = 'pincel:editlog';
10
+ const XMP_HEADER = 'http://ns.adobe.com/xap/1.0/\0';
11
+ const ATTR = 'sealpixel:editLog="';
12
+ const ATTR_LEGACY = 'pincel:editLog="';
13
+ /** The raw embedded text, or null when the file carries none. */
14
+ export function readEmbeddedEditLog(bytes) {
15
+ if (startsWith(bytes, [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]))
16
+ return readPng(bytes);
17
+ if (startsWith(bytes, [0xff, 0xd8, 0xff]))
18
+ return readJpeg(bytes);
19
+ if (bytes.length >= 12 && ascii(bytes, 0, 4) === 'RIFF' && ascii(bytes, 8, 12) === 'WEBP') {
20
+ return readWebp(bytes);
21
+ }
22
+ throw new SealpixelError('UNSUPPORTED_FORMAT', 'unknown container');
23
+ }
24
+ /**
25
+ * Parses and validates an embedded `{ log, index }` state through `registry`.
26
+ * Returns null when nothing is embedded.
27
+ */
28
+ export function readEmbeddedState(bytes, registry) {
29
+ const text = readEmbeddedEditLog(bytes);
30
+ if (text === null)
31
+ return null;
32
+ let value;
33
+ try {
34
+ value = JSON.parse(text);
35
+ }
36
+ catch (error) {
37
+ throw new SealpixelError('INVALID_EDIT_LOG', `embedded edit log is not JSON: ${String(error)}`);
38
+ }
39
+ const state = value;
40
+ const log = registry.parseEditLog(state.log);
41
+ const index = typeof state.index === 'number' ? state.index : log.ops.length;
42
+ return { log, index: Math.max(0, Math.min(Math.floor(index), log.ops.length)) };
43
+ }
44
+ function readPng(bytes) {
45
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
46
+ let pos = 8;
47
+ while (pos + 8 <= bytes.length) {
48
+ const len = view.getUint32(pos);
49
+ const kind = ascii(bytes, pos + 4, pos + 8);
50
+ const start = pos + 8;
51
+ const end = start + len;
52
+ if (end > bytes.length)
53
+ return null;
54
+ if (kind === 'iTXt') {
55
+ const data = bytes.subarray(start, end);
56
+ const nul = data.indexOf(0);
57
+ const keyword = nul > 0 ? ascii(data, 0, nul) : '';
58
+ if (keyword === PNG_KEYWORD || keyword === PNG_KEYWORD_LEGACY) {
59
+ let i = nul + 1;
60
+ const compressed = data[i] !== 0;
61
+ i += 2;
62
+ i = data.indexOf(0, i) + 1; // language tag
63
+ i = data.indexOf(0, i) + 1; // translated keyword
64
+ if (compressed || i <= 0)
65
+ return null;
66
+ return new TextDecoder().decode(data.subarray(i));
67
+ }
68
+ }
69
+ if (kind === 'IEND')
70
+ return null;
71
+ pos = end + 4;
72
+ }
73
+ return null;
74
+ }
75
+ function readJpeg(bytes) {
76
+ let pos = 2;
77
+ while (pos + 4 <= bytes.length) {
78
+ if (bytes[pos] !== 0xff)
79
+ return null;
80
+ const marker = bytes[pos + 1];
81
+ if (marker === 0xda || marker === 0xd9)
82
+ return null;
83
+ const len = (bytes[pos + 2] << 8) | bytes[pos + 3];
84
+ const start = pos + 4;
85
+ const end = pos + 2 + len;
86
+ if (end > bytes.length)
87
+ return null;
88
+ if (marker === 0xe1 && ascii(bytes, start, start + XMP_HEADER.length) === XMP_HEADER) {
89
+ const xmp = new TextDecoder().decode(bytes.subarray(start + XMP_HEADER.length, end));
90
+ const payload = payloadFromXmp(xmp);
91
+ if (payload !== null)
92
+ return payload;
93
+ }
94
+ pos = end;
95
+ }
96
+ return null;
97
+ }
98
+ function readWebp(bytes) {
99
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
100
+ let pos = 12;
101
+ while (pos + 8 <= bytes.length) {
102
+ const kind = ascii(bytes, pos, pos + 4);
103
+ const len = view.getUint32(pos + 4, true);
104
+ const start = pos + 8;
105
+ const end = start + len;
106
+ if (end > bytes.length)
107
+ return null;
108
+ if (kind === 'XMP ')
109
+ return payloadFromXmp(new TextDecoder().decode(bytes.subarray(start, end)));
110
+ pos = end + (len & 1);
111
+ }
112
+ return null;
113
+ }
114
+ /** Files written before the rename carry `pincel:editLog`; both attributes read back. */
115
+ function payloadFromXmp(xmp) {
116
+ let attr = ATTR;
117
+ let at = xmp.indexOf(attr);
118
+ if (at < 0) {
119
+ attr = ATTR_LEGACY;
120
+ at = xmp.indexOf(attr);
121
+ }
122
+ if (at < 0)
123
+ return null;
124
+ const start = at + attr.length;
125
+ const end = xmp.indexOf('"', start);
126
+ if (end < 0)
127
+ return null;
128
+ return xmp
129
+ .slice(start, end)
130
+ .replaceAll('&quot;', '"')
131
+ .replaceAll('&apos;', "'")
132
+ .replaceAll('&lt;', '<')
133
+ .replaceAll('&gt;', '>')
134
+ .replaceAll('&amp;', '&');
135
+ }
136
+ function startsWith(bytes, prefix) {
137
+ return prefix.every((b, i) => bytes[i] === b);
138
+ }
139
+ function ascii(bytes, start, end) {
140
+ let out = '';
141
+ for (let i = start; i < end && i < bytes.length; i++)
142
+ out += String.fromCharCode(bytes[i]);
143
+ return out;
144
+ }
145
+ //# sourceMappingURL=embedded.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedded.js","sourceRoot":"","sources":["../src/embedded.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export type SealpixelErrorCode = 'SOURCE_MISMATCH' | 'INVALID_EDIT_LOG' | 'UNKNOWN_PLUGIN' | 'OPTION_VIOLATION' | 'ABORTED' | 'NO_SOURCE' | 'NOT_RESIDENT' | 'NOT_CONFIGURED' | 'DOWNLOAD_UNSUPPORTED' | 'KERNEL_FAILED' | 'INVALID_REQUEST' | 'SOURCE_UNAVAILABLE' | 'FORBIDDEN_SOURCE' | 'TIMEOUT' | 'SERVER_ERROR' | import('@sealpixel/wasm').SealpixelErrorCode;
2
+ export declare class SealpixelError extends Error {
3
+ readonly name: SealpixelErrorCode;
4
+ readonly details: unknown;
5
+ constructor(code: SealpixelErrorCode, message: string, details?: unknown);
6
+ /** Re-throws core errors unchanged and wraps everything else. */
7
+ static from(error: unknown): SealpixelError;
8
+ }
9
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAC1B,iBAAiB,GACjB,kBAAkB,GAClB,gBAAgB,GAChB,kBAAkB,GAClB,SAAS,GACT,WAAW,GACX,cAAc,GACd,gBAAgB,GAChB,sBAAsB,GACtB,eAAe,GACf,iBAAiB,GACjB,oBAAoB,GACpB,kBAAkB,GAClB,SAAS,GACT,cAAc,GACd,OAAO,iBAAiB,EAAE,kBAAkB,CAAC;AAEjD,qBAAa,cAAe,SAAQ,KAAK;IACvC,SAAkB,IAAI,EAAE,kBAAkB,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;gBAEd,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO;IAMxE,iEAAiE;IACjE,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc;CAW5C"}
package/dist/errors.js ADDED
@@ -0,0 +1,19 @@
1
+ export class SealpixelError extends Error {
2
+ name;
3
+ details;
4
+ constructor(code, message, details) {
5
+ super(message);
6
+ this.name = code;
7
+ this.details = details;
8
+ }
9
+ /** Re-throws core errors unchanged and wraps everything else. */
10
+ static from(error) {
11
+ if (error instanceof SealpixelError)
12
+ return error;
13
+ if (error instanceof Error && /^[A-Z_]+$/.test(error.name)) {
14
+ return new SealpixelError(error.name, error.message, error.details);
15
+ }
16
+ return new SealpixelError('INVALID_EDIT_LOG', String(error));
17
+ }
18
+ }
19
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAkBA,MAAM,OAAO,cAAe,SAAQ,KAAK;IACrB,IAAI,CAAqB;IAClC,OAAO,CAAU;IAE1B,YAAY,IAAwB,EAAE,OAAe,EAAE,OAAiB;QACtE,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,iEAAiE;IACjE,MAAM,CAAC,IAAI,CAAC,KAAc;QACxB,IAAI,KAAK,YAAY,cAAc;YAAE,OAAO,KAAK,CAAC;QAClD,IAAI,KAAK,YAAY,KAAK,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3D,OAAO,IAAI,cAAc,CACvB,KAAK,CAAC,IAA0B,EAChC,KAAK,CAAC,OAAO,EACZ,KAA+B,CAAC,OAAO,CACzC,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,cAAc,CAAC,kBAAkB,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC/D,CAAC;CACF"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Runs third-party kernels between core segments: JavaScript functions, or
3
+ * WebAssembly modules implementing the Sealpixel kernel ABI v1
4
+ * (`sealpixel_alloc`, `sealpixel_free`, `sealpixel_run`, `sealpixel_kernel_abi`).
5
+ * WASM kernels transform the RGBA buffer in place; dimensions never change.
6
+ */
7
+ import type { RgbaBuffer } from '@sealpixel/wasm';
8
+ import type { AnyPlugin, KernelContext, StageParams } from './plugin.js';
9
+ /** Runs `plugin.kernel` on `image` with `params`. */
10
+ export declare function runExternalKernel(plugin: AnyPlugin, image: RgbaBuffer, params: StageParams, ctx: KernelContext): Promise<RgbaBuffer>;
11
+ /** Drops cached kernel instances (tests, hot reload). */
12
+ export declare function resetExternalKernels(): void;
13
+ //# sourceMappingURL=external-kernel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-kernel.d.ts","sourceRoot":"","sources":["../src/external-kernel.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAkBzE,qDAAqD;AACrD,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,WAAW,EACnB,GAAG,EAAE,aAAa,GACjB,OAAO,CAAC,UAAU,CAAC,CAqCrB;AAsCD,yDAAyD;AACzD,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}
@@ -0,0 +1,68 @@
1
+ import { SealpixelError } from './errors.js';
2
+ const instances = new Map();
3
+ /** Runs `plugin.kernel` on `image` with `params`. */
4
+ export async function runExternalKernel(plugin, image, params, ctx) {
5
+ const kernel = plugin.kernel;
6
+ if (kernel.kind === 'js')
7
+ return kernel.run(image, params, ctx);
8
+ if (kernel.kind !== 'wasm') {
9
+ throw new SealpixelError('INVALID_EDIT_LOG', `plugin "${plugin.id}" has a core kernel but no core stage`);
10
+ }
11
+ const exports = await instantiate(plugin.id, kernel.module);
12
+ const paramsBytes = new TextEncoder().encode(JSON.stringify(params));
13
+ const len = image.data.byteLength;
14
+ const imgPtr = exports.sealpixel_alloc(len);
15
+ const paramsPtr = exports.sealpixel_alloc(paramsBytes.byteLength);
16
+ try {
17
+ new Uint8Array(exports.memory.buffer, imgPtr, len).set(image.data);
18
+ new Uint8Array(exports.memory.buffer, paramsPtr, paramsBytes.byteLength).set(paramsBytes);
19
+ const status = exports.sealpixel_run(imgPtr, image.width, image.height, paramsPtr, paramsBytes.byteLength);
20
+ if (status !== 0) {
21
+ throw new SealpixelError('KERNEL_FAILED', `plugin "${plugin.id}" kernel returned ${status}`, {
22
+ status,
23
+ });
24
+ }
25
+ // Re-read the buffer: memory may have grown and detached the old view.
26
+ const out = new Uint8Array(len);
27
+ out.set(new Uint8Array(exports.memory.buffer, imgPtr, len));
28
+ return { width: image.width, height: image.height, data: out };
29
+ }
30
+ finally {
31
+ exports.sealpixel_free(imgPtr, len);
32
+ exports.sealpixel_free(paramsPtr, paramsBytes.byteLength);
33
+ }
34
+ }
35
+ function instantiate(id, load) {
36
+ let pending = instances.get(id);
37
+ if (!pending) {
38
+ pending = (async () => {
39
+ const module = await load();
40
+ const instance = await WebAssembly.instantiate(module, {});
41
+ const exports = instance.exports;
42
+ for (const name of [
43
+ 'memory',
44
+ 'sealpixel_alloc',
45
+ 'sealpixel_free',
46
+ 'sealpixel_run',
47
+ ]) {
48
+ if (!(name in exports)) {
49
+ throw new SealpixelError('KERNEL_FAILED', `plugin "${id}" kernel module lacks export "${name}"`);
50
+ }
51
+ }
52
+ const abi = exports.sealpixel_kernel_abi?.() ?? 1;
53
+ if (abi !== 1)
54
+ throw new SealpixelError('KERNEL_FAILED', `plugin "${id}" kernel ABI ${abi} is not supported`);
55
+ return exports;
56
+ })().catch((error) => {
57
+ instances.delete(id);
58
+ throw error;
59
+ });
60
+ instances.set(id, pending);
61
+ }
62
+ return pending;
63
+ }
64
+ /** Drops cached kernel instances (tests, hot reload). */
65
+ export function resetExternalKernels() {
66
+ instances.clear();
67
+ }
68
+ //# sourceMappingURL=external-kernel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-kernel.js","sourceRoot":"","sources":["../src/external-kernel.ts"],"names":[],"mappings":"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"}