genomic 4.0.1 → 5.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 (92) hide show
  1. package/README.md +153 -1127
  2. package/cache/cache-manager.d.ts +60 -0
  3. package/cache/cache-manager.js +228 -0
  4. package/cache/types.d.ts +22 -0
  5. package/esm/cache/cache-manager.js +191 -0
  6. package/esm/git/git-cloner.js +92 -0
  7. package/esm/index.js +41 -4
  8. package/esm/licenses.js +120 -0
  9. package/esm/scaffolder/index.js +2 -0
  10. package/esm/scaffolder/template-scaffolder.js +310 -0
  11. package/esm/scaffolder/types.js +1 -0
  12. package/esm/template/extract.js +162 -0
  13. package/esm/template/prompt.js +103 -0
  14. package/esm/template/replace.js +110 -0
  15. package/esm/template/templatizer.js +73 -0
  16. package/esm/template/types.js +1 -0
  17. package/esm/types.js +1 -0
  18. package/esm/utils/npm-version-check.js +52 -0
  19. package/esm/utils/types.js +1 -0
  20. package/git/git-cloner.d.ts +32 -0
  21. package/git/git-cloner.js +129 -0
  22. package/git/types.d.ts +15 -0
  23. package/index.d.ts +29 -4
  24. package/index.js +43 -4
  25. package/licenses-templates/APACHE-2.0.txt +18 -0
  26. package/licenses-templates/BSD-3-CLAUSE.txt +28 -0
  27. package/licenses-templates/CLOSED.txt +20 -0
  28. package/licenses-templates/GPL-3.0.txt +18 -0
  29. package/licenses-templates/ISC.txt +16 -0
  30. package/licenses-templates/MIT.txt +22 -0
  31. package/licenses-templates/MPL-2.0.txt +8 -0
  32. package/licenses-templates/UNLICENSE.txt +22 -0
  33. package/licenses.d.ts +18 -0
  34. package/licenses.js +162 -0
  35. package/package.json +9 -14
  36. package/scaffolder/index.d.ts +2 -0
  37. package/{question → scaffolder}/index.js +1 -0
  38. package/scaffolder/template-scaffolder.d.ts +91 -0
  39. package/scaffolder/template-scaffolder.js +347 -0
  40. package/scaffolder/types.d.ts +191 -0
  41. package/scaffolder/types.js +2 -0
  42. package/template/extract.d.ts +7 -0
  43. package/template/extract.js +198 -0
  44. package/template/prompt.d.ts +19 -0
  45. package/template/prompt.js +107 -0
  46. package/template/replace.d.ts +9 -0
  47. package/template/replace.js +146 -0
  48. package/template/templatizer.d.ts +33 -0
  49. package/template/templatizer.js +110 -0
  50. package/template/types.d.ts +18 -0
  51. package/template/types.js +2 -0
  52. package/types.d.ts +99 -0
  53. package/types.js +2 -0
  54. package/utils/npm-version-check.d.ts +17 -0
  55. package/utils/npm-version-check.js +57 -0
  56. package/utils/types.d.ts +6 -0
  57. package/utils/types.js +2 -0
  58. package/commander.d.ts +0 -21
  59. package/commander.js +0 -57
  60. package/esm/commander.js +0 -50
  61. package/esm/keypress.js +0 -95
  62. package/esm/prompt.js +0 -1024
  63. package/esm/question/index.js +0 -1
  64. package/esm/resolvers/date.js +0 -11
  65. package/esm/resolvers/git.js +0 -26
  66. package/esm/resolvers/index.js +0 -103
  67. package/esm/resolvers/npm.js +0 -24
  68. package/esm/resolvers/workspace.js +0 -141
  69. package/esm/utils.js +0 -12
  70. package/keypress.d.ts +0 -45
  71. package/keypress.js +0 -99
  72. package/prompt.d.ts +0 -116
  73. package/prompt.js +0 -1032
  74. package/question/index.d.ts +0 -1
  75. package/question/types.d.ts +0 -65
  76. package/resolvers/date.d.ts +0 -5
  77. package/resolvers/date.js +0 -14
  78. package/resolvers/git.d.ts +0 -11
  79. package/resolvers/git.js +0 -30
  80. package/resolvers/index.d.ts +0 -63
  81. package/resolvers/index.js +0 -111
  82. package/resolvers/npm.d.ts +0 -10
  83. package/resolvers/npm.js +0 -28
  84. package/resolvers/types.d.ts +0 -12
  85. package/resolvers/workspace.d.ts +0 -6
  86. package/resolvers/workspace.js +0 -144
  87. package/utils.d.ts +0 -2
  88. package/utils.js +0 -16
  89. /package/{question → cache}/types.js +0 -0
  90. /package/esm/{question → cache}/types.js +0 -0
  91. /package/esm/{resolvers → git}/types.js +0 -0
  92. /package/{resolvers → git}/types.js +0 -0
@@ -0,0 +1,22 @@
1
+ This is free and unencumbered software released into the public domain.
2
+
3
+ Anyone is free to copy, modify, publish, use, compile, sell, or
4
+ distribute this software, either in source code form or as a compiled
5
+ binary, for any purpose, commercial or non-commercial, and by any means.
6
+
7
+ In jurisdictions that recognize copyright laws, the author or authors
8
+ of this software dedicate any and all copyright interest in the
9
+ software to the public domain. We make this dedication for the benefit
10
+ of the public at large and to the detriment of our heirs and
11
+ successors. We intend this dedication to be an overt act of
12
+ relinquishment in perpetuity of all present and future rights to this
13
+ software under copyright law.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
+ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21
+ OTHER DEALINGS IN THE SOFTWARE.
22
+
package/licenses.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ interface LicenseContext {
2
+ year: string;
3
+ author: string;
4
+ email: string;
5
+ }
6
+ export type SupportedLicense = string;
7
+ export declare const DEFAULT_LICENSE = "MIT";
8
+ export declare const CLOSED_LICENSE = "CLOSED";
9
+ export declare const LICENSE_VALUE_KEYS: string[];
10
+ export declare const LICENSE_AUTHOR_KEYS: string[];
11
+ export declare const LICENSE_EMAIL_KEYS: string[];
12
+ export declare function isSupportedLicense(name: string): name is SupportedLicense;
13
+ export declare function renderLicense(licenseName: string, context: Partial<LicenseContext>): string | null;
14
+ export declare function listSupportedLicenses(): string[];
15
+ export declare function findLicenseValue(answers: Record<string, any>): string | undefined;
16
+ export declare function findLicenseAuthor(answers: Record<string, any>): string | undefined;
17
+ export declare function findLicenseEmail(answers: Record<string, any>): string | undefined;
18
+ export {};
package/licenses.js ADDED
@@ -0,0 +1,162 @@
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.LICENSE_EMAIL_KEYS = exports.LICENSE_AUTHOR_KEYS = exports.LICENSE_VALUE_KEYS = exports.CLOSED_LICENSE = exports.DEFAULT_LICENSE = void 0;
37
+ exports.isSupportedLicense = isSupportedLicense;
38
+ exports.renderLicense = renderLicense;
39
+ exports.listSupportedLicenses = listSupportedLicenses;
40
+ exports.findLicenseValue = findLicenseValue;
41
+ exports.findLicenseAuthor = findLicenseAuthor;
42
+ exports.findLicenseEmail = findLicenseEmail;
43
+ const fs = __importStar(require("fs"));
44
+ const path = __importStar(require("path"));
45
+ const PLACEHOLDER_PATTERN = /{{(\w+)}}/g;
46
+ let cachedTemplates = null;
47
+ exports.DEFAULT_LICENSE = 'MIT';
48
+ exports.CLOSED_LICENSE = 'CLOSED';
49
+ exports.LICENSE_VALUE_KEYS = ['LICENSE', 'license'];
50
+ exports.LICENSE_AUTHOR_KEYS = [
51
+ 'USERFULLNAME',
52
+ 'AUTHOR',
53
+ 'AUTHORFULLNAME',
54
+ 'USERNAME',
55
+ 'fullName',
56
+ 'author',
57
+ 'authorFullName',
58
+ 'userName',
59
+ ];
60
+ exports.LICENSE_EMAIL_KEYS = ['USEREMAIL', 'EMAIL', 'email', 'userEmail'];
61
+ function isSupportedLicense(name) {
62
+ if (!name) {
63
+ return false;
64
+ }
65
+ return Boolean(loadLicenseTemplates()[name.toUpperCase()]);
66
+ }
67
+ function renderLicense(licenseName, context) {
68
+ if (!licenseName) {
69
+ return null;
70
+ }
71
+ const templates = loadLicenseTemplates();
72
+ const template = templates[licenseName.toUpperCase()];
73
+ if (!template) {
74
+ return null;
75
+ }
76
+ const ctx = {
77
+ year: context.year ?? new Date().getFullYear().toString(),
78
+ author: context.author ?? 'Unknown Author',
79
+ email: context.email ?? '',
80
+ };
81
+ const emailLine = ctx.email ? ` <${ctx.email}>` : '';
82
+ return template.replace(PLACEHOLDER_PATTERN, (_, rawKey) => {
83
+ const key = rawKey.toUpperCase();
84
+ if (key === 'EMAIL_LINE') {
85
+ return emailLine;
86
+ }
87
+ const normalizedKey = key.toLowerCase();
88
+ const value = ctx[normalizedKey];
89
+ return value || '';
90
+ });
91
+ }
92
+ function listSupportedLicenses() {
93
+ const licenses = Object.keys(loadLicenseTemplates());
94
+ // Sort with DEFAULT_LICENSE first, CLOSED_LICENSE last, then alphabetically
95
+ return licenses.sort((a, b) => {
96
+ if (a === exports.DEFAULT_LICENSE)
97
+ return -1;
98
+ if (b === exports.DEFAULT_LICENSE)
99
+ return 1;
100
+ if (a === exports.CLOSED_LICENSE)
101
+ return 1;
102
+ if (b === exports.CLOSED_LICENSE)
103
+ return -1;
104
+ return a.localeCompare(b);
105
+ });
106
+ }
107
+ function findLicenseValue(answers) {
108
+ return getAnswerValue(answers, exports.LICENSE_VALUE_KEYS);
109
+ }
110
+ function findLicenseAuthor(answers) {
111
+ return getAnswerValue(answers, exports.LICENSE_AUTHOR_KEYS);
112
+ }
113
+ function findLicenseEmail(answers) {
114
+ return getAnswerValue(answers, exports.LICENSE_EMAIL_KEYS);
115
+ }
116
+ function loadLicenseTemplates() {
117
+ if (cachedTemplates) {
118
+ return cachedTemplates;
119
+ }
120
+ const dir = findTemplatesDir();
121
+ if (!dir) {
122
+ cachedTemplates = {};
123
+ return cachedTemplates;
124
+ }
125
+ const files = fs.readdirSync(dir);
126
+ const templates = {};
127
+ for (const file of files) {
128
+ const fullPath = path.join(dir, file);
129
+ const stats = fs.statSync(fullPath);
130
+ if (!stats.isFile()) {
131
+ continue;
132
+ }
133
+ if (path.extname(file).toLowerCase() !== '.txt') {
134
+ continue;
135
+ }
136
+ const key = path.basename(file, path.extname(file)).toUpperCase();
137
+ templates[key] = fs.readFileSync(fullPath, 'utf8');
138
+ }
139
+ cachedTemplates = templates;
140
+ return cachedTemplates;
141
+ }
142
+ function findTemplatesDir() {
143
+ const candidates = [
144
+ path.resolve(__dirname, '..', 'licenses-templates'),
145
+ path.resolve(__dirname, 'licenses-templates'),
146
+ ];
147
+ for (const candidate of candidates) {
148
+ if (fs.existsSync(candidate)) {
149
+ return candidate;
150
+ }
151
+ }
152
+ return null;
153
+ }
154
+ function getAnswerValue(answers, keys) {
155
+ for (const key of keys) {
156
+ const value = answers?.[key];
157
+ if (typeof value === 'string' && value.trim() !== '') {
158
+ return value;
159
+ }
160
+ }
161
+ return undefined;
162
+ }
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "genomic",
3
- "version": "4.0.1",
3
+ "version": "5.0.0",
4
4
  "author": "Constructive <developers@constructive.io>",
5
- "description": "TypeScript-first library for building beautiful CLI interfaces with interactive prompts",
5
+ "description": "Clone and customize template repositories with variable replacement",
6
6
  "main": "index.js",
7
7
  "module": "esm/index.js",
8
8
  "types": "index.d.ts",
@@ -20,26 +20,21 @@
20
20
  "url": "https://github.com/constructive-io/dev-utils/issues"
21
21
  },
22
22
  "scripts": {
23
- "copy": "makage assets",
23
+ "copy": "copyfiles -f ../../LICENSE README.md package.json dist && copyfiles -f \"licenses-templates/**/*\" dist/licenses-templates",
24
24
  "clean": "makage clean",
25
25
  "prepublishOnly": "npm run build",
26
- "build": "makage build",
27
- "dev": "ts-node dev/index",
26
+ "build": "npm run clean && tsc && tsc -p tsconfig.esm.json && npm run copy",
28
27
  "test": "jest",
29
28
  "test:watch": "jest --watch"
30
29
  },
31
30
  "dependencies": {
32
- "deepmerge": "^4.3.1",
33
- "find-and-require-package-json": "0.8.3",
34
- "js-yaml": "^4.1.0",
35
- "minimist": "^1.2.8",
36
- "yanse": "0.1.9"
31
+ "appstash": "0.2.6",
32
+ "inquirerer": "4.0.0"
37
33
  },
38
- "keywords": [],
39
34
  "devDependencies": {
40
- "@types/minimist": "^1.2.5",
41
- "clean-ansi": "0.1.6",
35
+ "copyfiles": "^2.4.1",
42
36
  "makage": "0.1.8"
43
37
  },
44
- "gitHead": "a3cc79dcdfee205c15394fcd485212a25e383d2d"
38
+ "keywords": [],
39
+ "gitHead": "ab5945f162906da8fdf6776510ba30d82769b47f"
45
40
  }
@@ -0,0 +1,2 @@
1
+ export * from './template-scaffolder';
2
+ export * from './types';
@@ -14,4 +14,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./template-scaffolder"), exports);
17
18
  __exportStar(require("./types"), exports);
@@ -0,0 +1,91 @@
1
+ import { CacheManager } from '../cache/cache-manager';
2
+ import { GitCloner } from '../git/git-cloner';
3
+ import { Templatizer } from '../template/templatizer';
4
+ import { TemplateScaffolderConfig, ScaffoldOptions, ScaffoldResult, BoilerplatesConfig, BoilerplateConfig, InspectOptions, InspectResult } from './types';
5
+ /**
6
+ * High-level orchestrator for template scaffolding operations.
7
+ * Combines CacheManager, GitCloner, and Templatizer into a single, easy-to-use API.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * const scaffolder = new TemplateScaffolder({
12
+ * toolName: 'my-cli',
13
+ * defaultRepo: 'https://github.com/org/templates.git',
14
+ * ttlMs: 7 * 24 * 60 * 60 * 1000, // 1 week
15
+ * });
16
+ *
17
+ * await scaffolder.scaffold({
18
+ * outputDir: './my-project',
19
+ * fromPath: 'starter',
20
+ * answers: { name: 'my-project' },
21
+ * });
22
+ * ```
23
+ */
24
+ export declare class TemplateScaffolder {
25
+ private config;
26
+ private cacheManager;
27
+ private gitCloner;
28
+ private templatizer;
29
+ constructor(config: TemplateScaffolderConfig);
30
+ /**
31
+ * Scaffold a new project from a template.
32
+ *
33
+ * Handles both local directories and remote git repositories.
34
+ * For remote repos, caching is used to avoid repeated cloning.
35
+ *
36
+ * @param options - Scaffold options
37
+ * @returns Scaffold result with output path and metadata
38
+ */
39
+ scaffold(options: ScaffoldOptions): Promise<ScaffoldResult>;
40
+ /**
41
+ * Inspect a template without scaffolding.
42
+ * Clones/caches the template and reads its .boilerplate.json configuration
43
+ * without copying any files to an output directory.
44
+ *
45
+ * This is useful for metadata-driven workflows where you need to know
46
+ * the template's type or other configuration before deciding how to handle it.
47
+ *
48
+ * @param options - Inspect options
49
+ * @returns Inspect result with template metadata
50
+ */
51
+ inspect(options: InspectOptions): InspectResult;
52
+ /**
53
+ * Read the .boilerplates.json configuration from a template repository root.
54
+ */
55
+ readBoilerplatesConfig(templateDir: string): BoilerplatesConfig | null;
56
+ /**
57
+ * Read the .boilerplate.json configuration from a boilerplate directory.
58
+ */
59
+ readBoilerplateConfig(boilerplatePath: string): BoilerplateConfig | null;
60
+ /**
61
+ * Get the underlying CacheManager instance for advanced cache operations.
62
+ */
63
+ getCacheManager(): CacheManager;
64
+ /**
65
+ * Get the underlying GitCloner instance for advanced git operations.
66
+ */
67
+ getGitCloner(): GitCloner;
68
+ /**
69
+ * Get the underlying Templatizer instance for advanced template operations.
70
+ */
71
+ getTemplatizer(): Templatizer;
72
+ private inspectLocal;
73
+ private inspectRemote;
74
+ private scaffoldFromLocal;
75
+ private scaffoldFromRemote;
76
+ /**
77
+ * Resolve the fromPath using .boilerplates.json convention.
78
+ *
79
+ * Resolution order:
80
+ * 1. If explicit fromPath is provided and exists, use it directly
81
+ * 2. If useBoilerplatesConfig is true and .boilerplates.json exists with a dir field, prepend it to fromPath
82
+ * 3. Return the fromPath as-is
83
+ *
84
+ * @param templateDir - The template repository root directory
85
+ * @param fromPath - The subdirectory path to resolve
86
+ * @param useBoilerplatesConfig - Whether to use .boilerplates.json for fallback resolution (default: true)
87
+ */
88
+ private resolveFromPath;
89
+ private isLocalPath;
90
+ private resolveTemplatePath;
91
+ }