@antelopejs/dms-frontend 0.0.1

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 (54) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +131 -0
  3. package/dist/commands/build.js +66 -0
  4. package/dist/commands/clean.js +42 -0
  5. package/dist/commands/dev.js +116 -0
  6. package/dist/commands/prepare.js +60 -0
  7. package/dist/commands/start.js +49 -0
  8. package/dist/commands/verify-source.js +39 -0
  9. package/dist/common.js +24 -0
  10. package/dist/config.js +142 -0
  11. package/dist/discovery.js +123 -0
  12. package/dist/fs-sync.js +142 -0
  13. package/dist/index.js +44 -0
  14. package/dist/layer-watch.js +154 -0
  15. package/dist/layers.js +120 -0
  16. package/dist/manifest.js +109 -0
  17. package/dist/materialize.js +249 -0
  18. package/dist/ports.js +30 -0
  19. package/dist/update-check.js +173 -0
  20. package/dist/utils/cli-ui.js +178 -0
  21. package/dist/verify-source-runner.js +228 -0
  22. package/dist/workspace-setup.js +109 -0
  23. package/dist/workspace.js +76 -0
  24. package/package.json +97 -0
  25. package/templates/vue/DmsDynamicPage.vue +89 -0
  26. package/templates/vue/app-config-stub.mjs +1 -0
  27. package/templates/vue/app-runtime.ts +240 -0
  28. package/templates/vue/compress-assets.mjs +48 -0
  29. package/templates/vue/email-locales.ts +32 -0
  30. package/templates/vue/email-renderer.ts +159 -0
  31. package/templates/vue/email-runtime.ts +23 -0
  32. package/templates/vue/frontend-module.ts +1418 -0
  33. package/templates/vue/globals.d.ts +1 -0
  34. package/templates/vue/index.html +24 -0
  35. package/templates/vue/main.ts +33 -0
  36. package/templates/vue/npmrc +2 -0
  37. package/templates/vue/package.json +35 -0
  38. package/templates/vue/pnpm-workspace.yaml +4 -0
  39. package/templates/vue/server/auth/backend.mjs +83 -0
  40. package/templates/vue/server/auth/client-ip.mjs +52 -0
  41. package/templates/vue/server/auth/oauth.mjs +213 -0
  42. package/templates/vue/server/auth/routes.mjs +254 -0
  43. package/templates/vue/server/auth/session.mjs +180 -0
  44. package/templates/vue/server/client-manifest.mjs +116 -0
  45. package/templates/vue/server/email.mjs +36 -0
  46. package/templates/vue/server/inertia.mjs +79 -0
  47. package/templates/vue/server/render-token.mjs +81 -0
  48. package/templates/vue/server/tester.mjs +228 -0
  49. package/templates/vue/server.mjs +526 -0
  50. package/templates/vue/ssr-renderer.ts +146 -0
  51. package/templates/vue/tsconfig.json +31 -0
  52. package/templates/vue/typecheck-loader.mjs +13 -0
  53. package/templates/vue/vite.config.ts +161 -0
  54. package/templates/vue/vite.email.config.ts +77 -0
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseLocalPackages = parseLocalPackages;
4
+ exports.cmdVerifySource = cmdVerifySource;
5
+ const node_path_1 = require("node:path");
6
+ const commander_1 = require("commander");
7
+ const common_1 = require("../common");
8
+ function collectOption(value, values) {
9
+ return [...values, value];
10
+ }
11
+ function parseLocalPackages(values) {
12
+ return Object.fromEntries(values.map((value) => {
13
+ const separator = value.indexOf("=");
14
+ if (separator <= 0 || separator === value.length - 1)
15
+ throw new Error(`Invalid local package "${value}"; expected name=path`);
16
+ return [value.slice(0, separator), (0, node_path_1.resolve)(value.slice(separator + 1))];
17
+ }));
18
+ }
19
+ async function verifySource(options) {
20
+ const runner = (0, node_path_1.join)((0, common_1.getPackageRoot)(), "dist", "verify-source-runner.js");
21
+ const code = await (0, common_1.runCommand)(process.execPath, [runner], {
22
+ env: {
23
+ ...process.env,
24
+ DMS_LAYER_SOURCE: (0, node_path_1.resolve)(options.layer),
25
+ DMS_MODULE_SOURCES: JSON.stringify(options.module.map((path) => (0, node_path_1.resolve)(path))),
26
+ DMS_LOCAL_PACKAGES: JSON.stringify(parseLocalPackages(options.localPackage)),
27
+ },
28
+ });
29
+ if (code !== 0)
30
+ throw new Error("Source verification failed");
31
+ }
32
+ function cmdVerifySource() {
33
+ return new commander_1.Command("verify-source")
34
+ .description("Build and typecheck unpublished DMS frontend sources")
35
+ .requiredOption("-l, --layer <path>", "DMS frontend package root")
36
+ .option("-m, --module <path>", "Additional frontend package root (repeatable)", collectOption, [])
37
+ .option("--local-package <name=path>", "Bind a local package into the generated workspace (repeatable)", collectOption, [])
38
+ .action(verifySource);
39
+ }
package/dist/common.js ADDED
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./config"), exports);
18
+ __exportStar(require("./layers"), exports);
19
+ __exportStar(require("./manifest"), exports);
20
+ __exportStar(require("./fs-sync"), exports);
21
+ __exportStar(require("./layer-watch"), exports);
22
+ __exportStar(require("./materialize"), exports);
23
+ __exportStar(require("./workspace"), exports);
24
+ __exportStar(require("./workspace-setup"), exports);
package/dist/config.js ADDED
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Options = exports.TAILWIND_SOURCE_GLOB = exports.PNPM_LIFECYCLE_SCRIPTS = exports.layerCopyIgnore = exports.LAYER_COPY_BLOCKLIST = exports.FRONTEND_MODULE_ENTRY = exports.LAYERS_SUBDIR = exports.TEMPLATE_FILES = exports.WORKSPACE_DIR_MODE = exports.DEPS_HASH_FILE = exports.DMS_FRONTEND_HOME = void 0;
7
+ exports.writeSecretBearingFile = writeSecretBearingFile;
8
+ exports.normalizeBootstrapSecret = normalizeBootstrapSecret;
9
+ exports.resolveBootstrapSecret = resolveBootstrapSecret;
10
+ exports.sha256Hex = sha256Hex;
11
+ exports.canonicalizeBackendUrl = canonicalizeBackendUrl;
12
+ const node_crypto_1 = require("node:crypto");
13
+ const node_fs_1 = require("node:fs");
14
+ const node_os_1 = require("node:os");
15
+ const node_path_1 = require("node:path");
16
+ const commander_1 = require("commander");
17
+ const ignore_1 = __importDefault(require("ignore"));
18
+ const discovery_1 = require("./discovery");
19
+ const ANTELOPEJS_HOME = (0, node_path_1.join)((0, node_os_1.homedir)(), ".antelopejs");
20
+ exports.DMS_FRONTEND_HOME = (0, node_path_1.join)(ANTELOPEJS_HOME, "dms-frontend");
21
+ exports.DEPS_HASH_FILE = ".deps-hash";
22
+ const SECRET_BEARING_FILE_MODE = 0o600;
23
+ const TEMP_FILE_SUFFIX = ".tmp";
24
+ exports.WORKSPACE_DIR_MODE = 0o700;
25
+ function writeSecretBearingFile(file, content) {
26
+ const temp = `${file}.${process.pid}${TEMP_FILE_SUFFIX}`;
27
+ (0, node_fs_1.writeFileSync)(temp, content, { mode: SECRET_BEARING_FILE_MODE });
28
+ (0, node_fs_1.chmodSync)(temp, SECRET_BEARING_FILE_MODE);
29
+ (0, node_fs_1.renameSync)(temp, file);
30
+ }
31
+ exports.TEMPLATE_FILES = [
32
+ ["vite.config.ts", "vite.config.ts"],
33
+ ["vite.email.config.ts", "vite.email.config.ts"],
34
+ ["index.html", "index.html"],
35
+ ["main.ts", "main.ts"],
36
+ ["app-runtime.ts", "app-runtime.ts"],
37
+ ["ssr-renderer.ts", "ssr-renderer.ts"],
38
+ ["frontend-module.ts", "frontend-module.ts"],
39
+ ["globals.d.ts", "globals.d.ts"],
40
+ ["compress-assets.mjs", "compress-assets.mjs"],
41
+ ["email-renderer.ts", "email-renderer.ts"],
42
+ ["email-runtime.ts", "email-runtime.ts"],
43
+ ["email-locales.ts", "email-locales.ts"],
44
+ ["tsconfig.json", "tsconfig.json"],
45
+ ["typecheck-loader.mjs", "typecheck-loader.mjs"],
46
+ ["app-config-stub.mjs", "app-config-stub.mjs"],
47
+ ["DmsDynamicPage.vue", "DmsDynamicPage.vue"],
48
+ ["server.mjs", "server.mjs"],
49
+ ["server", "server"],
50
+ ["npmrc", ".npmrc"],
51
+ ["pnpm-workspace.yaml", "pnpm-workspace.yaml"],
52
+ ];
53
+ exports.LAYERS_SUBDIR = "frontend-modules";
54
+ exports.FRONTEND_MODULE_ENTRY = "dms.frontend.ts";
55
+ exports.LAYER_COPY_BLOCKLIST = [
56
+ "node_modules",
57
+ "dist",
58
+ ".git",
59
+ "coverage",
60
+ ".cache",
61
+ ".turbo",
62
+ "server",
63
+ "**/server",
64
+ "tsconfig.json",
65
+ "tsconfig.*.json",
66
+ ];
67
+ exports.layerCopyIgnore = (0, ignore_1.default)().add([...exports.LAYER_COPY_BLOCKLIST]);
68
+ exports.PNPM_LIFECYCLE_SCRIPTS = [
69
+ "preinstall",
70
+ "install",
71
+ "postinstall",
72
+ "preprepare",
73
+ "prepare",
74
+ "postprepare",
75
+ "prepack",
76
+ "postpack",
77
+ ];
78
+ exports.TAILWIND_SOURCE_GLOB = "**/*.{vue,ts,tsx,js,jsx,mjs,cjs}";
79
+ function booleanFromEnv(name) {
80
+ const value = process.env[name];
81
+ if (value === undefined)
82
+ return false;
83
+ return !["", "0", "false", "no", "off"].includes(value.trim().toLowerCase());
84
+ }
85
+ exports.Options = {
86
+ backendUrl: new commander_1.Option("-b, --backend-url <url>", "Backend DMS URL (when omitted, dev mode discovers it from the enclosing antelope project's .antelope/dev.json)").env("DMS_BACKEND_URL"),
87
+ port: new commander_1.Option("-p, --port <port>", "Port to run on")
88
+ .default("3001")
89
+ .env("PORT"),
90
+ force: new commander_1.Option("-f, --force", "Force reinstall dependencies"),
91
+ offline: new commander_1.Option("--offline", "Skip the backend manifest fetch and reuse the last cached manifest (env: DMS_OFFLINE)").default(booleanFromEnv("DMS_OFFLINE")),
92
+ bootstrapSecret: new commander_1.Option("--bootstrap-secret <secret>", "Credential presented to the backend's layer endpoints (env: DMS_BOOTSTRAP_SECRET, preferred — " +
93
+ "a secret passed on the command line is visible to every process on the machine). In dev it is " +
94
+ "discovered from the antelope project's .antelope/dms-dev.json.").env("DMS_BOOTSTRAP_SECRET"),
95
+ };
96
+ const HEADER_SAFE_CREDENTIAL = /^[\x21-\x7e]+$/;
97
+ const DEFAULT_CREDENTIAL_SOURCE = "DMS_BOOTSTRAP_SECRET";
98
+ function normalizeBootstrapSecret(value, source = DEFAULT_CREDENTIAL_SOURCE) {
99
+ const trimmed = value?.trim();
100
+ if (!trimmed)
101
+ return undefined;
102
+ if (!HEADER_SAFE_CREDENTIAL.test(trimmed)) {
103
+ throw new Error("The bootstrap credential contains characters that cannot travel in an HTTP header.\n" +
104
+ ` Check ${source} for a line break or a non-ASCII byte — a secret read from\n` +
105
+ " a file commonly keeps its trailing newline.");
106
+ }
107
+ return trimmed;
108
+ }
109
+ function resolveBootstrapSecret(explicit, backendUrl, options = {}) {
110
+ const normalized = normalizeBootstrapSecret(explicit);
111
+ if (normalized)
112
+ return normalized;
113
+ const result = (0, discovery_1.discoverBackend)(options.cwd ?? process.cwd(), options);
114
+ if (result.status !== "found")
115
+ return undefined;
116
+ if (canonicalizeBackendUrl(result.backend.backendUrl) !==
117
+ canonicalizeBackendUrl(backendUrl)) {
118
+ return undefined;
119
+ }
120
+ return normalizeBootstrapSecret((0, discovery_1.readDevBootstrapCredential)(result.backend.projectDir, options), (0, node_path_1.join)(result.backend.projectDir, discovery_1.DEV_HANDSHAKE_RELATIVE_PATH));
121
+ }
122
+ function sha256Hex(input) {
123
+ return (0, node_crypto_1.createHash)("sha256").update(input).digest("hex");
124
+ }
125
+ function canonicalizeBackendUrl(backendUrl) {
126
+ const raw = backendUrl.trim();
127
+ let url;
128
+ try {
129
+ url = new URL(raw);
130
+ }
131
+ catch {
132
+ return raw;
133
+ }
134
+ if (url.hostname === "localhost" || url.hostname === "[::1]") {
135
+ url.hostname = "127.0.0.1";
136
+ }
137
+ const out = url.toString();
138
+ if (url.pathname === "/" && !url.search && !url.hash) {
139
+ return out.replace(/\/$/, "");
140
+ }
141
+ return out;
142
+ }
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEV_HANDSHAKE_RELATIVE_PATH = exports.DEV_REGISTRY_RELATIVE_PATH = void 0;
4
+ exports.isPidAlive = isPidAlive;
5
+ exports.buildBackendUrl = buildBackendUrl;
6
+ exports.discoverBackend = discoverBackend;
7
+ exports.describeDiscoveryFailure = describeDiscoveryFailure;
8
+ exports.readDevBootstrapCredential = readDevBootstrapCredential;
9
+ const node_fs_1 = require("node:fs");
10
+ const node_path_1 = require("node:path");
11
+ exports.DEV_REGISTRY_RELATIVE_PATH = (0, node_path_1.join)(".antelope", "dev.json");
12
+ function isPidAlive(pid) {
13
+ if (!Number.isInteger(pid) || pid <= 0)
14
+ return false;
15
+ try {
16
+ process.kill(pid, 0);
17
+ return true;
18
+ }
19
+ catch (err) {
20
+ return err?.code === "EPERM";
21
+ }
22
+ }
23
+ function parseRegistry(file) {
24
+ try {
25
+ const parsed = JSON.parse((0, node_fs_1.readFileSync)(file, "utf-8"));
26
+ if (typeof parsed?.pid !== "number" ||
27
+ typeof parsed?.servers !== "object" ||
28
+ parsed.servers === null) {
29
+ return undefined;
30
+ }
31
+ return parsed;
32
+ }
33
+ catch {
34
+ return undefined;
35
+ }
36
+ }
37
+ function buildBackendUrl(endpoint) {
38
+ let host = endpoint.host;
39
+ if (host === "0.0.0.0" || host === "::" || host === "[::]") {
40
+ host = "localhost";
41
+ }
42
+ else if (host.includes(":") && !host.startsWith("[")) {
43
+ host = `[${host}]`;
44
+ }
45
+ return `${endpoint.protocol}://${host}:${endpoint.port}`;
46
+ }
47
+ function discoverBackend(cwd, options = {}) {
48
+ const alive = options.isPidAlive ?? isPidAlive;
49
+ let dir = (0, node_path_1.resolve)(cwd);
50
+ while (true) {
51
+ const file = (0, node_path_1.join)(dir, exports.DEV_REGISTRY_RELATIVE_PATH);
52
+ if ((0, node_fs_1.existsSync)(file)) {
53
+ const registry = parseRegistry(file);
54
+ if (!registry) {
55
+ return { status: "malformed", projectDir: dir };
56
+ }
57
+ if (!alive(registry.pid)) {
58
+ return { status: "stale", projectDir: dir, pid: registry.pid };
59
+ }
60
+ const endpoint = registry.servers.api?.endpoints?.[0];
61
+ if (!endpoint) {
62
+ return { status: "no-api-endpoint", projectDir: dir };
63
+ }
64
+ return {
65
+ status: "found",
66
+ backend: {
67
+ projectDir: dir,
68
+ registry,
69
+ backendUrl: buildBackendUrl(endpoint),
70
+ },
71
+ };
72
+ }
73
+ const parent = (0, node_path_1.dirname)(dir);
74
+ if (parent === dir)
75
+ return { status: "not-found" };
76
+ dir = parent;
77
+ }
78
+ }
79
+ function describeDiscoveryFailure(result) {
80
+ switch (result.status) {
81
+ case "not-found":
82
+ return ("No backend URL provided and no running antelope project found.\n" +
83
+ ` Searched for ${exports.DEV_REGISTRY_RELATIVE_PATH} from the current directory upward.\n` +
84
+ " Either run this command inside an antelope project started with 'ajs project dev',\n" +
85
+ " or pass the backend explicitly with -b <url> (env: DMS_BACKEND_URL).");
86
+ case "stale":
87
+ return (`Found ${(0, node_path_1.join)(result.projectDir, exports.DEV_REGISTRY_RELATIVE_PATH)} but its process (pid ${result.pid}) is no longer running.\n` +
88
+ " Start the backend with 'ajs project dev', or pass -b <url> explicitly.");
89
+ case "no-api-endpoint":
90
+ return (`Found a running antelope project at ${result.projectDir} but it exposes no 'api' server endpoint.\n` +
91
+ " Make sure the api module is loaded, or pass -b <url> explicitly.");
92
+ case "malformed":
93
+ return (`Found ${(0, node_path_1.join)(result.projectDir, exports.DEV_REGISTRY_RELATIVE_PATH)} but could not parse it.\n` +
94
+ " Restart the backend with 'ajs project dev' to rewrite it, or pass -b <url> explicitly.");
95
+ case "found":
96
+ return "";
97
+ }
98
+ }
99
+ exports.DEV_HANDSHAKE_RELATIVE_PATH = (0, node_path_1.join)(".antelope", "dms-dev.json");
100
+ function parseHandshake(file) {
101
+ try {
102
+ const parsed = JSON.parse((0, node_fs_1.readFileSync)(file, "utf-8"));
103
+ if (typeof parsed?.pid !== "number" ||
104
+ typeof parsed?.bootstrapSecret !== "string" ||
105
+ !parsed.bootstrapSecret) {
106
+ return undefined;
107
+ }
108
+ return parsed;
109
+ }
110
+ catch {
111
+ return undefined;
112
+ }
113
+ }
114
+ function readDevBootstrapCredential(projectDir, options = {}) {
115
+ const alive = options.isPidAlive ?? isPidAlive;
116
+ const file = (0, node_path_1.join)(projectDir, exports.DEV_HANDSHAKE_RELATIVE_PATH);
117
+ if (!(0, node_fs_1.existsSync)(file))
118
+ return undefined;
119
+ const handshake = parseHandshake(file);
120
+ if (!handshake || !alive(handshake.pid))
121
+ return undefined;
122
+ return handshake.bootstrapSecret;
123
+ }
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.stripExtendedLengthPrefix = stripExtendedLengthPrefix;
7
+ exports.isBlocklistedCopyPath = isBlocklistedCopyPath;
8
+ exports.sanitizedPackageContent = sanitizedPackageContent;
9
+ exports.filesIdentical = filesIdentical;
10
+ exports.applyContent = applyContent;
11
+ exports.applyFile = applyFile;
12
+ exports.collectFiles = collectFiles;
13
+ exports.syncDirectories = syncDirectories;
14
+ const node_fs_1 = require("node:fs");
15
+ const node_path_1 = require("node:path");
16
+ const ignore_1 = __importDefault(require("ignore"));
17
+ const config_1 = require("./config");
18
+ function stripExtendedLengthPrefix(p) {
19
+ return p.replace(/^\\\\\?\\/, "");
20
+ }
21
+ function isBlocklistedCopyPath(src, srcPath) {
22
+ const rel = (0, node_path_1.relative)((0, node_path_1.resolve)(stripExtendedLengthPrefix(src)), (0, node_path_1.resolve)(stripExtendedLengthPrefix(srcPath)));
23
+ if (!rel || rel.startsWith(".."))
24
+ return false;
25
+ return config_1.layerCopyIgnore.ignores(rel.split(node_path_1.sep).join("/"));
26
+ }
27
+ function sanitizedPackageContent(raw) {
28
+ const pkg = JSON.parse(raw);
29
+ delete pkg.devDependencies;
30
+ if (pkg.scripts) {
31
+ for (const name of config_1.PNPM_LIFECYCLE_SCRIPTS) {
32
+ delete pkg.scripts[name];
33
+ }
34
+ }
35
+ return `${JSON.stringify(pkg, null, 2)}\n`;
36
+ }
37
+ function filesIdentical(srcPath, destPath) {
38
+ if (!(0, node_fs_1.existsSync)(destPath))
39
+ return false;
40
+ try {
41
+ const a = (0, node_fs_1.statSync)(srcPath);
42
+ const b = (0, node_fs_1.statSync)(destPath);
43
+ if (!a.isFile() || !b.isFile())
44
+ return false;
45
+ if (a.size !== b.size)
46
+ return false;
47
+ return (0, node_fs_1.readFileSync)(srcPath).equals((0, node_fs_1.readFileSync)(destPath));
48
+ }
49
+ catch {
50
+ return false;
51
+ }
52
+ }
53
+ function applyContent(content, destPath) {
54
+ const buf = Buffer.from(content);
55
+ if ((0, node_fs_1.existsSync)(destPath)) {
56
+ try {
57
+ if ((0, node_fs_1.readFileSync)(destPath).equals(buf))
58
+ return;
59
+ }
60
+ catch {
61
+ }
62
+ }
63
+ (0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(destPath), { recursive: true });
64
+ const tmp = `${destPath}.ajs-dms-tmp-${process.pid}-${Date.now()}`;
65
+ try {
66
+ (0, node_fs_1.writeFileSync)(tmp, buf);
67
+ (0, node_fs_1.renameSync)(tmp, destPath);
68
+ }
69
+ finally {
70
+ if ((0, node_fs_1.existsSync)(tmp))
71
+ (0, node_fs_1.rmSync)(tmp, { force: true });
72
+ }
73
+ }
74
+ function applyFile(srcPath, destPath) {
75
+ if (filesIdentical(srcPath, destPath))
76
+ return;
77
+ (0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(destPath), { recursive: true });
78
+ const tmp = `${destPath}.ajs-dms-tmp-${process.pid}-${Date.now()}`;
79
+ try {
80
+ (0, node_fs_1.cpSync)(srcPath, tmp, { force: true, dereference: true });
81
+ (0, node_fs_1.renameSync)(tmp, destPath);
82
+ }
83
+ finally {
84
+ if ((0, node_fs_1.existsSync)(tmp))
85
+ (0, node_fs_1.rmSync)(tmp, { force: true });
86
+ }
87
+ }
88
+ function loadGitignore(layerPath) {
89
+ const ig = (0, ignore_1.default)();
90
+ const gitignorePath = (0, node_path_1.join)(layerPath, ".gitignore");
91
+ if ((0, node_fs_1.existsSync)(gitignorePath)) {
92
+ ig.add((0, node_fs_1.readFileSync)(gitignorePath, "utf-8"));
93
+ }
94
+ return ig;
95
+ }
96
+ function collectFiles(dir, baseDir = dir) {
97
+ const files = [];
98
+ if (!(0, node_fs_1.existsSync)(dir))
99
+ return files;
100
+ const entries = (0, node_fs_1.readdirSync)(dir, { withFileTypes: true });
101
+ for (const entry of entries) {
102
+ const fullPath = (0, node_path_1.join)(dir, entry.name);
103
+ const { relative } = require("node:path");
104
+ const relPath = relative(baseDir, fullPath);
105
+ if (entry.isDirectory()) {
106
+ files.push(...collectFiles(fullPath, baseDir));
107
+ }
108
+ else {
109
+ files.push(relPath);
110
+ }
111
+ }
112
+ return files;
113
+ }
114
+ function syncDirectories(src, dest) {
115
+ const ig = loadGitignore(src);
116
+ const srcFiles = collectFiles(src).filter((f) => !ig.ignores(f));
117
+ const destFiles = collectFiles(dest);
118
+ for (const file of srcFiles) {
119
+ applyFile((0, node_path_1.join)(src, file), (0, node_path_1.join)(dest, file));
120
+ }
121
+ for (const file of destFiles) {
122
+ if (ig.ignores(file))
123
+ continue;
124
+ if (!srcFiles.includes(file)) {
125
+ (0, node_fs_1.rmSync)((0, node_path_1.join)(dest, file), { force: true });
126
+ }
127
+ }
128
+ cleanEmptyDirs(dest);
129
+ }
130
+ function cleanEmptyDirs(dir) {
131
+ const { statSync } = require("node:fs");
132
+ if (!(0, node_fs_1.existsSync)(dir) || !statSync(dir).isDirectory())
133
+ return;
134
+ for (const entry of (0, node_fs_1.readdirSync)(dir)) {
135
+ const full = (0, node_path_1.join)(dir, entry);
136
+ if (statSync(full).isDirectory())
137
+ cleanEmptyDirs(full);
138
+ }
139
+ if ((0, node_fs_1.readdirSync)(dir).length === 0) {
140
+ (0, node_fs_1.rmSync)(dir, { recursive: true, force: true });
141
+ }
142
+ }
package/dist/index.js ADDED
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const commander_1 = require("commander");
9
+ const build_1 = require("./commands/build");
10
+ const clean_1 = require("./commands/clean");
11
+ const dev_1 = require("./commands/dev");
12
+ const prepare_1 = require("./commands/prepare");
13
+ const start_1 = require("./commands/start");
14
+ const verify_source_1 = require("./commands/verify-source");
15
+ const update_check_1 = require("./update-check");
16
+ const cli_ui_1 = require("./utils/cli-ui");
17
+ const { version } = require("../package.json");
18
+ const runCLI = async () => {
19
+ const argv = process.argv.slice(2);
20
+ void (0, update_check_1.checkForUpdate)({ currentVersion: version, argv });
21
+ if (process.argv.length <= 2) {
22
+ (0, cli_ui_1.displayBanner)("Antelope DMS");
23
+ console.log(chalk_1.default.dim(` Frontend Loader for AntelopeJS DMS - v${version}\n`));
24
+ }
25
+ const program = new commander_1.Command()
26
+ .name("ajs-dms")
27
+ .description(`Antelope DMS - Frontend Loader v${version}\n\n` +
28
+ `Materializes frontend modules from an AntelopeJS backend and starts a Vue or React Vite and Inertia application.`)
29
+ .version(version, "-v, --version", "Display version number")
30
+ .option("--no-update-check", "Skip the daily check for a newer DMS frontend release")
31
+ .helpCommand("help [command]", "Display help for a specific command");
32
+ program.addCommand((0, dev_1.cmdDev)());
33
+ program.addCommand((0, build_1.cmdBuild)());
34
+ program.addCommand((0, start_1.cmdStart)());
35
+ program.addCommand((0, prepare_1.cmdPrepare)());
36
+ program.addCommand((0, clean_1.cmdClean)());
37
+ program.addCommand((0, verify_source_1.cmdVerifySource)());
38
+ await program.parseAsync((0, update_check_1.stripUpdateCheckFlag)(argv), { from: "user" });
39
+ };
40
+ process.on("SIGINT", () => process.exit(0));
41
+ runCLI().catch((err) => {
42
+ console.error(chalk_1.default.red("Error:"), err.message || err);
43
+ process.exit(1);
44
+ });
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.startLayerWatchers = startLayerWatchers;
7
+ const node_fs_1 = require("node:fs");
8
+ const node_path_1 = require("node:path");
9
+ const chokidar_1 = __importDefault(require("chokidar"));
10
+ const layers_1 = require("./layers");
11
+ const fs_sync_1 = require("./fs-sync");
12
+ const WATCH_DEBOUNCE_MS = 80;
13
+ function createLayerSync(src, dest) {
14
+ const fileUpserts = new Set();
15
+ const fileDeletes = new Set();
16
+ const dirCreates = new Set();
17
+ const dirDeletes = new Set();
18
+ let timer = null;
19
+ const toRel = (p) => {
20
+ const r = (0, node_path_1.relative)(src, p);
21
+ return r ? r : null;
22
+ };
23
+ const warnFailure = (rel, err) => {
24
+ console.warn(`[ajs-dms] layer sync skipped ${rel}:`, err);
25
+ };
26
+ const flush = () => {
27
+ timer = null;
28
+ for (const rel of [...dirCreates].sort((a, b) => a.length - b.length)) {
29
+ try {
30
+ (0, node_fs_1.mkdirSync)((0, node_path_1.join)(dest, rel), { recursive: true });
31
+ }
32
+ catch (err) {
33
+ warnFailure(rel, err);
34
+ }
35
+ }
36
+ dirCreates.clear();
37
+ for (const rel of fileUpserts) {
38
+ try {
39
+ const srcPath = (0, node_path_1.join)(src, rel);
40
+ if (!(0, node_fs_1.existsSync)(srcPath))
41
+ continue;
42
+ const destPath = (0, node_path_1.join)(dest, rel);
43
+ if (rel === "package.json") {
44
+ (0, fs_sync_1.applyContent)((0, fs_sync_1.sanitizedPackageContent)((0, node_fs_1.readFileSync)(srcPath, "utf-8")), destPath);
45
+ }
46
+ else {
47
+ (0, fs_sync_1.applyFile)(srcPath, destPath);
48
+ }
49
+ }
50
+ catch (err) {
51
+ warnFailure(rel, err);
52
+ }
53
+ }
54
+ fileUpserts.clear();
55
+ for (const rel of fileDeletes) {
56
+ try {
57
+ if ((0, node_fs_1.existsSync)((0, node_path_1.join)(src, rel)))
58
+ continue;
59
+ const destPath = (0, node_path_1.join)(dest, rel);
60
+ if ((0, node_fs_1.existsSync)(destPath))
61
+ (0, node_fs_1.rmSync)(destPath, { force: true });
62
+ }
63
+ catch (err) {
64
+ warnFailure(rel, err);
65
+ }
66
+ }
67
+ fileDeletes.clear();
68
+ for (const rel of [...dirDeletes].sort((a, b) => b.length - a.length)) {
69
+ try {
70
+ if ((0, node_fs_1.existsSync)((0, node_path_1.join)(src, rel)))
71
+ continue;
72
+ const destPath = (0, node_path_1.join)(dest, rel);
73
+ if ((0, node_fs_1.existsSync)(destPath))
74
+ (0, node_fs_1.rmSync)(destPath, { recursive: true, force: true });
75
+ }
76
+ catch (err) {
77
+ warnFailure(rel, err);
78
+ }
79
+ }
80
+ dirDeletes.clear();
81
+ };
82
+ const arm = () => {
83
+ if (timer)
84
+ clearTimeout(timer);
85
+ timer = setTimeout(flush, WATCH_DEBOUNCE_MS);
86
+ };
87
+ return {
88
+ upsertFile(p) {
89
+ const r = toRel(p);
90
+ if (!r)
91
+ return;
92
+ fileDeletes.delete(r);
93
+ fileUpserts.add(r);
94
+ arm();
95
+ },
96
+ deleteFile(p) {
97
+ const r = toRel(p);
98
+ if (!r)
99
+ return;
100
+ fileUpserts.delete(r);
101
+ fileDeletes.add(r);
102
+ arm();
103
+ },
104
+ createDir(p) {
105
+ const r = toRel(p);
106
+ if (!r)
107
+ return;
108
+ dirDeletes.delete(r);
109
+ dirCreates.add(r);
110
+ arm();
111
+ },
112
+ deleteDir(p) {
113
+ const r = toRel(p);
114
+ if (!r)
115
+ return;
116
+ dirCreates.delete(r);
117
+ dirDeletes.add(r);
118
+ arm();
119
+ },
120
+ flushNow() {
121
+ if (timer)
122
+ clearTimeout(timer);
123
+ flush();
124
+ },
125
+ };
126
+ }
127
+ function startLayerWatchers(workspaceDir, layers) {
128
+ const watchers = [];
129
+ const syncs = [];
130
+ for (const layer of layers) {
131
+ if (!layer.packageName)
132
+ continue;
133
+ const dest = (0, layers_1.getLayerWorkspacePath)(workspaceDir, layer);
134
+ const src = layer.path;
135
+ const sync = createLayerSync(src, dest);
136
+ syncs.push(sync);
137
+ const watcher = chokidar_1.default.watch(src, {
138
+ ignoreInitial: true,
139
+ ignored: (path) => (0, fs_sync_1.isBlocklistedCopyPath)(src, path),
140
+ persistent: true,
141
+ });
142
+ watcher.on("add", (p) => sync.upsertFile(p));
143
+ watcher.on("change", (p) => sync.upsertFile(p));
144
+ watcher.on("unlink", (p) => sync.deleteFile(p));
145
+ watcher.on("addDir", (p) => sync.createDir(p));
146
+ watcher.on("unlinkDir", (p) => sync.deleteDir(p));
147
+ watchers.push(watcher);
148
+ }
149
+ return async () => {
150
+ await Promise.all(watchers.map((w) => w.close().catch(() => { })));
151
+ for (const sync of syncs)
152
+ sync.flushNow();
153
+ };
154
+ }