@aglyn/tenant-runtime 1.0.0-beta.221 → 1.0.0-beta.222
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 +6 -3
- package/package.json +5 -3
- package/src/index.d.ts +0 -3
- package/src/index.js +1 -4
- package/src/index.js.map +1 -1
- package/src/lib/apply-publish-schedule.js +41 -17
- package/src/lib/apply-publish-schedule.js.map +1 -1
- package/src/lib/compose-screen-nodes.d.ts +9 -0
- package/src/lib/compose-screen-nodes.js +13 -4
- package/src/lib/compose-screen-nodes.js.map +1 -1
- package/src/lib/get-site-icon-facts.d.ts +43 -0
- package/src/lib/get-site-icon-facts.js +105 -0
- package/src/lib/get-site-icon-facts.js.map +1 -0
- package/src/lib/self-hosted-fonts.d.ts +44 -0
- package/src/lib/self-hosted-fonts.js +149 -0
- package/src/lib/self-hosted-fonts.js.map +1 -0
- package/src/lib/assign-contact-owner.d.ts +0 -162
- package/src/lib/assign-contact-owner.js +0 -340
- package/src/lib/assign-contact-owner.js.map +0 -1
- package/src/lib/associate-company-by-domain.d.ts +0 -70
- package/src/lib/associate-company-by-domain.js +0 -153
- package/src/lib/associate-company-by-domain.js.map +0 -1
- package/src/lib/capture-host-contact.d.ts +0 -104
- package/src/lib/capture-host-contact.js +0 -151
- package/src/lib/capture-host-contact.js.map +0 -1
- package/src/lib/repeat-record-pages.d.ts +0 -48
- package/src/lib/repeat-record-pages.js +0 -64
- package/src/lib/repeat-record-pages.js.map +0 -1
- package/src/lib/resolve-dataset.d.ts +0 -40
- package/src/lib/resolve-dataset.js +0 -64
- package/src/lib/resolve-dataset.js.map +0 -1
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright 2026 Aglyn LLC
|
|
4
|
-
*
|
|
5
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
-
* you may not use this file except in compliance with the License.
|
|
7
|
-
* You may obtain a copy of the License at
|
|
8
|
-
*
|
|
9
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
-
*
|
|
11
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
-
* See the License for the specific language governing permissions and
|
|
15
|
-
* limitations under the License.
|
|
16
|
-
*/
|
|
17
|
-
import { type HostDatasetRecord } from '@aglyn/aglyn/app-utils/datasets';
|
|
18
|
-
/** One record document as either Firestore SDK hands it back. */
|
|
19
|
-
export interface RepeatRecordSnapshot {
|
|
20
|
-
id: string;
|
|
21
|
-
data: HostDatasetRecord;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* The records a repeat renders, in the order it renders them, from the two
|
|
25
|
-
* bounded reads that find them (AGL-1302).
|
|
26
|
-
*
|
|
27
|
-
* The rows a repeat shows are the ones `sortDatasetRecords` puts first: every
|
|
28
|
-
* record with an editor `order`, ascending, then the records without one —
|
|
29
|
-
* forms and Actions append those — by document id. A `limit()` with no
|
|
30
|
-
* `orderBy` cannot find them: Firestore answers it in document-id order, so on
|
|
31
|
-
* a dataset past the bound it reads an arbitrary sample, and sorting that
|
|
32
|
-
* sample afterwards only makes it look ordered.
|
|
33
|
-
*
|
|
34
|
-
* `byOrder` is the page ordered by `order`, bounded by
|
|
35
|
-
* {@link REPEAT_MAX_RECORDS}, which matches only documents that carry the
|
|
36
|
-
* field. When it comes back short every ordered record is already in hand, so
|
|
37
|
-
* `byId` — the same bound over the document id — supplies exactly the first
|
|
38
|
-
* unordered ones; a caller whose `byOrder` came back full does not need to
|
|
39
|
-
* read it, and passes an empty list.
|
|
40
|
-
*
|
|
41
|
-
* The published page's composition and the besigner's canvas preview both
|
|
42
|
-
* read through this, with the Admin SDK and the client SDK respectively, so
|
|
43
|
-
* the canvas cannot preview a row the page would not render.
|
|
44
|
-
*
|
|
45
|
-
* Each row is the record's value map, with `$id` inside it so incoming
|
|
46
|
-
* reference hops (AGL-180) can resolve rows.
|
|
47
|
-
*/
|
|
48
|
-
export declare function repeatRecordsFromPages(byOrder: readonly RepeatRecordSnapshot[], byId: readonly RepeatRecordSnapshot[]): Array<Record<string, unknown>>;
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
2
|
-
/**
|
|
3
|
-
* @license
|
|
4
|
-
* Copyright 2026 Aglyn LLC
|
|
5
|
-
*
|
|
6
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
-
* you may not use this file except in compliance with the License.
|
|
8
|
-
* You may obtain a copy of the License at
|
|
9
|
-
*
|
|
10
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
-
*
|
|
12
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
-
* See the License for the specific language governing permissions and
|
|
16
|
-
* limitations under the License.
|
|
17
|
-
*/ // By path, not `@aglyn/aglyn/server`: this module is also read in the browser
|
|
18
|
-
// (the besigner's repeat preview, AGL-3111), and the server entry carries
|
|
19
|
-
// `node:` modules no browser bundle can hold.
|
|
20
|
-
import { sortDatasetRecords } from "@aglyn/aglyn/app-utils/datasets";
|
|
21
|
-
import { REPEAT_MAX_RECORDS } from "@aglyn/aglyn/app-utils/expand-repeatables";
|
|
22
|
-
/**
|
|
23
|
-
* The records a repeat renders, in the order it renders them, from the two
|
|
24
|
-
* bounded reads that find them (AGL-1302).
|
|
25
|
-
*
|
|
26
|
-
* The rows a repeat shows are the ones `sortDatasetRecords` puts first: every
|
|
27
|
-
* record with an editor `order`, ascending, then the records without one —
|
|
28
|
-
* forms and Actions append those — by document id. A `limit()` with no
|
|
29
|
-
* `orderBy` cannot find them: Firestore answers it in document-id order, so on
|
|
30
|
-
* a dataset past the bound it reads an arbitrary sample, and sorting that
|
|
31
|
-
* sample afterwards only makes it look ordered.
|
|
32
|
-
*
|
|
33
|
-
* `byOrder` is the page ordered by `order`, bounded by
|
|
34
|
-
* {@link REPEAT_MAX_RECORDS}, which matches only documents that carry the
|
|
35
|
-
* field. When it comes back short every ordered record is already in hand, so
|
|
36
|
-
* `byId` — the same bound over the document id — supplies exactly the first
|
|
37
|
-
* unordered ones; a caller whose `byOrder` came back full does not need to
|
|
38
|
-
* read it, and passes an empty list.
|
|
39
|
-
*
|
|
40
|
-
* The published page's composition and the besigner's canvas preview both
|
|
41
|
-
* read through this, with the Admin SDK and the client SDK respectively, so
|
|
42
|
-
* the canvas cannot preview a row the page would not render.
|
|
43
|
-
*
|
|
44
|
-
* Each row is the record's value map, with `$id` inside it so incoming
|
|
45
|
-
* reference hops (AGL-180) can resolve rows.
|
|
46
|
-
*/ export function repeatRecordsFromPages(byOrder, byId) {
|
|
47
|
-
const snapshots = [
|
|
48
|
-
...byOrder
|
|
49
|
-
];
|
|
50
|
-
if (byOrder.length < REPEAT_MAX_RECORDS) {
|
|
51
|
-
const held = new Set(byOrder.map((snapshot)=>snapshot.id));
|
|
52
|
-
snapshots.push(...byId.filter((snapshot)=>!held.has(snapshot.id)));
|
|
53
|
-
}
|
|
54
|
-
return sortDatasetRecords(snapshots.map((snapshot)=>_extends({
|
|
55
|
-
$id: snapshot.id
|
|
56
|
-
}, snapshot.data))).slice(0, REPEAT_MAX_RECORDS).map((record)=>{
|
|
57
|
-
var _record_values;
|
|
58
|
-
return _extends({}, (_record_values = record.values) != null ? _record_values : {}, {
|
|
59
|
-
$id: record.$id
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
//# sourceMappingURL=repeat-record-pages.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../libs/tenant/runtime/src/lib/repeat-record-pages.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// By path, not `@aglyn/aglyn/server`: this module is also read in the browser\n// (the besigner's repeat preview, AGL-3111), and the server entry carries\n// `node:` modules no browser bundle can hold.\nimport {\n type HostDatasetRecord,\n sortDatasetRecords,\n} from '@aglyn/aglyn/app-utils/datasets'\nimport { REPEAT_MAX_RECORDS } from '@aglyn/aglyn/app-utils/expand-repeatables'\n\n/** One record document as either Firestore SDK hands it back. */\nexport interface RepeatRecordSnapshot {\n id: string\n data: HostDatasetRecord\n}\n\n/**\n * The records a repeat renders, in the order it renders them, from the two\n * bounded reads that find them (AGL-1302).\n *\n * The rows a repeat shows are the ones `sortDatasetRecords` puts first: every\n * record with an editor `order`, ascending, then the records without one —\n * forms and Actions append those — by document id. A `limit()` with no\n * `orderBy` cannot find them: Firestore answers it in document-id order, so on\n * a dataset past the bound it reads an arbitrary sample, and sorting that\n * sample afterwards only makes it look ordered.\n *\n * `byOrder` is the page ordered by `order`, bounded by\n * {@link REPEAT_MAX_RECORDS}, which matches only documents that carry the\n * field. When it comes back short every ordered record is already in hand, so\n * `byId` — the same bound over the document id — supplies exactly the first\n * unordered ones; a caller whose `byOrder` came back full does not need to\n * read it, and passes an empty list.\n *\n * The published page's composition and the besigner's canvas preview both\n * read through this, with the Admin SDK and the client SDK respectively, so\n * the canvas cannot preview a row the page would not render.\n *\n * Each row is the record's value map, with `$id` inside it so incoming\n * reference hops (AGL-180) can resolve rows.\n */\nexport function repeatRecordsFromPages(\n byOrder: readonly RepeatRecordSnapshot[],\n byId: readonly RepeatRecordSnapshot[],\n): Array<Record<string, unknown>> {\n const snapshots = [...byOrder]\n if (byOrder.length < REPEAT_MAX_RECORDS) {\n const held = new Set(byOrder.map((snapshot) => snapshot.id))\n snapshots.push(...byId.filter((snapshot) => !held.has(snapshot.id)))\n }\n return sortDatasetRecords(\n snapshots.map((snapshot) => ({ $id: snapshot.id, ...snapshot.data })),\n )\n .slice(0, REPEAT_MAX_RECORDS)\n .map((record) => ({ ...(record.values ?? {}), $id: record.$id }))\n}\n"],"names":["sortDatasetRecords","REPEAT_MAX_RECORDS","repeatRecordsFromPages","byOrder","byId","snapshots","length","held","Set","map","snapshot","id","push","filter","has","$id","data","slice","record","values"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,8EAA8E;AAC9E,0EAA0E;AAC1E,8CAA8C;AAC9C,SAEEA,kBAAkB,QACb,kCAAiC;AACxC,SAASC,kBAAkB,QAAQ,4CAA2C;AAQ9E;;;;;;;;;;;;;;;;;;;;;;;;CAwBC,GACD,OAAO,SAASC,uBACdC,OAAwC,EACxCC,IAAqC;IAErC,MAAMC,YAAY;WAAIF;KAAQ;IAC9B,IAAIA,QAAQG,MAAM,GAAGL,oBAAoB;QACvC,MAAMM,OAAO,IAAIC,IAAIL,QAAQM,GAAG,CAAC,CAACC,WAAaA,SAASC,EAAE;QAC1DN,UAAUO,IAAI,IAAIR,KAAKS,MAAM,CAAC,CAACH,WAAa,CAACH,KAAKO,GAAG,CAACJ,SAASC,EAAE;IACnE;IACA,OAAOX,mBACLK,UAAUI,GAAG,CAAC,CAACC,WAAc;YAAEK,KAAKL,SAASC,EAAE;WAAKD,SAASM,IAAI,IAEhEC,KAAK,CAAC,GAAGhB,oBACTQ,GAAG,CAAC,CAACS;YAAkBA;eAAN,cAAMA,iBAAAA,OAAOC,MAAM,YAAbD,iBAAiB,CAAC;YAAIH,KAAKG,OAAOH,GAAG;;;AACjE"}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright 2026 Aglyn LLC
|
|
4
|
-
*
|
|
5
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
-
* you may not use this file except in compliance with the License.
|
|
7
|
-
* You may obtain a copy of the License at
|
|
8
|
-
*
|
|
9
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
-
*
|
|
11
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
-
* See the License for the specific language governing permissions and
|
|
15
|
-
* limitations under the License.
|
|
16
|
-
*/
|
|
17
|
-
/**
|
|
18
|
-
* Resolves a dataset by its human name: console-created docs store it as
|
|
19
|
-
* `displayName` (AGL-536); the `name` fallback covers pre-migration docs.
|
|
20
|
-
*
|
|
21
|
-
* `scope` narrows the candidates to what one host may see (AGL-1039). It
|
|
22
|
-
* is applied INSIDE the query rather than to the result, which is what
|
|
23
|
-
* makes the collision case come out right: when a host-scoped dataset and
|
|
24
|
-
* an org-wide one share a display name, an unscoped `limit(1)` would pick
|
|
25
|
-
* one arbitrarily and a post-filter would then reject it — reading as
|
|
26
|
-
* "no such dataset" when a perfectly visible one exists.
|
|
27
|
-
*/
|
|
28
|
-
export declare function findDatasetByName(datasetsRef: FirebaseFirestore.CollectionReference, datasetName: string, scope?: (query: FirebaseFirestore.Query) => FirebaseFirestore.Query): Promise<FirebaseFirestore.QueryDocumentSnapshot | undefined>;
|
|
29
|
-
/**
|
|
30
|
-
* Id-first dataset resolution (AGL-556): a `datasetId` binding is a
|
|
31
|
-
* direct doc get — display names never enter into it, so renamed
|
|
32
|
-
* datasets keep receiving records. When the id is absent or doesn't
|
|
33
|
-
* resolve, the human-name query (AGL-536 semantics) is the legacy
|
|
34
|
-
* fallback. Returns undefined when neither resolves; callers still own
|
|
35
|
-
* the `deletedAt` check.
|
|
36
|
-
*/
|
|
37
|
-
export declare function resolveDatasetDoc(datasetsRef: FirebaseFirestore.CollectionReference, binding: {
|
|
38
|
-
datasetId?: string | null;
|
|
39
|
-
datasetName?: string | null;
|
|
40
|
-
}, hostId: string): Promise<FirebaseFirestore.DocumentSnapshot | undefined>;
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright 2026 Aglyn LLC
|
|
4
|
-
*
|
|
5
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
-
* you may not use this file except in compliance with the License.
|
|
7
|
-
* You may obtain a copy of the License at
|
|
8
|
-
*
|
|
9
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
-
*
|
|
11
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
-
* See the License for the specific language governing permissions and
|
|
15
|
-
* limitations under the License.
|
|
16
|
-
*/ import * as Aglyn from "@aglyn/aglyn/server";
|
|
17
|
-
/**
|
|
18
|
-
* Resolves a dataset by its human name: console-created docs store it as
|
|
19
|
-
* `displayName` (AGL-536); the `name` fallback covers pre-migration docs.
|
|
20
|
-
*
|
|
21
|
-
* `scope` narrows the candidates to what one host may see (AGL-1039). It
|
|
22
|
-
* is applied INSIDE the query rather than to the result, which is what
|
|
23
|
-
* makes the collision case come out right: when a host-scoped dataset and
|
|
24
|
-
* an org-wide one share a display name, an unscoped `limit(1)` would pick
|
|
25
|
-
* one arbitrarily and a post-filter would then reject it — reading as
|
|
26
|
-
* "no such dataset" when a perfectly visible one exists.
|
|
27
|
-
*/ export async function findDatasetByName(datasetsRef, datasetName, scope) {
|
|
28
|
-
const narrow = scope != null ? scope : (query)=>query;
|
|
29
|
-
const byDisplayName = await narrow(datasetsRef.where('displayName', '==', datasetName)).limit(1).get();
|
|
30
|
-
if (!byDisplayName.empty) return byDisplayName.docs[0];
|
|
31
|
-
return (await narrow(datasetsRef.where('name', '==', datasetName)).limit(1).get()).docs[0];
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Id-first dataset resolution (AGL-556): a `datasetId` binding is a
|
|
35
|
-
* direct doc get — display names never enter into it, so renamed
|
|
36
|
-
* datasets keep receiving records. When the id is absent or doesn't
|
|
37
|
-
* resolve, the human-name query (AGL-536 semantics) is the legacy
|
|
38
|
-
* fallback. Returns undefined when neither resolves; callers still own
|
|
39
|
-
* the `deletedAt` check.
|
|
40
|
-
*/ export async function resolveDatasetDoc(datasetsRef, binding, hostId) {
|
|
41
|
-
var _datasetsRef_parent_parent, _datasetsRef_parent, _binding_datasetId, _binding_datasetName;
|
|
42
|
-
// `hostId` is required rather than optional on purpose (AGL-1039): every
|
|
43
|
-
// caller here writes records into whatever comes back, and an optional
|
|
44
|
-
// scope is one a future caller forgets to pass. The Admin SDK ignores
|
|
45
|
-
// rules, so this is the only thing standing between a client site and
|
|
46
|
-
// another client's dataset.
|
|
47
|
-
const orgScoped = ((_datasetsRef_parent = datasetsRef.parent) == null ? void 0 : (_datasetsRef_parent_parent = _datasetsRef_parent.parent) == null ? void 0 : _datasetsRef_parent_parent.id) === 'orgs';
|
|
48
|
-
const datasetId = (_binding_datasetId = binding.datasetId) == null ? void 0 : _binding_datasetId.trim();
|
|
49
|
-
if (datasetId) {
|
|
50
|
-
const datasetDoc = await datasetsRef.doc(datasetId).get();
|
|
51
|
-
if (datasetDoc.exists && (!orgScoped || Aglyn.visibleToHost(datasetDoc.get('visibleTo'), hostId))) {
|
|
52
|
-
return datasetDoc;
|
|
53
|
-
}
|
|
54
|
-
// A hit this host cannot see is NOT a reason to fall through to the
|
|
55
|
-
// name lookup — that would answer "which dataset is called X" for a
|
|
56
|
-
// binding that already named a specific one.
|
|
57
|
-
if (datasetDoc.exists) return undefined;
|
|
58
|
-
}
|
|
59
|
-
const datasetName = (_binding_datasetName = binding.datasetName) == null ? void 0 : _binding_datasetName.trim();
|
|
60
|
-
if (!datasetName) return undefined;
|
|
61
|
-
return findDatasetByName(datasetsRef, datasetName, orgScoped ? (query)=>query.where('visibleTo', 'array-contains-any', Aglyn.scopeTokensForHost(hostId)) : undefined);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
//# sourceMappingURL=resolve-dataset.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../libs/tenant/runtime/src/lib/resolve-dataset.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as Aglyn from '@aglyn/aglyn/server'\n\n/**\n * Resolves a dataset by its human name: console-created docs store it as\n * `displayName` (AGL-536); the `name` fallback covers pre-migration docs.\n *\n * `scope` narrows the candidates to what one host may see (AGL-1039). It\n * is applied INSIDE the query rather than to the result, which is what\n * makes the collision case come out right: when a host-scoped dataset and\n * an org-wide one share a display name, an unscoped `limit(1)` would pick\n * one arbitrarily and a post-filter would then reject it — reading as\n * \"no such dataset\" when a perfectly visible one exists.\n */\nexport async function findDatasetByName(\n datasetsRef: FirebaseFirestore.CollectionReference,\n datasetName: string,\n scope?: (query: FirebaseFirestore.Query) => FirebaseFirestore.Query,\n): Promise<FirebaseFirestore.QueryDocumentSnapshot | undefined> {\n const narrow = scope ?? ((query: FirebaseFirestore.Query) => query)\n const byDisplayName = await narrow(\n datasetsRef.where('displayName', '==', datasetName),\n )\n .limit(1)\n .get()\n if (!byDisplayName.empty) return byDisplayName.docs[0]\n return (\n await narrow(datasetsRef.where('name', '==', datasetName)).limit(1).get()\n ).docs[0]\n}\n\n/**\n * Id-first dataset resolution (AGL-556): a `datasetId` binding is a\n * direct doc get — display names never enter into it, so renamed\n * datasets keep receiving records. When the id is absent or doesn't\n * resolve, the human-name query (AGL-536 semantics) is the legacy\n * fallback. Returns undefined when neither resolves; callers still own\n * the `deletedAt` check.\n */\nexport async function resolveDatasetDoc(\n datasetsRef: FirebaseFirestore.CollectionReference,\n binding: { datasetId?: string | null; datasetName?: string | null },\n hostId: string,\n): Promise<FirebaseFirestore.DocumentSnapshot | undefined> {\n // `hostId` is required rather than optional on purpose (AGL-1039): every\n // caller here writes records into whatever comes back, and an optional\n // scope is one a future caller forgets to pass. The Admin SDK ignores\n // rules, so this is the only thing standing between a client site and\n // another client's dataset.\n const orgScoped = datasetsRef.parent?.parent?.id === 'orgs'\n const datasetId = binding.datasetId?.trim()\n if (datasetId) {\n const datasetDoc = await datasetsRef.doc(datasetId).get()\n if (\n datasetDoc.exists &&\n (!orgScoped ||\n Aglyn.visibleToHost(datasetDoc.get('visibleTo'), hostId))\n ) {\n return datasetDoc\n }\n // A hit this host cannot see is NOT a reason to fall through to the\n // name lookup — that would answer \"which dataset is called X\" for a\n // binding that already named a specific one.\n if (datasetDoc.exists) return undefined\n }\n const datasetName = binding.datasetName?.trim()\n if (!datasetName) return undefined\n return findDatasetByName(\n datasetsRef,\n datasetName,\n orgScoped\n ? (query) =>\n query.where(\n 'visibleTo',\n 'array-contains-any',\n Aglyn.scopeTokensForHost(hostId),\n )\n : undefined,\n )\n}\n"],"names":["Aglyn","findDatasetByName","datasetsRef","datasetName","scope","narrow","query","byDisplayName","where","limit","get","empty","docs","resolveDatasetDoc","binding","hostId","orgScoped","parent","id","datasetId","trim","datasetDoc","doc","exists","visibleToHost","undefined","scopeTokensForHost"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,sBAAqB;AAE5C;;;;;;;;;;CAUC,GACD,OAAO,eAAeC,kBACpBC,WAAkD,EAClDC,WAAmB,EACnBC,KAAmE;IAEnE,MAAMC,SAASD,gBAAAA,QAAU,CAACE,QAAmCA;IAC7D,MAAMC,gBAAgB,MAAMF,OAC1BH,YAAYM,KAAK,CAAC,eAAe,MAAML,cAEtCM,KAAK,CAAC,GACNC,GAAG;IACN,IAAI,CAACH,cAAcI,KAAK,EAAE,OAAOJ,cAAcK,IAAI,CAAC,EAAE;IACtD,OAAO,AACL,CAAA,MAAMP,OAAOH,YAAYM,KAAK,CAAC,QAAQ,MAAML,cAAcM,KAAK,CAAC,GAAGC,GAAG,EAAC,EACxEE,IAAI,CAAC,EAAE;AACX;AAEA;;;;;;;CAOC,GACD,OAAO,eAAeC,kBACpBX,WAAkD,EAClDY,OAAmE,EACnEC,MAAc;QAOIb,4BAAAA,qBACAY,oBAeEA;IArBpB,yEAAyE;IACzE,uEAAuE;IACvE,sEAAsE;IACtE,sEAAsE;IACtE,4BAA4B;IAC5B,MAAME,YAAYd,EAAAA,sBAAAA,YAAYe,MAAM,sBAAlBf,6BAAAA,oBAAoBe,MAAM,qBAA1Bf,2BAA4BgB,EAAE,MAAK;IACrD,MAAMC,aAAYL,qBAAAA,QAAQK,SAAS,qBAAjBL,mBAAmBM,IAAI;IACzC,IAAID,WAAW;QACb,MAAME,aAAa,MAAMnB,YAAYoB,GAAG,CAACH,WAAWT,GAAG;QACvD,IACEW,WAAWE,MAAM,IAChB,CAAA,CAACP,aACAhB,MAAMwB,aAAa,CAACH,WAAWX,GAAG,CAAC,cAAcK,OAAM,GACzD;YACA,OAAOM;QACT;QACA,oEAAoE;QACpE,oEAAoE;QACpE,6CAA6C;QAC7C,IAAIA,WAAWE,MAAM,EAAE,OAAOE;IAChC;IACA,MAAMtB,eAAcW,uBAAAA,QAAQX,WAAW,qBAAnBW,qBAAqBM,IAAI;IAC7C,IAAI,CAACjB,aAAa,OAAOsB;IACzB,OAAOxB,kBACLC,aACAC,aACAa,YACI,CAACV,QACCA,MAAME,KAAK,CACT,aACA,sBACAR,MAAM0B,kBAAkB,CAACX,WAE7BU;AAER"}
|