@mnemonica/tactica 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.
package/lib/graph.js ADDED
@@ -0,0 +1,81 @@
1
+ 'use strict';
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TypeGraphImpl = void 0;
4
+ /**
5
+ * Trie-based type graph for storing Mnemonica type hierarchy
6
+ */
7
+ class TypeGraphImpl {
8
+ constructor() {
9
+ this.roots = new Map();
10
+ this.allTypes = new Map();
11
+ }
12
+ addRoot(node) {
13
+ this.roots.set(node.name, node);
14
+ this.allTypes.set(node.fullPath, node);
15
+ }
16
+ addChild(parent, child) {
17
+ parent.children.set(child.name, child);
18
+ child.parent = parent;
19
+ this.allTypes.set(child.fullPath, child);
20
+ }
21
+ findType(fullPath) {
22
+ return this.allTypes.get(fullPath);
23
+ }
24
+ getAllTypes() {
25
+ return Array.from(this.allTypes.values());
26
+ }
27
+ clear() {
28
+ this.roots.clear();
29
+ this.allTypes.clear();
30
+ }
31
+ /**
32
+ * Create a new TypeNode
33
+ */
34
+ static createNode(name, parent, sourceFile, line, column) {
35
+ const fullPath = parent ? `${parent.fullPath}.${name}` : name;
36
+ return {
37
+ name,
38
+ fullPath,
39
+ properties: new Map(),
40
+ parent,
41
+ children: new Map(),
42
+ sourceFile,
43
+ line,
44
+ column,
45
+ };
46
+ }
47
+ /**
48
+ * Traverse the graph in breadth-first order
49
+ */
50
+ *bfs() {
51
+ const visited = new Set();
52
+ const queue = Array.from(this.roots.values());
53
+ while (queue.length > 0) {
54
+ const node = queue.shift();
55
+ if (visited.has(node.fullPath)) {
56
+ continue;
57
+ }
58
+ visited.add(node.fullPath);
59
+ yield node;
60
+ for (const child of node.children.values()) {
61
+ queue.push(child);
62
+ }
63
+ }
64
+ }
65
+ /**
66
+ * Traverse the graph in depth-first order
67
+ */
68
+ *dfs(node, visited = new Set()) {
69
+ const startNode = node || this.roots.values().next().value;
70
+ if (!startNode || visited.has(startNode.fullPath)) {
71
+ return;
72
+ }
73
+ visited.add(startNode.fullPath);
74
+ yield startNode;
75
+ for (const child of startNode.children.values()) {
76
+ yield* this.dfs(child, visited);
77
+ }
78
+ }
79
+ }
80
+ exports.TypeGraphImpl = TypeGraphImpl;
81
+ //# sourceMappingURL=graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.js","sourceRoot":"","sources":["../src/graph.ts"],"names":[],"mappings":"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"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Tactica - TypeScript Language Service Plugin for Mnemonica
3
+ *
4
+ * Generates type definitions for Mnemonica's dynamic nested constructors,
5
+ * enabling TypeScript to understand runtime type hierarchies created through
6
+ * define() and decorate() calls.
7
+ */
8
+ export { MnemonicaAnalyzer } from './analyzer';
9
+ export { TypeGraphImpl } from './graph';
10
+ export { TypesGenerator } from './generator';
11
+ export { TypesWriter } from './writer';
12
+ export type { TacticaConfig, TypeNode, TypeGraph, PropertyInfo, AnalyzeResult, AnalyzeError, GeneratedTypes, } from './types';
13
+ export { main, run, watch, parseArgs } from './cli';
14
+ export { default } from './plugin';
15
+ export declare const VERSION = "0.1.0";
package/lib/index.js ADDED
@@ -0,0 +1,33 @@
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.VERSION = exports.default = exports.parseArgs = exports.watch = exports.run = exports.main = exports.TypesWriter = exports.TypesGenerator = exports.TypeGraphImpl = exports.MnemonicaAnalyzer = void 0;
7
+ /**
8
+ * Tactica - TypeScript Language Service Plugin for Mnemonica
9
+ *
10
+ * Generates type definitions for Mnemonica's dynamic nested constructors,
11
+ * enabling TypeScript to understand runtime type hierarchies created through
12
+ * define() and decorate() calls.
13
+ */
14
+ var analyzer_1 = require("./analyzer");
15
+ Object.defineProperty(exports, "MnemonicaAnalyzer", { enumerable: true, get: function () { return analyzer_1.MnemonicaAnalyzer; } });
16
+ var graph_1 = require("./graph");
17
+ Object.defineProperty(exports, "TypeGraphImpl", { enumerable: true, get: function () { return graph_1.TypeGraphImpl; } });
18
+ var generator_1 = require("./generator");
19
+ Object.defineProperty(exports, "TypesGenerator", { enumerable: true, get: function () { return generator_1.TypesGenerator; } });
20
+ var writer_1 = require("./writer");
21
+ Object.defineProperty(exports, "TypesWriter", { enumerable: true, get: function () { return writer_1.TypesWriter; } });
22
+ // CLI entry point
23
+ var cli_1 = require("./cli");
24
+ Object.defineProperty(exports, "main", { enumerable: true, get: function () { return cli_1.main; } });
25
+ Object.defineProperty(exports, "run", { enumerable: true, get: function () { return cli_1.run; } });
26
+ Object.defineProperty(exports, "watch", { enumerable: true, get: function () { return cli_1.watch; } });
27
+ Object.defineProperty(exports, "parseArgs", { enumerable: true, get: function () { return cli_1.parseArgs; } });
28
+ // Plugin entry point (for TypeScript Language Service)
29
+ var plugin_1 = require("./plugin");
30
+ Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(plugin_1).default; } });
31
+ // Version
32
+ exports.VERSION = '0.1.0';
33
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;;;;AAEb;;;;;;GAMG;AAEH,uCAA+C;AAAtC,6GAAA,iBAAiB,OAAA;AAC1B,iCAAwC;AAA/B,sGAAA,aAAa,OAAA;AACtB,yCAA6C;AAApC,2GAAA,cAAc,OAAA;AACvB,mCAAuC;AAA9B,qGAAA,WAAW,OAAA;AAapB,kBAAkB;AAClB,6BAAoD;AAA3C,2FAAA,IAAI,OAAA;AAAE,0FAAA,GAAG,OAAA;AAAE,4FAAA,KAAK,OAAA;AAAE,gGAAA,SAAS,OAAA;AAEpC,uDAAuD;AACvD,mCAAmC;AAA1B,kHAAA,OAAO,OAAA;AAEhB,UAAU;AACG,QAAA,OAAO,GAAG,OAAO,CAAC"}
@@ -0,0 +1,8 @@
1
+ import * as ts from 'typescript';
2
+ /**
3
+ * Initialize the plugin
4
+ */
5
+ declare function init(modules: {
6
+ typescript: typeof ts;
7
+ }): ts.server.PluginModule;
8
+ export = init;
package/lib/plugin.js ADDED
@@ -0,0 +1,128 @@
1
+ 'use strict';
2
+ const analyzer_1 = require("./analyzer");
3
+ const graph_1 = require("./graph");
4
+ const generator_1 = require("./generator");
5
+ const writer_1 = require("./writer");
6
+ let pluginInfo;
7
+ let typeGraph = new graph_1.TypeGraphImpl();
8
+ /**
9
+ * Initialize the plugin
10
+ */
11
+ function init(modules) {
12
+ const tsModule = modules.typescript;
13
+ function create(info) {
14
+ const config = info.config || {};
15
+ config.outputDir = config.outputDir || '.tactica';
16
+ // Store plugin info
17
+ pluginInfo = {
18
+ config,
19
+ project: info.project,
20
+ serverHost: info.serverHost,
21
+ moduleResolver: info.project,
22
+ };
23
+ // Set up file watching
24
+ setupFileWatcher(info, tsModule);
25
+ // Initial type generation
26
+ generateTypes(info, tsModule);
27
+ // Wrap the language service to intercept requests if needed
28
+ const proxy = Object.create(null);
29
+ const oldService = info.languageService;
30
+ for (const key of Object.keys(oldService)) {
31
+ const fn = oldService[key];
32
+ proxy[key] = (...args) => {
33
+ return fn.apply(oldService, args);
34
+ };
35
+ }
36
+ return proxy;
37
+ }
38
+ function onConfigurationChanged(config) {
39
+ if (pluginInfo) {
40
+ pluginInfo.config = { ...pluginInfo.config, ...config };
41
+ }
42
+ }
43
+ return {
44
+ create,
45
+ onConfigurationChanged,
46
+ };
47
+ }
48
+ /**
49
+ * Set up file watching for incremental updates
50
+ */
51
+ function setupFileWatcher(info, _tsModule) {
52
+ const serverHost = info.serverHost;
53
+ // Hook into file change notifications
54
+ const originalFileChanged = serverHost.fileChanged;
55
+ if (originalFileChanged) {
56
+ serverHost.fileChanged = function (...args) {
57
+ const result = originalFileChanged.apply(this, args);
58
+ // Regenerate types when files change
59
+ generateTypes(info, _tsModule);
60
+ return result;
61
+ };
62
+ }
63
+ }
64
+ /**
65
+ * Generate types from the project
66
+ */
67
+ function generateTypes(info, _tsModule) {
68
+ try {
69
+ const program = info.languageService.getProgram();
70
+ if (!program) {
71
+ return;
72
+ }
73
+ const config = pluginInfo?.config || { outputDir: '.tactica' };
74
+ const include = config.include || ['**/*.ts'];
75
+ const exclude = config.exclude || ['**/*.d.ts', 'node_modules/**'];
76
+ // Create analyzer
77
+ const analyzer = new analyzer_1.MnemonicaAnalyzer(program);
78
+ // Clear existing graph
79
+ typeGraph.clear();
80
+ // Analyze all source files
81
+ for (const sourceFile of program.getSourceFiles()) {
82
+ // Skip declaration files and files outside the project
83
+ if (sourceFile.isDeclarationFile) {
84
+ continue;
85
+ }
86
+ const fileName = sourceFile.fileName;
87
+ // Check exclude patterns
88
+ if (exclude.some(pattern => matchesGlob(fileName, pattern))) {
89
+ continue;
90
+ }
91
+ // Check include patterns (if specified)
92
+ if (include.length > 0 && !include.some(pattern => matchesGlob(fileName, pattern))) {
93
+ continue;
94
+ }
95
+ // Analyze the file
96
+ analyzer.analyzeFile(sourceFile);
97
+ }
98
+ // Get the graph and generate types
99
+ typeGraph = analyzer.getGraph();
100
+ const generator = new generator_1.TypesGenerator(typeGraph);
101
+ const generated = generator.generateTypesFile();
102
+ // Write types to file
103
+ const writer = new writer_1.TypesWriter(config.outputDir);
104
+ const outputPath = writer.writeTypesFile(generated);
105
+ // Log success
106
+ if (config.verbose) {
107
+ info.project.projectService.logger.info(`[Tactica] Generated types at ${outputPath} (${generated.types.length} types)`);
108
+ }
109
+ }
110
+ catch (error) {
111
+ info.project.projectService.logger.info(`[Tactica] Error generating types: ${error}`);
112
+ }
113
+ }
114
+ /**
115
+ * Simple glob matching function
116
+ */
117
+ function matchesGlob(filePath, pattern) {
118
+ // Convert glob pattern to regex
119
+ const regexPattern = pattern
120
+ .replace(/\*\*/g, '<<<DOUBLESTAR>>>')
121
+ .replace(/\*/g, '[^/]*')
122
+ .replace(/<<<DOUBLESTAR>>>/g, '.*')
123
+ .replace(/\?/g, '.');
124
+ const regex = new RegExp(regexPattern);
125
+ return regex.test(filePath);
126
+ }
127
+ module.exports = init;
128
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
package/lib/types.d.ts ADDED
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Type definitions for Tactica
3
+ */
4
+ export interface TacticaConfig {
5
+ /** Output directory for generated types (default: .tactica) */
6
+ outputDir?: string;
7
+ /** Files to include (glob patterns) */
8
+ include?: string[];
9
+ /** Files to exclude (glob patterns) */
10
+ exclude?: string[];
11
+ /** Enable verbose logging */
12
+ verbose?: boolean;
13
+ /** Generate global augmentation instead of module augmentation (default: true) */
14
+ globalAugmentation?: boolean;
15
+ }
16
+ export interface PropertyInfo {
17
+ name: string;
18
+ type: string;
19
+ optional: boolean;
20
+ }
21
+ export interface TypeNode {
22
+ /** Type name (e.g., "SecondType") */
23
+ name: string;
24
+ /** Full path (e.g., "FirstType.SecondType") */
25
+ fullPath: string;
26
+ /** Properties defined in this type's constructor */
27
+ properties: Map<string, PropertyInfo>;
28
+ /** Parent type node */
29
+ parent?: TypeNode;
30
+ /** Child types */
31
+ children: Map<string, TypeNode>;
32
+ /** Source file path */
33
+ sourceFile: string;
34
+ /** Line number in source */
35
+ line: number;
36
+ /** Column number in source */
37
+ column: number;
38
+ /** Constructor function name or class name */
39
+ constructorName?: string;
40
+ }
41
+ export interface TypeGraph {
42
+ /** Root types (defined at module level) */
43
+ roots: Map<string, TypeNode>;
44
+ /** All types by full path */
45
+ allTypes: Map<string, TypeNode>;
46
+ /** Add a root type */
47
+ addRoot(node: TypeNode): void;
48
+ /** Find a type by full path */
49
+ findType(fullPath: string): TypeNode | undefined;
50
+ /** Get all types as array */
51
+ getAllTypes(): TypeNode[];
52
+ /** Clear the graph */
53
+ clear(): void;
54
+ }
55
+ export interface AnalyzeResult {
56
+ /** Types found in the analysis */
57
+ types: TypeNode[];
58
+ /** Errors encountered */
59
+ errors: AnalyzeError[];
60
+ }
61
+ export interface AnalyzeError {
62
+ message: string;
63
+ file: string;
64
+ line: number;
65
+ column: number;
66
+ }
67
+ export interface GeneratedTypes {
68
+ /** Content of the .d.ts file */
69
+ content: string;
70
+ /** Types that were generated */
71
+ types: string[];
72
+ }
package/lib/types.js ADDED
@@ -0,0 +1,3 @@
1
+ 'use strict';
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { GeneratedTypes } from './types';
2
+ /**
3
+ * File writer for generated types
4
+ */
5
+ export declare class TypesWriter {
6
+ private outputDir;
7
+ constructor(outputDir?: string);
8
+ /**
9
+ * Write generated types to file
10
+ */
11
+ write(generated: GeneratedTypes): string;
12
+ /**
13
+ * Write types.ts file with complete interfaces
14
+ */
15
+ writeTypesFile(generated: GeneratedTypes): string;
16
+ /**
17
+ * Write global augmentation file
18
+ */
19
+ writeGlobalAugmentation(generated: GeneratedTypes): string;
20
+ /**
21
+ * Write types with custom filename
22
+ */
23
+ writeTo(filename: string, content: string): string;
24
+ /**
25
+ * Ensure output directory exists
26
+ */
27
+ private ensureDirectory;
28
+ /**
29
+ * Update .gitignore to exclude .tactica folder
30
+ */
31
+ private updateGitignore;
32
+ /**
33
+ * Clean the output directory
34
+ */
35
+ clean(): void;
36
+ /**
37
+ * Get the output directory path
38
+ */
39
+ getOutputDir(): string;
40
+ }
package/lib/writer.js ADDED
@@ -0,0 +1,139 @@
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.TypesWriter = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ /**
40
+ * File writer for generated types
41
+ */
42
+ class TypesWriter {
43
+ constructor(outputDir = '.tactica') {
44
+ this.outputDir = outputDir;
45
+ }
46
+ /**
47
+ * Write generated types to file
48
+ */
49
+ write(generated) {
50
+ // Ensure output directory exists
51
+ this.ensureDirectory();
52
+ const outputPath = path.join(this.outputDir, 'types.d.ts');
53
+ // Write the file
54
+ fs.writeFileSync(outputPath, generated.content, 'utf-8');
55
+ // Update .gitignore if needed
56
+ this.updateGitignore();
57
+ return outputPath;
58
+ }
59
+ /**
60
+ * Write types.ts file with complete interfaces
61
+ */
62
+ writeTypesFile(generated) {
63
+ this.ensureDirectory();
64
+ const outputPath = path.join(this.outputDir, 'types.ts');
65
+ fs.writeFileSync(outputPath, generated.content, 'utf-8');
66
+ return outputPath;
67
+ }
68
+ /**
69
+ * Write global augmentation file
70
+ */
71
+ writeGlobalAugmentation(generated) {
72
+ this.ensureDirectory();
73
+ // Use index.d.ts so TypeScript picks it up automatically from typeRoots
74
+ const outputPath = path.join(this.outputDir, 'index.d.ts');
75
+ fs.writeFileSync(outputPath, generated.content, 'utf-8');
76
+ // Update .gitignore if needed
77
+ this.updateGitignore();
78
+ return outputPath;
79
+ }
80
+ /**
81
+ * Write types with custom filename
82
+ */
83
+ writeTo(filename, content) {
84
+ this.ensureDirectory();
85
+ const outputPath = path.join(this.outputDir, filename);
86
+ fs.writeFileSync(outputPath, content, 'utf-8');
87
+ return outputPath;
88
+ }
89
+ /**
90
+ * Ensure output directory exists
91
+ */
92
+ ensureDirectory() {
93
+ if (!fs.existsSync(this.outputDir)) {
94
+ fs.mkdirSync(this.outputDir, { recursive: true });
95
+ }
96
+ }
97
+ /**
98
+ * Update .gitignore to exclude .tactica folder
99
+ */
100
+ updateGitignore() {
101
+ const gitignorePath = path.join(process.cwd(), '.gitignore');
102
+ if (!fs.existsSync(gitignorePath)) {
103
+ // Create .gitignore
104
+ fs.writeFileSync(gitignorePath, `${this.outputDir}/\n`, 'utf-8');
105
+ return;
106
+ }
107
+ const content = fs.readFileSync(gitignorePath, 'utf-8');
108
+ const lines = content.split('\n');
109
+ // Check if already ignored
110
+ const isIgnored = lines.some(line => line.trim() === this.outputDir ||
111
+ line.trim() === `${this.outputDir}/`);
112
+ if (!isIgnored) {
113
+ // Add to .gitignore
114
+ const newContent = content.endsWith('\n')
115
+ ? `${content}${this.outputDir}/\n`
116
+ : `${content}\n${this.outputDir}/\n`;
117
+ fs.writeFileSync(gitignorePath, newContent, 'utf-8');
118
+ }
119
+ }
120
+ /**
121
+ * Clean the output directory
122
+ */
123
+ clean() {
124
+ if (fs.existsSync(this.outputDir)) {
125
+ const files = fs.readdirSync(this.outputDir);
126
+ for (const file of files) {
127
+ fs.unlinkSync(path.join(this.outputDir, file));
128
+ }
129
+ }
130
+ }
131
+ /**
132
+ * Get the output directory path
133
+ */
134
+ getOutputDir() {
135
+ return this.outputDir;
136
+ }
137
+ }
138
+ exports.TypesWriter = TypesWriter;
139
+ //# sourceMappingURL=writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writer.js","sourceRoot":"","sources":["../src/writer.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEb,uCAAyB;AACzB,2CAA6B;AAG7B;;GAEG;AACH,MAAa,WAAW;IAGvB,YAAY,SAAS,GAAG,UAAU;QACjC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC5B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAyB;QAC9B,iCAAiC;QACjC,IAAI,CAAC,eAAe,EAAE,CAAC;QAEvB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QAE3D,iBAAiB;QACjB,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAEzD,8BAA8B;QAC9B,IAAI,CAAC,eAAe,EAAE,CAAC;QAEvB,OAAO,UAAU,CAAC;IACnB,CAAC;IAED;;OAEG;IACH,cAAc,CAAC,SAAyB;QACvC,IAAI,CAAC,eAAe,EAAE,CAAC;QAEvB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;QACzD,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAEzD,OAAO,UAAU,CAAC;IACnB,CAAC;IAED;;WAEI;IACH,uBAAuB,CAAC,SAAyB;QAChD,IAAI,CAAC,eAAe,EAAE,CAAC;QAEvB,wEAAwE;QACxE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QAC3D,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAEzD,8BAA8B;QAC9B,IAAI,CAAC,eAAe,EAAE,CAAC;QAEvB,OAAO,UAAU,CAAC;IACnB,CAAC;IAEF;;UAEG;IACH,OAAO,CAAC,QAAgB,EAAE,OAAe;QACxC,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QACvD,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC/C,OAAO,UAAU,CAAC;IACnB,CAAC;IAED;;OAEG;IACK,eAAe;QACtB,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YACpC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,CAAC;IACF,CAAC;IAED;;OAEG;IACK,eAAe;QACtB,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,YAAY,CAAC,CAAC;QAE7D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;YACnC,oBAAoB;YACpB,EAAE,CAAC,aAAa,CAAC,aAAa,EAAE,GAAG,IAAI,CAAC,SAAS,KAAK,EAAE,OAAO,CAAC,CAAC;YACjE,OAAO;QACR,CAAC;QAED,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QACxD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAElC,2BAA2B;QAC3B,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACnC,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC,SAAS;YAC9B,IAAI,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC,SAAS,GAAG,CACpC,CAAC;QAEF,IAAI,CAAC,SAAS,EAAE,CAAC;YAChB,oBAAoB;YACpB,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;gBACxC,CAAC,CAAC,GAAG,OAAO,GAAG,IAAI,CAAC,SAAS,KAAK;gBAClC,CAAC,CAAC,GAAG,OAAO,KAAK,IAAI,CAAC,SAAS,KAAK,CAAC;YACtC,EAAE,CAAC,aAAa,CAAC,aAAa,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;QACtD,CAAC;IACF,CAAC;IAED;;OAEG;IACH,KAAK;QACJ,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YACnC,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC7C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBAC1B,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;YAChD,CAAC;QACF,CAAC;IACF,CAAC;IAED;;OAEG;IACH,YAAY;QACX,OAAO,IAAI,CAAC,SAAS,CAAC;IACvB,CAAC;CACD;AAxHD,kCAwHC"}
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@mnemonica/tactica",
3
+ "version": "0.1.0",
4
+ "description": "TypeScript Language Service Plugin for Mnemonica - generates types for nested constructors",
5
+ "main": "lib/index.js",
6
+ "types": "lib/index.d.ts",
7
+ "bin": {
8
+ "tactica": "lib/cli.js"
9
+ },
10
+ "files": [
11
+ "lib/",
12
+ "README.md",
13
+ "LICENSE"
14
+ ],
15
+ "scripts": {
16
+ "build": "rm -rf ./lib && npx tsc --pretty && npm run fix-permissions",
17
+ "fix-permissions": "chmod +x lib/cli.js",
18
+ "watch": "npx tsc --pretty -w",
19
+ "test": "TS_NODE_PROJECT=./tsconfig.test.json mocha test/**/*.test.ts",
20
+ "test:coverage": "npx nyc npm test",
21
+ "test:coverage:html": "npx nyc --reporter=html npm test",
22
+ "lint": "npx eslint --fix ./src"
23
+ },
24
+ "keywords": [
25
+ "mnemonica",
26
+ "typescript",
27
+ "language-service",
28
+ "plugin",
29
+ "types",
30
+ "intellisense"
31
+ ],
32
+ "author": "went.out@gmail.com",
33
+ "contributors": [
34
+ "Roo AI <ai-assistant@example.com>"
35
+ ],
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "git+https://github.com/mythographica/tactica.git"
39
+ },
40
+
41
+ "license": "MIT",
42
+ "peerDependencies": {
43
+ "mnemonica": "^0.9.0",
44
+ "typescript": "^5.0.0"
45
+ },
46
+ "devDependencies": {
47
+ "@istanbuljs/nyc-config-typescript": "^1.0.2",
48
+ "@types/chai": "^4.3.0",
49
+ "@types/mocha": "^10.0.0",
50
+ "@types/node": "^20.0.0",
51
+ "chai": "^4.3.10",
52
+ "mnemonica": "^0.9.99780",
53
+ "mocha": "^10.2.0",
54
+ "nyc": "^17.1.0",
55
+ "ts-node": "^10.9.0",
56
+ "typeomatica": "^0.3.57",
57
+ "typescript": "^5.3.0"
58
+ },
59
+ "dependencies": {
60
+ "@types/chokidar": "^2.1.0",
61
+ "chokidar": "^3.5.0"
62
+ }
63
+ }