@alizarin/napi 0.2.1-alpha.83 → 0.2.1-alpha.85

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.
@@ -4,7 +4,7 @@ import path from 'node:path';
4
4
  import fs from 'node:fs';
5
5
  import { fileURLToPath } from 'node:url';
6
6
 
7
- import { NapiPrebuildLoader, NapiStaticGraph, NapiStaticResourceRegistry, NapiResourceModelWrapper, NapiResourceInstanceWrapper } from '../index.js';
7
+ import { NapiStaticGraph, NapiStaticResourceRegistry, NapiResourceModelWrapper, NapiResourceInstanceWrapper } from '../index.js';
8
8
 
9
9
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
10
10
  const TEST_DATA = path.resolve(__dirname, '..', '..', '..', 'tests');
@@ -59,15 +59,6 @@ describe('NapiStaticResourceRegistry', () => {
59
59
  });
60
60
  });
61
61
 
62
- describe('NapiPrebuildLoader', () => {
63
- it('throws for nonexistent directory', () => {
64
- assert.throws(
65
- () => new NapiPrebuildLoader('/nonexistent/path'),
66
- /not found/i
67
- );
68
- });
69
- });
70
-
71
62
  // =============================================================================
72
63
  // NapiResourceModelWrapper
73
64
  // =============================================================================
Binary file
Binary file
Binary file
Binary file
package/index.d.ts CHANGED
@@ -40,6 +40,17 @@ export declare function extensionResolveMarkers(datatype: string, tileData: any,
40
40
  export declare function hasExtensionHandler(datatype: string): boolean
41
41
  /** List all registered extension handler datatypes. */
42
42
  export declare function getRegisteredExtensionHandlers(): Array<string>
43
+ /**
44
+ * Import a prebuild/pkg directory: register graphs, load SKOS collections,
45
+ * and load ontology configs.
46
+ *
47
+ * 1. Loads and registers all graphs from graphs/resource_models/ and graphs/branches/
48
+ * 2. Parses SKOS XML from reference_data/collections/ into the global RDM cache
49
+ * 3. Loads ontology configs from ontologies/ (if present)
50
+ *
51
+ * Returns `{ graphIds, collectionIds, collections, ontologyConfigs }`.
52
+ */
53
+ export declare function importPrebuild(prebuildDir: string, baseUri: string): any
43
54
  export declare class NapiRdmCache {
44
55
  constructor()
45
56
  /** Load collections from a SKOS JSON string. */
@@ -160,8 +171,12 @@ export declare class NapiResourceInstanceWrapper {
160
171
  valuesFromResourceNodegroup(existingValuesJs: any, nodegroupTileIds: Array<string>, nodegroupId: string): NapiValuesFromNodegroupResult
161
172
  /** Resolve a dot-separated path and return a PseudoList. */
162
173
  getValuesAtPath(path: string): NapiPseudoList
163
- /** Get semantic child value for a parent/child relationship. */
164
- getSemanticChildValue(parentTileId: string | undefined | null, parentNodeId: string, parentNodegroupId: string | undefined | null, childAlias: string): any
174
+ /**
175
+ * Get semantic child value for a parent/child relationship.
176
+ * Returns a NapiPseudoList (or null for empty). Singles are wrapped in a
177
+ * single-element list so the JS `wrapRustPseudo` path works uniformly.
178
+ */
179
+ getSemanticChildValue(parentTileId: string | undefined | null, parentNodeId: string, parentNodegroupId: string | undefined | null, childAlias: string): NapiPseudoList | null
165
180
  /** Get all semantic child values for a parent node. */
166
181
  getAllSemanticChildValues(parentTileId: string | undefined | null, parentNodeId: string, parentNodegroupId?: string | undefined | null): any
167
182
  /** Find all semantic children of a parent node (returns map of alias → tile IDs). */
@@ -247,24 +262,6 @@ export declare class NapiResourceModelWrapper {
247
262
  /** Prune graph to only include permitted nodegroups and their dependencies. */
248
263
  pruneGraph(keepFunctions?: Array<string> | undefined | null): void
249
264
  }
250
- export declare class NapiPrebuildLoader {
251
- constructor(path: string)
252
- /** Load a single graph from a JSON file path (relative to prebuild root or absolute). */
253
- loadGraph(path: string): NapiStaticGraph
254
- /** Load all graphs from prebuild/graphs/resource_models/ */
255
- loadAllGraphs(): Array<NapiStaticGraph>
256
- /**
257
- * Load full resources (with tiles) from a single business data file,
258
- * filtered by graph ID.
259
- */
260
- loadFullResourcesFromFile(path: string, graphId: string): any
261
- /** Find all business data JSON files in the prebuild directory. */
262
- findBusinessDataFiles(): Array<string>
263
- /** Get prebuild directory info. */
264
- getInfo(): any
265
- /** Count resources for a given graph ID. */
266
- countResourcesForGraph(graphId: string): number
267
- }
268
265
  export declare class NapiPrebuildExporter {
269
266
  constructor()
270
267
  /**
package/index.js CHANGED
@@ -310,7 +310,7 @@ if (!nativeBinding) {
310
310
  throw new Error(`Failed to load native binding`)
311
311
  }
312
312
 
313
- const { NapiRdmCache, NapiNodeConfigManager, NapiPseudoValue, NapiPseudoList, NapiPopulateResult, NapiEnsureNodegroupResult, NapiValuesFromNodegroupResult, NapiResourceInstanceWrapper, NapiResourceModelWrapper, NapiPrebuildLoader, NapiPrebuildExporter, NapiStaticGraph, NapiStaticResourceRegistry, buildGraphFromCsvs, buildBusinessDataFromCsv, extensionCoerce, extensionRenderDisplay, extensionResolveMarkers, hasExtensionHandler, getRegisteredExtensionHandlers } = nativeBinding
313
+ const { NapiRdmCache, NapiNodeConfigManager, NapiPseudoValue, NapiPseudoList, NapiPopulateResult, NapiEnsureNodegroupResult, NapiValuesFromNodegroupResult, NapiResourceInstanceWrapper, NapiResourceModelWrapper, NapiPrebuildExporter, NapiStaticGraph, NapiStaticResourceRegistry, buildGraphFromCsvs, buildBusinessDataFromCsv, extensionCoerce, extensionRenderDisplay, extensionResolveMarkers, hasExtensionHandler, getRegisteredExtensionHandlers, importPrebuild } = nativeBinding
314
314
 
315
315
  module.exports.NapiRdmCache = NapiRdmCache
316
316
  module.exports.NapiNodeConfigManager = NapiNodeConfigManager
@@ -321,7 +321,6 @@ module.exports.NapiEnsureNodegroupResult = NapiEnsureNodegroupResult
321
321
  module.exports.NapiValuesFromNodegroupResult = NapiValuesFromNodegroupResult
322
322
  module.exports.NapiResourceInstanceWrapper = NapiResourceInstanceWrapper
323
323
  module.exports.NapiResourceModelWrapper = NapiResourceModelWrapper
324
- module.exports.NapiPrebuildLoader = NapiPrebuildLoader
325
324
  module.exports.NapiPrebuildExporter = NapiPrebuildExporter
326
325
  module.exports.NapiStaticGraph = NapiStaticGraph
327
326
  module.exports.NapiStaticResourceRegistry = NapiStaticResourceRegistry
@@ -332,3 +331,4 @@ module.exports.extensionRenderDisplay = extensionRenderDisplay
332
331
  module.exports.extensionResolveMarkers = extensionResolveMarkers
333
332
  module.exports.hasExtensionHandler = hasExtensionHandler
334
333
  module.exports.getRegisteredExtensionHandlers = getRegisteredExtensionHandlers
334
+ module.exports.importPrebuild = importPrebuild
package/package.json CHANGED
@@ -1,7 +1,12 @@
1
1
  {
2
2
  "name": "@alizarin/napi",
3
- "version": "0.2.1-alpha.83",
3
+ "version": "0.2.1-alpha.85",
4
4
  "license": "AGPL-3.0-or-later",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/flaxandteal/alizarin",
8
+ "directory": "crates/alizarin-napi"
9
+ },
5
10
  "main": "index.js",
6
11
  "types": "index.d.ts",
7
12
  "bin": {
@@ -25,8 +30,8 @@
25
30
  "@napi-rs/cli": "^2.18.0"
26
31
  },
27
32
  "optionalDependencies": {
28
- "@alizarin/napi-win32-x64-msvc": "0.2.1-alpha.83",
29
- "@alizarin/napi-darwin-x64": "0.2.1-alpha.83",
30
- "@alizarin/napi-linux-x64-gnu": "0.2.1-alpha.83"
33
+ "@alizarin/napi-win32-x64-msvc": "0.2.1-alpha.85",
34
+ "@alizarin/napi-darwin-x64": "0.2.1-alpha.85",
35
+ "@alizarin/napi-linux-x64-gnu": "0.2.1-alpha.85"
31
36
  }
32
37
  }
@@ -906,6 +906,8 @@ impl NapiResourceInstanceWrapper {
906
906
  // =========================================================================
907
907
 
908
908
  /// Get semantic child value for a parent/child relationship.
909
+ /// Returns a NapiPseudoList (or null for empty). Singles are wrapped in a
910
+ /// single-element list so the JS `wrapRustPseudo` path works uniformly.
909
911
  #[napi]
910
912
  pub fn get_semantic_child_value(
911
913
  &self,
@@ -913,7 +915,7 @@ impl NapiResourceInstanceWrapper {
913
915
  parent_node_id: String,
914
916
  parent_nodegroup_id: Option<String>,
915
917
  child_alias: String,
916
- ) -> Result<serde_json::Value> {
918
+ ) -> Result<Option<NapiPseudoList>> {
917
919
  let result = self
918
920
  .inner
919
921
  .get_semantic_child_value(
@@ -926,15 +928,18 @@ impl NapiResourceInstanceWrapper {
926
928
  .map_err(sc_err)?;
927
929
 
928
930
  match result {
929
- SemanticChildResult::List(list) => {
930
- Ok(serde_json::to_value(NapiPseudoListJson::from(&list))
931
- .unwrap_or(serde_json::Value::Null))
932
- }
931
+ SemanticChildResult::List(list) => Ok(Some(NapiPseudoList { inner: list })),
933
932
  SemanticChildResult::Single(val) => {
934
- Ok(serde_json::to_value(NapiPseudoValueJson::from(&val))
935
- .unwrap_or(serde_json::Value::Null))
933
+ // Wrap single value in a PseudoListCore so JS sees a uniform interface
934
+ let list = alizarin_core::PseudoListCore {
935
+ node_alias: val.node.alias.clone().unwrap_or_default(),
936
+ is_single: true,
937
+ is_loaded: true,
938
+ values: vec![val],
939
+ };
940
+ Ok(Some(NapiPseudoList { inner: list }))
936
941
  }
937
- SemanticChildResult::Empty => Ok(serde_json::Value::Null),
942
+ SemanticChildResult::Empty => Ok(None),
938
943
  }
939
944
  }
940
945
 
package/src/lib.rs CHANGED
@@ -12,7 +12,7 @@ use alizarin_core::skos::SkosCollection;
12
12
  use alizarin_core::type_serialization::SerializationContext;
13
13
  use alizarin_core::{
14
14
  build_graph_from_model_csvs, build_resources_from_business_csv, wrap_business_data,
15
- PrebuildLoader, StaticGraph, StaticResource, StaticResourceRegistry,
15
+ StaticGraph, StaticResource, StaticResourceRegistry,
16
16
  };
17
17
 
18
18
  // ============================================================================
@@ -43,87 +43,6 @@ fn loader_err(e: alizarin_core::LoaderError) -> napi::Error {
43
43
  napi::Error::from_reason(e.to_string())
44
44
  }
45
45
 
46
- // ============================================================================
47
- // NapiPrebuildLoader
48
- // ============================================================================
49
-
50
- #[napi]
51
- pub struct NapiPrebuildLoader {
52
- inner: PrebuildLoader,
53
- }
54
-
55
- #[napi]
56
- impl NapiPrebuildLoader {
57
- #[napi(constructor)]
58
- pub fn new(path: String) -> Result<Self> {
59
- let inner = PrebuildLoader::new(&path).map_err(loader_err)?;
60
- Ok(NapiPrebuildLoader { inner })
61
- }
62
-
63
- /// Load a single graph from a JSON file path (relative to prebuild root or absolute).
64
- #[napi]
65
- pub fn load_graph(&self, path: String) -> Result<NapiStaticGraph> {
66
- let graph = self.inner.load_graph(&path).map_err(loader_err)?;
67
- Ok(NapiStaticGraph { inner: graph })
68
- }
69
-
70
- /// Load all graphs from prebuild/graphs/resource_models/
71
- #[napi]
72
- pub fn load_all_graphs(&self) -> Result<Vec<NapiStaticGraph>> {
73
- let graphs = self.inner.load_all_graphs().map_err(loader_err)?;
74
- Ok(graphs
75
- .into_iter()
76
- .map(|g| NapiStaticGraph { inner: g })
77
- .collect())
78
- }
79
-
80
- /// Load full resources (with tiles) from a single business data file,
81
- /// filtered by graph ID.
82
- #[napi]
83
- pub fn load_full_resources_from_file(
84
- &self,
85
- path: String,
86
- graph_id: String,
87
- ) -> Result<serde_json::Value> {
88
- let resources = self
89
- .inner
90
- .load_full_resources_from_file(std::path::Path::new(&path), &graph_id)
91
- .map_err(loader_err)?;
92
- serde_json::to_value(&resources).map_err(|e| napi::Error::from_reason(e.to_string()))
93
- }
94
-
95
- /// Find all business data JSON files in the prebuild directory.
96
- #[napi]
97
- pub fn find_business_data_files(&self) -> Result<Vec<String>> {
98
- let files = self.inner.find_business_data_files().map_err(loader_err)?;
99
- Ok(files.into_iter().map(|p| p.display().to_string()).collect())
100
- }
101
-
102
- /// Get prebuild directory info.
103
- #[napi]
104
- pub fn get_info(&self) -> Result<serde_json::Value> {
105
- let info = self.inner.get_info().map_err(loader_err)?;
106
- Ok(serde_json::json!({
107
- "path": info.path.display().to_string(),
108
- "hasGraphs": info.has_graphs,
109
- "hasBusinessData": info.has_business_data,
110
- "hasReferenceData": info.has_reference_data,
111
- "hasIndexTemplates": info.has_index_templates,
112
- "graphFiles": info.graph_files.iter().map(|p| p.display().to_string()).collect::<Vec<_>>(),
113
- }))
114
- }
115
-
116
- /// Count resources for a given graph ID.
117
- #[napi]
118
- pub fn count_resources_for_graph(&self, graph_id: String) -> Result<u32> {
119
- let count = self
120
- .inner
121
- .count_resources_for_graph(&graph_id)
122
- .map_err(loader_err)?;
123
- Ok(count as u32)
124
- }
125
- }
126
-
127
46
  // ============================================================================
128
47
  // NapiPrebuildExporter
129
48
  // ============================================================================
@@ -609,3 +528,35 @@ pub fn get_registered_extension_handlers() -> Vec<String> {
609
528
  .map(|s| s.to_string())
610
529
  .collect()
611
530
  }
531
+
532
+ // ============================================================================
533
+ // Prebuild import (high-level convenience)
534
+ // ============================================================================
535
+
536
+ /// Import a prebuild/pkg directory: register graphs, load SKOS collections,
537
+ /// and load ontology configs.
538
+ ///
539
+ /// 1. Loads and registers all graphs from graphs/resource_models/ and graphs/branches/
540
+ /// 2. Parses SKOS XML from reference_data/collections/ into the global RDM cache
541
+ /// 3. Loads ontology configs from ontologies/ (if present)
542
+ ///
543
+ /// Returns `{ graphIds, collectionIds, collections, ontologyConfigs }`.
544
+ #[napi(js_name = "importPrebuild")]
545
+ pub fn import_prebuild(prebuild_dir: String, base_uri: String) -> Result<serde_json::Value> {
546
+ let result = alizarin_core::import_prebuild(&prebuild_dir, &base_uri).map_err(loader_err)?;
547
+
548
+ let collections_json = serde_json::to_value(&result.collections)
549
+ .map_err(|e| napi::Error::from_reason(e.to_string()))?;
550
+ let ontology_configs: Vec<serde_json::Value> = result
551
+ .ontology_configs
552
+ .iter()
553
+ .filter_map(|c| serde_json::to_value(c).ok())
554
+ .collect();
555
+
556
+ Ok(serde_json::json!({
557
+ "graphIds": result.graph_ids,
558
+ "collectionIds": result.collection_ids,
559
+ "collections": collections_json,
560
+ "ontologyConfigs": ontology_configs,
561
+ }))
562
+ }