@aglyn/plugins-data 1.0.0-beta.219 → 1.0.0-beta.220
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 +1 -1
- package/package.json +10 -10
- package/src/lib/constants/bundle-common.d.ts +2 -0
- package/src/lib/constants/bundle-common.js +1 -0
- package/src/lib/constants/bundle-common.js.map +1 -1
- package/src/lib/declarations.console-server.d.ts +47 -0
- package/src/lib/declarations.console-server.js +74 -0
- package/src/lib/declarations.console-server.js.map +1 -0
- package/src/lib/declarations.server.d.ts +4 -0
- package/src/lib/declarations.server.js +11 -1
- package/src/lib/declarations.server.js.map +1 -1
- package/src/lib/model/dataset-csv.d.ts +36 -0
- package/src/lib/model/dataset-csv.js +85 -0
- package/src/lib/model/dataset-csv.js.map +1 -0
- package/src/lib/model/dataset-io.d.ts +8 -7
- package/src/lib/model/dataset-io.js +9 -8
- package/src/lib/model/dataset-io.js.map +1 -1
- package/src/lib/model/dataset-record-list.d.ts +40 -0
- package/src/lib/model/dataset-record-list.js +61 -0
- package/src/lib/model/dataset-record-list.js.map +1 -0
- package/src/lib/model/dataset-record.d.ts +33 -0
- package/src/lib/model/dataset-record.js +68 -0
- package/src/lib/model/dataset-record.js.map +1 -0
- package/src/lib/plugin.js +3 -0
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/server/announce-dataset-records.d.ts +37 -0
- package/src/lib/server/announce-dataset-records.js +54 -0
- package/src/lib/server/announce-dataset-records.js.map +1 -0
- package/src/lib/server/api-v1/datasets.d.ts +18 -0
- package/src/lib/server/api-v1/datasets.js +646 -0
- package/src/lib/server/api-v1/datasets.js.map +1 -0
- package/src/lib/server/api-v1/openapi.d.ts +26 -0
- package/src/lib/server/api-v1/openapi.js +260 -0
- package/src/lib/server/api-v1/openapi.js.map +1 -0
- package/src/lib/server/api-v1/usage.d.ts +26 -0
- package/src/lib/server/api-v1/usage.js +33 -0
- package/src/lib/server/api-v1/usage.js.map +1 -0
- package/src/lib/server/custom-field-types.d.ts +39 -0
- package/src/lib/server/custom-field-types.js +41 -0
- package/src/lib/server/custom-field-types.js.map +1 -0
- package/src/lib/server/dataset-figures.d.ts +61 -0
- package/src/lib/server/dataset-figures.js +413 -0
- package/src/lib/server/dataset-figures.js.map +1 -0
- package/src/lib/server/dataset-record-index.d.ts +18 -0
- package/src/lib/server/dataset-record-index.js +62 -0
- package/src/lib/server/dataset-record-index.js.map +1 -0
- package/src/lib/server/dataset-storage-meter.d.ts +29 -0
- package/src/lib/server/dataset-storage-meter.js +82 -0
- package/src/lib/server/dataset-storage-meter.js.map +1 -0
- package/src/lib/server/datasets-export-route.d.ts +57 -0
- package/src/lib/server/datasets-export-route.js +229 -0
- package/src/lib/server/datasets-export-route.js.map +1 -0
- package/src/lib/server/datasets-route.d.ts +38 -0
- package/src/lib/server/datasets-route.js +614 -0
- package/src/lib/server/datasets-route.js.map +1 -0
- package/src/lib/server.d.ts +23 -0
- package/src/lib/server.js +54 -0
- package/src/lib/server.js.map +1 -0
- package/src/lib/site-bundle/datasets-site-bundle.server.js +2 -15
- package/src/lib/site-bundle/datasets-site-bundle.server.js.map +1 -1
- package/src/lib/usage-axes.d.ts +24 -0
- package/src/lib/usage-axes.js +32 -0
- package/src/lib/usage-axes.js.map +1 -0
package/README.md
CHANGED
|
@@ -32,7 +32,7 @@ The plugin is console-only and declares one registrar, `registerDataConsole` (th
|
|
|
32
32
|
|
|
33
33
|
| import | contents |
|
|
34
34
|
| -- | -- |
|
|
35
|
-
| `@aglyn/plugins-data` | `BUNDLE_ID`, `registerDataConsole`, `HostDatasetsCard`, and the import/export model: `parseImportRows`, `mapImportColumns`,
|
|
35
|
+
| `@aglyn/plugins-data` | `BUNDLE_ID`, `registerDataConsole`, `HostDatasetsCard`, and the import/export model: `parseImportRows`, `mapImportColumns`, the dataset CSV/JSON writers (`datasetRecordsToCsv`, `datasetCsvHeader`, `datasetCsvRow`, `datasetRecordToJson`, `serializeDatasetValue`), and the platform's CSV helpers re-exported from the core (`parseCsv`, `countCsvDataRows`, `exportShortfall`) |
|
|
36
36
|
| `@aglyn/plugins-data/*` | any module under `src/lib/`, for example `@aglyn/plugins-data/model/dataset-record-view` (`datasetRecordFields`, `describeDatasetValue`) |
|
|
37
37
|
|
|
38
38
|
## Usage
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aglyn/plugins-data",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.220",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"homepage": "https://aglyn.com",
|
|
6
6
|
"repository": {
|
|
@@ -25,15 +25,15 @@
|
|
|
25
25
|
"./package.json": "./package.json"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@aglyn/aglyn": "1.0.0-beta.
|
|
29
|
-
"@aglyn/shared-data-mdi": "1.0.0-beta.
|
|
30
|
-
"@aglyn/shared-ui-jsx": "1.0.0-beta.
|
|
31
|
-
"@aglyn/shared-ui-snackstack": "1.0.0-beta.
|
|
32
|
-
"@aglyn/shared-util-http": "1.0.0-beta.
|
|
33
|
-
"@aglyn/shared-util-timestamp": "1.0.0-beta.
|
|
34
|
-
"@aglyn/tenant-data-admin": "1.0.0-beta.
|
|
35
|
-
"@aglyn/tenant-feature-instance": "1.0.0-beta.
|
|
36
|
-
"@aglyn/tenant-runtime": "1.0.0-beta.
|
|
28
|
+
"@aglyn/aglyn": "1.0.0-beta.220",
|
|
29
|
+
"@aglyn/shared-data-mdi": "1.0.0-beta.220",
|
|
30
|
+
"@aglyn/shared-ui-jsx": "1.0.0-beta.220",
|
|
31
|
+
"@aglyn/shared-ui-snackstack": "1.0.0-beta.220",
|
|
32
|
+
"@aglyn/shared-util-http": "1.0.0-beta.220",
|
|
33
|
+
"@aglyn/shared-util-timestamp": "1.0.0-beta.220",
|
|
34
|
+
"@aglyn/tenant-data-admin": "1.0.0-beta.220",
|
|
35
|
+
"@aglyn/tenant-feature-instance": "1.0.0-beta.220",
|
|
36
|
+
"@aglyn/tenant-runtime": "1.0.0-beta.220",
|
|
37
37
|
"@swc/helpers": "0.5.23"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
@@ -12,3 +12,5 @@ export declare const BUNDLE_ID = "data";
|
|
|
12
12
|
* alike, and the `repeatSource` this plugin declares in `plugins.config.json`.
|
|
13
13
|
*/
|
|
14
14
|
export declare const DATASET_REPEAT_SOURCE_ID = "dataset";
|
|
15
|
+
/** The dataset storage meter in the monthly usage sweep (`server/dataset-storage-meter.ts`). */
|
|
16
|
+
export declare const DATASET_STORAGE_METER_ID = "dataset-storage";
|
|
@@ -10,5 +10,6 @@
|
|
|
10
10
|
* (`repeat-sources.ts`) and the published page's reader (`repeat-rows.ts`)
|
|
11
11
|
* alike, and the `repeatSource` this plugin declares in `plugins.config.json`.
|
|
12
12
|
*/ export const DATASET_REPEAT_SOURCE_ID = 'dataset';
|
|
13
|
+
/** The dataset storage meter in the monthly usage sweep (`server/dataset-storage-meter.ts`). */ export const DATASET_STORAGE_METER_ID = 'dataset-storage';
|
|
13
14
|
|
|
14
15
|
//# sourceMappingURL=bundle-common.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/data/src/lib/constants/bundle-common.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 */\n\nexport const BUNDLE_ID = 'data'\n\n/**\n * The id datasets are a repeat source under — the editor's source\n * (`repeat-sources.ts`) and the published page's reader (`repeat-rows.ts`)\n * alike, and the `repeatSource` this plugin declares in `plugins.config.json`.\n */\nexport const DATASET_REPEAT_SOURCE_ID = 'dataset'\n"],"names":["BUNDLE_ID","DATASET_REPEAT_SOURCE_ID"],"mappings":"AAAA;;;;;;CAMC,GAED,OAAO,MAAMA,YAAY,OAAM;AAE/B;;;;CAIC,GACD,OAAO,MAAMC,2BAA2B,UAAS"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/data/src/lib/constants/bundle-common.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 */\n\nexport const BUNDLE_ID = 'data'\n\n/**\n * The id datasets are a repeat source under — the editor's source\n * (`repeat-sources.ts`) and the published page's reader (`repeat-rows.ts`)\n * alike, and the `repeatSource` this plugin declares in `plugins.config.json`.\n */\nexport const DATASET_REPEAT_SOURCE_ID = 'dataset'\n\n/** The dataset storage meter in the monthly usage sweep (`server/dataset-storage-meter.ts`). */\nexport const DATASET_STORAGE_METER_ID = 'dataset-storage'\n"],"names":["BUNDLE_ID","DATASET_REPEAT_SOURCE_ID","DATASET_STORAGE_METER_ID"],"mappings":"AAAA;;;;;;CAMC,GAED,OAAO,MAAMA,YAAY,OAAM;AAE/B;;;;CAIC,GACD,OAAO,MAAMC,2BAA2B,UAAS;AAEjD,8FAA8F,GAC9F,OAAO,MAAMC,2BAA2B,kBAAiB"}
|
|
@@ -0,0 +1,47 @@
|
|
|
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
|
+
* The data plugin's CONSOLE-ONLY server declarations, named under
|
|
19
|
+
* `consoleServerDeclarations` in `plugins.config.json` and run at the
|
|
20
|
+
* console's boot. Everything here is the console's alone, so the tenant
|
|
21
|
+
* runtime does not register any of it.
|
|
22
|
+
*
|
|
23
|
+
* It serves the organization's datasets on the customer REST API,
|
|
24
|
+
* `/v1/datasets/…`: the console's router owns the pipeline in front — the
|
|
25
|
+
* key, the plan's API access, the quota, the rate limit, the error envelope —
|
|
26
|
+
* and hands every request under `/v1/datasets` here once the key is
|
|
27
|
+
* authenticated. No plan feature is named on the registration: the handler
|
|
28
|
+
* answers reads on every plan and refuses a create the plan does not carry
|
|
29
|
+
* (`dataStore`) with its own sentence, as it always has. The resource brings
|
|
30
|
+
* its description for the API's OpenAPI document, and the datasets band
|
|
31
|
+
* joins `GET /v1/usage`.
|
|
32
|
+
*
|
|
33
|
+
* And another plugin that works over the workspace's datasets — an AI job
|
|
34
|
+
* naming a dataset in an automation, a planner listing what a site already
|
|
35
|
+
* has, an insight summarizing a dataset's fields — runs on the console's
|
|
36
|
+
* server, and reads them here rather than from the datasets collection:
|
|
37
|
+
* through the `dataset` record index, and through the dataset figure readers
|
|
38
|
+
* an insight asks.
|
|
39
|
+
*
|
|
40
|
+
* Light at boot: the API handler is imported with its first request, the
|
|
41
|
+
* description when the document is first built, the usage reader with the
|
|
42
|
+
* first usage call and the index's reader with its first read; the figure
|
|
43
|
+
* readers reach Firestore only when one is asked. Registering again replaces
|
|
44
|
+
* this plugin's own entries, so a second call (a hot reload, a spec) is
|
|
45
|
+
* harmless.
|
|
46
|
+
*/
|
|
47
|
+
export declare function registerDataConsoleServerDeclarations(): void;
|
|
@@ -0,0 +1,74 @@
|
|
|
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
|
+
*/ // The registries' own modules, not the data layer's or the plugin-manager's
|
|
17
|
+
// barrel: boot needs these registries, not the whole server surface or the
|
|
18
|
+
// console's client contexts.
|
|
19
|
+
import { registerPluginRecordIndex } from "@aglyn/aglyn/plugin-manager/plugin-record-index";
|
|
20
|
+
import { registerApiV1Resource, registerApiV1UsageFigures } from "@aglyn/tenant-data-admin/server/api-v1-resources";
|
|
21
|
+
import { firebaseAdmin } from "@aglyn/tenant-data-admin/server/firebase-admin";
|
|
22
|
+
import { BUNDLE_ID } from "./constants/bundle-common.js";
|
|
23
|
+
import { registerDatasetFigureReaders } from "./server/dataset-figures.js";
|
|
24
|
+
/**
|
|
25
|
+
* The data plugin's CONSOLE-ONLY server declarations, named under
|
|
26
|
+
* `consoleServerDeclarations` in `plugins.config.json` and run at the
|
|
27
|
+
* console's boot. Everything here is the console's alone, so the tenant
|
|
28
|
+
* runtime does not register any of it.
|
|
29
|
+
*
|
|
30
|
+
* It serves the organization's datasets on the customer REST API,
|
|
31
|
+
* `/v1/datasets/…`: the console's router owns the pipeline in front — the
|
|
32
|
+
* key, the plan's API access, the quota, the rate limit, the error envelope —
|
|
33
|
+
* and hands every request under `/v1/datasets` here once the key is
|
|
34
|
+
* authenticated. No plan feature is named on the registration: the handler
|
|
35
|
+
* answers reads on every plan and refuses a create the plan does not carry
|
|
36
|
+
* (`dataStore`) with its own sentence, as it always has. The resource brings
|
|
37
|
+
* its description for the API's OpenAPI document, and the datasets band
|
|
38
|
+
* joins `GET /v1/usage`.
|
|
39
|
+
*
|
|
40
|
+
* And another plugin that works over the workspace's datasets — an AI job
|
|
41
|
+
* naming a dataset in an automation, a planner listing what a site already
|
|
42
|
+
* has, an insight summarizing a dataset's fields — runs on the console's
|
|
43
|
+
* server, and reads them here rather than from the datasets collection:
|
|
44
|
+
* through the `dataset` record index, and through the dataset figure readers
|
|
45
|
+
* an insight asks.
|
|
46
|
+
*
|
|
47
|
+
* Light at boot: the API handler is imported with its first request, the
|
|
48
|
+
* description when the document is first built, the usage reader with the
|
|
49
|
+
* first usage call and the index's reader with its first read; the figure
|
|
50
|
+
* readers reach Firestore only when one is asked. Registering again replaces
|
|
51
|
+
* this plugin's own entries, so a second call (a hot reload, a spec) is
|
|
52
|
+
* harmless.
|
|
53
|
+
*/ export function registerDataConsoleServerDeclarations() {
|
|
54
|
+
registerApiV1Resource('datasets', {
|
|
55
|
+
handle: async (...args)=>(await import("./server/api-v1/datasets.js")).handleDatasets(...args),
|
|
56
|
+
describe: async ()=>(await import("./server/api-v1/openapi.js")).DATASETS_API_V1_DESCRIPTION
|
|
57
|
+
}, {
|
|
58
|
+
pluginId: BUNDLE_ID
|
|
59
|
+
});
|
|
60
|
+
registerApiV1UsageFigures(async (ctx)=>(await import("./server/api-v1/usage.js")).datasetUsageFigures(ctx), {
|
|
61
|
+
pluginId: BUNDLE_ID
|
|
62
|
+
});
|
|
63
|
+
registerPluginRecordIndex('dataset', lazyDatasetIndex, {
|
|
64
|
+
pluginId: BUNDLE_ID
|
|
65
|
+
});
|
|
66
|
+
registerDatasetFigureReaders(()=>firebaseAdmin.app().firestore());
|
|
67
|
+
}
|
|
68
|
+
const loadDatasetIndex = async ()=>(await import("./server/dataset-record-index.js")).datasetRecordIndex;
|
|
69
|
+
const lazyDatasetIndex = {
|
|
70
|
+
list: async (request)=>(await loadDatasetIndex()).list(request),
|
|
71
|
+
get: async (request)=>(await loadDatasetIndex()).get(request)
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
//# sourceMappingURL=declarations.console-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/plugins/data/src/lib/declarations.console-server.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// The registries' own modules, not the data layer's or the plugin-manager's\n// barrel: boot needs these registries, not the whole server surface or the\n// console's client contexts.\nimport {\n registerPluginRecordIndex,\n type PluginRecordIndex,\n} from '@aglyn/aglyn/plugin-manager/plugin-record-index'\nimport {\n registerApiV1Resource,\n registerApiV1UsageFigures,\n} from '@aglyn/tenant-data-admin/server/api-v1-resources'\nimport { firebaseAdmin } from '@aglyn/tenant-data-admin/server/firebase-admin'\nimport { BUNDLE_ID } from './constants/bundle-common'\nimport { registerDatasetFigureReaders } from './server/dataset-figures'\n\n/**\n * The data plugin's CONSOLE-ONLY server declarations, named under\n * `consoleServerDeclarations` in `plugins.config.json` and run at the\n * console's boot. Everything here is the console's alone, so the tenant\n * runtime does not register any of it.\n *\n * It serves the organization's datasets on the customer REST API,\n * `/v1/datasets/…`: the console's router owns the pipeline in front — the\n * key, the plan's API access, the quota, the rate limit, the error envelope —\n * and hands every request under `/v1/datasets` here once the key is\n * authenticated. No plan feature is named on the registration: the handler\n * answers reads on every plan and refuses a create the plan does not carry\n * (`dataStore`) with its own sentence, as it always has. The resource brings\n * its description for the API's OpenAPI document, and the datasets band\n * joins `GET /v1/usage`.\n *\n * And another plugin that works over the workspace's datasets — an AI job\n * naming a dataset in an automation, a planner listing what a site already\n * has, an insight summarizing a dataset's fields — runs on the console's\n * server, and reads them here rather than from the datasets collection:\n * through the `dataset` record index, and through the dataset figure readers\n * an insight asks.\n *\n * Light at boot: the API handler is imported with its first request, the\n * description when the document is first built, the usage reader with the\n * first usage call and the index's reader with its first read; the figure\n * readers reach Firestore only when one is asked. Registering again replaces\n * this plugin's own entries, so a second call (a hot reload, a spec) is\n * harmless.\n */\nexport function registerDataConsoleServerDeclarations(): void {\n registerApiV1Resource(\n 'datasets',\n {\n handle: async (...args) =>\n (await import('./server/api-v1/datasets')).handleDatasets(...args),\n describe: async () =>\n (await import('./server/api-v1/openapi')).DATASETS_API_V1_DESCRIPTION,\n },\n { pluginId: BUNDLE_ID },\n )\n registerApiV1UsageFigures(\n async (ctx) => (await import('./server/api-v1/usage')).datasetUsageFigures(ctx),\n { pluginId: BUNDLE_ID },\n )\n registerPluginRecordIndex('dataset', lazyDatasetIndex, { pluginId: BUNDLE_ID })\n registerDatasetFigureReaders(() => firebaseAdmin.app().firestore())\n}\n\nconst loadDatasetIndex = async () => (await import('./server/dataset-record-index')).datasetRecordIndex\n\nconst lazyDatasetIndex: PluginRecordIndex = {\n list: async (request) => (await loadDatasetIndex()).list(request),\n get: async (request) => (await loadDatasetIndex()).get(request),\n}\n"],"names":["registerPluginRecordIndex","registerApiV1Resource","registerApiV1UsageFigures","firebaseAdmin","BUNDLE_ID","registerDatasetFigureReaders","registerDataConsoleServerDeclarations","handle","args","handleDatasets","describe","DATASETS_API_V1_DESCRIPTION","pluginId","ctx","datasetUsageFigures","lazyDatasetIndex","app","firestore","loadDatasetIndex","datasetRecordIndex","list","request","get"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,4EAA4E;AAC5E,2EAA2E;AAC3E,6BAA6B;AAC7B,SACEA,yBAAyB,QAEpB,kDAAiD;AACxD,SACEC,qBAAqB,EACrBC,yBAAyB,QACpB,mDAAkD;AACzD,SAASC,aAAa,QAAQ,iDAAgD;AAC9E,SAASC,SAAS,QAAQ,+BAA2B;AACrD,SAASC,4BAA4B,QAAQ,8BAA0B;AAEvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BC,GACD,OAAO,SAASC;IACdL,sBACE,YACA;QACEM,QAAQ,OAAO,GAAGC,OAChB,AAAC,CAAA,MAAM,MAAM,CAAC,8BAA0B,EAAGC,cAAc,IAAID;QAC/DE,UAAU,UACR,AAAC,CAAA,MAAM,MAAM,CAAC,6BAAyB,EAAGC,2BAA2B;IACzE,GACA;QAAEC,UAAUR;IAAU;IAExBF,0BACE,OAAOW,MAAQ,AAAC,CAAA,MAAM,MAAM,CAAC,2BAAuB,EAAGC,mBAAmB,CAACD,MAC3E;QAAED,UAAUR;IAAU;IAExBJ,0BAA0B,WAAWe,kBAAkB;QAAEH,UAAUR;IAAU;IAC7EC,6BAA6B,IAAMF,cAAca,GAAG,GAAGC,SAAS;AAClE;AAEA,MAAMC,mBAAmB,UAAY,AAAC,CAAA,MAAM,MAAM,CAAC,mCAA+B,EAAGC,kBAAkB;AAEvG,MAAMJ,mBAAsC;IAC1CK,MAAM,OAAOC,UAAY,AAAC,CAAA,MAAMH,kBAAiB,EAAGE,IAAI,CAACC;IACzDC,KAAK,OAAOD,UAAY,AAAC,CAAA,MAAMH,kBAAiB,EAAGI,GAAG,CAACD;AACzD"}
|
|
@@ -35,5 +35,9 @@
|
|
|
35
35
|
* (`siteBundleSections`), so a boot that skipped this fails the export rather
|
|
36
36
|
* than shipping a backup without them; the answers load when a backup is made
|
|
37
37
|
* or restored.
|
|
38
|
+
*
|
|
39
|
+
* And the monthly usage sweep, a core cron, measures what the datasets store
|
|
40
|
+
* through this plugin's meter — declared in `usageAxes`, so the sweep refuses
|
|
41
|
+
* to bill a month without it. Its reads load with the first sweep.
|
|
38
42
|
*/
|
|
39
43
|
export declare function registerDataServerDeclarations(): void;
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
import { registerFormRecordTarget } from "@aglyn/aglyn/plugin-manager/submission-record-target";
|
|
19
19
|
import { registerRepeatRowReader } from "@aglyn/aglyn/plugin-manager/repeat-rows";
|
|
20
20
|
import { registerPluginSiteBundleSection } from "@aglyn/aglyn/plugin-manager/plugin-site-bundle";
|
|
21
|
-
import {
|
|
21
|
+
import { registerPluginUsageMeter } from "@aglyn/aglyn/plugin-manager/plugin-usage-meters";
|
|
22
|
+
import { BUNDLE_ID, DATASET_REPEAT_SOURCE_ID, DATASET_STORAGE_METER_ID } from "./constants/bundle-common.js";
|
|
22
23
|
/**
|
|
23
24
|
* The data plugin's server declarations: the light registrations core reads
|
|
24
25
|
* at boot, before any surface loads.
|
|
@@ -40,6 +41,10 @@ import { BUNDLE_ID, DATASET_REPEAT_SOURCE_ID } from "./constants/bundle-common.j
|
|
|
40
41
|
* (`siteBundleSections`), so a boot that skipped this fails the export rather
|
|
41
42
|
* than shipping a backup without them; the answers load when a backup is made
|
|
42
43
|
* or restored.
|
|
44
|
+
*
|
|
45
|
+
* And the monthly usage sweep, a core cron, measures what the datasets store
|
|
46
|
+
* through this plugin's meter — declared in `usageAxes`, so the sweep refuses
|
|
47
|
+
* to bill a month without it. Its reads load with the first sweep.
|
|
43
48
|
*/ export function registerDataServerDeclarations() {
|
|
44
49
|
registerRepeatRowReader(DATASET_REPEAT_SOURCE_ID, async (request)=>(await import("./repeat/dataset-repeat-rows.server.js")).readPublishedDatasetRows(request), {
|
|
45
50
|
pluginId: BUNDLE_ID
|
|
@@ -58,6 +63,11 @@ import { BUNDLE_ID, DATASET_REPEAT_SOURCE_ID } from "./constants/bundle-common.j
|
|
|
58
63
|
}, {
|
|
59
64
|
pluginId: BUNDLE_ID
|
|
60
65
|
});
|
|
66
|
+
registerPluginUsageMeter({
|
|
67
|
+
pluginId: BUNDLE_ID,
|
|
68
|
+
id: DATASET_STORAGE_METER_ID,
|
|
69
|
+
measure: async (context)=>(await import("./server/dataset-storage-meter.js")).measureDatasetStorage(context)
|
|
70
|
+
});
|
|
61
71
|
}
|
|
62
72
|
|
|
63
73
|
//# sourceMappingURL=declarations.server.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../libs/plugins/data/src/lib/declarations.server.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// The seam from its own module, not the plugin-manager barrel: boot needs the\n// registry and nothing else, and the barrel reaches the client contexts.\nimport { registerFormRecordTarget } from '@aglyn/aglyn/plugin-manager/submission-record-target'\nimport { registerRepeatRowReader } from '@aglyn/aglyn/plugin-manager/repeat-rows'\nimport { registerPluginSiteBundleSection } from '@aglyn/aglyn/plugin-manager/plugin-site-bundle'\nimport { BUNDLE_ID
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/plugins/data/src/lib/declarations.server.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// The seam from its own module, not the plugin-manager barrel: boot needs the\n// registry and nothing else, and the barrel reaches the client contexts.\nimport { registerFormRecordTarget } from '@aglyn/aglyn/plugin-manager/submission-record-target'\nimport { registerRepeatRowReader } from '@aglyn/aglyn/plugin-manager/repeat-rows'\nimport { registerPluginSiteBundleSection } from '@aglyn/aglyn/plugin-manager/plugin-site-bundle'\nimport { registerPluginUsageMeter } from '@aglyn/aglyn/plugin-manager/plugin-usage-meters'\nimport {\n BUNDLE_ID,\n DATASET_REPEAT_SOURCE_ID,\n DATASET_STORAGE_METER_ID,\n} from './constants/bundle-common'\n\n/**\n * The data plugin's server declarations: the light registrations core reads\n * at boot, before any surface loads.\n *\n * A published page that repeats an element over a dataset asks the platform\n * for the rows, and this is who answers — in every process that composes a\n * page, the tenant's and the console's previews alike. The reader, and the\n * Admin SDK with it, loads on the first page that repeats, not at boot.\n * `plugins.config.json` declares the same source (`repeatSource`), so a boot\n * that skipped this is refused rather than rendered as \"no rows\".\n *\n * A form can also file every submission as a dataset record, and this is the\n * target that stamps such a form with its signed binding when a page renders\n * and writes the record when the submission comes back. Declared the same way\n * (`formRecordTarget`), and just as light: both halves load on first use.\n *\n * A site's datasets are also its section of the whole-site backup: the\n * console's export and restore ask this plugin for them. Declared too\n * (`siteBundleSections`), so a boot that skipped this fails the export rather\n * than shipping a backup without them; the answers load when a backup is made\n * or restored.\n *\n * And the monthly usage sweep, a core cron, measures what the datasets store\n * through this plugin's meter — declared in `usageAxes`, so the sweep refuses\n * to bill a month without it. Its reads load with the first sweep.\n */\nexport function registerDataServerDeclarations(): void {\n registerRepeatRowReader(\n DATASET_REPEAT_SOURCE_ID,\n async (request) =>\n (await import('./repeat/dataset-repeat-rows.server')).readPublishedDatasetRows(\n request,\n ),\n { pluginId: BUNDLE_ID },\n )\n registerFormRecordTarget(\n {\n stamp: async (nodes, hostId) =>\n (await import('./form-target/stamp-form-dataset-bindings')).stampFormDatasetBindings(\n nodes,\n hostId,\n ),\n write: async (request) =>\n (await import('./form-target/dataset-form-record-target.server')).writeFormSubmissionRecord(\n request,\n ),\n },\n { pluginId: BUNDLE_ID },\n )\n const datasets = () => import('./site-bundle/datasets-site-bundle.server')\n registerPluginSiteBundleSection(\n 'datasets',\n {\n export: async (request) => (await datasets()).exportSiteDatasets(request),\n refusal: async (request) => (await datasets()).siteDatasetsRefusal(request),\n import: async (request) => (await datasets()).importSiteDatasets(request),\n },\n { pluginId: BUNDLE_ID },\n )\n registerPluginUsageMeter({\n pluginId: BUNDLE_ID,\n id: DATASET_STORAGE_METER_ID,\n measure: async (context) =>\n (await import('./server/dataset-storage-meter')).measureDatasetStorage(context),\n })\n}\n"],"names":["registerFormRecordTarget","registerRepeatRowReader","registerPluginSiteBundleSection","registerPluginUsageMeter","BUNDLE_ID","DATASET_REPEAT_SOURCE_ID","DATASET_STORAGE_METER_ID","registerDataServerDeclarations","request","readPublishedDatasetRows","pluginId","stamp","nodes","hostId","stampFormDatasetBindings","write","writeFormSubmissionRecord","datasets","export","exportSiteDatasets","refusal","siteDatasetsRefusal","import","importSiteDatasets","id","measure","context","measureDatasetStorage"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,8EAA8E;AAC9E,yEAAyE;AACzE,SAASA,wBAAwB,QAAQ,uDAAsD;AAC/F,SAASC,uBAAuB,QAAQ,0CAAyC;AACjF,SAASC,+BAA+B,QAAQ,iDAAgD;AAChG,SAASC,wBAAwB,QAAQ,kDAAiD;AAC1F,SACEC,SAAS,EACTC,wBAAwB,EACxBC,wBAAwB,QACnB,+BAA2B;AAElC;;;;;;;;;;;;;;;;;;;;;;;;;CAyBC,GACD,OAAO,SAASC;IACdN,wBACEI,0BACA,OAAOG,UACL,AAAC,CAAA,MAAM,MAAM,CAAC,yCAAqC,EAAGC,wBAAwB,CAC5ED,UAEJ;QAAEE,UAAUN;IAAU;IAExBJ,yBACE;QACEW,OAAO,OAAOC,OAAOC,SACnB,AAAC,CAAA,MAAM,MAAM,CAAC,+CAA2C,EAAGC,wBAAwB,CAClFF,OACAC;QAEJE,OAAO,OAAOP,UACZ,AAAC,CAAA,MAAM,MAAM,CAAC,qDAAiD,EAAGQ,yBAAyB,CACzFR;IAEN,GACA;QAAEE,UAAUN;IAAU;IAExB,MAAMa,WAAW,IAAM,MAAM,CAAC;IAC9Bf,gCACE,YACA;QACEgB,QAAQ,OAAOV,UAAY,AAAC,CAAA,MAAMS,UAAS,EAAGE,kBAAkB,CAACX;QACjEY,SAAS,OAAOZ,UAAY,AAAC,CAAA,MAAMS,UAAS,EAAGI,mBAAmB,CAACb;QACnEc,QAAQ,OAAOd,UAAY,AAAC,CAAA,MAAMS,UAAS,EAAGM,kBAAkB,CAACf;IACnE,GACA;QAAEE,UAAUN;IAAU;IAExBD,yBAAyB;QACvBO,UAAUN;QACVoB,IAAIlB;QACJmB,SAAS,OAAOC,UACd,AAAC,CAAA,MAAM,MAAM,CAAC,oCAAgC,EAAGC,qBAAqB,CAACD;IAC3E;AACF"}
|
|
@@ -0,0 +1,36 @@
|
|
|
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 { DatasetFieldDefinition, DatasetModel } from '@aglyn/aglyn/app-utils/dataset-models';
|
|
18
|
+
/** Storage value → portable string (CSV cell / JSON value). */
|
|
19
|
+
export declare function serializeDatasetValue(field: DatasetFieldDefinition, value: unknown): string;
|
|
20
|
+
/**
|
|
21
|
+
* The header line — field ids, in model order (AGL-2335).
|
|
22
|
+
*
|
|
23
|
+
* Split out of {@link datasetRecordsToCsv} so a server export can emit the
|
|
24
|
+
* file a page at a time. The whole point of that export is that it is not
|
|
25
|
+
* bounded by what one process can hold in memory, and a helper that only
|
|
26
|
+
* takes a complete `rows` array cannot serve it. Everything below shares
|
|
27
|
+
* one escaper: there are already five divergent hand-rolled CSV escapers in
|
|
28
|
+
* this repo and this is not becoming the sixth.
|
|
29
|
+
*/
|
|
30
|
+
export declare function datasetCsvHeader(model: DatasetModel): string;
|
|
31
|
+
/** One record's values (storage form) → one CSV line, no terminator. */
|
|
32
|
+
export declare function datasetCsvRow(model: DatasetModel, row: Record<string, unknown>): string;
|
|
33
|
+
/** One record's values → the portable JSON object the JSON export emits. */
|
|
34
|
+
export declare function datasetRecordToJson(model: DatasetModel, row: Record<string, unknown>): Record<string, string>;
|
|
35
|
+
/** Rows (storage-form value maps) → CSV with a fieldId header row. */
|
|
36
|
+
export declare function datasetRecordsToCsv(model: DatasetModel, rows: Array<Record<string, unknown>>): string;
|
|
@@ -0,0 +1,85 @@
|
|
|
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
|
+
* Dataset CSV/JSON serialization (AGL-182). The predictable inverse of
|
|
18
|
+
* `coerceDocumentValues`: ISO dates, `lat, lon` coordinates, comma-joined
|
|
19
|
+
* lists, JSON maps, reference ids — so an export re-imports losslessly
|
|
20
|
+
* through the same coercion.
|
|
21
|
+
*
|
|
22
|
+
* This plugin's own: the export route that streams a dataset a page at a
|
|
23
|
+
* time and the hub's client-side download both write through it. The
|
|
24
|
+
* escaper, the parser and the row-count check are the platform's
|
|
25
|
+
* (`app-utils/csv`), because the email, commerce and CRM imports read files
|
|
26
|
+
* too and may not reach this plugin.
|
|
27
|
+
*/ import { escapeCsvCell as csvEscape } from "@aglyn/aglyn/app-utils/csv";
|
|
28
|
+
/** Storage value → portable string (CSV cell / JSON value). */ export function serializeDatasetValue(field, value) {
|
|
29
|
+
if (value == null) return '';
|
|
30
|
+
switch(field.type){
|
|
31
|
+
case 'timestamp':
|
|
32
|
+
return typeof value === 'number' && Number.isFinite(value) ? new Date(value).toISOString() : String(value);
|
|
33
|
+
case 'coordinates':
|
|
34
|
+
{
|
|
35
|
+
const coordinates = value;
|
|
36
|
+
return coordinates && typeof coordinates.latitude === 'number' && typeof coordinates.longitude === 'number' ? `${coordinates.latitude}, ${coordinates.longitude}` : String(value);
|
|
37
|
+
}
|
|
38
|
+
case 'sorted':
|
|
39
|
+
case 'reference':
|
|
40
|
+
return Array.isArray(value) ? value.join(', ') : String(value);
|
|
41
|
+
case 'map':
|
|
42
|
+
try {
|
|
43
|
+
return JSON.stringify(value);
|
|
44
|
+
} catch (unused) {
|
|
45
|
+
return String(value);
|
|
46
|
+
}
|
|
47
|
+
default:
|
|
48
|
+
return String(value);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The header line — field ids, in model order (AGL-2335).
|
|
53
|
+
*
|
|
54
|
+
* Split out of {@link datasetRecordsToCsv} so a server export can emit the
|
|
55
|
+
* file a page at a time. The whole point of that export is that it is not
|
|
56
|
+
* bounded by what one process can hold in memory, and a helper that only
|
|
57
|
+
* takes a complete `rows` array cannot serve it. Everything below shares
|
|
58
|
+
* one escaper: there are already five divergent hand-rolled CSV escapers in
|
|
59
|
+
* this repo and this is not becoming the sixth.
|
|
60
|
+
*/ export function datasetCsvHeader(model) {
|
|
61
|
+
return model.order.map(csvEscape).join(',');
|
|
62
|
+
}
|
|
63
|
+
/** One record's values (storage form) → one CSV line, no terminator. */ export function datasetCsvRow(model, row) {
|
|
64
|
+
return model.order.map((fieldId)=>{
|
|
65
|
+
const field = model.fields[fieldId];
|
|
66
|
+
return csvEscape(field ? serializeDatasetValue(field, row[fieldId]) : '');
|
|
67
|
+
}).join(',');
|
|
68
|
+
}
|
|
69
|
+
/** One record's values → the portable JSON object the JSON export emits. */ export function datasetRecordToJson(model, row) {
|
|
70
|
+
return Object.fromEntries(model.order.map((fieldId)=>{
|
|
71
|
+
const field = model.fields[fieldId];
|
|
72
|
+
return [
|
|
73
|
+
fieldId,
|
|
74
|
+
field ? serializeDatasetValue(field, row[fieldId]) : ''
|
|
75
|
+
];
|
|
76
|
+
}));
|
|
77
|
+
}
|
|
78
|
+
/** Rows (storage-form value maps) → CSV with a fieldId header row. */ export function datasetRecordsToCsv(model, rows) {
|
|
79
|
+
return [
|
|
80
|
+
datasetCsvHeader(model),
|
|
81
|
+
...rows.map((row)=>datasetCsvRow(model, row))
|
|
82
|
+
].join('\n');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
//# sourceMappingURL=dataset-csv.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/data/src/lib/model/dataset-csv.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/**\n * Dataset CSV/JSON serialization (AGL-182). The predictable inverse of\n * `coerceDocumentValues`: ISO dates, `lat, lon` coordinates, comma-joined\n * lists, JSON maps, reference ids — so an export re-imports losslessly\n * through the same coercion.\n *\n * This plugin's own: the export route that streams a dataset a page at a\n * time and the hub's client-side download both write through it. The\n * escaper, the parser and the row-count check are the platform's\n * (`app-utils/csv`), because the email, commerce and CRM imports read files\n * too and may not reach this plugin.\n */\n\nimport { escapeCsvCell as csvEscape } from '@aglyn/aglyn/app-utils/csv'\nimport type {\n DatasetFieldDefinition,\n DatasetModel,\n} from '@aglyn/aglyn/app-utils/dataset-models'\n\n\n/** Storage value → portable string (CSV cell / JSON value). */\nexport function serializeDatasetValue(\n field: DatasetFieldDefinition,\n value: unknown,\n): string {\n if (value == null) return ''\n switch (field.type) {\n case 'timestamp':\n return typeof value === 'number' && Number.isFinite(value)\n ? new Date(value).toISOString()\n : String(value)\n case 'coordinates': {\n const coordinates = value as { latitude?: number; longitude?: number }\n return coordinates &&\n typeof coordinates.latitude === 'number' &&\n typeof coordinates.longitude === 'number'\n ? `${coordinates.latitude}, ${coordinates.longitude}`\n : String(value)\n }\n case 'sorted':\n case 'reference':\n return Array.isArray(value) ? value.join(', ') : String(value)\n case 'map':\n try {\n return JSON.stringify(value)\n } catch {\n return String(value)\n }\n default:\n return String(value)\n }\n}\n\n/**\n * The header line — field ids, in model order (AGL-2335).\n *\n * Split out of {@link datasetRecordsToCsv} so a server export can emit the\n * file a page at a time. The whole point of that export is that it is not\n * bounded by what one process can hold in memory, and a helper that only\n * takes a complete `rows` array cannot serve it. Everything below shares\n * one escaper: there are already five divergent hand-rolled CSV escapers in\n * this repo and this is not becoming the sixth.\n */\nexport function datasetCsvHeader(model: DatasetModel): string {\n return model.order.map(csvEscape).join(',')\n}\n\n/** One record's values (storage form) → one CSV line, no terminator. */\nexport function datasetCsvRow(\n model: DatasetModel,\n row: Record<string, unknown>,\n): string {\n return model.order\n .map((fieldId) => {\n const field = model.fields[fieldId]\n return csvEscape(field ? serializeDatasetValue(field, row[fieldId]) : '')\n })\n .join(',')\n}\n\n/** One record's values → the portable JSON object the JSON export emits. */\nexport function datasetRecordToJson(\n model: DatasetModel,\n row: Record<string, unknown>,\n): Record<string, string> {\n return Object.fromEntries(\n model.order.map((fieldId) => {\n const field = model.fields[fieldId]\n return [fieldId, field ? serializeDatasetValue(field, row[fieldId]) : '']\n }),\n )\n}\n\n/** Rows (storage-form value maps) → CSV with a fieldId header row. */\nexport function datasetRecordsToCsv(\n model: DatasetModel,\n rows: Array<Record<string, unknown>>,\n): string {\n return [\n datasetCsvHeader(model),\n ...rows.map((row) => datasetCsvRow(model, row)),\n ].join('\\n')\n}\n"],"names":["escapeCsvCell","csvEscape","serializeDatasetValue","field","value","type","Number","isFinite","Date","toISOString","String","coordinates","latitude","longitude","Array","isArray","join","JSON","stringify","datasetCsvHeader","model","order","map","datasetCsvRow","row","fieldId","fields","datasetRecordToJson","Object","fromEntries","datasetRecordsToCsv","rows"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;;CAWC,GAED,SAASA,iBAAiBC,SAAS,QAAQ,6BAA4B;AAOvE,6DAA6D,GAC7D,OAAO,SAASC,sBACdC,KAA6B,EAC7BC,KAAc;IAEd,IAAIA,SAAS,MAAM,OAAO;IAC1B,OAAQD,MAAME,IAAI;QAChB,KAAK;YACH,OAAO,OAAOD,UAAU,YAAYE,OAAOC,QAAQ,CAACH,SAChD,IAAII,KAAKJ,OAAOK,WAAW,KAC3BC,OAAON;QACb,KAAK;YAAe;gBAClB,MAAMO,cAAcP;gBACpB,OAAOO,eACL,OAAOA,YAAYC,QAAQ,KAAK,YAChC,OAAOD,YAAYE,SAAS,KAAK,WAC/B,GAAGF,YAAYC,QAAQ,CAAC,EAAE,EAAED,YAAYE,SAAS,EAAE,GACnDH,OAAON;YACb;QACA,KAAK;QACL,KAAK;YACH,OAAOU,MAAMC,OAAO,CAACX,SAASA,MAAMY,IAAI,CAAC,QAAQN,OAAON;QAC1D,KAAK;YACH,IAAI;gBACF,OAAOa,KAAKC,SAAS,CAACd;YACxB,EAAE,eAAM;gBACN,OAAOM,OAAON;YAChB;QACF;YACE,OAAOM,OAAON;IAClB;AACF;AAEA;;;;;;;;;CASC,GACD,OAAO,SAASe,iBAAiBC,KAAmB;IAClD,OAAOA,MAAMC,KAAK,CAACC,GAAG,CAACrB,WAAWe,IAAI,CAAC;AACzC;AAEA,sEAAsE,GACtE,OAAO,SAASO,cACdH,KAAmB,EACnBI,GAA4B;IAE5B,OAAOJ,MAAMC,KAAK,CACfC,GAAG,CAAC,CAACG;QACJ,MAAMtB,QAAQiB,MAAMM,MAAM,CAACD,QAAQ;QACnC,OAAOxB,UAAUE,QAAQD,sBAAsBC,OAAOqB,GAAG,CAACC,QAAQ,IAAI;IACxE,GACCT,IAAI,CAAC;AACV;AAEA,0EAA0E,GAC1E,OAAO,SAASW,oBACdP,KAAmB,EACnBI,GAA4B;IAE5B,OAAOI,OAAOC,WAAW,CACvBT,MAAMC,KAAK,CAACC,GAAG,CAAC,CAACG;QACf,MAAMtB,QAAQiB,MAAMM,MAAM,CAACD,QAAQ;QACnC,OAAO;YAACA;YAAStB,QAAQD,sBAAsBC,OAAOqB,GAAG,CAACC,QAAQ,IAAI;SAAG;IAC3E;AAEJ;AAEA,oEAAoE,GACpE,OAAO,SAASK,oBACdV,KAAmB,EACnBW,IAAoC;IAEpC,OAAO;QACLZ,iBAAiBC;WACdW,KAAKT,GAAG,CAAC,CAACE,MAAQD,cAAcH,OAAOI;KAC3C,CAACR,IAAI,CAAC;AACT"}
|
|
@@ -17,15 +17,16 @@
|
|
|
17
17
|
/**
|
|
18
18
|
* Dataset CSV/JSON round-tripping (AGL-182) — the IMPORT half.
|
|
19
19
|
*
|
|
20
|
-
*
|
|
21
|
-
* `
|
|
22
|
-
*
|
|
23
|
-
* here
|
|
24
|
-
* for everything dataset-io. What stays here is the part that is
|
|
25
|
-
* DATASETS — mapping a file's columns onto a `DatasetModel`.
|
|
20
|
+
* The serialization half is `dataset-csv.ts` beside this, and the CSV parser
|
|
21
|
+
* and the row-count check are the platform's `app-utils/csv` (AGL-2335), so
|
|
22
|
+
* the email, commerce and CRM imports read files with the same parser; all of
|
|
23
|
+
* them are re-exported here, so `@aglyn/plugins-data/model` remains the one
|
|
24
|
+
* import site for everything dataset-io. What stays here is the part that is
|
|
25
|
+
* about DATASETS — mapping a file's columns onto a `DatasetModel`.
|
|
26
26
|
*/
|
|
27
27
|
import type { DatasetModel } from '@aglyn/aglyn';
|
|
28
|
-
export { countCsvDataRows,
|
|
28
|
+
export { countCsvDataRows, exportShortfall, parseCsv, } from '@aglyn/aglyn/app-utils/csv';
|
|
29
|
+
export { datasetCsvHeader, datasetCsvRow, datasetRecordToJson, datasetRecordsToCsv, serializeDatasetValue, } from './dataset-csv';
|
|
29
30
|
/**
|
|
30
31
|
* Parses pasted/uploaded import text — a JSON array of objects or CSV
|
|
31
32
|
* with a header row — into raw string maps keyed by the source column
|
|
@@ -16,14 +16,15 @@
|
|
|
16
16
|
*/ /**
|
|
17
17
|
* Dataset CSV/JSON round-tripping (AGL-182) — the IMPORT half.
|
|
18
18
|
*
|
|
19
|
-
*
|
|
20
|
-
* `
|
|
21
|
-
*
|
|
22
|
-
* here
|
|
23
|
-
* for everything dataset-io. What stays here is the part that is
|
|
24
|
-
* DATASETS — mapping a file's columns onto a `DatasetModel`.
|
|
25
|
-
*/ import { parseCsv } from "@aglyn/aglyn/app-utils/
|
|
26
|
-
export { countCsvDataRows,
|
|
19
|
+
* The serialization half is `dataset-csv.ts` beside this, and the CSV parser
|
|
20
|
+
* and the row-count check are the platform's `app-utils/csv` (AGL-2335), so
|
|
21
|
+
* the email, commerce and CRM imports read files with the same parser; all of
|
|
22
|
+
* them are re-exported here, so `@aglyn/plugins-data/model` remains the one
|
|
23
|
+
* import site for everything dataset-io. What stays here is the part that is
|
|
24
|
+
* about DATASETS — mapping a file's columns onto a `DatasetModel`.
|
|
25
|
+
*/ import { parseCsv } from "@aglyn/aglyn/app-utils/csv";
|
|
26
|
+
export { countCsvDataRows, exportShortfall, parseCsv } from "@aglyn/aglyn/app-utils/csv";
|
|
27
|
+
export { datasetCsvHeader, datasetCsvRow, datasetRecordToJson, datasetRecordsToCsv, serializeDatasetValue } from "./dataset-csv.js";
|
|
27
28
|
/**
|
|
28
29
|
* Parses pasted/uploaded import text — a JSON array of objects or CSV
|
|
29
30
|
* with a header row — into raw string maps keyed by the source column
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/data/src/lib/model/dataset-io.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/**\n * Dataset CSV/JSON round-tripping (AGL-182) — the IMPORT half.\n *\n *
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/data/src/lib/model/dataset-io.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/**\n * Dataset CSV/JSON round-tripping (AGL-182) — the IMPORT half.\n *\n * The serialization half is `dataset-csv.ts` beside this, and the CSV parser\n * and the row-count check are the platform's `app-utils/csv` (AGL-2335), so\n * the email, commerce and CRM imports read files with the same parser; all of\n * them are re-exported here, so `@aglyn/plugins-data/model` remains the one\n * import site for everything dataset-io. What stays here is the part that is\n * about DATASETS — mapping a file's columns onto a `DatasetModel`.\n */\n\nimport type { DatasetModel } from '@aglyn/aglyn'\nimport { parseCsv } from '@aglyn/aglyn/app-utils/csv'\nexport {\n countCsvDataRows,\n exportShortfall,\n parseCsv,\n} from '@aglyn/aglyn/app-utils/csv'\nexport {\n datasetCsvHeader,\n datasetCsvRow,\n datasetRecordToJson,\n datasetRecordsToCsv,\n serializeDatasetValue,\n} from './dataset-csv'\n\n/**\n * Parses pasted/uploaded import text — a JSON array of objects or CSV\n * with a header row — into raw string maps keyed by the source column\n * names. Returns null when nothing parseable is found.\n */\nexport function parseImportRows(\n text: string,\n): Array<Record<string, string>> | null {\n const trimmed = String(text ?? '').trim()\n if (!trimmed) return null\n if (trimmed.startsWith('[') || trimmed.startsWith('{')) {\n try {\n const parsed = JSON.parse(trimmed)\n const list = Array.isArray(parsed) ? parsed : [parsed]\n return list\n .filter((entry) => entry && typeof entry === 'object')\n .map((entry) =>\n Object.fromEntries(\n Object.entries(entry as Record<string, unknown>).map(\n ([key, value]) => [\n key,\n typeof value === 'string' ? value : JSON.stringify(value),\n ],\n ),\n ),\n )\n } catch {\n return null\n }\n }\n const rows = parseCsv(trimmed)\n if (rows.length < 2) return null\n const [header, ...body] = rows\n return body.map((cells) =>\n Object.fromEntries(\n header.map((column, index) => [column.trim(), cells[index] ?? '']),\n ),\n )\n}\n\n/**\n * Maps raw import columns to model fieldIds: exact fieldId match first,\n * then case-insensitive display-name match. Unmatched columns are\n * reported, never silently dropped.\n */\nexport function mapImportColumns(\n model: DatasetModel,\n columns: string[],\n): { mapping: Record<string, string>; unmatched: string[] } {\n const byName = new Map<string, string>()\n for (const fieldId of model.order) {\n byName.set(fieldId.toLowerCase(), fieldId)\n const display = model.fields[fieldId]?.name\n if (display) byName.set(display.trim().toLowerCase(), fieldId)\n }\n const mapping: Record<string, string> = {}\n const unmatched: string[] = []\n for (const column of columns) {\n const fieldId = byName.get(column.trim().toLowerCase())\n if (fieldId) mapping[column] = fieldId\n else unmatched.push(column)\n }\n return { mapping, unmatched }\n}\n"],"names":["parseCsv","countCsvDataRows","exportShortfall","datasetCsvHeader","datasetCsvRow","datasetRecordToJson","datasetRecordsToCsv","serializeDatasetValue","parseImportRows","text","trimmed","String","trim","startsWith","parsed","JSON","parse","list","Array","isArray","filter","entry","map","Object","fromEntries","entries","key","value","stringify","rows","length","header","body","cells","column","index","mapImportColumns","model","columns","byName","Map","fieldId","order","set","toLowerCase","display","fields","name","mapping","unmatched","get","push"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;CASC,GAGD,SAASA,QAAQ,QAAQ,6BAA4B;AACrD,SACEC,gBAAgB,EAChBC,eAAe,EACfF,QAAQ,QACH,6BAA4B;AACnC,SACEG,gBAAgB,EAChBC,aAAa,EACbC,mBAAmB,EACnBC,mBAAmB,EACnBC,qBAAqB,QAChB,mBAAe;AAEtB;;;;CAIC,GACD,OAAO,SAASC,gBACdC,IAAY;IAEZ,MAAMC,UAAUC,OAAOF,eAAAA,OAAQ,IAAIG,IAAI;IACvC,IAAI,CAACF,SAAS,OAAO;IACrB,IAAIA,QAAQG,UAAU,CAAC,QAAQH,QAAQG,UAAU,CAAC,MAAM;QACtD,IAAI;YACF,MAAMC,SAASC,KAAKC,KAAK,CAACN;YAC1B,MAAMO,OAAOC,MAAMC,OAAO,CAACL,UAAUA,SAAS;gBAACA;aAAO;YACtD,OAAOG,KACJG,MAAM,CAAC,CAACC,QAAUA,SAAS,OAAOA,UAAU,UAC5CC,GAAG,CAAC,CAACD,QACJE,OAAOC,WAAW,CAChBD,OAAOE,OAAO,CAACJ,OAAkCC,GAAG,CAClD,CAAC,CAACI,KAAKC,MAAM,GAAK;wBAChBD;wBACA,OAAOC,UAAU,WAAWA,QAAQZ,KAAKa,SAAS,CAACD;qBACpD;QAIX,EAAE,eAAM;YACN,OAAO;QACT;IACF;IACA,MAAME,OAAO7B,SAASU;IACtB,IAAImB,KAAKC,MAAM,GAAG,GAAG,OAAO;IAC5B,MAAM,CAACC,QAAQ,GAAGC,KAAK,GAAGH;IAC1B,OAAOG,KAAKV,GAAG,CAAC,CAACW,QACfV,OAAOC,WAAW,CAChBO,OAAOT,GAAG,CAAC,CAACY,QAAQC;gBAA0BF;mBAAhB;gBAACC,OAAOtB,IAAI;iBAAIqB,eAAAA,KAAK,CAACE,MAAM,YAAZF,eAAgB;aAAG;;AAGvE;AAEA;;;;CAIC,GACD,OAAO,SAASG,iBACdC,KAAmB,EACnBC,OAAiB;IAEjB,MAAMC,SAAS,IAAIC;IACnB,KAAK,MAAMC,WAAWJ,MAAMK,KAAK,CAAE;YAEjBL;QADhBE,OAAOI,GAAG,CAACF,QAAQG,WAAW,IAAIH;QAClC,MAAMI,WAAUR,wBAAAA,MAAMS,MAAM,CAACL,QAAQ,qBAArBJ,sBAAuBU,IAAI;QAC3C,IAAIF,SAASN,OAAOI,GAAG,CAACE,QAAQjC,IAAI,GAAGgC,WAAW,IAAIH;IACxD;IACA,MAAMO,UAAkC,CAAC;IACzC,MAAMC,YAAsB,EAAE;IAC9B,KAAK,MAAMf,UAAUI,QAAS;QAC5B,MAAMG,UAAUF,OAAOW,GAAG,CAAChB,OAAOtB,IAAI,GAAGgC,WAAW;QACpD,IAAIH,SAASO,OAAO,CAACd,OAAO,GAAGO;aAC1BQ,UAAUE,IAAI,CAACjB;IACtB;IACA,OAAO;QAAEc;QAASC;IAAU;AAC9B"}
|
|
@@ -0,0 +1,40 @@
|
|
|
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 PluginRecordListSource } from '@aglyn/aglyn/plugin-manager/plugin-record-lists';
|
|
18
|
+
/**
|
|
19
|
+
* The workspace's datasets, listed in the console for another plugin's picker
|
|
20
|
+
* or check (AGL-3080) — an automation step choosing the dataset it writes to,
|
|
21
|
+
* a reference check confirming one still exists.
|
|
22
|
+
*
|
|
23
|
+
* Narrowed to a site (`hostId`), the query asks only for the datasets shared
|
|
24
|
+
* with it, by the site's scope tokens: an automation runs on the site, so it
|
|
25
|
+
* may only reach datasets the site can use, and the filter is the one the
|
|
26
|
+
* security rules require of a member scoped to the site. With no site, a
|
|
27
|
+
* member who is not organization-wide (`memberScope`) is asked for the ones
|
|
28
|
+
* shared with any site they reach — the rules refuse them an unfiltered
|
|
29
|
+
* list — and an organization-wide reader lists the organization's own.
|
|
30
|
+
* `installedFrom` keeps the ones installed from that listing, by the
|
|
31
|
+
* `source.listingId` every dataset install stamps.
|
|
32
|
+
*
|
|
33
|
+
* Ordered by document id, which the automatic index serves beside the
|
|
34
|
+
* `visibleTo` filter, and the composite index on (`source.listingId`,
|
|
35
|
+
* `visibleTo`) beside both. Each record is `datasetIndexedRecord`'s, the
|
|
36
|
+
* server index's shape.
|
|
37
|
+
*/
|
|
38
|
+
export declare const datasetRecordListSource: PluginRecordListSource;
|
|
39
|
+
/** Called from the console registrar, owner named for a spec that calls it directly. */
|
|
40
|
+
export declare function registerDatasetRecordList(): void;
|
|
@@ -0,0 +1,61 @@
|
|
|
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 { scopeTokensForHost } from "@aglyn/aglyn/app-utils/scope-tokens";
|
|
17
|
+
import { registerPluginRecordListSource } from "@aglyn/aglyn/plugin-manager/plugin-record-lists";
|
|
18
|
+
import { collection, documentId, limit, orderBy, query, where } from "firebase/firestore";
|
|
19
|
+
import { BUNDLE_ID } from "../constants/bundle-common.js";
|
|
20
|
+
import { datasetIndexedRecord } from "./dataset-record.js";
|
|
21
|
+
/**
|
|
22
|
+
* The workspace's datasets, listed in the console for another plugin's picker
|
|
23
|
+
* or check (AGL-3080) — an automation step choosing the dataset it writes to,
|
|
24
|
+
* a reference check confirming one still exists.
|
|
25
|
+
*
|
|
26
|
+
* Narrowed to a site (`hostId`), the query asks only for the datasets shared
|
|
27
|
+
* with it, by the site's scope tokens: an automation runs on the site, so it
|
|
28
|
+
* may only reach datasets the site can use, and the filter is the one the
|
|
29
|
+
* security rules require of a member scoped to the site. With no site, a
|
|
30
|
+
* member who is not organization-wide (`memberScope`) is asked for the ones
|
|
31
|
+
* shared with any site they reach — the rules refuse them an unfiltered
|
|
32
|
+
* list — and an organization-wide reader lists the organization's own.
|
|
33
|
+
* `installedFrom` keeps the ones installed from that listing, by the
|
|
34
|
+
* `source.listingId` every dataset install stamps.
|
|
35
|
+
*
|
|
36
|
+
* Ordered by document id, which the automatic index serves beside the
|
|
37
|
+
* `visibleTo` filter, and the composite index on (`source.listingId`,
|
|
38
|
+
* `visibleTo`) beside both. Each record is `datasetIndexedRecord`'s, the
|
|
39
|
+
* server index's shape.
|
|
40
|
+
*/ export const datasetRecordListSource = {
|
|
41
|
+
query (firestore, request) {
|
|
42
|
+
var _request_memberScope;
|
|
43
|
+
if (!request.orgId) return null;
|
|
44
|
+
const scope = request.hostId ? scopeTokensForHost(request.hostId) : (_request_memberScope = request.memberScope) != null ? _request_memberScope : null;
|
|
45
|
+
return query(collection(firestore, 'orgs', request.orgId, 'datasets'), ...request.installedFrom ? [
|
|
46
|
+
where('source.listingId', '==', request.installedFrom)
|
|
47
|
+
] : [], ...scope ? [
|
|
48
|
+
where('visibleTo', 'array-contains-any', [
|
|
49
|
+
...scope
|
|
50
|
+
])
|
|
51
|
+
] : [], orderBy(documentId()), limit(request.limit));
|
|
52
|
+
},
|
|
53
|
+
record: datasetIndexedRecord
|
|
54
|
+
};
|
|
55
|
+
/** Called from the console registrar, owner named for a spec that calls it directly. */ export function registerDatasetRecordList() {
|
|
56
|
+
registerPluginRecordListSource('dataset', datasetRecordListSource, {
|
|
57
|
+
pluginId: BUNDLE_ID
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
//# sourceMappingURL=dataset-record-list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/data/src/lib/model/dataset-record-list.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 { scopeTokensForHost } from '@aglyn/aglyn/app-utils/scope-tokens'\nimport {\n registerPluginRecordListSource,\n type PluginRecordListSource,\n} from '@aglyn/aglyn/plugin-manager/plugin-record-lists'\nimport {\n collection,\n documentId,\n limit,\n orderBy,\n query,\n where,\n} from 'firebase/firestore'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { datasetIndexedRecord } from './dataset-record'\n\n/**\n * The workspace's datasets, listed in the console for another plugin's picker\n * or check (AGL-3080) — an automation step choosing the dataset it writes to,\n * a reference check confirming one still exists.\n *\n * Narrowed to a site (`hostId`), the query asks only for the datasets shared\n * with it, by the site's scope tokens: an automation runs on the site, so it\n * may only reach datasets the site can use, and the filter is the one the\n * security rules require of a member scoped to the site. With no site, a\n * member who is not organization-wide (`memberScope`) is asked for the ones\n * shared with any site they reach — the rules refuse them an unfiltered\n * list — and an organization-wide reader lists the organization's own.\n * `installedFrom` keeps the ones installed from that listing, by the\n * `source.listingId` every dataset install stamps.\n *\n * Ordered by document id, which the automatic index serves beside the\n * `visibleTo` filter, and the composite index on (`source.listingId`,\n * `visibleTo`) beside both. Each record is `datasetIndexedRecord`'s, the\n * server index's shape.\n */\nexport const datasetRecordListSource: PluginRecordListSource = {\n query(firestore, request) {\n if (!request.orgId) return null\n const scope = request.hostId ? scopeTokensForHost(request.hostId) : (request.memberScope ?? null)\n return query(\n collection(firestore, 'orgs', request.orgId, 'datasets'),\n ...(request.installedFrom ? [where('source.listingId', '==', request.installedFrom)] : []),\n ...(scope ? [where('visibleTo', 'array-contains-any', [...scope])] : []),\n orderBy(documentId()),\n limit(request.limit),\n )\n },\n record: datasetIndexedRecord,\n}\n\n/** Called from the console registrar, owner named for a spec that calls it directly. */\nexport function registerDatasetRecordList(): void {\n registerPluginRecordListSource('dataset', datasetRecordListSource, { pluginId: BUNDLE_ID })\n}\n"],"names":["scopeTokensForHost","registerPluginRecordListSource","collection","documentId","limit","orderBy","query","where","BUNDLE_ID","datasetIndexedRecord","datasetRecordListSource","firestore","request","orgId","scope","hostId","memberScope","installedFrom","record","registerDatasetRecordList","pluginId"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,SAASA,kBAAkB,QAAQ,sCAAqC;AACxE,SACEC,8BAA8B,QAEzB,kDAAiD;AACxD,SACEC,UAAU,EACVC,UAAU,EACVC,KAAK,EACLC,OAAO,EACPC,KAAK,EACLC,KAAK,QACA,qBAAoB;AAC3B,SAASC,SAAS,QAAQ,gCAA4B;AACtD,SAASC,oBAAoB,QAAQ,sBAAkB;AAEvD;;;;;;;;;;;;;;;;;;;CAmBC,GACD,OAAO,MAAMC,0BAAkD;IAC7DJ,OAAMK,SAAS,EAAEC,OAAO;YAE+CA;QADrE,IAAI,CAACA,QAAQC,KAAK,EAAE,OAAO;QAC3B,MAAMC,QAAQF,QAAQG,MAAM,GAAGf,mBAAmBY,QAAQG,MAAM,KAAKH,uBAAAA,QAAQI,WAAW,YAAnBJ,uBAAuB;QAC5F,OAAON,MACLJ,WAAWS,WAAW,QAAQC,QAAQC,KAAK,EAAE,gBACzCD,QAAQK,aAAa,GAAG;YAACV,MAAM,oBAAoB,MAAMK,QAAQK,aAAa;SAAE,GAAG,EAAE,KACrFH,QAAQ;YAACP,MAAM,aAAa,sBAAsB;mBAAIO;aAAM;SAAE,GAAG,EAAE,EACvET,QAAQF,eACRC,MAAMQ,QAAQR,KAAK;IAEvB;IACAc,QAAQT;AACV,EAAC;AAED,sFAAsF,GACtF,OAAO,SAASU;IACdlB,+BAA+B,WAAWS,yBAAyB;QAAEU,UAAUZ;IAAU;AAC3F"}
|