@navneet_25/tempjs 1.1.0 → 3.0.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 (100) hide show
  1. package/README.md +800 -35
  2. package/cli/brand-manager.js +277 -78
  3. package/cli/config.js +22 -1
  4. package/cli/copy.js +4 -18
  5. package/cli/db-setup.js +170 -49
  6. package/cli/doctor.js +393 -0
  7. package/cli/fetch-core-modules.js +130 -0
  8. package/cli/fetch.js +47 -29
  9. package/cli/file-tree.js +113 -0
  10. package/cli/fs-ignore.js +60 -0
  11. package/cli/index.js +274 -112
  12. package/cli/info.js +115 -0
  13. package/cli/init-options.js +209 -0
  14. package/cli/module-manager.js +168 -0
  15. package/cli/parse-args.js +177 -0
  16. package/cli/progress.js +33 -0
  17. package/cli/project-stamp.js +69 -0
  18. package/cli/prompt.js +19 -0
  19. package/cli/template-resolver.js +48 -0
  20. package/cli/theme-manager.js +28 -2
  21. package/cli/update.js +227 -0
  22. package/cli/version-manager.js +518 -0
  23. package/package.json +31 -4
  24. package/packages/core/modules/README.md +72 -0
  25. package/packages/core/modules/blog-compose/app/admin/components/blog-compose-form.ts +44 -0
  26. package/packages/core/modules/blog-compose/app/admin/hooks/useBlogPosts.ts +103 -0
  27. package/packages/core/modules/blog-compose/app/admin/panels/BlogComposePanel.tsx +388 -0
  28. package/packages/core/modules/blog-compose/app/api/blog-posts/[id]/route.ts +29 -0
  29. package/packages/core/modules/blog-compose/app/api/blog-posts/route.ts +21 -0
  30. package/packages/core/modules/blog-compose/app/blog/[slug]/page.tsx +79 -0
  31. package/packages/core/modules/blog-compose/app/blog/layout.tsx +22 -0
  32. package/packages/core/modules/blog-compose/app/blog/page.tsx +102 -0
  33. package/packages/core/modules/blog-compose/app/components/BlogSection.tsx +74 -0
  34. package/packages/core/modules/blog-compose/app/components/BlogShell.tsx +36 -0
  35. package/packages/core/modules/blog-compose/app/components/BlogSidebar.tsx +112 -0
  36. package/packages/core/modules/blog-compose/lib/blog/compose/annotate-text.tsx +103 -0
  37. package/packages/core/modules/blog-compose/lib/blog/compose/blocks/media-blocks.tsx +97 -0
  38. package/packages/core/modules/blog-compose/lib/blog/compose/blocks/text-blocks.tsx +115 -0
  39. package/packages/core/modules/blog-compose/lib/blog/compose/index.ts +21 -0
  40. package/packages/core/modules/blog-compose/lib/blog/compose/interpreter.tsx +55 -0
  41. package/packages/core/modules/blog-compose/lib/blog/compose/registry.ts +276 -0
  42. package/packages/core/modules/blog-compose/lib/blog/compose/types.ts +128 -0
  43. package/packages/core/modules/blog-compose/lib/blog/register-sitemap.ts +18 -0
  44. package/packages/core/modules/blog-compose/lib/controllers/BlogComposeController.ts +2 -0
  45. package/packages/core/modules/blog-compose/lib/features/blog-compose/blog-compose.controller.ts +78 -0
  46. package/packages/core/modules/blog-compose/lib/features/blog-compose/blog-compose.repository.ts +78 -0
  47. package/packages/core/modules/blog-compose/lib/features/blog-compose/blog-compose.service.ts +72 -0
  48. package/packages/core/modules/blog-compose/lib/features/blog-compose/blog-compose.types.ts +20 -0
  49. package/packages/core/modules/blog-compose/lib/features/blog-compose/index.ts +7 -0
  50. package/packages/core/modules/blog-compose/prisma/blog-compose.prisma +13 -0
  51. package/packages/core/modules/enquiry-modal/app/components/EnquiryModal.tsx +308 -0
  52. package/packages/core/modules/footer/app/components/Footer.tsx +127 -0
  53. package/packages/core/modules/gallery/app/admin/components/GalleryFormModal.tsx +132 -0
  54. package/packages/core/modules/gallery/app/admin/components/GalleryList.tsx +142 -0
  55. package/packages/core/modules/gallery/app/admin/hooks/useGallery.ts +72 -0
  56. package/packages/core/modules/gallery/app/api/gallery/[id]/route.ts +29 -0
  57. package/packages/core/modules/gallery/app/api/gallery/route.ts +22 -0
  58. package/packages/core/modules/gallery/app/components/GallerySection.tsx +92 -0
  59. package/packages/core/modules/gallery/app/gallery/layout.tsx +12 -0
  60. package/packages/core/modules/gallery/app/gallery/page.tsx +179 -0
  61. package/packages/core/modules/gallery/lib/controllers/GalleryController.ts +2 -0
  62. package/packages/core/modules/gallery/lib/features/gallery/gallery.controller.ts +78 -0
  63. package/packages/core/modules/gallery/lib/features/gallery/gallery.repository.ts +55 -0
  64. package/packages/core/modules/gallery/lib/features/gallery/gallery.service.ts +43 -0
  65. package/packages/core/modules/gallery/lib/features/gallery/gallery.types.ts +17 -0
  66. package/packages/core/modules/gallery/lib/features/gallery/index.ts +4 -0
  67. package/packages/core/modules/gallery/prisma/gallery.prisma +11 -0
  68. package/packages/core/modules/hero-simple/app/components/Hero.tsx +160 -0
  69. package/packages/core/modules/legal-pages/app/components/LegalDocumentPage.tsx +61 -0
  70. package/packages/core/modules/legal-pages/app/privacy-policy/page.tsx +19 -0
  71. package/packages/core/modules/legal-pages/app/terms-and-conditions/page.tsx +19 -0
  72. package/packages/core/modules/reviews/app/admin/components/ReviewFormModal.tsx +110 -0
  73. package/packages/core/modules/reviews/app/admin/components/ReviewsList.tsx +116 -0
  74. package/packages/core/modules/reviews/app/admin/hooks/useReviews.ts +70 -0
  75. package/packages/core/modules/reviews/app/api/reviews/[id]/route.ts +29 -0
  76. package/packages/core/modules/reviews/app/api/reviews/route.ts +17 -0
  77. package/packages/core/modules/reviews/app/components/ReviewsSection.tsx +100 -0
  78. package/packages/core/modules/reviews/lib/controllers/ReviewController.ts +2 -0
  79. package/packages/core/modules/reviews/lib/features/reviews/index.ts +3 -0
  80. package/packages/core/modules/reviews/lib/features/reviews/review.controller.ts +64 -0
  81. package/packages/core/modules/reviews/lib/features/reviews/review.repository.ts +50 -0
  82. package/packages/core/modules/reviews/lib/features/reviews/review.service.ts +38 -0
  83. package/packages/core/modules/reviews/prisma/reviews.prisma +9 -0
  84. package/packages/core/modules/seo/app/components/SiteJsonLd.tsx +16 -0
  85. package/packages/core/modules/seo/app/robots.ts +30 -0
  86. package/packages/core/modules/seo/app/sitemap.ts +9 -0
  87. package/packages/core/modules/seo/lib/seo/index.ts +5 -0
  88. package/packages/core/modules/seo/lib/seo/json-ld.ts +128 -0
  89. package/packages/core/modules/seo/lib/seo/metadata.ts +65 -0
  90. package/packages/core/modules/seo/lib/seo/sitemap.ts +82 -0
  91. package/packages/core/modules/seo/lib/seo/types.ts +30 -0
  92. package/packages/core/modules/seo/lib/seo/urls.ts +27 -0
  93. package/packages/core/modules/theme-modes/app/components/ThemeModeInit.tsx +24 -0
  94. package/packages/core/modules/theme-modes/app/components/ThemeModeToggle.tsx +58 -0
  95. package/packages/core/modules.json +140 -0
  96. package/packages/core/prisma/schema.prisma +33 -0
  97. package/scripts/module-installer-core.mjs +657 -0
  98. package/scripts/template-modules-admin.mjs +366 -0
  99. package/scripts/template-modules-home.mjs +120 -0
  100. package/templates.json +188 -3
@@ -0,0 +1,48 @@
1
+ import { removeDirectory } from "./copy.js";
2
+ import { fetchTemplateFromGitHub, loadLocalTemplate } from "./fetch.js";
3
+
4
+ /**
5
+ * @typedef {{
6
+ * templateRoot: string,
7
+ * cleanupDir: string,
8
+ * stats: import('./fetch.js').FetchStats,
9
+ * release: () => void
10
+ * }} ResolvedTemplate
11
+ */
12
+
13
+ /**
14
+ * Resolve template source from local package or remote GitHub tarball.
15
+ * @param {{
16
+ * repo: import('./config.js').RepositoryConfig,
17
+ * packageRoot: string,
18
+ * templateDirectory: string,
19
+ * useRemote: boolean
20
+ * }} options
21
+ * @returns {Promise<ResolvedTemplate>}
22
+ */
23
+ export async function resolveTemplateSource(options) {
24
+ const { repo, packageRoot, templateDirectory, useRemote } = options;
25
+
26
+ let result = null;
27
+
28
+ if (!useRemote) {
29
+ result = await loadLocalTemplate(packageRoot, repo.templatesPath, templateDirectory);
30
+ }
31
+
32
+ if (!result) {
33
+ result = await fetchTemplateFromGitHub(repo, templateDirectory);
34
+ }
35
+
36
+ const cleanupDir = result.cleanupDir;
37
+
38
+ return {
39
+ templateRoot: result.templateRoot,
40
+ cleanupDir,
41
+ stats: result.stats,
42
+ release: () => {
43
+ if (cleanupDir) {
44
+ removeDirectory(cleanupDir);
45
+ }
46
+ },
47
+ };
48
+ }
@@ -152,6 +152,26 @@ export function getSavedConfig(targetDir) {
152
152
  return {};
153
153
  }
154
154
 
155
+ export function resolveThemeId(id) {
156
+ const theme = THEMES.find((t) => t.id === id);
157
+ if (!theme) {
158
+ throw new Error(
159
+ `Unknown theme: ${id}. Valid options: ${THEMES.map((t) => t.id).join(", ")}`
160
+ );
161
+ }
162
+ return theme.id;
163
+ }
164
+
165
+ export function resolveFontId(id) {
166
+ const font = FONTS.find((f) => f.id === id);
167
+ if (!font) {
168
+ throw new Error(
169
+ `Unknown font: ${id}. Valid options: ${FONTS.map((f) => f.id).join(", ")}`
170
+ );
171
+ }
172
+ return font.id;
173
+ }
174
+
155
175
  async function promptSelection(options, promptText, defaultValue) {
156
176
  const rl = createInterface({ input, output });
157
177
  try {
@@ -179,11 +199,17 @@ async function promptSelection(options, promptText, defaultValue) {
179
199
  }
180
200
  }
181
201
 
182
- export async function promptTheme(currentThemeId = "theme1") {
202
+ export async function promptTheme(currentThemeId = "theme1", options = {}) {
203
+ if (options.yes || options.theme) {
204
+ return resolveThemeId(options.theme || currentThemeId || "theme1");
205
+ }
183
206
  return promptSelection(THEMES, "Available Themes:", currentThemeId);
184
207
  }
185
208
 
186
- export async function promptFont(currentFontId = "default") {
209
+ export async function promptFont(currentFontId = "default", options = {}) {
210
+ if (options.yes || options.font) {
211
+ return resolveFontId(options.font || currentFontId || "default");
212
+ }
187
213
  return promptSelection(FONTS, "Available Font combinations:", currentFontId);
188
214
  }
189
215
 
package/cli/update.js ADDED
@@ -0,0 +1,227 @@
1
+ import { cpSync, existsSync, mkdirSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { loadManifest, resolveRepositoryConfig, getPackageRoot } from "./config.js";
4
+ import { isUpdateProtected, shouldSkipFileName } from "./fs-ignore.js";
5
+ import {
6
+ collectFileHashes,
7
+ diffTemplateTrees,
8
+ hashFileContents,
9
+ } from "./file-tree.js";
10
+ import { readProjectStamp, writeProjectStamp } from "./project-stamp.js";
11
+ import { confirmYesNo } from "./prompt.js";
12
+ import { resolveTemplateSource } from "./template-resolver.js";
13
+
14
+ /**
15
+ * @param {import('./file-tree.js').UpdateDiff} diff
16
+ * @param {{
17
+ * projectVersion: string,
18
+ * latestVersion: string,
19
+ * templateName: string
20
+ * }} meta
21
+ */
22
+ export function printUpdateReport(diff, meta) {
23
+ console.log(`\nTemplate update report: ${meta.templateName}`);
24
+ console.log(` Project version: ${meta.projectVersion}`);
25
+ console.log(` Latest version: ${meta.latestVersion}`);
26
+ console.log("");
27
+
28
+ if (
29
+ diff.newFiles.length === 0 &&
30
+ diff.safeUpdates.length === 0 &&
31
+ diff.conflicts.length === 0 &&
32
+ diff.removedFromTemplate.length === 0
33
+ ) {
34
+ console.log("Your project is up to date with the latest template.");
35
+ return;
36
+ }
37
+
38
+ if (diff.newFiles.length > 0) {
39
+ console.log(`New files in template (${diff.newFiles.length}):`);
40
+ diff.newFiles.slice(0, 25).forEach((p) => console.log(` + ${p}`));
41
+ if (diff.newFiles.length > 25) {
42
+ console.log(` ... and ${diff.newFiles.length - 25} more`);
43
+ }
44
+ console.log("");
45
+ }
46
+
47
+ if (diff.safeUpdates.length > 0) {
48
+ console.log(`Safe updates (${diff.safeUpdates.length}) — template changed, you did not edit:`);
49
+ diff.safeUpdates.slice(0, 25).forEach((p) => console.log(` ~ ${p}`));
50
+ if (diff.safeUpdates.length > 25) {
51
+ console.log(` ... and ${diff.safeUpdates.length - 25} more`);
52
+ }
53
+ console.log("");
54
+ }
55
+
56
+ if (diff.conflicts.length > 0) {
57
+ console.log(`Conflicts (${diff.conflicts.length}) — you modified these files:`);
58
+ diff.conflicts.slice(0, 25).forEach((p) => console.log(` ! ${p}`));
59
+ if (diff.conflicts.length > 25) {
60
+ console.log(` ... and ${diff.conflicts.length - 25} more`);
61
+ }
62
+ console.log("");
63
+ }
64
+
65
+ if (meta.projectVersion !== meta.latestVersion) {
66
+ console.log(
67
+ `Version ${meta.projectVersion} → ${meta.latestVersion}: see CHANGELOG.md for release notes.`
68
+ );
69
+ console.log("");
70
+ }
71
+
72
+ if (diff.removedFromTemplate.length > 0) {
73
+ console.log(`Removed from template (${diff.removedFromTemplate.length}) — not deleted locally:`);
74
+ diff.removedFromTemplate.slice(0, 15).forEach((p) => console.log(` - ${p}`));
75
+ if (diff.removedFromTemplate.length > 15) {
76
+ console.log(` ... and ${diff.removedFromTemplate.length - 15} more`);
77
+ }
78
+ console.log("");
79
+ }
80
+
81
+ if (diff.upToDate.length > 0) {
82
+ console.log(`${diff.upToDate.length} file(s) already match the latest template.\n`);
83
+ }
84
+ }
85
+
86
+ /**
87
+ * @param {string} sourcePath
88
+ * @param {string} targetPath
89
+ */
90
+ export function copyTemplateFile(sourcePath, targetPath) {
91
+ mkdirSync(dirname(targetPath), { recursive: true });
92
+ cpSync(sourcePath, targetPath, { force: true });
93
+ }
94
+
95
+ /**
96
+ * @param {string} projectDir
97
+ * @param {import('./parse-args.js').CliFlags} flags
98
+ * @param {{ checkOnly: boolean }} mode
99
+ */
100
+ export async function runUpdate(projectDir, flags, mode) {
101
+ const stamp = readProjectStamp(projectDir);
102
+
103
+ if (!stamp) {
104
+ console.error("No .tempjs.json found in this directory.");
105
+ console.error("Run `tempjs <template-id>` here first, or this project was not created with tempjs.");
106
+ process.exitCode = 1;
107
+ return;
108
+ }
109
+
110
+ const manifest = loadManifest();
111
+ const entry = manifest.templates[stamp.template];
112
+ if (!entry) {
113
+ console.error(`Unknown template in .tempjs.json: ${stamp.template}`);
114
+ process.exitCode = 1;
115
+ return;
116
+ }
117
+
118
+ const repo = resolveRepositoryConfig(manifest.repository);
119
+ const packageRoot = getPackageRoot();
120
+ const useRemote =
121
+ flags.remote ||
122
+ process.env.TEMPLATE_USE_REMOTE === "1" ||
123
+ process.env.TEMPLATE_USE_REMOTE === "true";
124
+
125
+ const latestVersion = entry.version ?? "0.0.0";
126
+ let resolved = null;
127
+
128
+ try {
129
+ resolved = await resolveTemplateSource({
130
+ repo,
131
+ packageRoot,
132
+ templateDirectory: entry.directory,
133
+ useRemote,
134
+ });
135
+
136
+ const latestHashes = collectFileHashes(resolved.templateRoot);
137
+ const baselineHashes = stamp.fileHashes ?? {};
138
+ const currentHashes = {};
139
+
140
+ for (const path of Object.keys(latestHashes)) {
141
+ const projectPath = join(projectDir, path);
142
+ if (existsSync(projectPath) && !shouldSkipFileName(path.split("/").pop() ?? "")) {
143
+ currentHashes[path] = hashFileContents(projectPath);
144
+ }
145
+ }
146
+
147
+ const diff = diffTemplateTrees(baselineHashes, currentHashes, latestHashes);
148
+
149
+ printUpdateReport(diff, {
150
+ projectVersion: stamp.templateVersion,
151
+ latestVersion,
152
+ templateName: entry.name,
153
+ });
154
+
155
+ if (mode.checkOnly) {
156
+ if (stamp.templateVersion !== latestVersion) {
157
+ const changelogPath = join(projectDir, "CHANGELOG.md");
158
+ console.log("Run `tempjs update --merge` to apply non-conflicting template updates.");
159
+ if (existsSync(changelogPath)) {
160
+ console.log(`See CHANGELOG.md for what changed in v${latestVersion}.`);
161
+ } else {
162
+ console.log(
163
+ `After updating, read CHANGELOG.md in the template for v${latestVersion} changes.`
164
+ );
165
+ }
166
+ }
167
+ return;
168
+ }
169
+
170
+ const pathsToApply = [...diff.newFiles, ...diff.safeUpdates].filter(
171
+ (path) => !isUpdateProtected(path)
172
+ );
173
+
174
+ const skippedProtected = [...diff.newFiles, ...diff.safeUpdates].filter((path) =>
175
+ isUpdateProtected(path)
176
+ );
177
+ if (skippedProtected.length > 0) {
178
+ console.log(`Skipping ${skippedProtected.length} protected path(s) (brand, .env, etc.).`);
179
+ }
180
+
181
+ if (pathsToApply.length === 0) {
182
+ if (diff.conflicts.length > 0) {
183
+ console.log("\nNo safe updates to apply. Resolve conflicts manually.");
184
+ }
185
+ return;
186
+ }
187
+
188
+ const confirmed = await confirmYesNo(
189
+ `\nApply ${pathsToApply.length} non-conflicting update(s)? [y/N] `,
190
+ flags.yes
191
+ );
192
+
193
+ if (!confirmed) {
194
+ console.log("Aborted.");
195
+ return;
196
+ }
197
+
198
+ for (const relPath of pathsToApply) {
199
+ const from = join(resolved.templateRoot, relPath);
200
+ const to = join(projectDir, relPath);
201
+ copyTemplateFile(from, to);
202
+ }
203
+
204
+ await writeProjectStamp(projectDir, {
205
+ templateId: stamp.template,
206
+ templateVersion: latestVersion,
207
+ templateDirectory: entry.directory,
208
+ repository: `${repo.owner}/${repo.repo}`,
209
+ branch: repo.branch,
210
+ sourceDir: resolved.templateRoot,
211
+ isUpdate: true,
212
+ });
213
+
214
+ console.log(`\nApplied ${pathsToApply.length} update(s). Project stamped at template v${latestVersion}.`);
215
+
216
+ if (diff.conflicts.length > 0) {
217
+ console.log(`${diff.conflicts.length} conflict(s) still need manual review.`);
218
+ }
219
+ } catch (error) {
220
+ console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
221
+ process.exitCode = 1;
222
+ } finally {
223
+ if (resolved) {
224
+ resolved.release();
225
+ }
226
+ }
227
+ }