@jointhedots/gear 1.2.2 → 1.2.3

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.
Files changed (32) hide show
  1. package/esm/builder/build-app-bundle.d.ts +1 -0
  2. package/esm/builder/build-app-bundle.js +9 -5
  3. package/esm/builder/build-app-host.js +20 -18
  4. package/esm/builder/build-application.d.ts +4 -0
  5. package/esm/builder/build-application.js +52 -72
  6. package/esm/builder/build-library.d.ts +1 -0
  7. package/esm/builder/build-library.js +12 -8
  8. package/esm/builder/build-target.d.ts +13 -4
  9. package/esm/builder/build-target.js +20 -11
  10. package/esm/builder/helpers/emit-artifact.d.ts +13 -0
  11. package/esm/builder/helpers/emit-artifact.js +40 -0
  12. package/esm/builder/helpers/emit-bundle-manifest.d.ts +12 -2
  13. package/esm/builder/helpers/emit-bundle-manifest.js +37 -14
  14. package/esm/builder/helpers/emit-esmodules.d.ts +2 -2
  15. package/esm/builder/helpers/emit-esmodules.js +17 -17
  16. package/esm/builder/helpers/emit-package-manifest.js +1 -1
  17. package/esm/builder/helpers/emit-typescript-definition.js +1 -1
  18. package/esm/commands/install.js +1 -1
  19. package/esm/commands/make.d.ts +1 -0
  20. package/esm/commands/make.js +10 -2
  21. package/esm/commands/serve.js +8 -9
  22. package/esm/workspace/helpers/create-manifests.js +3 -3
  23. package/esm/workspace/helpers/discover-workspace.d.ts +2 -2
  24. package/esm/workspace/helpers/discover-workspace.js +19 -29
  25. package/esm/workspace/helpers/lockfile.d.ts +3 -3
  26. package/esm/workspace/helpers/lockfile.js +13 -13
  27. package/esm/workspace/helpers/logger.d.ts +1 -1
  28. package/esm/workspace/helpers/logger.js +1 -1
  29. package/esm/workspace/packagers/packager-standard.js +3 -3
  30. package/esm/workspace/workspace.d.ts +11 -7
  31. package/esm/workspace/workspace.js +26 -14
  32. package/package.json +74 -73
@@ -8,6 +8,7 @@ export type BuildBundleOptions = {
8
8
  devmode: boolean;
9
9
  watch: boolean;
10
10
  clean: boolean;
11
+ artifactDir?: string;
11
12
  };
12
13
  export declare enum PathStatus {
13
14
  Unknown,
@@ -8,6 +8,7 @@ import { PathQualifier } from "./helpers/path-helpers.js";
8
8
  import { create_export_map } from "../workspace/helpers/create-manifests.js";
9
9
  import { DependencyDeduplicationPlugin, collectLibraryGraph } from "./helpers/emit-esmodules.js";
10
10
  import { BundleManifestTask } from "./helpers/emit-bundle-manifest.js";
11
+ import { ArtifactNpmTask } from "./helpers/emit-artifact.js";
11
12
  export var PathStatus;
12
13
  (function (PathStatus) {
13
14
  PathStatus[PathStatus["Unknown"] = undefined] = "Unknown";
@@ -18,7 +19,7 @@ export var PathStatus;
18
19
  })(PathStatus || (PathStatus = {}));
19
20
  export function create_bundle_target(opts) {
20
21
  const { bundle, library: lib, storage } = opts;
21
- const target = new BuildTarget(bundle.id, storage, lib.workspace, opts.devmode == true, opts.watch == true, opts.clean == true);
22
+ const target = new BuildTarget(bundle.id, storage, lib, opts.devmode == true, opts.watch == true, opts.clean == true);
22
23
  // Prepare esm setup
23
24
  target.esmodules.set_root(lib.path);
24
25
  // Add bundle package.json
@@ -26,7 +27,7 @@ export function create_bundle_target(opts) {
26
27
  // Add bundle types.d.ts
27
28
  target.tasks.push(new TypescriptDefinitionTask(target, lib));
28
29
  // Add bundle exporteds
29
- const entries = create_export_map(lib, lib.bundle);
30
+ const entries = create_export_map(lib, lib.master);
30
31
  for (const exp_id in entries) {
31
32
  const exp = entries[exp_id];
32
33
  target.esmodules.add_entry(exp.basename, exp.source);
@@ -34,11 +35,11 @@ export function create_bundle_target(opts) {
34
35
  // Add bundle content
35
36
  if (bundle) {
36
37
  // Add bundle manifest
37
- target.tasks.push(new BundleManifestTask(target, lib.bundle));
38
+ target.tasks.push(new BundleManifestTask(target, bundle));
38
39
  // Add bundle components
39
40
  for (const [path, desc] of bundle.components) {
40
41
  const baseDir = Path.dirname(path);
41
- target.add_component(desc, baseDir, lib);
42
+ target.add_component(desc, baseDir, bundle);
42
43
  }
43
44
  }
44
45
  // Add declarations descriptors
@@ -158,7 +159,7 @@ export function create_bundle_target(opts) {
158
159
  return {
159
160
  contents,
160
161
  loader: "js",
161
- resolveDir: target.workspace.path,
162
+ resolveDir: lib.path,
162
163
  };
163
164
  });
164
165
  // Handle imports from within the proxy modules - these should be truly external
@@ -187,6 +188,9 @@ export async function build_app_composable_bundle(opts) {
187
188
  watch: opts.watch,
188
189
  clean: opts.clean,
189
190
  });
191
+ if (opts.artifactDir) {
192
+ target.finalTasks.push(new ArtifactNpmTask(target, opts.artifactDir));
193
+ }
190
194
  target.log.info(`Build bundle: ${target.name}`);
191
195
  await target.build();
192
196
  return target;
@@ -7,6 +7,7 @@ import { PWAPackageTask, WebviewTask } from "./build-application.js";
7
7
  import { makeComponentPublication } from "../workspace/component.js";
8
8
  import { topologicalSort } from "../utils/graph-ordering.js";
9
9
  import { BuildTask } from "./helpers/task.js";
10
+ import { ArtifactZipTask } from "./helpers/emit-artifact.js";
10
11
  export class ShelveManifestTask extends BuildTask {
11
12
  target;
12
13
  bundles;
@@ -45,11 +46,9 @@ export class ShelveManifestTask extends BuildTask {
45
46
  }
46
47
  function create_application_composable_target(opts) {
47
48
  const { app, bundles, version } = opts;
48
- const { type, name, webviews, modules, assets, components } = app.descriptor;
49
- const lib = app.library;
50
- const bundle = lib.bundle;
51
- const ws = lib.workspace;
52
- const target = new BuildTarget(name, opts.storage, ws, opts.devmode == true, opts.watch == true, opts.clean == true);
49
+ const { name, webviews, modules, components } = app.descriptor;
50
+ const { library: lib } = app;
51
+ const target = new BuildTarget(name, opts.storage, lib, opts.devmode == true, opts.watch == true, opts.clean == true, opts.onNotification);
53
52
  // Prepare esm setup
54
53
  target.esmodules.set_root(lib.path);
55
54
  // Generate hotreload assets
@@ -70,7 +69,7 @@ function create_application_composable_target(opts) {
70
69
  const entry_name = lib.make_file_id("webview", name);
71
70
  const webview = {
72
71
  ...webviews[name],
73
- entry: `./${bundle.id}/${entry_name}.js`,
72
+ entry: `./${lib.master.id}/${entry_name}.js`,
74
73
  favicon: favicon ? app.library.resolve_entry_path(favicon, Path.dirname(app.baseDir)) : null,
75
74
  };
76
75
  target.tasks.push(new WebviewTask(target, name, title || name, webview, html_injects));
@@ -82,7 +81,7 @@ function create_application_composable_target(opts) {
82
81
  for (const name in modules) {
83
82
  if (name.endsWith(".js")) {
84
83
  const entry_name = lib.make_file_id("module", name.slice(0, -3));
85
- target.esmodules.add_entry_typescript(`export * from "./${bundle.id}/${entry_name}.js"`, name.slice(0, -3));
84
+ target.esmodules.add_entry_typescript(`export * from "./${lib.master.id}/${entry_name}.js"`, name.slice(0, -3));
86
85
  if (opts.devserver) {
87
86
  target.log.info(`+ 🔌 module: ${name} : ${opts.devserver}/${name}`);
88
87
  }
@@ -107,14 +106,14 @@ function create_application_composable_target(opts) {
107
106
  }
108
107
  }*/
109
108
  // Add workspace assets
110
- for (const lib of ws.libraries) {
111
- for (const [path, desc] of lib.declarations) {
109
+ for (const slib of lib.workspace.libraries) {
110
+ for (const [path, desc] of slib.declarations) {
112
111
  if (!matchComponentSelection(components, desc.selectors))
113
112
  continue;
114
113
  if (desc.assets) {
115
114
  const baseDir = Path.dirname(path);
116
115
  for (const entry of desc.assets) {
117
- target.assets.add_entry(entry, baseDir, lib);
116
+ target.assets.add_entry(entry, baseDir, slib);
118
117
  }
119
118
  }
120
119
  }
@@ -123,12 +122,11 @@ function create_application_composable_target(opts) {
123
122
  }
124
123
  export async function build_app_composable_host(opts) {
125
124
  const { app, storage } = opts;
126
- const ws = app.library.workspace;
125
+ const { library: lib } = app;
127
126
  opts.storage.clean();
128
- const shelveBundles = new BundleSelector(ws);
129
- const { bundle } = app.library;
130
- if (bundle)
131
- shelveBundles.add(bundle);
127
+ const shelveBundles = new BundleSelector(lib.workspace);
128
+ if (lib.master)
129
+ shelveBundles.add(lib.master);
132
130
  const shelvePendings = [];
133
131
  for (const bundle of shelveBundles) {
134
132
  shelvePendings.push(build_app_composable_bundle({
@@ -141,7 +139,7 @@ export async function build_app_composable_host(opts) {
141
139
  }));
142
140
  }
143
141
  if (shelveBundles.missing.length > 0) {
144
- ws.log.warn(`Missing bundle dependencies: ${shelveBundles.missing.join(", ")}`);
142
+ lib.log.warn(`Missing bundle dependencies: ${shelveBundles.missing.join(", ")}`);
145
143
  }
146
144
  const target = create_application_composable_target({
147
145
  app,
@@ -152,7 +150,11 @@ export async function build_app_composable_host(opts) {
152
150
  devserver: opts.devserver,
153
151
  watch: opts.devserver ? true : opts.watch,
154
152
  clean: opts.clean,
153
+ onNotification: opts.onNotification,
155
154
  });
155
+ if (opts.artifactDir) {
156
+ target.finalTasks.push(new ArtifactZipTask(target, opts.artifactDir, target.name));
157
+ }
156
158
  target.log.info(`Build app: ${target.name}`);
157
159
  return target.build();
158
160
  }
@@ -187,8 +189,8 @@ export class BundleSelector {
187
189
  if (bun.source) {
188
190
  for (const depId in bun.source.descriptor?.dependencies) {
189
191
  const lib = this.workspace.get_library(depId);
190
- if (lib?.bundle)
191
- this.add(lib.bundle);
192
+ if (lib?.master)
193
+ this.add(lib.master);
192
194
  }
193
195
  }
194
196
  return this;
@@ -4,6 +4,7 @@ import { StorageFiles } from "../workspace/storage.ts";
4
4
  import { BuildTarget } from "./build-target.ts";
5
5
  import type { WebAppManifest } from "web-app-manifest";
6
6
  import { BuildTask } from "./helpers/task.ts";
7
+ import type { BuildNotification } from "./build-target.ts";
7
8
  export type BuildApplicationOptions = {
8
9
  app: AppEntry;
9
10
  storage: StorageFiles;
@@ -12,6 +13,8 @@ export type BuildApplicationOptions = {
12
13
  watch?: boolean;
13
14
  clean?: boolean;
14
15
  devserver?: string;
16
+ artifactDir?: string;
17
+ onNotification?: (event: BuildNotification) => void;
15
18
  };
16
19
  export declare function create_application_monolith_target(opts: {
17
20
  app: AppEntry;
@@ -21,6 +24,7 @@ export declare function create_application_monolith_target(opts: {
21
24
  devserver?: string;
22
25
  watch: boolean;
23
26
  clean: boolean;
27
+ onNotification?: BuildApplicationOptions["onNotification"];
24
28
  }): BuildTarget;
25
29
  export declare function build_app_monolith(opts: BuildApplicationOptions): Promise<void>;
26
30
  export declare function build_application(opts: BuildApplicationOptions): Promise<void>;
@@ -1,41 +1,20 @@
1
1
  import Path from "node:path";
2
2
  import Sharp from "sharp";
3
3
  import MIME from "mime";
4
- import { Library, matchComponentSelection } from "../workspace/workspace.js";
4
+ import { Bundle, matchComponentSelection } from "../workspace/workspace.js";
5
5
  import { StorageFiles } from "../workspace/storage.js";
6
6
  import { BuildTarget } from "./build-target.js";
7
7
  import { build_app_composable_host } from "./build-app-host.js";
8
8
  import { DependencyDeduplicationPlugin } from "./helpers/emit-esmodules.js";
9
- import { BundleManifestTask } from "./helpers/emit-bundle-manifest.js";
9
+ import { ApplicationManifestTask } from "./helpers/emit-bundle-manifest.js";
10
10
  import { BuildTask } from "./helpers/task.js";
11
- function collect_app_libraries(app) {
12
- const libs = [app.library];
13
- function collect_library_deps(lib) {
14
- const ws = lib.workspace;
15
- const deps = {
16
- ...lib.descriptor.dependencies,
17
- ...lib.descriptor.peerDependencies,
18
- ...lib.descriptor.optionalDependencies,
19
- };
20
- for (const depId in deps) {
21
- const lib = ws.get_library(depId);
22
- if (lib && !libs.includes(lib)) {
23
- libs.push(lib);
24
- }
25
- }
26
- }
27
- for (let i = 0; i < libs.length; i++) {
28
- collect_library_deps(libs[i]);
29
- }
30
- return libs;
31
- }
11
+ import { ArtifactZipTask } from "./helpers/emit-artifact.js";
32
12
  export function create_application_monolith_target(opts) {
33
13
  const { app, version } = opts;
34
14
  const { type, name, webviews, modules, assets, components } = app.descriptor;
35
- const lib = app.library;
36
- const target = new BuildTarget(name, opts.storage, lib.workspace, opts.devmode == true, opts.watch == true, opts.clean == true);
37
- const libs = collect_app_libraries(app);
38
- target.log.info(`+ 🧭 app-library-graph: ${libs.map(lib => `${lib.name}@${lib.descriptor.version}`).join(", ")}`);
15
+ const { library: lib } = app;
16
+ const target = new BuildTarget(name, opts.storage, lib, opts.devmode == true, opts.watch == true, opts.clean == true, opts.onNotification);
17
+ target.log.info(`+ 📚 shelve: ${lib.shelve.map(b => b.id).join(", ")}`);
39
18
  // Prepare esm setup
40
19
  target.esmodules.set_root(lib.path);
41
20
  // Generate hotreload assets
@@ -62,12 +41,12 @@ export function create_application_monolith_target(opts) {
62
41
  for (const name in webviews) {
63
42
  const { title, favicon, entry } = webviews[name];
64
43
  const entry_name = lib.make_file_id("webview", name);
65
- const entry_path = app.library.resolve_entry_path(entry, app.baseDir);
44
+ const entry_path = lib.resolve_entry_path(entry, app.baseDir);
66
45
  target.esmodules.add_entry(entry_name, entry_path);
67
46
  const webview = {
68
47
  ...webviews[name],
69
48
  entry: `./${entry_name}.js`,
70
- favicon: favicon ? app.library.resolve_entry_path(favicon, app.baseDir) : null,
49
+ favicon: favicon ? lib.resolve_entry_path(favicon, app.baseDir) : null,
71
50
  };
72
51
  target.tasks.push(new WebviewTask(target, name, title || name, webview, html_injects));
73
52
  if (opts.devserver) {
@@ -76,7 +55,7 @@ export function create_application_monolith_target(opts) {
76
55
  }
77
56
  // Add application modules
78
57
  for (const name in modules) {
79
- const entry_path = app.library.resolve_entry_path(modules[name], app.baseDir);
58
+ const entry_path = lib.resolve_entry_path(modules[name], app.baseDir);
80
59
  if (!entry_path) {
81
60
  target.log.error(`Invalid module '${name}' path at ${entry_path}`);
82
61
  }
@@ -94,65 +73,62 @@ export function create_application_monolith_target(opts) {
94
73
  // Add application static assets
95
74
  if (Array.isArray(assets)) {
96
75
  for (const asset of assets) {
97
- target.assets.add_entry(asset, app.baseDir, app.library);
76
+ target.assets.add_entry(asset, app.baseDir, lib);
98
77
  }
99
78
  }
100
- // Add bundle content
101
- const { bundle } = lib;
102
- if (bundle) {
103
- // Add bundle manifest
104
- target.tasks.push(new BundleManifestTask(target, bundle));
105
- // Add workspace components
106
- const added_components = new Map();
107
- for (const lib of libs) {
108
- if (lib.bundle) {
109
- for (const [path, desc] of lib.bundle.components) {
110
- if (!matchComponentSelection(components, desc.selectors))
111
- continue;
112
- const cid = desc.$id;
113
- const added = added_components.get(cid);
114
- if (added) {
115
- target.log.error({
116
- id: "duplicate-component-skip",
117
- text: `skip duplicate component '${cid}'`,
118
- notes: [
119
- {
120
- title: "kept",
121
- text: `${added.lib.name}@${added.lib.descriptor.version}`,
122
- location: added.path,
123
- },
124
- {
125
- title: "skipped",
126
- text: `${lib.name}@${lib.descriptor.version}`,
127
- location: path,
128
- },
129
- ],
130
- });
131
- continue;
132
- }
133
- const baseDir = Path.dirname(path);
134
- target.add_component(desc, baseDir, lib);
135
- added_components.set(cid, { lib, path });
136
- }
79
+ // Add workspace components
80
+ const added_components = new Map();
81
+ for (const bundle of lib.shelve) {
82
+ for (const [path, desc] of bundle.components) {
83
+ if (!matchComponentSelection(components, desc.selectors))
84
+ continue;
85
+ const cid = desc.$id;
86
+ const added = added_components.get(cid);
87
+ if (added) {
88
+ target.log.error({
89
+ id: "duplicate-component-skip",
90
+ text: `skip duplicate component '${cid}'`,
91
+ notes: [
92
+ {
93
+ title: "kept",
94
+ text: `${added.bundle.id}`,
95
+ location: added.path,
96
+ },
97
+ {
98
+ title: "skipped",
99
+ text: `${bundle.id}`,
100
+ location: path,
101
+ },
102
+ ],
103
+ });
104
+ continue;
137
105
  }
106
+ const baseDir = Path.dirname(path);
107
+ target.add_component(desc, baseDir, bundle);
108
+ added_components.set(cid, { bundle, path });
138
109
  }
139
110
  }
111
+ // Add bundle manifest
112
+ target.tasks.push(new ApplicationManifestTask(target, app.descriptor));
140
113
  // Add workspace assets
141
- for (const lib of libs) {
142
- for (const [path, desc] of lib.declarations) {
114
+ for (const bundle of lib.shelve) {
115
+ if (!bundle.source)
116
+ continue;
117
+ for (const [path, desc] of bundle.source.declarations) {
143
118
  if (!matchComponentSelection(components, desc.selectors))
144
119
  continue;
145
120
  if (desc.assets) {
146
121
  const baseDir = Path.dirname(path);
147
122
  for (const entry of desc.assets) {
148
- target.assets.add_entry(entry, baseDir, lib);
123
+ target.assets.add_entry(entry, baseDir, bundle.source);
149
124
  }
150
125
  }
151
126
  }
152
127
  }
153
128
  // Register esbuild plugin for dependency deduplication (graph-based + singleton)
129
+ const bundleLibs = lib.shelve.map(b => b.source).filter(Boolean);
154
130
  const rootNodeModules = lib.search_directories[0] || Path.join(lib.path, 'node_modules');
155
- target.esmodules.plugins.push(DependencyDeduplicationPlugin(libs, rootNodeModules, target.log));
131
+ target.esmodules.plugins.push(DependencyDeduplicationPlugin(bundleLibs, rootNodeModules, target.log));
156
132
  return target;
157
133
  }
158
134
  export async function build_app_monolith(opts) {
@@ -166,7 +142,11 @@ export async function build_app_monolith(opts) {
166
142
  devserver: opts.devserver,
167
143
  watch: opts.devserver ? true : opts.watch,
168
144
  clean: opts.clean,
145
+ onNotification: opts.onNotification,
169
146
  });
147
+ if (opts.artifactDir) {
148
+ target.finalTasks.push(new ArtifactZipTask(target, opts.artifactDir, target.name));
149
+ }
170
150
  target.log.info(`Build app: ${target.name}`);
171
151
  return target.build();
172
152
  }
@@ -8,6 +8,7 @@ export type BuildLibraryOptions = {
8
8
  devmode: boolean;
9
9
  watch: boolean;
10
10
  clean: boolean;
11
+ artifactDir?: string;
11
12
  };
12
13
  export declare function create_library_target(opts: {
13
14
  library: Library;
@@ -8,13 +8,14 @@ import { PackageManifestTask } from "./helpers/emit-package-manifest.js";
8
8
  import { create_export_map } from "../workspace/helpers/create-manifests.js";
9
9
  import { BundleManifestTask } from "./helpers/emit-bundle-manifest.js";
10
10
  import { ComponentsDtsTask } from "./helpers/emit-components-dts.js";
11
+ import { ArtifactNpmTask } from "./helpers/emit-artifact.js";
11
12
  export function create_library_target(opts) {
12
13
  const lib = opts.library;
13
- const target = new BuildTarget(lib.name, opts.storage, lib.workspace, opts.devmode == true, opts.watch == true, opts.clean == true);
14
+ const target = new BuildTarget(lib.name, opts.storage, lib, opts.devmode == true, opts.watch == true, opts.clean == true);
14
15
  // Prepare esm setup
15
16
  target.esmodules.set_root(lib.path);
16
17
  // Add bundle exporteds
17
- const entries = create_export_map(lib, lib.bundle);
18
+ const entries = create_export_map(lib, lib.master);
18
19
  for (const exp_id in entries) {
19
20
  const exp = entries[exp_id];
20
21
  target.esmodules.add_entry(exp.basename, exp.source);
@@ -23,16 +24,16 @@ export function create_library_target(opts) {
23
24
  target.tasks.push(new TypescriptDefinitionTask(target, lib));
24
25
  // Add library package.json
25
26
  target.tasks.push(new PackageManifestTask(target, lib, opts.version));
26
- target.tasks.push(new ComponentsDtsTask(target, lib.bundle));
27
+ target.tasks.push(new ComponentsDtsTask(target, lib.master));
27
28
  // Add bundle content
28
- const { bundle } = lib;
29
- if (bundle) {
29
+ const { master } = lib;
30
+ if (master) {
30
31
  // Add bundle catalog
31
- target.tasks.push(new BundleManifestTask(target, bundle));
32
+ target.tasks.push(new BundleManifestTask(target, master));
32
33
  // Add library components
33
- for (const [path, desc] of bundle.components) {
34
+ for (const [path, desc] of master.components) {
34
35
  const baseDir = Path.dirname(path);
35
- target.add_component(desc, baseDir, lib);
36
+ target.add_component(desc, baseDir, master);
36
37
  }
37
38
  }
38
39
  // Add declarations descriptors
@@ -70,6 +71,9 @@ export async function build_library(opts, packageDir) {
70
71
  watch: opts.watch,
71
72
  clean: opts.clean,
72
73
  });
74
+ if (opts.artifactDir) {
75
+ target.finalTasks.push(new ArtifactNpmTask(target, opts.artifactDir));
76
+ }
73
77
  target.log.info(`Build library: ${target.name}`);
74
78
  await target.build();
75
79
  if (!target.watch && packageDir) {
@@ -1,27 +1,36 @@
1
1
  import { type ComponentManifest } from "../workspace/component.ts";
2
- import { Library, Workspace } from "../workspace/workspace.ts";
2
+ import { Bundle, Library } from "../workspace/workspace.ts";
3
3
  import type { Log } from "../workspace/helpers/logger.ts";
4
4
  import { ESModulesTask } from "./helpers/emit-esmodules.ts";
5
5
  import { type IStorageTransaction, type IStorageZone } from "../workspace/storage.ts";
6
6
  import { AssetsTask } from "./helpers/emit-static-assets.ts";
7
7
  import type { BuildTask } from "./helpers/task.ts";
8
+ export type BuildNotification = {
9
+ target?: string;
10
+ task?: string;
11
+ } & ({
12
+ type: "build-complete";
13
+ elapsed: number;
14
+ });
8
15
  export declare class BuildTarget {
9
16
  readonly name: string;
10
17
  readonly storage: IStorageZone;
11
- readonly workspace: Workspace;
18
+ readonly library: Library;
12
19
  readonly devmode: boolean;
13
20
  readonly watch: boolean;
14
21
  readonly clean: boolean;
22
+ readonly onNotification?: (event: BuildNotification) => void;
15
23
  components: Map<string, ComponentManifest>;
16
24
  esmodules: ESModulesTask;
17
25
  assets: AssetsTask;
18
26
  tasks: BuildTask[];
27
+ finalTasks: BuildTask[];
19
28
  transaction: IStorageTransaction;
20
29
  readonly log: Log;
21
- constructor(name: string, storage: IStorageZone, workspace: Workspace, devmode: boolean, watch: boolean, clean: boolean);
30
+ constructor(name: string, storage: IStorageZone, library: Library, devmode: boolean, watch: boolean, clean: boolean, onNotification?: (event: BuildNotification) => void);
22
31
  edit(): IStorageTransaction;
23
32
  store(): Promise<void>;
24
- add_component(descriptor: ComponentManifest, baseDir: string, library: Library): void;
33
+ add_component(descriptor: ComponentManifest, baseDir: string, origin: Bundle): boolean;
25
34
  private chrona;
26
35
  build(): Promise<void>;
27
36
  }
@@ -1,29 +1,32 @@
1
1
  import {} from "../workspace/component.js";
2
- import { Library, Workspace } from "../workspace/workspace.js";
2
+ import { Bundle, Library } from "../workspace/workspace.js";
3
3
  import { ESModulesTask } from "./helpers/emit-esmodules.js";
4
4
  import {} from "../workspace/storage.js";
5
5
  import { AssetsTask } from "./helpers/emit-static-assets.js";
6
6
  export class BuildTarget {
7
7
  name;
8
8
  storage;
9
- workspace;
9
+ library;
10
10
  devmode;
11
11
  watch;
12
12
  clean;
13
+ onNotification;
13
14
  components = new Map();
14
15
  esmodules = new ESModulesTask(this);
15
16
  assets = new AssetsTask(this);
16
17
  tasks = [];
18
+ finalTasks = [];
17
19
  transaction = null;
18
20
  log;
19
- constructor(name, storage, workspace, devmode, watch, clean) {
21
+ constructor(name, storage, library, devmode, watch, clean, onNotification) {
20
22
  this.name = name;
21
23
  this.storage = storage;
22
- this.workspace = workspace;
24
+ this.library = library;
23
25
  this.devmode = devmode;
24
26
  this.watch = watch;
25
27
  this.clean = clean;
26
- this.log = workspace.logger.get(`build:${name}`);
28
+ this.onNotification = onNotification;
29
+ this.log = library.log.logger.get(`build:${name}`);
27
30
  }
28
31
  edit() {
29
32
  if (!this.transaction)
@@ -36,10 +39,11 @@ export class BuildTarget {
36
39
  this.transaction = null;
37
40
  }
38
41
  }
39
- add_component(descriptor, baseDir, library) {
42
+ add_component(descriptor, baseDir, origin) {
40
43
  const id = descriptor.$id;
41
44
  if (this.components.has(id)) {
42
- throw new Error(createComponentDuplicateMessage(id, library));
45
+ this.log.error(createComponentDuplicateMessage(id, origin));
46
+ return false;
43
47
  }
44
48
  const manifest = {
45
49
  ...descriptor,
@@ -50,16 +54,17 @@ export class BuildTarget {
50
54
  if (descriptor.apis) {
51
55
  manifest.apis = {};
52
56
  for (const name in descriptor.apis) {
53
- manifest.apis[name] = this.esmodules.add_resource_entry(descriptor.apis[name], baseDir, library);
57
+ manifest.apis[name] = this.esmodules.add_resource_entry(descriptor.apis[name], baseDir, origin);
54
58
  }
55
59
  }
56
60
  if (descriptor.resources) {
57
61
  manifest.resources = {};
58
62
  for (const name in descriptor.resources) {
59
- manifest.resources[name] = this.esmodules.add_resource_entry(descriptor.resources[name], baseDir, library);
63
+ manifest.resources[name] = this.esmodules.add_resource_entry(descriptor.resources[name], baseDir, origin);
60
64
  }
61
65
  }
62
66
  this.components.set(id, manifest);
67
+ return true;
63
68
  }
64
69
  async chrona(task) {
65
70
  const name = task.constructor.name;
@@ -84,6 +89,7 @@ export class BuildTarget {
84
89
  // Trace time
85
90
  const buildTime = (Date.now() - buildStartTime) / 1000;
86
91
  this.log.info(`Build completed in ${buildTime.toFixed(2)}s`);
92
+ this.onNotification?.({ type: "build-complete", target: this.name, elapsed: buildTime });
87
93
  if (this.watch) {
88
94
  await new Promise((resolve) => {
89
95
  process.on('SIGQUIT', () => resolve(null));
@@ -91,13 +97,16 @@ export class BuildTarget {
91
97
  }
92
98
  else {
93
99
  await this.store();
100
+ for (const task of this.finalTasks) {
101
+ await this.chrona(task);
102
+ }
94
103
  }
95
104
  }
96
105
  }
97
- function createComponentDuplicateMessage(id, library) {
106
+ function createComponentDuplicateMessage(id, origin) {
98
107
  const duplicates = [];
99
108
  const libs = [];
100
- for (const bun of library.shelve) {
109
+ for (const bun of origin.library.shelve) {
101
110
  for (const [cpath, cmanifest] of bun.components.entries()) {
102
111
  if (cmanifest.$id === id) {
103
112
  duplicates.push(`\n - ${cpath}`);
@@ -0,0 +1,13 @@
1
+ import { BuildTask } from "./task.ts";
2
+ import type { BuildTarget } from "../build-target.ts";
3
+ export declare class ArtifactNpmTask extends BuildTask {
4
+ readonly outputDir: string;
5
+ constructor(target: BuildTarget, outputDir: string);
6
+ execute(): Promise<void>;
7
+ }
8
+ export declare class ArtifactZipTask extends BuildTask {
9
+ readonly outputDir: string;
10
+ readonly name: string;
11
+ constructor(target: BuildTarget, outputDir: string, name: string);
12
+ execute(): Promise<void>;
13
+ }
@@ -0,0 +1,40 @@
1
+ import Path from "node:path";
2
+ import FS from "node:fs";
3
+ import ChildProcess from "node:child_process";
4
+ import { BuildTask } from "./task.js";
5
+ export class ArtifactNpmTask extends BuildTask {
6
+ outputDir;
7
+ constructor(target, outputDir) {
8
+ super(target);
9
+ this.outputDir = outputDir;
10
+ }
11
+ async execute() {
12
+ const sourceDir = this.target.storage.getBaseDirFS();
13
+ FS.mkdirSync(this.outputDir, { recursive: true });
14
+ this.log.info(`📦 npm pack → ${this.outputDir}`);
15
+ ChildProcess.execSync("npm pack --pack-destination " + JSON.stringify(this.outputDir), { cwd: sourceDir });
16
+ }
17
+ }
18
+ export class ArtifactZipTask extends BuildTask {
19
+ outputDir;
20
+ name;
21
+ constructor(target, outputDir, name) {
22
+ super(target);
23
+ this.outputDir = outputDir;
24
+ this.name = name;
25
+ }
26
+ async execute() {
27
+ const sourceDir = this.target.storage.getBaseDirFS();
28
+ FS.mkdirSync(this.outputDir, { recursive: true });
29
+ const outPath = Path.join(this.outputDir, `${this.name}.zip`);
30
+ this.log.info(`📦 zip → ${outPath}`);
31
+ const parent = Path.dirname(sourceDir);
32
+ const base = Path.basename(sourceDir);
33
+ if (process.platform === 'win32') {
34
+ ChildProcess.execSync(`powershell -NoProfile -Command "Compress-Archive -Path '${base}\\*' -DestinationPath '${outPath}' -Force"`, { cwd: parent });
35
+ }
36
+ else {
37
+ ChildProcess.execSync(`zip -r ${JSON.stringify(outPath)} ${JSON.stringify(base)}`, { cwd: parent });
38
+ }
39
+ }
40
+ }