@objectstack/core 3.0.8 → 3.0.9

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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @objectstack/core@3.0.8 build /home/runner/work/spec/spec/packages/core
2
+ > @objectstack/core@3.0.9 build /home/runner/work/spec/spec/packages/core
3
3
  > tsup --config ../../tsup.config.ts
4
4
 
5
5
  CLI Building entry: src/index.ts
@@ -10,13 +10,13 @@
10
10
  CLI Cleaning output folder
11
11
  ESM Build start
12
12
  CJS Build start
13
- ESM dist/index.js 135.90 KB
14
- ESM dist/index.js.map 286.19 KB
15
- ESM ⚡️ Build success in 101ms
16
- CJS dist/index.cjs 138.85 KB
17
- CJS dist/index.cjs.map 287.67 KB
18
- CJS ⚡️ Build success in 100ms
13
+ ESM dist/index.js 147.97 KB
14
+ ESM dist/index.js.map 312.63 KB
15
+ ESM ⚡️ Build success in 92ms
16
+ CJS dist/index.cjs 151.01 KB
17
+ CJS dist/index.cjs.map 314.27 KB
18
+ CJS ⚡️ Build success in 93ms
19
19
  DTS Build start
20
- DTS ⚡️ Build success in 3333ms
21
- DTS dist/index.d.ts 54.89 KB
22
- DTS dist/index.d.cts 54.89 KB
20
+ DTS ⚡️ Build success in 3452ms
21
+ DTS dist/index.d.ts 61.79 KB
22
+ DTS dist/index.d.cts 61.79 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # @objectstack/core
2
2
 
3
+ ## 3.0.9
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [15e0df6]
8
+ - @objectstack/spec@3.0.9
9
+
3
10
  ## 3.0.8
4
11
 
5
12
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -35,9 +35,11 @@ __export(index_exports, {
35
35
  DependencyResolver: () => DependencyResolver,
36
36
  HotReloadManager: () => HotReloadManager,
37
37
  LiteKernel: () => LiteKernel,
38
+ NamespaceResolver: () => NamespaceResolver,
38
39
  ObjectKernel: () => ObjectKernel,
39
40
  ObjectKernelBase: () => ObjectKernelBase,
40
41
  ObjectLogger: () => ObjectLogger,
42
+ PackageManager: () => PackageManager,
41
43
  PluginConfigValidator: () => PluginConfigValidator,
42
44
  PluginHealthMonitor: () => PluginHealthMonitor,
43
45
  PluginLoader: () => PluginLoader,
@@ -4499,6 +4501,398 @@ var DependencyResolver = class {
4499
4501
  }
4500
4502
  }
4501
4503
  };
4504
+
4505
+ // src/namespace-resolver.ts
4506
+ var NamespaceResolver = class {
4507
+ constructor(logger) {
4508
+ this.registry = /* @__PURE__ */ new Map();
4509
+ this.logger = logger.child({ component: "NamespaceResolver" });
4510
+ }
4511
+ /**
4512
+ * Register namespaces owned by a package.
4513
+ */
4514
+ register(packageId, namespaces) {
4515
+ const now = (/* @__PURE__ */ new Date()).toISOString();
4516
+ for (const ns of namespaces) {
4517
+ if (this.registry.has(ns)) {
4518
+ const existing = this.registry.get(ns);
4519
+ if (existing.packageId !== packageId) {
4520
+ this.logger.warn("Overwriting namespace entry", { namespace: ns, existing: existing.packageId, incoming: packageId });
4521
+ }
4522
+ }
4523
+ this.registry.set(ns, { namespace: ns, packageId, registeredAt: now });
4524
+ this.logger.debug("Namespace registered", { namespace: ns, packageId });
4525
+ }
4526
+ }
4527
+ /**
4528
+ * Unregister all namespaces belonging to a package.
4529
+ */
4530
+ unregister(packageId) {
4531
+ const removed = [];
4532
+ for (const [ns, entry] of this.registry) {
4533
+ if (entry.packageId === packageId) {
4534
+ this.registry.delete(ns);
4535
+ removed.push(ns);
4536
+ }
4537
+ }
4538
+ this.logger.debug("Namespaces unregistered", { packageId, count: removed.length });
4539
+ return removed;
4540
+ }
4541
+ /**
4542
+ * Check whether a set of namespaces is available for a given package.
4543
+ */
4544
+ checkAvailability(packageId, namespaces) {
4545
+ const conflicts = [];
4546
+ const suggestions = {};
4547
+ for (const ns of namespaces) {
4548
+ const existing = this.registry.get(ns);
4549
+ if (existing && existing.packageId !== packageId) {
4550
+ const suggestion = this.suggestAlternative(ns, packageId);
4551
+ conflicts.push({
4552
+ namespace: ns,
4553
+ existingPackageId: existing.packageId,
4554
+ incomingPackageId: packageId,
4555
+ suggestion
4556
+ });
4557
+ suggestions[ns] = suggestion;
4558
+ }
4559
+ }
4560
+ return {
4561
+ available: conflicts.length === 0,
4562
+ conflicts,
4563
+ suggestions
4564
+ };
4565
+ }
4566
+ /**
4567
+ * Extract namespace strings from a package's metadata definition.
4568
+ */
4569
+ extractNamespaces(config) {
4570
+ const namespaces = [];
4571
+ const categories = [
4572
+ "objects",
4573
+ "views",
4574
+ "pages",
4575
+ "flows",
4576
+ "workflows",
4577
+ "apps",
4578
+ "dashboards",
4579
+ "reports",
4580
+ "actions",
4581
+ "agents"
4582
+ ];
4583
+ for (const category of categories) {
4584
+ const items = config[category];
4585
+ if (Array.isArray(items)) {
4586
+ for (const item of items) {
4587
+ const name = item?.name;
4588
+ if (typeof name === "string") {
4589
+ namespaces.push(`${category}.${name}`);
4590
+ }
4591
+ }
4592
+ } else if (items && typeof items === "object") {
4593
+ for (const key of Object.keys(items)) {
4594
+ namespaces.push(`${category}.${key}`);
4595
+ }
4596
+ }
4597
+ }
4598
+ return namespaces;
4599
+ }
4600
+ /**
4601
+ * Get all registered entries.
4602
+ */
4603
+ getRegistry() {
4604
+ return this.registry;
4605
+ }
4606
+ /**
4607
+ * Get all namespaces belonging to a specific package.
4608
+ */
4609
+ getPackageNamespaces(packageId) {
4610
+ const namespaces = [];
4611
+ for (const [ns, entry] of this.registry) {
4612
+ if (entry.packageId === packageId) {
4613
+ namespaces.push(ns);
4614
+ }
4615
+ }
4616
+ return namespaces;
4617
+ }
4618
+ /**
4619
+ * Generate a prefixed alternative namespace to avoid conflicts.
4620
+ */
4621
+ suggestAlternative(ns, packageId) {
4622
+ const shortName = packageId.replace(/^@[^/]+\//, "").replace(/^plugin-/, "").replace(/-/g, "_");
4623
+ const parts = ns.split(".");
4624
+ if (parts.length >= 2) {
4625
+ return `${parts[0]}.${shortName}_${parts.slice(1).join(".")}`;
4626
+ }
4627
+ return `${shortName}_${ns}`;
4628
+ }
4629
+ };
4630
+
4631
+ // src/package-manager.ts
4632
+ var PackageManager = class {
4633
+ constructor(logger, options = {}) {
4634
+ this.packages = /* @__PURE__ */ new Map();
4635
+ this.snapshots = /* @__PURE__ */ new Map();
4636
+ this.logger = logger.child({ component: "PackageManager" });
4637
+ this.dependencyResolver = new DependencyResolver(logger);
4638
+ this.namespaceResolver = new NamespaceResolver(logger);
4639
+ this.platformVersion = options.platformVersion || "3.0.0";
4640
+ }
4641
+ /**
4642
+ * Install a package with full dependency resolution and namespace checking.
4643
+ */
4644
+ async install(packageId, version, manifest) {
4645
+ this.logger.info("Installing package", { packageId, version });
4646
+ if (this.packages.has(packageId)) {
4647
+ const existing = this.packages.get(packageId);
4648
+ if (existing.status === "installed") {
4649
+ return {
4650
+ success: false,
4651
+ packageId,
4652
+ version,
4653
+ installedDependencies: [],
4654
+ namespaceConflicts: [],
4655
+ errorMessage: `Package ${packageId}@${existing.version} is already installed. Use upgrade instead.`
4656
+ };
4657
+ }
4658
+ }
4659
+ const engine = manifest.engine?.objectstack;
4660
+ if (engine) {
4661
+ const platformSemver = SemanticVersionManager.parse(this.platformVersion);
4662
+ if (!SemanticVersionManager.satisfies(platformSemver, engine)) {
4663
+ return {
4664
+ success: false,
4665
+ packageId,
4666
+ version,
4667
+ installedDependencies: [],
4668
+ namespaceConflicts: [],
4669
+ errorMessage: `Package requires platform ${engine}, but current platform is v${this.platformVersion}`
4670
+ };
4671
+ }
4672
+ }
4673
+ const namespaces = this.namespaceResolver.extractNamespaces(manifest);
4674
+ const nsCheck = this.namespaceResolver.checkAvailability(packageId, namespaces);
4675
+ if (!nsCheck.available) {
4676
+ return {
4677
+ success: false,
4678
+ packageId,
4679
+ version,
4680
+ installedDependencies: [],
4681
+ namespaceConflicts: nsCheck.conflicts.map((c) => ({
4682
+ namespace: c.namespace,
4683
+ existingPackageId: c.existingPackageId
4684
+ })),
4685
+ errorMessage: `Namespace conflicts detected: ${nsCheck.conflicts.map((c) => c.namespace).join(", ")}`
4686
+ };
4687
+ }
4688
+ const deps = manifest.dependencies;
4689
+ const depNames = deps ? Object.keys(deps) : [];
4690
+ const missingDeps = depNames.filter((d) => !this.packages.has(d));
4691
+ if (missingDeps.length > 0) {
4692
+ return {
4693
+ success: false,
4694
+ packageId,
4695
+ version,
4696
+ installedDependencies: [],
4697
+ namespaceConflicts: [],
4698
+ errorMessage: `Missing dependencies: ${missingDeps.join(", ")}`
4699
+ };
4700
+ }
4701
+ this.packages.set(packageId, {
4702
+ packageId,
4703
+ version,
4704
+ manifest,
4705
+ installedAt: (/* @__PURE__ */ new Date()).toISOString(),
4706
+ status: "installed",
4707
+ namespaces,
4708
+ dependencies: depNames
4709
+ });
4710
+ this.namespaceResolver.register(packageId, namespaces);
4711
+ this.logger.info("Package installed", { packageId, version, namespaces: namespaces.length });
4712
+ return {
4713
+ success: true,
4714
+ packageId,
4715
+ version,
4716
+ installedDependencies: depNames,
4717
+ namespaceConflicts: []
4718
+ };
4719
+ }
4720
+ /**
4721
+ * Uninstall a package, checking for dependents first.
4722
+ */
4723
+ async uninstall(packageId) {
4724
+ const pkg = this.packages.get(packageId);
4725
+ if (!pkg) {
4726
+ return { success: false, errorMessage: `Package ${packageId} is not installed` };
4727
+ }
4728
+ const dependents = [];
4729
+ for (const [id, record] of this.packages) {
4730
+ if (id !== packageId && record.dependencies.includes(packageId)) {
4731
+ dependents.push(id);
4732
+ }
4733
+ }
4734
+ if (dependents.length > 0) {
4735
+ return {
4736
+ success: false,
4737
+ errorMessage: `Cannot uninstall ${packageId}: depended upon by ${dependents.join(", ")}`
4738
+ };
4739
+ }
4740
+ this.namespaceResolver.unregister(packageId);
4741
+ this.packages.delete(packageId);
4742
+ this.snapshots.delete(packageId);
4743
+ this.logger.info("Package uninstalled", { packageId });
4744
+ return { success: true };
4745
+ }
4746
+ /**
4747
+ * Upgrade a package: snapshot → update → register.
4748
+ */
4749
+ async upgrade(packageId, newVersion, newManifest) {
4750
+ const existing = this.packages.get(packageId);
4751
+ if (!existing) {
4752
+ return {
4753
+ success: false,
4754
+ packageId,
4755
+ fromVersion: "",
4756
+ toVersion: newVersion,
4757
+ snapshot: { packageId, previousVersion: "", previousManifest: {}, previousNamespaces: [], installedAt: "", createdAt: (/* @__PURE__ */ new Date()).toISOString() },
4758
+ errorMessage: `Package ${packageId} is not installed`
4759
+ };
4760
+ }
4761
+ const snapshot = {
4762
+ packageId,
4763
+ previousVersion: existing.version,
4764
+ previousManifest: existing.manifest,
4765
+ previousNamespaces: [...existing.namespaces],
4766
+ installedAt: existing.installedAt,
4767
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
4768
+ };
4769
+ this.snapshots.set(packageId, snapshot);
4770
+ const engine = newManifest.engine?.objectstack;
4771
+ if (engine) {
4772
+ const platformSemver = SemanticVersionManager.parse(this.platformVersion);
4773
+ if (!SemanticVersionManager.satisfies(platformSemver, engine)) {
4774
+ return {
4775
+ success: false,
4776
+ packageId,
4777
+ fromVersion: existing.version,
4778
+ toVersion: newVersion,
4779
+ snapshot,
4780
+ errorMessage: `New version requires platform ${engine}, current is v${this.platformVersion}`
4781
+ };
4782
+ }
4783
+ }
4784
+ const newNamespaces = this.namespaceResolver.extractNamespaces(newManifest);
4785
+ this.namespaceResolver.unregister(packageId);
4786
+ const nsCheck = this.namespaceResolver.checkAvailability(packageId, newNamespaces);
4787
+ if (!nsCheck.available) {
4788
+ this.namespaceResolver.register(packageId, existing.namespaces);
4789
+ return {
4790
+ success: false,
4791
+ packageId,
4792
+ fromVersion: existing.version,
4793
+ toVersion: newVersion,
4794
+ snapshot,
4795
+ errorMessage: `Namespace conflicts in new version: ${nsCheck.conflicts.map((c) => c.namespace).join(", ")}`
4796
+ };
4797
+ }
4798
+ this.namespaceResolver.register(packageId, newNamespaces);
4799
+ const deps = newManifest.dependencies;
4800
+ this.packages.set(packageId, {
4801
+ packageId,
4802
+ version: newVersion,
4803
+ manifest: newManifest,
4804
+ installedAt: existing.installedAt,
4805
+ status: "installed",
4806
+ namespaces: newNamespaces,
4807
+ dependencies: deps ? Object.keys(deps) : []
4808
+ });
4809
+ this.logger.info("Package upgraded", { packageId, from: existing.version, to: newVersion });
4810
+ return {
4811
+ success: true,
4812
+ packageId,
4813
+ fromVersion: existing.version,
4814
+ toVersion: newVersion,
4815
+ snapshot
4816
+ };
4817
+ }
4818
+ /**
4819
+ * Rollback a package to its pre-upgrade snapshot.
4820
+ */
4821
+ async rollback(packageId) {
4822
+ const snapshot = this.snapshots.get(packageId);
4823
+ if (!snapshot) {
4824
+ return {
4825
+ success: false,
4826
+ packageId,
4827
+ restoredVersion: "",
4828
+ errorMessage: `No upgrade snapshot found for ${packageId}`
4829
+ };
4830
+ }
4831
+ this.namespaceResolver.unregister(packageId);
4832
+ this.namespaceResolver.register(packageId, snapshot.previousNamespaces);
4833
+ const deps = snapshot.previousManifest.dependencies;
4834
+ this.packages.set(packageId, {
4835
+ packageId,
4836
+ version: snapshot.previousVersion,
4837
+ manifest: snapshot.previousManifest,
4838
+ installedAt: snapshot.installedAt,
4839
+ status: "installed",
4840
+ namespaces: snapshot.previousNamespaces,
4841
+ dependencies: deps ? Object.keys(deps) : []
4842
+ });
4843
+ this.snapshots.delete(packageId);
4844
+ this.logger.info("Package rolled back", { packageId, to: snapshot.previousVersion });
4845
+ return {
4846
+ success: true,
4847
+ packageId,
4848
+ restoredVersion: snapshot.previousVersion
4849
+ };
4850
+ }
4851
+ /**
4852
+ * Get an installed package record.
4853
+ */
4854
+ getPackage(packageId) {
4855
+ return this.packages.get(packageId);
4856
+ }
4857
+ /**
4858
+ * List all installed packages.
4859
+ */
4860
+ listPackages() {
4861
+ return Array.from(this.packages.values());
4862
+ }
4863
+ /**
4864
+ * Resolve dependencies for a set of packages.
4865
+ */
4866
+ resolveDependencies(packages) {
4867
+ return this.dependencyResolver.resolve(packages);
4868
+ }
4869
+ /**
4870
+ * Check namespace availability for a package's metadata.
4871
+ */
4872
+ checkNamespaces(packageId, config) {
4873
+ const namespaces = this.namespaceResolver.extractNamespaces(config);
4874
+ const result = this.namespaceResolver.checkAvailability(packageId, namespaces);
4875
+ return {
4876
+ available: result.available,
4877
+ conflicts: result.conflicts.map((c) => ({
4878
+ namespace: c.namespace,
4879
+ existingPackageId: c.existingPackageId
4880
+ }))
4881
+ };
4882
+ }
4883
+ /**
4884
+ * Get the namespace resolver instance.
4885
+ */
4886
+ getNamespaceResolver() {
4887
+ return this.namespaceResolver;
4888
+ }
4889
+ /**
4890
+ * Get a snapshot for a given package (if available).
4891
+ */
4892
+ getSnapshot(packageId) {
4893
+ return this.snapshots.get(packageId);
4894
+ }
4895
+ };
4502
4896
  // Annotate the CommonJS export names for ESM import in node:
4503
4897
  0 && (module.exports = {
4504
4898
  ApiRegistry,
@@ -4506,9 +4900,11 @@ var DependencyResolver = class {
4506
4900
  DependencyResolver,
4507
4901
  HotReloadManager,
4508
4902
  LiteKernel,
4903
+ NamespaceResolver,
4509
4904
  ObjectKernel,
4510
4905
  ObjectKernelBase,
4511
4906
  ObjectLogger,
4907
+ PackageManager,
4512
4908
  PluginConfigValidator,
4513
4909
  PluginHealthMonitor,
4514
4910
  PluginLoader,