fundus 0.28.1 → 0.29.1
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/README.md +41 -33
- package/build/client/_app/immutable/chunks/{apKHI4vq.js → C0uU_Rhe.js} +2 -2
- package/build/client/_app/immutable/chunks/C0uU_Rhe.js.br +0 -0
- package/build/client/_app/immutable/chunks/C0uU_Rhe.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{Bsj1ssvc.js → CE3cWlK6.js} +1 -1
- package/build/client/_app/immutable/chunks/CE3cWlK6.js.br +0 -0
- package/build/client/_app/immutable/chunks/CE3cWlK6.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{g2rma9Ym.js → CMJ10zbJ.js} +1 -1
- package/build/client/_app/immutable/chunks/CMJ10zbJ.js.br +0 -0
- package/build/client/_app/immutable/chunks/CMJ10zbJ.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{QlQ-jeIO.js → Cq3PJxJG.js} +1 -1
- package/build/client/_app/immutable/chunks/Cq3PJxJG.js.br +2 -0
- package/build/client/_app/immutable/chunks/Cq3PJxJG.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{OL1Dh1oP.js → Wk7WcyQU.js} +1 -1
- package/build/client/_app/immutable/chunks/Wk7WcyQU.js.br +0 -0
- package/build/client/_app/immutable/chunks/Wk7WcyQU.js.gz +0 -0
- package/build/client/_app/immutable/entry/{app.DpZM49_s.js → app.Dit62aNJ.js} +2 -2
- package/build/client/_app/immutable/entry/app.Dit62aNJ.js.br +0 -0
- package/build/client/_app/immutable/entry/app.Dit62aNJ.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.CCBu6ABN.js +1 -0
- package/build/client/_app/immutable/entry/start.CCBu6ABN.js.br +0 -0
- package/build/client/_app/immutable/entry/start.CCBu6ABN.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{0.Wqvn8XD-.js → 0.DnyKXqLr.js} +1 -1
- package/build/client/_app/immutable/nodes/0.DnyKXqLr.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.DnyKXqLr.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{1.Z-UvvLkP.js → 1.Cz-4S6LF.js} +1 -1
- package/build/client/_app/immutable/nodes/1.Cz-4S6LF.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.Cz-4S6LF.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{2.lu89W_qJ.js → 2.C75-hsCY.js} +1 -1
- package/build/client/_app/immutable/nodes/2.C75-hsCY.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.C75-hsCY.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{3.Dt32EAoq.js → 3.4pSddugU.js} +1 -1
- package/build/client/_app/immutable/nodes/3.4pSddugU.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.4pSddugU.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{4.WipzcX8_.js → 4.KoQxJEWQ.js} +1 -1
- package/build/client/_app/immutable/nodes/4.KoQxJEWQ.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.KoQxJEWQ.js.gz +0 -0
- package/build/client/_app/version.json +1 -1
- package/build/client/_app/version.json.br +0 -0
- package/build/client/_app/version.json.gz +0 -0
- package/build/handler.js +7 -7
- package/build/index.js +7 -7
- package/build/server/chunks/chunks/{context.js-BZSZNuAd.js → context.js-BR2IRl9z.js} +205 -115
- package/build/server/chunks/chunks/context.js-BR2IRl9z.js.map +1 -0
- package/build/server/chunks/chunks/{contract.js-B4JdXFgm.js → contract.js-DHeIVVv8.js} +46 -12
- package/build/server/chunks/chunks/contract.js-DHeIVVv8.js.map +1 -0
- package/build/server/chunks/chunks/{core.js-BHxa3VBo.js → core.js-AGKlECJ0.js} +32 -32
- package/build/server/chunks/chunks/core.js-AGKlECJ0.js.map +1 -0
- package/build/server/chunks/chunks/{exports.js-D0dALD2Q.js → exports.js-CNZgoxR0.js} +2 -2
- package/build/server/chunks/chunks/{exports.js-D0dALD2Q.js.map → exports.js-CNZgoxR0.js.map} +1 -1
- package/build/server/chunks/chunks/{http.js-DYYKvppy.js → http.js-dk5jbOFm.js} +2 -2
- package/build/server/chunks/chunks/{http.js-DYYKvppy.js.map → http.js-dk5jbOFm.js.map} +1 -1
- package/build/server/chunks/chunks/{internal.js-CJkB_gzV.js → internal.js-DlRiYJji.js} +3 -3
- package/build/server/chunks/chunks/{internal.js-CJkB_gzV.js.map → internal.js-DlRiYJji.js.map} +1 -1
- package/build/server/chunks/chunks/internal2.js-BlXt2rfE.js.map +1 -1
- package/build/server/chunks/chunks/{manifest-membership.js-BkrPsM_r.js → manifest-membership.js-DkHaPk2F.js} +2 -2
- package/build/server/chunks/chunks/{manifest-membership.js-BkrPsM_r.js.map → manifest-membership.js-DkHaPk2F.js.map} +1 -1
- package/build/server/chunks/chunks/{raw-reconciliation2.js-DKOpJ8if.js → raw-reconciliation.js-Cco4r8lr.js} +52 -18
- package/build/server/chunks/chunks/raw-reconciliation.js-Cco4r8lr.js.map +1 -0
- package/build/server/chunks/chunks/raw-reconciliation2.js-CuYSsYTP.js +11 -0
- package/build/server/chunks/chunks/raw-reconciliation2.js-CuYSsYTP.js.map +1 -0
- package/build/server/chunks/chunks/{shared.js-D3ZDVUlh.js → shared.js-C6qC0jnA.js} +2 -2
- package/build/server/chunks/chunks/{shared.js-D3ZDVUlh.js.map → shared.js-C6qC0jnA.js.map} +1 -1
- package/build/server/chunks/chunks/{utils.js-CqWW_v-5.js → utils.js-BZ32hXFI.js} +3 -3
- package/build/server/chunks/chunks/{utils.js-CqWW_v-5.js.map → utils.js-BZ32hXFI.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/_...path_/{_server.ts.js-Dw2MW5Tm.js → _server.ts.js-8jGLP2Aj.js} +6 -6
- package/build/server/chunks/entries/endpoints/api/_...path_/{_server.ts.js-Dw2MW5Tm.js.map → _server.ts.js-8jGLP2Aj.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/assets/_id_/{_server.ts.js-GQDuJGug.js → _server.ts.js-BOW9Ejim.js} +7 -7
- package/build/server/chunks/entries/endpoints/api/assets/_id_/{_server.ts.js-GQDuJGug.js.map → _server.ts.js-BOW9Ejim.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/assets/_id_/raw/{_server.ts.js-JbLSv7Xx.js → _server.ts.js-Clac8atJ.js} +7 -7
- package/build/server/chunks/entries/endpoints/api/assets/_id_/raw/{_server.ts.js-JbLSv7Xx.js.map → _server.ts.js-Clac8atJ.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/assets/_id_/reimport/{_server.ts.js-BPae-BYF.js → _server.ts.js-EdHTA-SO.js} +7 -7
- package/build/server/chunks/entries/endpoints/api/assets/_id_/reimport/{_server.ts.js-BPae-BYF.js.map → _server.ts.js-EdHTA-SO.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/assets/_id_/retag/{_server.ts.js-BafrrUxu.js → _server.ts.js-ZBCRgRYi.js} +7 -7
- package/build/server/chunks/entries/endpoints/api/assets/_id_/retag/{_server.ts.js-BafrrUxu.js.map → _server.ts.js-ZBCRgRYi.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/assets/{_server.ts.js-UOlSNEi9.js → _server.ts.js-DY_e5K6d.js} +7 -7
- package/build/server/chunks/entries/endpoints/api/assets/{_server.ts.js-UOlSNEi9.js.map → _server.ts.js-DY_e5K6d.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/assets/delete/{_server.ts.js-QE1vUuAx.js → _server.ts.js-Cl2jxJNi.js} +7 -7
- package/build/server/chunks/entries/endpoints/api/assets/delete/{_server.ts.js-QE1vUuAx.js.map → _server.ts.js-Cl2jxJNi.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/assets/move/{_server.ts.js-DIVfppGt.js → _server.ts.js-DrrZWUbd.js} +7 -7
- package/build/server/chunks/entries/endpoints/api/assets/move/{_server.ts.js-DIVfppGt.js.map → _server.ts.js-DrrZWUbd.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/events/{_server.ts.js-B6R_kqP8.js → _server.ts.js-Bnw0HbEk.js} +7 -7
- package/build/server/chunks/entries/endpoints/api/events/{_server.ts.js-B6R_kqP8.js.map → _server.ts.js-Bnw0HbEk.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/folders/_path_/{_server.ts.js-CertbDsH.js → _server.ts.js-NeVn2ap9.js} +7 -7
- package/build/server/chunks/entries/endpoints/api/folders/_path_/{_server.ts.js-CertbDsH.js.map → _server.ts.js-NeVn2ap9.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/folders/{_server.ts.js-DEIF3Hu2.js → _server.ts.js-ENGDgoLy.js} +7 -7
- package/build/server/chunks/entries/endpoints/api/folders/{_server.ts.js-DEIF3Hu2.js.map → _server.ts.js-ENGDgoLy.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/imports/{_server.ts.js-DNFsNGr4.js → _server.ts.js-BQVGCzBR.js} +7 -7
- package/build/server/chunks/entries/endpoints/api/imports/{_server.ts.js-DNFsNGr4.js.map → _server.ts.js-BQVGCzBR.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/manifests/_name_/{_server.ts.js-DDW8XRPe.js → _server.ts.js-Pxver0Y-.js} +7 -7
- package/build/server/chunks/entries/endpoints/api/manifests/_name_/{_server.ts.js-DDW8XRPe.js.map → _server.ts.js-Pxver0Y-.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/manifests/{_server.ts.js-C222-xli.js → _server.ts.js-DYtiqzJq.js} +7 -7
- package/build/server/chunks/entries/endpoints/api/manifests/{_server.ts.js-C222-xli.js.map → _server.ts.js-DYtiqzJq.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/raw/adopt/{_server.ts.js-CI1P1uyd.js → _server.ts.js-lBgmEZHV.js} +7 -7
- package/build/server/chunks/entries/endpoints/api/raw/adopt/{_server.ts.js-CI1P1uyd.js.map → _server.ts.js-lBgmEZHV.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/raw/edited/accept/{_server.ts.js-DpiUwaSh.js → _server.ts.js-BJHyONFH.js} +7 -7
- package/build/server/chunks/entries/endpoints/api/raw/edited/accept/{_server.ts.js-DpiUwaSh.js.map → _server.ts.js-BJHyONFH.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/raw/edited/dismiss/{_server.ts.js-DT0VPqPT.js → _server.ts.js-Bm5XO80W.js} +7 -7
- package/build/server/chunks/entries/endpoints/api/raw/edited/dismiss/{_server.ts.js-DT0VPqPT.js.map → _server.ts.js-Bm5XO80W.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/reconcile/{_server.ts.js-DBpHM42g.js → _server.ts.js-B7Z20kYf.js} +7 -7
- package/build/server/chunks/entries/endpoints/api/reconcile/{_server.ts.js-DBpHM42g.js.map → _server.ts.js-B7Z20kYf.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/reveal/{_server.ts.js-Cxu5b6Au.js → _server.ts.js-Cg-f37jc.js} +7 -7
- package/build/server/chunks/entries/endpoints/api/reveal/{_server.ts.js-Cxu5b6Au.js.map → _server.ts.js-Cg-f37jc.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/state/{_server.ts.js-W4dhMo8Y.js → _server.ts.js-dIXZiq5l.js} +7 -7
- package/build/server/chunks/entries/endpoints/api/state/{_server.ts.js-W4dhMo8Y.js.map → _server.ts.js-dIXZiq5l.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/api/usage/{_server.ts.js-DJ_adxbT.js → _server.ts.js-CnTrS5pT.js} +7 -7
- package/build/server/chunks/entries/endpoints/api/usage/{_server.ts.js-DJ_adxbT.js.map → _server.ts.js-CnTrS5pT.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/files/_...path_/{_server.ts.js-BisoHihD.js → _server.ts.js-B7TcFRuL.js} +6 -6
- package/build/server/chunks/entries/endpoints/files/_...path_/{_server.ts.js-BisoHihD.js.map → _server.ts.js-B7TcFRuL.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/files/proxy/_...path_/{_server.ts.js-D4jLLuko.js → _server.ts.js-BkUQInqW.js} +7 -7
- package/build/server/chunks/entries/endpoints/files/proxy/_...path_/{_server.ts.js-D4jLLuko.js.map → _server.ts.js-BkUQInqW.js.map} +1 -1
- package/build/server/chunks/entries/endpoints/files/raw/_...path_/{_server.ts.js-Dfv2ItjT.js → _server.ts.js-CshyvqOq.js} +7 -7
- package/build/server/chunks/entries/endpoints/files/raw/_...path_/{_server.ts.js-Dfv2ItjT.js.map → _server.ts.js-CshyvqOq.js.map} +1 -1
- package/build/server/chunks/entries/{hooks.server.js-oHJX5INm.js → hooks.server.js-D4DECjz_.js} +8 -7
- package/build/server/chunks/entries/hooks.server.js-D4DECjz_.js.map +1 -0
- package/build/server/chunks/{handler-BAe0c9yw.js → handler-Cna54zf6.js} +5 -5
- package/build/server/chunks/{handler-BAe0c9yw.js.map → handler-Cna54zf6.js.map} +1 -1
- package/build/server/chunks/{index.js-DUYD4JB0.js → index.js-BnpHWDec.js} +5 -5
- package/build/server/chunks/{index.js-DUYD4JB0.js.map → index.js-BnpHWDec.js.map} +1 -1
- package/build/server/chunks/{manifest.js-zwun-T7O.js → manifest.js-9WMEOpxH.js} +31 -31
- package/build/server/chunks/{manifest.js-zwun-T7O.js.map → manifest.js-9WMEOpxH.js.map} +1 -1
- package/build/server/chunks/nodes/{0.js-BmkXwDRY.js → 0.js-C2b1a672.js} +2 -2
- package/build/server/chunks/nodes/{0.js-BmkXwDRY.js.map → 0.js-C2b1a672.js.map} +1 -1
- package/build/server/chunks/nodes/1.js-P3Ai28oj.js +7 -0
- package/build/server/chunks/nodes/{1.js-xbOwEHCW.js.map → 1.js-P3Ai28oj.js.map} +1 -1
- package/build/server/chunks/nodes/{2.js-BuNw1vTZ.js → 2.js-sM3j5BqB.js} +2 -2
- package/build/server/chunks/nodes/{2.js-BuNw1vTZ.js.map → 2.js-sM3j5BqB.js.map} +1 -1
- package/build/server/chunks/nodes/3.js-G0jV-ymM.js +7 -0
- package/build/server/chunks/nodes/{3.js-Dpr_DvNU.js.map → 3.js-G0jV-ymM.js.map} +1 -1
- package/build/server/chunks/nodes/4.js-BUTPrI45.js +7 -0
- package/build/server/chunks/nodes/{4.js-14Lypd4o.js.map → 4.js-BUTPrI45.js.map} +1 -1
- package/dist/cli.js +3 -4
- package/dist/core/figma-tag-links.d.ts +66 -0
- package/dist/core/figma-tag-links.js +97 -0
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +1 -1
- package/dist/server/cli-commands.d.ts +1 -1
- package/dist/server/cli-commands.js +1 -1
- package/dist/server/cli-figma-tags.d.ts +1 -1
- package/dist/server/cli-figma-tags.js +149 -88
- package/dist/server/concurrency.d.ts +12 -0
- package/dist/server/concurrency.js +23 -0
- package/dist/server/figma-tags.d.ts +72 -24
- package/dist/server/figma-tags.js +130 -79
- package/dist/server/image-duplicates.js +6 -4
- package/dist/server/importers/figma.d.ts +20 -15
- package/dist/server/importers/figma.js +172 -92
- package/dist/server/operations.d.ts +7 -0
- package/dist/server/operations.js +53 -26
- package/dist/server/processing/processor.d.ts +29 -1
- package/dist/server/processing/processor.js +42 -5
- package/dist/server/raw-reconciliation.js +26 -10
- package/package.json +1 -1
- package/build/client/_app/immutable/chunks/Bsj1ssvc.js.br +0 -0
- package/build/client/_app/immutable/chunks/Bsj1ssvc.js.gz +0 -0
- package/build/client/_app/immutable/chunks/OL1Dh1oP.js.br +0 -0
- package/build/client/_app/immutable/chunks/OL1Dh1oP.js.gz +0 -0
- package/build/client/_app/immutable/chunks/QlQ-jeIO.js.br +0 -2
- package/build/client/_app/immutable/chunks/QlQ-jeIO.js.gz +0 -0
- package/build/client/_app/immutable/chunks/apKHI4vq.js.br +0 -0
- package/build/client/_app/immutable/chunks/apKHI4vq.js.gz +0 -0
- package/build/client/_app/immutable/chunks/g2rma9Ym.js.br +0 -0
- package/build/client/_app/immutable/chunks/g2rma9Ym.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.DpZM49_s.js.br +0 -0
- package/build/client/_app/immutable/entry/app.DpZM49_s.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.B3EMVPEN.js +0 -1
- package/build/client/_app/immutable/entry/start.B3EMVPEN.js.br +0 -0
- package/build/client/_app/immutable/entry/start.B3EMVPEN.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.Wqvn8XD-.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.Wqvn8XD-.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.Z-UvvLkP.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.Z-UvvLkP.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.lu89W_qJ.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.lu89W_qJ.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.Dt32EAoq.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.Dt32EAoq.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.WipzcX8_.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.WipzcX8_.js.gz +0 -0
- package/build/server/chunks/chunks/context.js-BZSZNuAd.js.map +0 -1
- package/build/server/chunks/chunks/contract.js-B4JdXFgm.js.map +0 -1
- package/build/server/chunks/chunks/core.js-BHxa3VBo.js.map +0 -1
- package/build/server/chunks/chunks/raw-reconciliation.js-DPnNXe0b.js +0 -11
- package/build/server/chunks/chunks/raw-reconciliation.js-DPnNXe0b.js.map +0 -1
- package/build/server/chunks/chunks/raw-reconciliation2.js-DKOpJ8if.js.map +0 -1
- package/build/server/chunks/entries/hooks.server.js-oHJX5INm.js.map +0 -1
- package/build/server/chunks/nodes/1.js-xbOwEHCW.js +0 -7
- package/build/server/chunks/nodes/3.js-Dpr_DvNU.js +0 -7
- package/build/server/chunks/nodes/4.js-14Lypd4o.js +0 -7
- package/dist/core/figma-tag-script.d.ts +0 -154
- package/dist/core/figma-tag-script.js +0 -248
package/build/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import http from 'node:http';
|
|
2
2
|
import fs__default from 'node:fs';
|
|
3
3
|
import process from 'node:process';
|
|
4
|
-
import { p as polka, h as handler, f as format_listening_address } from './server/chunks/handler-
|
|
4
|
+
import { p as polka, h as handler, f as format_listening_address } from './server/chunks/handler-Cna54zf6.js';
|
|
5
5
|
import { env, timeout_env } from './env.js';
|
|
6
6
|
import { rm } from 'node:fs/promises';
|
|
7
7
|
import './shims.js';
|
|
@@ -11,15 +11,15 @@ import 'node:path';
|
|
|
11
11
|
import 'node:timers';
|
|
12
12
|
import 'node:querystring';
|
|
13
13
|
import 'node:stream';
|
|
14
|
-
import './server/chunks/chunks/shared.js-
|
|
15
|
-
import './server/chunks/chunks/internal.js-
|
|
14
|
+
import './server/chunks/chunks/shared.js-C6qC0jnA.js';
|
|
15
|
+
import './server/chunks/chunks/internal.js-DlRiYJji.js';
|
|
16
16
|
import 'node:module';
|
|
17
|
-
import './server/chunks/chunks/utils.js-
|
|
18
|
-
import './server/chunks/index.js-
|
|
17
|
+
import './server/chunks/chunks/utils.js-BZ32hXFI.js';
|
|
18
|
+
import './server/chunks/index.js-BnpHWDec.js';
|
|
19
19
|
import './server/chunks/chunks/internal2.js-BlXt2rfE.js';
|
|
20
|
-
import './server/chunks/chunks/exports.js-
|
|
20
|
+
import './server/chunks/chunks/exports.js-CNZgoxR0.js';
|
|
21
21
|
import './server/chunks/chunks/routing.js-y-tryuip.js';
|
|
22
|
-
import './server/chunks/manifest.js-
|
|
22
|
+
import './server/chunks/manifest.js-9WMEOpxH.js';
|
|
23
23
|
import 'node:url';
|
|
24
24
|
|
|
25
25
|
const path = env('SOCKET_PATH', false);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { c as compareCodeUnits, h as folderOfRawPath, j as rawFileNameOfPath, g as canonicalizeParameters, n as normalizeFolderPath, J as typesForFileName, k as parentFolderPath, u as portableFolderPathKey } from './core.js-
|
|
2
|
-
import { i as isRecord, s as serverPluginsByType, L as LibraryStore, d as descriptorsByType, m as manifestModuleFileName, l as locateGeneratedAssetDeclaration, a as serializeLibrary, b as serverPluginForType, S as SourceImportError, p as processAssets, g as generateManifestModules, r as readCurrentProxy, e as encodeRelativePathForUrl, c as invalidInput, f as parseLibrary } from './contract.js-
|
|
3
|
-
import { c as collectAllReferences,
|
|
1
|
+
import { c as compareCodeUnits, h as folderOfRawPath, j as rawFileNameOfPath, g as canonicalizeParameters, n as normalizeFolderPath, J as typesForFileName, k as parentFolderPath, u as portableFolderPathKey } from './core.js-AGKlECJ0.js';
|
|
2
|
+
import { i as isRecord, s as serverPluginsByType, P as ProxyInfoCache, L as LibraryStore, d as descriptorsByType, m as manifestModuleFileName, l as locateGeneratedAssetDeclaration, a as serializeLibrary, b as serverPluginForType, S as SourceImportError, p as processAssets, g as generateManifestModules, r as readCurrentProxy, e as encodeRelativePathForUrl, c as invalidInput, f as parseLibrary } from './contract.js-DHeIVVv8.js';
|
|
3
|
+
import { c as collectAllReferences, d as allDeliveredAssetIds, b as computeLibraryMembership, a as assetIdError, i as isValidAssetId } from './manifest-membership.js-DkHaPk2F.js';
|
|
4
4
|
import { v as validateDependencyList, f as formatRequiredBy } from './dependencies.js-pUkjICr5.js';
|
|
5
|
-
import { v as verifyStableRawFile, c as classifyRawDirectory } from './raw-
|
|
5
|
+
import { m as mapConcurrent, v as verifyStableRawFile, c as classifyRawDirectory } from './raw-reconciliation.js-Cco4r8lr.js';
|
|
6
6
|
import { createRequire } from 'node:module';
|
|
7
7
|
import { isAbsolute, resolve, basename, dirname, join, extname, relative, sep } from 'node:path';
|
|
8
8
|
import { existsSync, watch, readFileSync } from 'node:fs';
|
|
@@ -16,14 +16,59 @@ import { lookup } from 'node:dns/promises';
|
|
|
16
16
|
import { isIP } from 'node:net';
|
|
17
17
|
import { request } from 'node:https';
|
|
18
18
|
|
|
19
|
-
//#region src/lib/core/figma-tag-script.ts
|
|
20
19
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* they report its tag without being a separate taggable node.
|
|
20
|
+
* The tag a link URL names, or `null`. An exact string match (no URL parsing)
|
|
21
|
+
* makes any path segment, query, fragment or percent-escape fail the tag grammar.
|
|
24
22
|
*/
|
|
25
|
-
function
|
|
26
|
-
|
|
23
|
+
function parseFundusTagLink(url) {
|
|
24
|
+
if (!url.startsWith("https://fundus.invalid/asset/")) return null;
|
|
25
|
+
const tag = url.slice(29);
|
|
26
|
+
return isValidAssetId(tag) ? tag : null;
|
|
27
|
+
}
|
|
28
|
+
var TAGGABLE_NODE_ID = /^\d+:\d+$/;
|
|
29
|
+
/**
|
|
30
|
+
* The Fundus tags carried by own links on plain scene-node ids; inherited,
|
|
31
|
+
* sublayer, foreign and unparsable links are dropped. One entry per link, so
|
|
32
|
+
* several tags on one node stay several entries. Sorted by tag, then node id.
|
|
33
|
+
*/
|
|
34
|
+
function figmaTagEntries(links) {
|
|
35
|
+
const entries = [];
|
|
36
|
+
for (const link of links) {
|
|
37
|
+
if (link.inherited || !TAGGABLE_NODE_ID.test(link.nodeId)) continue;
|
|
38
|
+
const tag = parseFundusTagLink(link.url);
|
|
39
|
+
if (tag === null) continue;
|
|
40
|
+
entries.push(link.linkId === void 0 ? {
|
|
41
|
+
tag,
|
|
42
|
+
nodeId: link.nodeId
|
|
43
|
+
} : {
|
|
44
|
+
tag,
|
|
45
|
+
nodeId: link.nodeId,
|
|
46
|
+
linkId: link.linkId
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return entries.sort((left, right) => compareCodeUnits(left.tag, right.tag) || compareCodeUnits(left.nodeId, right.nodeId));
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The links in a REST `GET /v1/files/:key/dev_resources` body, or `null` when
|
|
53
|
+
* `dev_resources` is not an array. Entries without string `id`/`url`/`node_id`
|
|
54
|
+
* are skipped.
|
|
55
|
+
*/
|
|
56
|
+
function figmaLinksFromRest(body) {
|
|
57
|
+
const resources = typeof body === "object" && body !== null ? body.dev_resources : void 0;
|
|
58
|
+
if (!Array.isArray(resources)) return null;
|
|
59
|
+
const links = [];
|
|
60
|
+
for (const resource of resources) {
|
|
61
|
+
if (typeof resource !== "object" || resource === null) continue;
|
|
62
|
+
const { id, url, node_id: nodeId } = resource;
|
|
63
|
+
if (typeof id !== "string" || typeof url !== "string" || typeof nodeId !== "string") continue;
|
|
64
|
+
links.push({
|
|
65
|
+
nodeId,
|
|
66
|
+
url,
|
|
67
|
+
inherited: false,
|
|
68
|
+
linkId: id
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return links;
|
|
27
72
|
}
|
|
28
73
|
//#endregion
|
|
29
74
|
//#region src/lib/core/propose-asset-id.ts
|
|
@@ -427,6 +472,9 @@ var PNG_SIGNATURE = Uint8Array.from([
|
|
|
427
472
|
26,
|
|
428
473
|
10
|
|
429
474
|
]);
|
|
475
|
+
/** Worst case per API call: 3 attempts × 30 s timeout + 2 waits × 10 s = 110 s. */
|
|
476
|
+
var FIGMA_RATE_LIMIT_ATTEMPTS = 3;
|
|
477
|
+
var FIGMA_RATE_LIMIT_MAX_WAIT_SECONDS = 10;
|
|
430
478
|
function record(value) {
|
|
431
479
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
|
|
432
480
|
}
|
|
@@ -506,12 +554,12 @@ function retryAfter(response) {
|
|
|
506
554
|
const seconds = Number(raw);
|
|
507
555
|
return Number.isSafeInteger(seconds) ? seconds : void 0;
|
|
508
556
|
}
|
|
509
|
-
function upstreamStatusError(response) {
|
|
557
|
+
function upstreamStatusError(response, scope) {
|
|
510
558
|
if (response.status === 401) return new SourceImportError("unauthorized", "Figma authentication failed.");
|
|
511
|
-
if (response.status === 403) return new SourceImportError("forbidden", "Figma authentication or access failed. The token may be invalid or expired, or it may not have access to this file.");
|
|
559
|
+
if (response.status === 403) return new SourceImportError("forbidden", scope ? `Figma authentication or access failed. The token may be invalid or expired, may lack the ${scope} scope, or may not have access to this file.` : "Figma authentication or access failed. The token may be invalid or expired, or it may not have access to this file.");
|
|
512
560
|
if (response.status === 404) return new SourceImportError("not-found", "The Figma file or node was not found.");
|
|
513
561
|
if (response.status === 429) return new SourceImportError("rate-limited", "Figma rate-limited this request.", retryAfter(response));
|
|
514
|
-
return new SourceImportError("upstream-failed", `Figma
|
|
562
|
+
return new SourceImportError("upstream-failed", `Figma request failed with status ${response.status}.`);
|
|
515
563
|
}
|
|
516
564
|
function isForbiddenIpv4(address) {
|
|
517
565
|
const parts = address.split(".").map(Number);
|
|
@@ -570,7 +618,7 @@ async function resolveSafeDownloadTarget(value) {
|
|
|
570
618
|
addresses
|
|
571
619
|
};
|
|
572
620
|
}
|
|
573
|
-
async function fetchWithDeadline(fetcher, url, init,
|
|
621
|
+
async function fetchWithDeadline(fetcher, url, init, scope) {
|
|
574
622
|
const controller = new AbortController();
|
|
575
623
|
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
576
624
|
try {
|
|
@@ -578,12 +626,12 @@ async function fetchWithDeadline(fetcher, url, init, consume) {
|
|
|
578
626
|
...init,
|
|
579
627
|
signal: controller.signal
|
|
580
628
|
});
|
|
581
|
-
if (!response.ok) throw upstreamStatusError(response);
|
|
582
|
-
return await
|
|
629
|
+
if (!response.ok) throw upstreamStatusError(response, scope);
|
|
630
|
+
return new Uint8Array(await response.arrayBuffer());
|
|
583
631
|
} catch (cause) {
|
|
584
|
-
if (controller.signal.aborted || cause instanceof Error && cause.name === "AbortError") throw new SourceImportError("download-timeout", "Figma
|
|
632
|
+
if (controller.signal.aborted || cause instanceof Error && cause.name === "AbortError") throw new SourceImportError("download-timeout", "Figma request timed out.");
|
|
585
633
|
if (cause instanceof SourceImportError) throw cause;
|
|
586
|
-
throw new SourceImportError("upstream-failed", "Figma
|
|
634
|
+
throw new SourceImportError("upstream-failed", "Figma request failed.");
|
|
587
635
|
} finally {
|
|
588
636
|
clearTimeout(timeout);
|
|
589
637
|
}
|
|
@@ -684,44 +732,28 @@ async function validatePng(bytes) {
|
|
|
684
732
|
if (!metadata.width || !metadata.height) throw new SourceImportError("invalid-response", "Figma export has invalid dimensions.");
|
|
685
733
|
if (metadata.width * metadata.height > MAX_PIXELS) throw new SourceImportError("image-too-large", "Figma export exceeds the 32 megapixel limit.");
|
|
686
734
|
}
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
const current = record(value);
|
|
696
|
-
if (!current) return;
|
|
697
|
-
const name = typeof current.name === "string" ? current.name : "";
|
|
698
|
-
const pageName = current.type === "CANVAS" ? name : page;
|
|
699
|
-
if (typeof current.id === "string" && current.type !== "DOCUMENT" && current.type !== "CANVAS" && !isInstanceSublayerId(current.id)) {
|
|
700
|
-
const shared = record(current.sharedPluginData);
|
|
701
|
-
const fundus = shared ? record(shared.fundus) : null;
|
|
702
|
-
const tag = fundus && typeof fundus.assetId === "string" ? fundus.assetId : "";
|
|
703
|
-
nodes.push({
|
|
704
|
-
nodeId: current.id,
|
|
705
|
-
nodeName: name,
|
|
706
|
-
page: pageName,
|
|
707
|
-
tag: tag === "" ? null : tag
|
|
708
|
-
});
|
|
709
|
-
}
|
|
710
|
-
if (Array.isArray(current.children)) for (const child of current.children) visit(child, pageName);
|
|
711
|
-
};
|
|
712
|
-
visit(record(document), "");
|
|
713
|
-
return nodes;
|
|
735
|
+
async function fetchFigmaApiBytes(endpoint, init, scope, context) {
|
|
736
|
+
for (let attempt = 1;; attempt++) try {
|
|
737
|
+
return await fetchWithDeadline(context.fetch, endpoint, init, scope);
|
|
738
|
+
} catch (cause) {
|
|
739
|
+
const wait = cause instanceof SourceImportError && cause.code === "rate-limited" ? cause.retryAfterSeconds : void 0;
|
|
740
|
+
if (wait === void 0 || wait > FIGMA_RATE_LIMIT_MAX_WAIT_SECONDS || attempt >= FIGMA_RATE_LIMIT_ATTEMPTS) throw cause;
|
|
741
|
+
await new Promise((resolve) => setTimeout(resolve, wait * 1e3));
|
|
742
|
+
}
|
|
714
743
|
}
|
|
715
|
-
|
|
716
|
-
async function fetchFigmaDocument(fileKey, context) {
|
|
744
|
+
async function requestFigmaApi(endpoint, context, request) {
|
|
717
745
|
const token = context.config.import.figma.token;
|
|
718
746
|
if (!token) throw new SourceImportError("not-configured", "Figma access is not configured.");
|
|
719
|
-
const
|
|
720
|
-
|
|
721
|
-
const jsonBytes = await fetchWithDeadline(context.fetch, endpoint, {
|
|
747
|
+
const jsonBytes = await fetchFigmaApiBytes(endpoint, {
|
|
748
|
+
method: request.method ?? "GET",
|
|
722
749
|
redirect: "error",
|
|
723
|
-
headers: {
|
|
724
|
-
|
|
750
|
+
headers: {
|
|
751
|
+
"X-Figma-Token": token,
|
|
752
|
+
...request.body !== void 0 ? { "Content-Type": "application/json" } : {}
|
|
753
|
+
},
|
|
754
|
+
...request.body !== void 0 ? { body: JSON.stringify(request.body) } : {}
|
|
755
|
+
}, request.scope, context);
|
|
756
|
+
if (jsonBytes.byteLength === 0) return {};
|
|
725
757
|
let payload;
|
|
726
758
|
try {
|
|
727
759
|
payload = JSON.parse(new TextDecoder().decode(jsonBytes));
|
|
@@ -729,38 +761,64 @@ async function fetchFigmaDocument(fileKey, context) {
|
|
|
729
761
|
throw new SourceImportError("invalid-response", "Figma returned an invalid response.");
|
|
730
762
|
}
|
|
731
763
|
const body = record(payload);
|
|
732
|
-
if (!body || body.err || typeof body.status === "number" && body.status >= 400) throw new SourceImportError("invalid-response",
|
|
733
|
-
|
|
764
|
+
if (!body || body.err || body.error === true || typeof body.status === "number" && body.status >= 400) throw new SourceImportError("invalid-response", request.errorMessage);
|
|
765
|
+
if (Array.isArray(body.errors) && body.errors.length > 0) throw new SourceImportError("upstream-failed", `Figma rejected the request: ${body.errors.map((entry) => {
|
|
766
|
+
const reason = record(entry)?.error;
|
|
767
|
+
return typeof reason === "string" ? reason : "unknown error";
|
|
768
|
+
}).join("; ")}`);
|
|
769
|
+
return body;
|
|
770
|
+
}
|
|
771
|
+
function figmaFileEndpoint(fileKey, path) {
|
|
772
|
+
return new URL(`https://api.figma.com/v1/files/${encodeURIComponent(fileKey)}${path}`);
|
|
773
|
+
}
|
|
774
|
+
/** Every Fundus tag link in the file (orphaned ones included); each entry has its `linkId`. */
|
|
775
|
+
async function listFigmaTagEntries(fileKey, context) {
|
|
776
|
+
const links = figmaLinksFromRest(await requestFigmaApi(figmaFileEndpoint(fileKey, "/dev_resources"), context, {
|
|
777
|
+
scope: "file_dev_resources:read",
|
|
778
|
+
errorMessage: "Figma returned an invalid response."
|
|
779
|
+
}));
|
|
780
|
+
if (!links) throw new SourceImportError("invalid-response", "Figma returned an invalid Dev Resources list.");
|
|
781
|
+
return figmaTagEntries(links).filter((entry) => entry.linkId !== void 0);
|
|
782
|
+
}
|
|
783
|
+
/** Export URLs for the nodes in one `/images` call; `null` for a node Figma cannot render. */
|
|
784
|
+
async function exportImageUrls(fileKey, nodeIds, scale, context) {
|
|
785
|
+
const endpoint = new URL(`https://api.figma.com/v1/images/${encodeURIComponent(fileKey)}`);
|
|
786
|
+
endpoint.searchParams.set("ids", nodeIds.join(","));
|
|
787
|
+
endpoint.searchParams.set("format", "png");
|
|
788
|
+
endpoint.searchParams.set("scale", String(scale));
|
|
789
|
+
const images = record((await requestFigmaApi(endpoint, context, {
|
|
790
|
+
scope: "file_content:read",
|
|
791
|
+
errorMessage: "Figma could not render this node."
|
|
792
|
+
})).images);
|
|
793
|
+
const urls = {};
|
|
794
|
+
for (const nodeId of nodeIds) {
|
|
795
|
+
if (!images || !Object.hasOwn(images, nodeId)) throw new SourceImportError("invalid-response", "Figma did not return the requested node.");
|
|
796
|
+
const imageUrl = images[nodeId];
|
|
797
|
+
urls[nodeId] = typeof imageUrl === "string" && imageUrl.length > 0 ? imageUrl : null;
|
|
798
|
+
}
|
|
799
|
+
return urls;
|
|
734
800
|
}
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
801
|
+
/**
|
|
802
|
+
* The one renderable node carrying `tag`. All candidates go into a single
|
|
803
|
+
* `/images` call, which answers deleted nodes with `null`; a live but
|
|
804
|
+
* unrenderable second candidate therefore goes unnoticed.
|
|
805
|
+
*/
|
|
806
|
+
async function resolveTaggedNode(fileKey, tag, scale, context) {
|
|
807
|
+
const candidates = [...new Set((await listFigmaTagEntries(fileKey, context)).filter((entry) => entry.tag === tag).map((entry) => entry.nodeId))];
|
|
808
|
+
if (candidates.length === 0) throw new SourceImportError("not-found", `No Figma node is tagged "${tag}" in this file.`);
|
|
809
|
+
const urls = await exportImageUrls(fileKey, candidates, scale, context);
|
|
810
|
+
const live = candidates.flatMap((nodeId) => {
|
|
811
|
+
const imageUrl = urls[nodeId];
|
|
812
|
+
return imageUrl ? [{
|
|
813
|
+
nodeId,
|
|
814
|
+
imageUrl
|
|
815
|
+
}] : [];
|
|
816
|
+
});
|
|
817
|
+
if (live.length === 0) throw new SourceImportError("not-found", `Every Figma node tagged "${tag}" (${candidates.join(", ")}) is deleted or cannot be rendered.`);
|
|
818
|
+
if (live.length > 1) throw new SourceImportError("ambiguous-tag", `More than one Figma node is tagged "${tag}" in this file (${live.map((node) => node.nodeId).join(", ")}).`);
|
|
819
|
+
return live[0];
|
|
740
820
|
}
|
|
741
|
-
async function
|
|
742
|
-
const token = context.config.import.figma.token;
|
|
743
|
-
if (!token) throw new SourceImportError("not-configured", "Figma access is not configured.");
|
|
744
|
-
const endpoint = new URL(`https://api.figma.com/v1/images/${encodeURIComponent(source.fileKey)}`);
|
|
745
|
-
endpoint.searchParams.set("ids", source.nodeId);
|
|
746
|
-
endpoint.searchParams.set("format", source.format);
|
|
747
|
-
endpoint.searchParams.set("scale", String(source.scale));
|
|
748
|
-
const jsonBytes = await fetchWithDeadline(context.fetch, endpoint, {
|
|
749
|
-
redirect: "error",
|
|
750
|
-
headers: { "X-Figma-Token": token }
|
|
751
|
-
}, async (response) => new Uint8Array(await response.arrayBuffer()));
|
|
752
|
-
let payload;
|
|
753
|
-
try {
|
|
754
|
-
payload = JSON.parse(new TextDecoder().decode(jsonBytes));
|
|
755
|
-
} catch {
|
|
756
|
-
throw new SourceImportError("invalid-response", "Figma returned an invalid response.");
|
|
757
|
-
}
|
|
758
|
-
const body = record(payload);
|
|
759
|
-
if (!body || body.err || typeof body.status === "number" && body.status >= 400) throw new SourceImportError("invalid-response", "Figma could not render this node.");
|
|
760
|
-
const images = record(body.images);
|
|
761
|
-
if (!images || !Object.hasOwn(images, source.nodeId)) throw new SourceImportError("invalid-response", "Figma did not return the requested node.");
|
|
762
|
-
const imageUrl = images[source.nodeId];
|
|
763
|
-
if (typeof imageUrl !== "string" || imageUrl.length === 0) throw new SourceImportError("invalid-response", "Figma could not render the requested node.");
|
|
821
|
+
async function downloadRaw(source, imageUrl, context) {
|
|
764
822
|
const bytes = await downloadExport(context.httpsTransport ?? requestPinnedHttps, imageUrl);
|
|
765
823
|
await validatePng(bytes);
|
|
766
824
|
return {
|
|
@@ -772,6 +830,18 @@ async function materialize(source, context) {
|
|
|
772
830
|
}
|
|
773
831
|
};
|
|
774
832
|
}
|
|
833
|
+
async function importNode(source, context) {
|
|
834
|
+
const imageUrl = (await exportImageUrls(source.fileKey, [source.nodeId], source.scale, context))[source.nodeId];
|
|
835
|
+
if (!imageUrl) throw new SourceImportError("invalid-response", "Figma could not render the requested node.");
|
|
836
|
+
return downloadRaw(source, imageUrl, context);
|
|
837
|
+
}
|
|
838
|
+
async function importTag(source, context) {
|
|
839
|
+
const { nodeId, imageUrl } = await resolveTaggedNode(source.fileKey, source.fundusTag, source.scale, context);
|
|
840
|
+
return downloadRaw({
|
|
841
|
+
...source,
|
|
842
|
+
nodeId
|
|
843
|
+
}, imageUrl, context);
|
|
844
|
+
}
|
|
775
845
|
var figmaSourceImporter = {
|
|
776
846
|
kind: "figma",
|
|
777
847
|
label: "Figma",
|
|
@@ -780,18 +850,16 @@ var figmaSourceImporter = {
|
|
|
780
850
|
if (input.mode === "tag") {
|
|
781
851
|
const fileKey = input.fileKey ?? context.config.import.figma.defaultFileKey;
|
|
782
852
|
if (!fileKey) throw new SourceImportError("not-configured", "Figma tag import needs a fileKey or import.figma.defaultFileKey in fundus.config.");
|
|
783
|
-
|
|
784
|
-
return materialize({
|
|
853
|
+
return importTag({
|
|
785
854
|
mode: "tag",
|
|
786
855
|
fileKey,
|
|
787
856
|
fundusTag: input.tag,
|
|
788
|
-
nodeId,
|
|
789
857
|
format: "png",
|
|
790
858
|
scale: input.scale ?? context.config.import.figma.defaults.scale
|
|
791
859
|
}, context);
|
|
792
860
|
}
|
|
793
861
|
const parsed = parseFigmaSelectionUrl(input.url);
|
|
794
|
-
return
|
|
862
|
+
return importNode({
|
|
795
863
|
fileKey: parsed.fileKey,
|
|
796
864
|
nodeId: parsed.nodeId,
|
|
797
865
|
format: "png",
|
|
@@ -800,14 +868,8 @@ var figmaSourceImporter = {
|
|
|
800
868
|
},
|
|
801
869
|
validateSourceParameters: validateFigmaSourceParameters,
|
|
802
870
|
async reimportRaw(source, context) {
|
|
803
|
-
if (source.mode === "tag")
|
|
804
|
-
|
|
805
|
-
return materialize({
|
|
806
|
-
...source,
|
|
807
|
-
nodeId
|
|
808
|
-
}, context);
|
|
809
|
-
}
|
|
810
|
-
return materialize(source, context);
|
|
871
|
+
if (source.mode === "tag") return importTag(source, context);
|
|
872
|
+
return importNode(source, context);
|
|
811
873
|
}
|
|
812
874
|
};
|
|
813
875
|
//#endregion
|
|
@@ -1451,22 +1513,22 @@ var ImageDuplicateDetector = class {
|
|
|
1451
1513
|
const images = Object.entries(library.assets).filter(([, record]) => record.type === "image").sort(([left], [right]) => compareCodeUnits(left, right));
|
|
1452
1514
|
const activeHashes = new Set(images.map(([, record]) => record.rawHash));
|
|
1453
1515
|
for (const hash of this.#fingerprints.keys()) if (!activeHashes.has(hash)) this.#fingerprints.delete(hash);
|
|
1454
|
-
const readable = []
|
|
1455
|
-
for (const [id, record] of images) {
|
|
1516
|
+
const readable = (await mapConcurrent(images, 8, async ([id, record]) => {
|
|
1456
1517
|
let fingerprint = this.#fingerprints.get(record.rawHash);
|
|
1457
1518
|
if (!fingerprint) {
|
|
1458
1519
|
fingerprint = imageFingerprint(join(rawDir, record.raw), 8);
|
|
1459
1520
|
this.#fingerprints.set(record.rawHash, fingerprint);
|
|
1460
1521
|
}
|
|
1461
1522
|
try {
|
|
1462
|
-
|
|
1523
|
+
return {
|
|
1463
1524
|
id,
|
|
1464
1525
|
fingerprint: await fingerprint
|
|
1465
|
-
}
|
|
1526
|
+
};
|
|
1466
1527
|
} catch {
|
|
1467
1528
|
this.#fingerprints.delete(record.rawHash);
|
|
1529
|
+
return null;
|
|
1468
1530
|
}
|
|
1469
|
-
}
|
|
1531
|
+
})).filter((entry) => entry !== null);
|
|
1470
1532
|
const duplicates = /* @__PURE__ */ new Map();
|
|
1471
1533
|
for (let leftIndex = 0; leftIndex < readable.length; leftIndex++) for (let rightIndex = leftIndex + 1; rightIndex < readable.length; rightIndex++) {
|
|
1472
1534
|
const left = readable[leftIndex];
|
|
@@ -1527,6 +1589,7 @@ var FundusOperations = class {
|
|
|
1527
1589
|
#importers;
|
|
1528
1590
|
#usageAnalyzer;
|
|
1529
1591
|
#duplicateDetector = new ImageDuplicateDetector();
|
|
1592
|
+
#proxyInfoCache = new ProxyInfoCache();
|
|
1530
1593
|
#operationQueue = Promise.resolve();
|
|
1531
1594
|
#pipelineQueue = Promise.resolve();
|
|
1532
1595
|
constructor(config, registry = serverPluginsByType, importerRegistry = serverImporters) {
|
|
@@ -1622,6 +1685,17 @@ var FundusOperations = class {
|
|
|
1622
1685
|
const classification = await this.#classifyRawDirectory(library);
|
|
1623
1686
|
return this.#snapshotState(library, classification);
|
|
1624
1687
|
}
|
|
1688
|
+
/**
|
|
1689
|
+
* Fill the image-fingerprint and proxy-probe caches without scanning raws or
|
|
1690
|
+
* joining the operation queue, so an early editor reconcile shares this
|
|
1691
|
+
* in-flight work instead of waiting behind it. Both caches are keyed by
|
|
1692
|
+
* content, so a concurrent mutation can only make an entry unused.
|
|
1693
|
+
*/
|
|
1694
|
+
async warmCaches() {
|
|
1695
|
+
const library = await this.#store.read();
|
|
1696
|
+
const delivered = allDeliveredAssetIds(computeLibraryMembership(library, collectAllReferences(library, descriptorsByType(this.#registry))));
|
|
1697
|
+
await Promise.all([this.#duplicateDetector.find(library, this.#config.rawDir), mapConcurrent([...delivered].sort(compareCodeUnits), 8, (assetId) => this.#proxyState(assetId, library.assets[assetId], delivered))]);
|
|
1698
|
+
}
|
|
1625
1699
|
/** Reconcile only changes that are safe without a user decision: unique moves and deletions. */
|
|
1626
1700
|
reconcileRawState() {
|
|
1627
1701
|
return this.#enqueueOperation(async () => {
|
|
@@ -2245,12 +2319,38 @@ var FundusOperations = class {
|
|
|
2245
2319
|
state: await this.#snapshotState(latestLibrary, latestClassification, pipelineIssues)
|
|
2246
2320
|
};
|
|
2247
2321
|
}
|
|
2322
|
+
async #proxyState(assetId, record, delivered) {
|
|
2323
|
+
if (!delivered.has(assetId)) return { proxy: null };
|
|
2324
|
+
try {
|
|
2325
|
+
const currentProxy = await readCurrentProxy(assetId, record, this.#config, this.#registry, this.#proxyInfoCache);
|
|
2326
|
+
if (!currentProxy) return {
|
|
2327
|
+
proxy: null,
|
|
2328
|
+
warning: "Proxy is stale or missing — it will be (re)processed on the next save."
|
|
2329
|
+
};
|
|
2330
|
+
return { proxy: {
|
|
2331
|
+
url: `/files/proxy/${encodeRelativePathForUrl(currentProxy.relativePath)}`,
|
|
2332
|
+
upToDate: true,
|
|
2333
|
+
...currentProxy
|
|
2334
|
+
} };
|
|
2335
|
+
} catch (cause) {
|
|
2336
|
+
return {
|
|
2337
|
+
proxy: null,
|
|
2338
|
+
warning: cause instanceof Error ? cause.message : String(cause)
|
|
2339
|
+
};
|
|
2340
|
+
}
|
|
2341
|
+
}
|
|
2248
2342
|
async #buildState(library, issues, classification) {
|
|
2249
|
-
const [gitBranch, changedGitAssets] = await Promise.all([currentGitBranch(this.#config.projectRoot), gitAssetChanges(this.#config.projectRoot, this.#config.library, library)]);
|
|
2250
2343
|
const referencesByAsset = collectAllReferences(library, descriptorsByType(this.#registry));
|
|
2251
|
-
const duplicatesByAsset = await this.#duplicateDetector.find(library, this.#config.rawDir);
|
|
2252
2344
|
const membershipByManifest = computeLibraryMembership(library, referencesByAsset);
|
|
2253
2345
|
const delivered = allDeliveredAssetIds(membershipByManifest);
|
|
2346
|
+
const assetIds = Object.keys(library.assets).sort(compareCodeUnits);
|
|
2347
|
+
const [gitBranch, changedGitAssets, duplicatesByAsset, proxies] = await Promise.all([
|
|
2348
|
+
currentGitBranch(this.#config.projectRoot),
|
|
2349
|
+
gitAssetChanges(this.#config.projectRoot, this.#config.library, library),
|
|
2350
|
+
this.#duplicateDetector.find(library, this.#config.rawDir),
|
|
2351
|
+
mapConcurrent(assetIds, 8, (assetId) => this.#proxyState(assetId, library.assets[assetId], delivered))
|
|
2352
|
+
]);
|
|
2353
|
+
this.#proxyInfoCache.retain(delivered);
|
|
2254
2354
|
const passiveManifestsByAsset = /* @__PURE__ */ new Map();
|
|
2255
2355
|
for (const manifestName of Object.keys(library.manifests).sort(compareCodeUnits)) for (const passiveMember of membershipByManifest[manifestName].passiveMembers) {
|
|
2256
2356
|
const passiveManifests = passiveManifestsByAsset.get(passiveMember.assetId) ?? [];
|
|
@@ -2272,24 +2372,14 @@ var FundusOperations = class {
|
|
|
2272
2372
|
const requiredByAsset = /* @__PURE__ */ new Map();
|
|
2273
2373
|
for (const dependency of this.#config.dependencies) requiredByAsset.set(dependency.id, [...dependency.sources]);
|
|
2274
2374
|
const assets = [];
|
|
2275
|
-
for (const assetId of
|
|
2375
|
+
for (const [index, assetId] of assetIds.entries()) {
|
|
2276
2376
|
const record = library.assets[assetId];
|
|
2277
2377
|
const warnings = [];
|
|
2278
2378
|
for (const issue of issues) if (issue.assetId === assetId) warnings.push(issue.message);
|
|
2279
2379
|
if (record.manifests.length === 0 && !delivered.has(assetId)) warnings.push("In no manifest and not referenced by any delivered asset — nothing is processed or generated for it.");
|
|
2280
2380
|
if (record.importSource && !this.#importers.has(record.importSource.importer)) warnings.push(`Importer "${record.importSource.importer}" is unavailable; the local raw file remains usable.`);
|
|
2281
|
-
|
|
2282
|
-
if (
|
|
2283
|
-
const currentProxy = await readCurrentProxy(assetId, record, this.#config, this.#registry);
|
|
2284
|
-
if (currentProxy) proxy = {
|
|
2285
|
-
url: `/files/proxy/${encodeRelativePathForUrl(currentProxy.relativePath)}`,
|
|
2286
|
-
upToDate: true,
|
|
2287
|
-
...currentProxy
|
|
2288
|
-
};
|
|
2289
|
-
else warnings.push("Proxy is stale or missing — it will be (re)processed on the next save.");
|
|
2290
|
-
} catch (cause) {
|
|
2291
|
-
warnings.push(cause instanceof Error ? cause.message : String(cause));
|
|
2292
|
-
}
|
|
2381
|
+
const { proxy, warning: proxyWarning } = proxies[index];
|
|
2382
|
+
if (proxyWarning) warnings.push(proxyWarning);
|
|
2293
2383
|
assets.push({
|
|
2294
2384
|
id: assetId,
|
|
2295
2385
|
type: record.type,
|
|
@@ -2514,4 +2604,4 @@ async function createFundusContext() {
|
|
|
2514
2604
|
}
|
|
2515
2605
|
|
|
2516
2606
|
export { getFundusContext as g, initializeFundusContext as i };
|
|
2517
|
-
//# sourceMappingURL=context.js-
|
|
2607
|
+
//# sourceMappingURL=context.js-BR2IRl9z.js.map
|