obsidian-plugin-config 1.0.2

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 (55) hide show
  1. package/.vscode/settings.json +4 -0
  2. package/README.md +45 -0
  3. package/bin/obsidian-inject.js +98 -0
  4. package/obsidian-plugin-config-1.0.2.tgz +0 -0
  5. package/package.json +88 -0
  6. package/scripts/acp.ts +71 -0
  7. package/scripts/build-npm.ts +137 -0
  8. package/scripts/esbuild.config.ts +311 -0
  9. package/scripts/help.ts +46 -0
  10. package/scripts/inject-path.ts +487 -0
  11. package/scripts/inject-prompt.ts +399 -0
  12. package/scripts/open-editor.mjs +18 -0
  13. package/scripts/release.ts +97 -0
  14. package/scripts/update-exports.js +91 -0
  15. package/scripts/update-version-config.ts +98 -0
  16. package/scripts/update-version.ts +102 -0
  17. package/scripts/utils.ts +117 -0
  18. package/src/index.ts +6 -0
  19. package/src/main_test.ts +106 -0
  20. package/src/modals/GenericConfirmModal.ts +67 -0
  21. package/src/modals/index.ts +3 -0
  22. package/src/test-centralized-utils.ts +23 -0
  23. package/src/tools/index.ts +9 -0
  24. package/src/utils/NoticeHelper.ts +102 -0
  25. package/src/utils/SettingsHelper.ts +180 -0
  26. package/src/utils/index.ts +3 -0
  27. package/templates/.vscode/settings.json +4 -0
  28. package/templates/eslint.config.ts +48 -0
  29. package/templates/help-plugin.ts +39 -0
  30. package/templates/package-versions.json +28 -0
  31. package/templates/tsconfig.json +37 -0
  32. package/test-plugin/manifest.json +10 -0
  33. package/test-plugin/package.json +38 -0
  34. package/test-plugin/scripts/acp.ts +71 -0
  35. package/test-plugin/scripts/esbuild.config.ts +165 -0
  36. package/test-plugin/scripts/help.ts +29 -0
  37. package/test-plugin/scripts/release.ts +97 -0
  38. package/test-plugin/scripts/update-version.ts +102 -0
  39. package/test-plugin/scripts/utils.ts +117 -0
  40. package/test-plugin/src/main.ts +11 -0
  41. package/test-plugin/yarn.lock +386 -0
  42. package/test-plugin-v2/main.js +5 -0
  43. package/test-plugin-v2/manifest.json +10 -0
  44. package/test-plugin-v2/package.json +40 -0
  45. package/test-plugin-v2/scripts/acp.ts +71 -0
  46. package/test-plugin-v2/scripts/esbuild.config.ts +165 -0
  47. package/test-plugin-v2/scripts/help.ts +29 -0
  48. package/test-plugin-v2/scripts/release.ts +97 -0
  49. package/test-plugin-v2/scripts/update-version.ts +102 -0
  50. package/test-plugin-v2/scripts/utils.ts +117 -0
  51. package/test-plugin-v2/src/main.ts +11 -0
  52. package/test-plugin-v2/tsconfig.json +31 -0
  53. package/test-plugin-v2/yarn.lock +1986 -0
  54. package/tsconfig.json +38 -0
  55. package/versions.json +5 -0
@@ -0,0 +1,311 @@
1
+ import esbuild from "esbuild";
2
+ import process from "process";
3
+ import builtins from "builtin-modules";
4
+ import { config } from "dotenv";
5
+ import path from "path";
6
+ import { readFileSync } from "fs";
7
+ import { rm } from "fs/promises";
8
+ import { isValidPath, copyFilesToTargetDir, askQuestion, createReadlineInterface } from "./utils.js";
9
+
10
+ // Determine the plugin directory (where the script is called from)
11
+ const pluginDir = process.cwd();
12
+
13
+ // Create readline interface for prompts
14
+ const rl = createReadlineInterface();
15
+
16
+ async function promptForVaultPath(envKey: string): Promise<string> {
17
+ const vaultType = envKey === "REAL_VAULT" ? "real" : "test";
18
+ const usage = envKey === "REAL_VAULT"
19
+ ? "for final plugin installation"
20
+ : "for development and testing";
21
+
22
+ console.log(`❓ ${envKey} path is required ${usage}`);
23
+ const path = await askQuestion(`📝 Enter your ${vaultType} vault path (or Ctrl+C to cancel): `, rl);
24
+
25
+ if (!path) {
26
+ console.log('❌ No path provided, exiting...');
27
+ process.exit(1);
28
+ }
29
+
30
+ return path;
31
+ }
32
+
33
+ async function promptForBothVaults(): Promise<void> {
34
+ console.log(`❓ Both vault paths are required for external development`);
35
+ console.log(` TEST_VAULT: for development and testing (yarn dev)`);
36
+ console.log(` REAL_VAULT: for final plugin installation (yarn real)`);
37
+
38
+ let confirmed = false;
39
+ while (!confirmed) {
40
+ const testPath = await askQuestion(`📝 Enter your test vault path: `, rl);
41
+ if (!testPath) {
42
+ console.log('❌ No test vault path provided, exiting...');
43
+ process.exit(1);
44
+ }
45
+
46
+ const realPath = await askQuestion(`📝 Enter your real vault path: `, rl);
47
+ if (!realPath) {
48
+ console.log('❌ No real vault path provided, exiting...');
49
+ process.exit(1);
50
+ }
51
+
52
+ // Show confirmation
53
+ console.log(`\n📋 Vault paths entered:`);
54
+ console.log(` TEST_VAULT: ${testPath}`);
55
+ console.log(` REAL_VAULT: ${realPath}`);
56
+
57
+ const confirm = await askQuestion(`✅ Are these paths correct? (y/n): `, rl);
58
+ if (confirm.toLowerCase() === 'y' || confirm.toLowerCase() === 'yes') {
59
+ await updateEnvFile("TEST_VAULT", testPath);
60
+ await updateEnvFile("REAL_VAULT", realPath);
61
+ confirmed = true;
62
+ } else {
63
+ console.log(`🔄 Let's try again...\n`);
64
+ }
65
+ }
66
+ }
67
+
68
+ async function updateEnvFile(envKey: string, vaultPath: string): Promise<void> {
69
+ const envPath = path.join(pluginDir, '.env');
70
+ let envContent = '';
71
+
72
+ // Read existing .env if it exists
73
+ try {
74
+ envContent = readFileSync(envPath, 'utf8');
75
+ } catch {
76
+ // File doesn't exist, start with empty content
77
+ }
78
+
79
+ // Update or add the variable
80
+ const regex = new RegExp(`^${envKey}=.*$`, 'm');
81
+ const newLine = `${envKey}=${vaultPath}`;
82
+
83
+ if (regex.test(envContent)) {
84
+ envContent = envContent.replace(regex, newLine);
85
+ } else {
86
+ envContent += envContent.endsWith('\n') ? '' : '\n';
87
+ envContent += newLine + '\n';
88
+ }
89
+
90
+ // Write back to .env
91
+ await import('fs').then(fs => fs.writeFileSync(envPath, envContent));
92
+ console.log(`✅ Updated ${envKey} in .env file`);
93
+ }
94
+
95
+ function getVaultPath(vaultPath: string): string {
96
+ // Check if the path already contains the plugins directory path
97
+ const pluginsPath = path.join(".obsidian", "plugins");
98
+ if (vaultPath.includes(pluginsPath)) {
99
+ return path.join(vaultPath, manifest.id);
100
+ } else {
101
+ return path.join(vaultPath, ".obsidian", "plugins", manifest.id);
102
+ }
103
+ }
104
+ const manifestPath = path.join(pluginDir, "manifest.json");
105
+ const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
106
+
107
+ config();
108
+
109
+ const EXTERNAL_DEPS = [
110
+ "obsidian",
111
+ "electron",
112
+ "@codemirror/autocomplete",
113
+ "@codemirror/collab",
114
+ "@codemirror/commands",
115
+ "@codemirror/language",
116
+ "@codemirror/lint",
117
+ "@codemirror/search",
118
+ "@codemirror/state",
119
+ "@codemirror/view",
120
+ "@lezer/common",
121
+ "@lezer/highlight",
122
+ "@lezer/lr",
123
+ ...builtins
124
+ ];
125
+
126
+ const BANNER = `/*
127
+ THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
128
+ if you want to view the source, please visit the github repository of this plugin
129
+ */`;
130
+
131
+ async function validateEnvironment(): Promise<void> {
132
+ const srcMainPath = path.join(pluginDir, "src/main.ts");
133
+ if (!await isValidPath(srcMainPath)) {
134
+ throw new Error("Invalid path for src/main.ts. main.ts must be in the src directory");
135
+ }
136
+ if (!await isValidPath(manifestPath)) {
137
+ throw new Error("Invalid path for manifest.json");
138
+ }
139
+ }
140
+
141
+ async function getBuildPath(isProd: boolean): Promise<string> {
142
+ // Check if we should use real vault (either -r flag or "real" argument)
143
+ const useRealVault = process.argv.includes("-r") || process.argv.includes("real");
144
+
145
+ // If production build without redirection, return plugin directory
146
+ if (isProd && !useRealVault) {
147
+ return pluginDir;
148
+ }
149
+
150
+ // Determine which path to use
151
+ const envKey = useRealVault ? "REAL_VAULT" : "TEST_VAULT";
152
+ const vaultPath = process.env[envKey]?.trim();
153
+
154
+ // Handle empty vault paths with intelligent logic
155
+ if (!vaultPath) {
156
+ // Check if we're in Obsidian plugins folder
157
+ const currentPath = process.cwd();
158
+ const isInObsidianPlugins = currentPath.includes('.obsidian/plugins') ||
159
+ currentPath.includes('.obsidian\\plugins');
160
+
161
+ const testVault = process.env.TEST_VAULT?.trim();
162
+ const realVault = process.env.REAL_VAULT?.trim();
163
+
164
+ // YARN REAL logic
165
+ if (envKey === "REAL_VAULT") {
166
+ if (!isInObsidianPlugins) {
167
+ // External development: ask for both if missing
168
+ if (!testVault || !realVault) {
169
+ await promptForBothVaults();
170
+ config();
171
+ // After updating both, get the REAL_VAULT path directly
172
+ const updatedRealVault = process.env.REAL_VAULT?.trim();
173
+ if (updatedRealVault) {
174
+ return getVaultPath(updatedRealVault);
175
+ }
176
+ } else {
177
+ const newPath = await promptForVaultPath(envKey);
178
+ await updateEnvFile(envKey, newPath);
179
+ config();
180
+ return getVaultPath(newPath);
181
+ }
182
+ } else {
183
+ // In obsidian/plugins: ask only for REAL_VAULT
184
+ const newPath = await promptForVaultPath(envKey);
185
+ await updateEnvFile(envKey, newPath);
186
+ return getVaultPath(newPath);
187
+ }
188
+ }
189
+
190
+ // YARN DEV/START logic
191
+ if (envKey === "TEST_VAULT") {
192
+ if (!isInObsidianPlugins) {
193
+ // External development: ask for both if missing
194
+ if (!testVault || !realVault) {
195
+ await promptForBothVaults();
196
+ config();
197
+ // After updating both, get the TEST_VAULT path directly
198
+ const updatedTestVault = process.env.TEST_VAULT?.trim();
199
+ if (updatedTestVault) {
200
+ return getVaultPath(updatedTestVault);
201
+ }
202
+ } else {
203
+ const newPath = await promptForVaultPath(envKey);
204
+ await updateEnvFile(envKey, newPath);
205
+ return getVaultPath(newPath);
206
+ }
207
+ } else {
208
+ // In obsidian/plugins: allow in-place development
209
+ console.log(`ℹ️ Building in Obsidian plugins folder (in-place development)`);
210
+ return pluginDir;
211
+ }
212
+ }
213
+ }
214
+
215
+ // If we reach here, use the vault path directly
216
+ return vaultPath ? getVaultPath(vaultPath) : pluginDir;
217
+ }
218
+
219
+ async function createBuildContext(buildPath: string, isProd: boolean, entryPoints: string[]): Promise<esbuild.BuildContext> {
220
+ return await esbuild.context({
221
+ banner: { js: BANNER },
222
+ minify: isProd,
223
+ entryPoints,
224
+ bundle: true,
225
+ external: EXTERNAL_DEPS,
226
+ format: "cjs",
227
+ target: "esNext",
228
+ platform: "node",
229
+ logLevel: "info",
230
+ sourcemap: isProd ? false : "inline",
231
+ treeShaking: true,
232
+ outdir: buildPath,
233
+ outbase: path.join(pluginDir, "src"),
234
+ plugins: [
235
+ // Plugin pour gérer les alias de chemin
236
+ {
237
+ name: "path-alias",
238
+ setup: (build): void => {
239
+ build.onResolve({ filter: /^@config\// }, (args) => {
240
+ const relativePath = args.path.replace(/^@config\//, "");
241
+ return {
242
+ path: path.resolve("../obsidian-plugin-config/src", relativePath)
243
+ };
244
+ });
245
+
246
+ build.onResolve({ filter: /^@config-scripts\// }, (args) => {
247
+ const relativePath = args.path.replace(/^@config-scripts\//, "");
248
+ return {
249
+ path: path.resolve("../obsidian-plugin-config/scripts", relativePath)
250
+ };
251
+ });
252
+ }
253
+ },
254
+ {
255
+ name: "copy-to-plugins-folder",
256
+ setup: (build): void => {
257
+ build.onEnd(async () => {
258
+ // if real or build
259
+ if (isProd) {
260
+ if (process.argv.includes("-r")) {
261
+ await copyFilesToTargetDir(buildPath);
262
+ console.log(`Successfully installed in ${buildPath}`);
263
+ } else {
264
+ const folderToRemove = path.join(buildPath, "_.._");
265
+ if (await isValidPath(folderToRemove)) {
266
+ await rm(folderToRemove, { recursive: true });
267
+ }
268
+ console.log("Built done in initial folder");
269
+ }
270
+ }
271
+ // if watch (dev)
272
+ else {
273
+ await copyFilesToTargetDir(buildPath);
274
+ }
275
+ });
276
+ }
277
+ }
278
+ ]
279
+ });
280
+ }
281
+
282
+ async function main(): Promise<void> {
283
+ try {
284
+ await validateEnvironment();
285
+ const isProd = process.argv[2] === "production";
286
+ const buildPath = await getBuildPath(isProd);
287
+ console.log(buildPath === pluginDir
288
+ ? "Building in initial folder"
289
+ : `Building in ${buildPath}`);
290
+ const srcStylesPath = path.join(pluginDir, "src/styles.css");
291
+ const rootStylesPath = path.join(pluginDir, "styles.css");
292
+ const stylePath = await isValidPath(srcStylesPath) ? srcStylesPath : await isValidPath(rootStylesPath) ? rootStylesPath : "";
293
+ const mainTsPath = path.join(pluginDir, "src/main.ts");
294
+ const entryPoints = stylePath ? [mainTsPath, stylePath] : [mainTsPath];
295
+ const context = await createBuildContext(buildPath, isProd, entryPoints);
296
+
297
+ if (isProd) {
298
+ await context.rebuild();
299
+ rl.close();
300
+ process.exit(0);
301
+ } else {
302
+ await context.watch();
303
+ }
304
+ } catch (error) {
305
+ console.error("Build failed:", error);
306
+ rl.close();
307
+ process.exit(1);
308
+ }
309
+ }
310
+
311
+ main().catch(console.error);
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env tsx
2
+
3
+ console.log(`
4
+ Obsidian Plugin Config - Command Reference
5
+ Système d'injection pour plugins Obsidian autonomes
6
+
7
+ STRATÉGIE NPM GLOBAL:
8
+ npm install -g obsidian-plugin-config # Installation globale (une seule fois)
9
+ obsidian-inject # Injection depuis n'importe où
10
+ obsidian-inject /chemin/vers/plugin # Injection par chemin
11
+
12
+ INJECTION LOCALE (développement):
13
+ yarn inject-path <chemin> Injection par chemin depuis plugin-config
14
+ yarn inject <chemin> Alias pour inject-path
15
+
16
+ MIGRATION (développement):
17
+ yarn migrate, m <chemin> Migration plugin vers architecture centralisée
18
+ yarn migrate --dry-run Aperçu des changements sans appliquer
19
+
20
+ MAINTENANCE:
21
+ yarn acp Add, commit, and push changes
22
+ yarn update-version, v Update version
23
+ yarn help, h Afficher cette aide
24
+
25
+ EXEMPLES D'UTILISATION:
26
+ # Installation globale (recommandée)
27
+ npm install -g obsidian-plugin-config
28
+ cd mon-plugin && obsidian-inject
29
+
30
+ # Développement local
31
+ yarn inject-path "../mon-plugin"
32
+ yarn inject "C:\\Users\\dev\\plugins\\mon-plugin"
33
+
34
+ CE QUI EST INJECTÉ:
35
+ ✅ Scripts locaux (esbuild.config.ts, acp.ts, utils.ts, etc.)
36
+ ✅ Configuration package.json (scripts, dépendances)
37
+ ✅ Protection yarn obligatoire
38
+ ✅ Installation automatique des dépendances
39
+
40
+ ARCHITECTURE:
41
+ - Plugin devient AUTONOME avec scripts locaux
42
+ - Aucune dépendance externe requise après injection
43
+ - Mise à jour possible via re-injection
44
+
45
+ COMPTE NPM: 3c0d (connecté)
46
+ `);