@doubledigit/cli 0.1.0

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 (89) hide show
  1. package/LICENSE +21 -0
  2. package/dist/codegen.d.ts +12 -0
  3. package/dist/codegen.d.ts.map +1 -0
  4. package/dist/codegen.js +107 -0
  5. package/dist/commands/add.d.ts +26 -0
  6. package/dist/commands/add.d.ts.map +1 -0
  7. package/dist/commands/add.js +548 -0
  8. package/dist/commands/browse.d.ts +8 -0
  9. package/dist/commands/browse.d.ts.map +1 -0
  10. package/dist/commands/browse.js +116 -0
  11. package/dist/commands/create.d.ts +12 -0
  12. package/dist/commands/create.d.ts.map +1 -0
  13. package/dist/commands/create.js +218 -0
  14. package/dist/commands/db.d.ts +2 -0
  15. package/dist/commands/db.d.ts.map +1 -0
  16. package/dist/commands/db.js +64 -0
  17. package/dist/commands/disable.d.ts +5 -0
  18. package/dist/commands/disable.d.ts.map +1 -0
  19. package/dist/commands/disable.js +29 -0
  20. package/dist/commands/doctor.d.ts +2 -0
  21. package/dist/commands/doctor.d.ts.map +1 -0
  22. package/dist/commands/doctor.js +88 -0
  23. package/dist/commands/enable.d.ts +5 -0
  24. package/dist/commands/enable.d.ts.map +1 -0
  25. package/dist/commands/enable.js +29 -0
  26. package/dist/commands/info.d.ts +8 -0
  27. package/dist/commands/info.d.ts.map +1 -0
  28. package/dist/commands/info.js +84 -0
  29. package/dist/commands/list.d.ts +5 -0
  30. package/dist/commands/list.d.ts.map +1 -0
  31. package/dist/commands/list.js +44 -0
  32. package/dist/commands/marketplace.d.ts +11 -0
  33. package/dist/commands/marketplace.d.ts.map +1 -0
  34. package/dist/commands/marketplace.js +205 -0
  35. package/dist/commands/onboard.d.ts +2 -0
  36. package/dist/commands/onboard.d.ts.map +1 -0
  37. package/dist/commands/onboard.js +58 -0
  38. package/dist/commands/outdated.d.ts +8 -0
  39. package/dist/commands/outdated.d.ts.map +1 -0
  40. package/dist/commands/outdated.js +107 -0
  41. package/dist/commands/reconcile.d.ts +12 -0
  42. package/dist/commands/reconcile.d.ts.map +1 -0
  43. package/dist/commands/reconcile.js +175 -0
  44. package/dist/commands/run.d.ts +2 -0
  45. package/dist/commands/run.d.ts.map +1 -0
  46. package/dist/commands/run.js +37 -0
  47. package/dist/commands/sync.d.ts +5 -0
  48. package/dist/commands/sync.d.ts.map +1 -0
  49. package/dist/commands/sync.js +34 -0
  50. package/dist/commands/uninstall.d.ts +14 -0
  51. package/dist/commands/uninstall.d.ts.map +1 -0
  52. package/dist/commands/uninstall.js +190 -0
  53. package/dist/config.d.ts +19 -0
  54. package/dist/config.d.ts.map +1 -0
  55. package/dist/config.js +37 -0
  56. package/dist/index.d.ts +13 -0
  57. package/dist/index.d.ts.map +1 -0
  58. package/dist/index.js +181 -0
  59. package/dist/lib/github-auth.d.ts +8 -0
  60. package/dist/lib/github-auth.d.ts.map +1 -0
  61. package/dist/lib/github-auth.js +30 -0
  62. package/dist/lib/lock-file.d.ts +67 -0
  63. package/dist/lib/lock-file.d.ts.map +1 -0
  64. package/dist/lib/lock-file.js +117 -0
  65. package/dist/lib/marketplace-schema.d.ts +607 -0
  66. package/dist/lib/marketplace-schema.d.ts.map +1 -0
  67. package/dist/lib/marketplace-schema.js +111 -0
  68. package/dist/lib/marketplace.d.ts +57 -0
  69. package/dist/lib/marketplace.d.ts.map +1 -0
  70. package/dist/lib/marketplace.js +270 -0
  71. package/dist/lib/onboarding.d.ts +84 -0
  72. package/dist/lib/onboarding.d.ts.map +1 -0
  73. package/dist/lib/onboarding.js +1004 -0
  74. package/dist/lib/rewrite-extension-tsconfig.d.ts +22 -0
  75. package/dist/lib/rewrite-extension-tsconfig.d.ts.map +1 -0
  76. package/dist/lib/rewrite-extension-tsconfig.js +80 -0
  77. package/dist/lib/source-parser.d.ts +35 -0
  78. package/dist/lib/source-parser.d.ts.map +1 -0
  79. package/dist/lib/source-parser.js +121 -0
  80. package/dist/lib/validators.d.ts +73 -0
  81. package/dist/lib/validators.d.ts.map +1 -0
  82. package/dist/lib/validators.js +435 -0
  83. package/dist/paths.d.ts +46 -0
  84. package/dist/paths.d.ts.map +1 -0
  85. package/dist/paths.js +85 -0
  86. package/dist/scanner.d.ts +41 -0
  87. package/dist/scanner.d.ts.map +1 -0
  88. package/dist/scanner.js +100 -0
  89. package/package.json +49 -0
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Manage dd-apps.lock.json — tracks externally-installed micro-apps.
3
+ *
4
+ * The lock file lives at the monorepo root and records the source,
5
+ * content hash, and timestamps for every app installed via `dd install`.
6
+ */
7
+ import fs from 'node:fs';
8
+ import path from 'node:path';
9
+ import crypto from 'node:crypto';
10
+ const EMPTY_LOCK = { version: 1, apps: {} };
11
+ /** Directories excluded from content hashing */
12
+ const HASH_EXCLUDE_DIRS = new Set(['node_modules', '.turbo', 'dist']);
13
+ /**
14
+ * Read and parse the lock file. Returns an empty lock structure if the file
15
+ * does not exist. Throws on malformed files to avoid silent data loss.
16
+ */
17
+ export function readLockFile(lockPath) {
18
+ if (!fs.existsSync(lockPath)) {
19
+ return { ...EMPTY_LOCK, apps: {} };
20
+ }
21
+ const raw = fs.readFileSync(lockPath, 'utf-8');
22
+ let parsed;
23
+ try {
24
+ parsed = JSON.parse(raw);
25
+ }
26
+ catch (err) {
27
+ // Back up the corrupted file so the user doesn't lose data
28
+ const backupPath = lockPath + '.bak';
29
+ fs.copyFileSync(lockPath, backupPath);
30
+ throw new Error(`Lock file is corrupted (backed up to ${backupPath}).\n` +
31
+ `Fix or delete ${lockPath} and retry.\n` +
32
+ `Parse error: ${err instanceof Error ? err.message : err}`);
33
+ }
34
+ const lock = parsed;
35
+ if (lock.version !== 1 ||
36
+ typeof lock.apps !== 'object' ||
37
+ lock.apps === null ||
38
+ Array.isArray(lock.apps)) {
39
+ const backupPath = lockPath + '.bak';
40
+ fs.copyFileSync(lockPath, backupPath);
41
+ throw new Error(`Lock file has unexpected format (backed up to ${backupPath}).\n` +
42
+ `Expected { version: 1, apps: {...} }. Fix or delete ${lockPath} and retry.`);
43
+ }
44
+ return lock;
45
+ }
46
+ /**
47
+ * Write the lock file to disk with deterministic key ordering.
48
+ */
49
+ export function writeLockFile(lockPath, lock) {
50
+ const sorted = {
51
+ version: lock.version,
52
+ apps: Object.fromEntries(Object.entries(lock.apps).sort(([a], [b]) => a.localeCompare(b))),
53
+ };
54
+ fs.mkdirSync(path.dirname(lockPath), { recursive: true });
55
+ fs.writeFileSync(lockPath, JSON.stringify(sorted, null, 2) + '\n', 'utf-8');
56
+ }
57
+ /**
58
+ * Add or update a single entry in the lock file.
59
+ */
60
+ export function addLockEntry(lockPath, key, entry) {
61
+ const lock = readLockFile(lockPath);
62
+ lock.apps[key] = entry;
63
+ writeLockFile(lockPath, lock);
64
+ }
65
+ /**
66
+ * Remove an entry from the lock file. No-op if the key doesn't exist.
67
+ */
68
+ export function removeLockEntry(lockPath, key) {
69
+ const lock = readLockFile(lockPath);
70
+ if (!(key in lock.apps))
71
+ return;
72
+ delete lock.apps[key];
73
+ writeLockFile(lockPath, lock);
74
+ }
75
+ /**
76
+ * Check whether an app was externally installed (i.e. tracked in the lock file).
77
+ */
78
+ export function isExternalApp(lockPath, key) {
79
+ const lock = readLockFile(lockPath);
80
+ return key in lock.apps;
81
+ }
82
+ /**
83
+ * Compute a deterministic SHA-256 content hash of every file in a directory.
84
+ *
85
+ * Excludes `node_modules`, `.turbo`, and `dist`. File paths are sorted for
86
+ * determinism and the hash covers both path and content.
87
+ */
88
+ export async function computeContentHash(dir) {
89
+ const entries = [];
90
+ collectFiles(dir, dir, entries);
91
+ // Sort by relative path for determinism
92
+ entries.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
93
+ const hash = crypto.createHash('sha256');
94
+ for (const entry of entries) {
95
+ hash.update(entry.relativePath);
96
+ hash.update(':');
97
+ hash.update(entry.content);
98
+ }
99
+ return hash.digest('hex');
100
+ }
101
+ function collectFiles(baseDir, currentDir, out) {
102
+ const items = fs.readdirSync(currentDir, { withFileTypes: true });
103
+ for (const item of items) {
104
+ if (HASH_EXCLUDE_DIRS.has(item.name))
105
+ continue;
106
+ const fullPath = path.join(currentDir, item.name);
107
+ if (item.isDirectory()) {
108
+ collectFiles(baseDir, fullPath, out);
109
+ }
110
+ else if (item.isFile()) {
111
+ out.push({
112
+ relativePath: path.relative(baseDir, fullPath).split(path.sep).join('/'),
113
+ content: fs.readFileSync(fullPath),
114
+ });
115
+ }
116
+ }
117
+ }