motia 0.7.2-beta.134 → 0.7.2-beta.135-604391
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/dist/cjs/cloud/build/builders/python/index.d.ts +0 -1
- package/dist/cjs/cloud/build/builders/python/index.js +10 -15
- package/dist/cjs/cloud/build/builders/python/python-data/__tests__/extract-python-data.test.js +4 -5
- package/dist/cjs/cloud/build/builders/python/python-data/__tests__/get-dependencies-from-file.test.js +3 -9
- package/dist/cjs/cloud/build/builders/python/python-data/__tests__/read-requirements.test.js +7 -29
- package/dist/cjs/cloud/build/builders/python/python-data/__tests__/resolve-dep-name.test.js +19 -10
- package/dist/cjs/cloud/build/builders/python/python-data/extract-python-data.d.ts +1 -1
- package/dist/cjs/cloud/build/builders/python/python-data/extract-python-data.js +3 -3
- package/dist/cjs/cloud/build/builders/python/python-data/get-dependencies-from-file.d.ts +1 -2
- package/dist/cjs/cloud/build/builders/python/python-data/get-dependencies-from-file.js +2 -2
- package/dist/cjs/cloud/build/builders/python/python-data/read-requirements.d.ts +8 -10
- package/dist/cjs/cloud/build/builders/python/python-data/read-requirements.js +3 -3
- package/dist/cjs/cloud/build/builders/python/python-data/{resolve-dep-name.d.ts → resolve-dep-names.d.ts} +2 -2
- package/dist/cjs/cloud/build/builders/python/python-data/{resolve-dep-name.js → resolve-dep-names.js} +4 -5
- package/dist/cjs/cloud/build/builders/python/python-data/traverse-tree.d.ts +1 -2
- package/dist/cjs/cloud/build/builders/python/python-data/traverse-tree.js +4 -4
- package/dist/cjs/create/templates/generate.js +2 -2
- package/dist/cjs/create/templates/generate.ts +2 -2
- package/dist/cjs/create/templates/nodejs/.cursor/architecture/database/database-migration.mdc +49 -0
- package/dist/cjs/create/templates/nodejs/.cursor/architecture/database/database.mdc +83 -0
- package/dist/cjs/create/templates/nodejs/src/services/pet-store/create-order.ts.txt +15 -0
- package/dist/cjs/create/templates/nodejs/src/services/pet-store/create-pet.ts.txt +14 -0
- package/dist/cjs/create/templates/nodejs/src/services/pet-store/index.ts.txt +9 -0
- package/dist/cjs/create/templates/nodejs/steps/{api.step.ts-features.json.txt → petstore/api.step.ts-features.json.txt} +9 -9
- package/dist/cjs/create/templates/nodejs/steps/{api.step.ts.txt → petstore/api.step.ts.txt} +1 -2
- package/dist/{esm/create/templates/nodejs/steps → cjs/create/templates/nodejs/steps/petstore}/process-food-order.step.ts.txt +1 -1
- package/dist/cjs/cursor-rules/dot-files/.cursor/architecture/architecture.mdc +96 -0
- package/dist/cjs/cursor-rules/dot-files/.cursor/architecture/error-handling.mdc +122 -0
- package/dist/cjs/cursor-rules/dot-files/.cursor/index.mdc +26 -0
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/motia/api-steps.mdc +317 -0
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/motia/cron-steps.mdc +144 -0
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/motia/event-steps.mdc +157 -0
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/motia/middlewares.mdc +122 -0
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/motia/realtime-streaming.mdc +231 -0
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/motia/state-management.mdc +73 -0
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/motia/ui-steps.mdc +76 -0
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/motia/virtual-steps.mdc +172 -0
- package/dist/esm/cloud/build/builders/python/index.d.ts +0 -1
- package/dist/esm/cloud/build/builders/python/index.js +10 -15
- package/dist/esm/cloud/build/builders/python/python-data/__tests__/extract-python-data.test.js +4 -5
- package/dist/esm/cloud/build/builders/python/python-data/__tests__/get-dependencies-from-file.test.js +3 -9
- package/dist/esm/cloud/build/builders/python/python-data/__tests__/read-requirements.test.js +7 -29
- package/dist/esm/cloud/build/builders/python/python-data/__tests__/resolve-dep-name.test.js +16 -7
- package/dist/esm/cloud/build/builders/python/python-data/extract-python-data.d.ts +1 -1
- package/dist/esm/cloud/build/builders/python/python-data/extract-python-data.js +3 -3
- package/dist/esm/cloud/build/builders/python/python-data/get-dependencies-from-file.d.ts +1 -2
- package/dist/esm/cloud/build/builders/python/python-data/get-dependencies-from-file.js +2 -2
- package/dist/esm/cloud/build/builders/python/python-data/read-requirements.d.ts +8 -10
- package/dist/esm/cloud/build/builders/python/python-data/read-requirements.js +3 -3
- package/dist/esm/cloud/build/builders/python/python-data/{resolve-dep-name.d.ts → resolve-dep-names.d.ts} +2 -2
- package/dist/esm/cloud/build/builders/python/python-data/{resolve-dep-name.js → resolve-dep-names.js} +4 -5
- package/dist/esm/cloud/build/builders/python/python-data/traverse-tree.d.ts +1 -2
- package/dist/esm/cloud/build/builders/python/python-data/traverse-tree.js +4 -4
- package/dist/esm/create/templates/generate.js +2 -2
- package/dist/esm/create/templates/generate.ts +2 -2
- package/dist/esm/create/templates/nodejs/.cursor/architecture/database/database-migration.mdc +49 -0
- package/dist/esm/create/templates/nodejs/.cursor/architecture/database/database.mdc +83 -0
- package/dist/esm/create/templates/nodejs/src/services/pet-store/create-order.ts.txt +15 -0
- package/dist/esm/create/templates/nodejs/src/services/pet-store/create-pet.ts.txt +14 -0
- package/dist/esm/create/templates/nodejs/src/services/pet-store/index.ts.txt +9 -0
- package/dist/esm/create/templates/nodejs/steps/{api.step.ts-features.json.txt → petstore/api.step.ts-features.json.txt} +9 -9
- package/dist/esm/create/templates/nodejs/steps/{api.step.ts.txt → petstore/api.step.ts.txt} +1 -2
- package/dist/{cjs/create/templates/nodejs/steps → esm/create/templates/nodejs/steps/petstore}/process-food-order.step.ts.txt +1 -1
- package/dist/esm/cursor-rules/dot-files/.cursor/architecture/architecture.mdc +96 -0
- package/dist/esm/cursor-rules/dot-files/.cursor/architecture/error-handling.mdc +122 -0
- package/dist/esm/cursor-rules/dot-files/.cursor/index.mdc +26 -0
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/motia/api-steps.mdc +317 -0
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/motia/cron-steps.mdc +144 -0
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/motia/event-steps.mdc +157 -0
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/motia/middlewares.mdc +122 -0
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/motia/realtime-streaming.mdc +231 -0
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/motia/state-management.mdc +73 -0
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/motia/ui-steps.mdc +76 -0
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/motia/virtual-steps.mdc +172 -0
- package/dist/types/cloud/build/builders/python/index.d.ts +0 -1
- package/dist/types/cloud/build/builders/python/python-data/extract-python-data.d.ts +1 -1
- package/dist/types/cloud/build/builders/python/python-data/get-dependencies-from-file.d.ts +1 -2
- package/dist/types/cloud/build/builders/python/python-data/read-requirements.d.ts +8 -10
- package/dist/types/cloud/build/builders/python/python-data/{resolve-dep-name.d.ts → resolve-dep-names.d.ts} +2 -2
- package/dist/types/cloud/build/builders/python/python-data/traverse-tree.d.ts +1 -2
- package/package.json +4 -4
- package/dist/cjs/create/templates/nodejs/services/pet-store.ts.txt +0 -29
- package/dist/cjs/cursor-rules/dot-files/.claude/CLAUDE.md +0 -467
- package/dist/cjs/cursor-rules/dot-files/.claude/README.md +0 -97
- package/dist/cjs/cursor-rules/dot-files/.claude/agents/code-reviewer.md +0 -153
- package/dist/cjs/cursor-rules/dot-files/.claude/agents/debugger.md +0 -259
- package/dist/cjs/cursor-rules/dot-files/.claude/agents/test-runner.md +0 -268
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/add-authentication.md +0 -491
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/ai-ml-patterns.md +0 -748
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/authentication.md +0 -515
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/backend-types.md +0 -719
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/build-api.md +0 -407
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/claude-workflows.md +0 -1032
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/complete-backend.md +0 -345
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/create-api.md +0 -96
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/data-processing.md +0 -977
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/integrate-ai.md +0 -852
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/javascript-patterns.md +0 -678
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/multi-language-workflow.md +0 -756
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/multi-language.md +0 -141
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/process-background-jobs.md +0 -587
- package/dist/cjs/cursor-rules/dot-files/.claude/commands/process-events.md +0 -89
- package/dist/cjs/cursor-rules/dot-files/.claude/hooks/pre-commit.sh +0 -84
- package/dist/cjs/cursor-rules/dot-files/.claude/settings.json +0 -37
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/ai-agent-patterns.mdc +0 -725
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/api-design-patterns.mdc +0 -740
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/api-steps.mdc +0 -230
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/architecture.mdc +0 -189
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/authentication-patterns.mdc +0 -620
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/background-job-patterns.mdc +0 -628
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/complete-application-patterns.mdc +0 -433
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/complete-backend-generator.mdc +0 -415
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/cron-steps.mdc +0 -257
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/event-steps.mdc +0 -504
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/instructions.mdc +0 -15
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/multi-language-workflows.mdc +0 -1059
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/noop-steps.mdc +0 -57
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/production-deployment.mdc +0 -668
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/realtime-streaming.mdc +0 -656
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/state-management.mdc +0 -371
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/steps.mdc +0 -373
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/testing.mdc +0 -329
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/typescript.mdc +0 -409
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/ui-steps.mdc +0 -429
- package/dist/cjs/cursor-rules/dot-files/.cursor/rules/workflow-patterns.mdc +0 -938
- package/dist/cjs/cursor-rules/dot-files/AGENTS.md +0 -397
- package/dist/cjs/cursor-rules/dot-files/README.md +0 -58
- package/dist/esm/create/templates/nodejs/services/pet-store.ts.txt +0 -29
- package/dist/esm/cursor-rules/dot-files/.claude/CLAUDE.md +0 -467
- package/dist/esm/cursor-rules/dot-files/.claude/README.md +0 -97
- package/dist/esm/cursor-rules/dot-files/.claude/agents/code-reviewer.md +0 -153
- package/dist/esm/cursor-rules/dot-files/.claude/agents/debugger.md +0 -259
- package/dist/esm/cursor-rules/dot-files/.claude/agents/test-runner.md +0 -268
- package/dist/esm/cursor-rules/dot-files/.claude/commands/add-authentication.md +0 -491
- package/dist/esm/cursor-rules/dot-files/.claude/commands/ai-ml-patterns.md +0 -748
- package/dist/esm/cursor-rules/dot-files/.claude/commands/authentication.md +0 -515
- package/dist/esm/cursor-rules/dot-files/.claude/commands/backend-types.md +0 -719
- package/dist/esm/cursor-rules/dot-files/.claude/commands/build-api.md +0 -407
- package/dist/esm/cursor-rules/dot-files/.claude/commands/claude-workflows.md +0 -1032
- package/dist/esm/cursor-rules/dot-files/.claude/commands/complete-backend.md +0 -345
- package/dist/esm/cursor-rules/dot-files/.claude/commands/create-api.md +0 -96
- package/dist/esm/cursor-rules/dot-files/.claude/commands/data-processing.md +0 -977
- package/dist/esm/cursor-rules/dot-files/.claude/commands/integrate-ai.md +0 -852
- package/dist/esm/cursor-rules/dot-files/.claude/commands/javascript-patterns.md +0 -678
- package/dist/esm/cursor-rules/dot-files/.claude/commands/multi-language-workflow.md +0 -756
- package/dist/esm/cursor-rules/dot-files/.claude/commands/multi-language.md +0 -141
- package/dist/esm/cursor-rules/dot-files/.claude/commands/process-background-jobs.md +0 -587
- package/dist/esm/cursor-rules/dot-files/.claude/commands/process-events.md +0 -89
- package/dist/esm/cursor-rules/dot-files/.claude/hooks/pre-commit.sh +0 -84
- package/dist/esm/cursor-rules/dot-files/.claude/settings.json +0 -37
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/ai-agent-patterns.mdc +0 -725
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/api-design-patterns.mdc +0 -740
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/api-steps.mdc +0 -230
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/architecture.mdc +0 -189
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/authentication-patterns.mdc +0 -620
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/background-job-patterns.mdc +0 -628
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/complete-application-patterns.mdc +0 -433
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/complete-backend-generator.mdc +0 -415
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/cron-steps.mdc +0 -257
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/event-steps.mdc +0 -504
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/instructions.mdc +0 -15
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/multi-language-workflows.mdc +0 -1059
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/noop-steps.mdc +0 -57
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/production-deployment.mdc +0 -668
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/realtime-streaming.mdc +0 -656
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/state-management.mdc +0 -371
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/steps.mdc +0 -373
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/testing.mdc +0 -329
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/typescript.mdc +0 -409
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/ui-steps.mdc +0 -429
- package/dist/esm/cursor-rules/dot-files/.cursor/rules/workflow-patterns.mdc +0 -938
- package/dist/esm/cursor-rules/dot-files/AGENTS.md +0 -397
- package/dist/esm/cursor-rules/dot-files/README.md +0 -58
- /package/dist/cjs/create/templates/nodejs/{services → src/services/pet-store}/types.ts.txt +0 -0
- /package/dist/cjs/create/templates/nodejs/steps/{notification.step.ts.txt → petstore/notification.step.ts.txt} +0 -0
- /package/dist/cjs/create/templates/nodejs/steps/{process-food-order.step.ts-features.json.txt → petstore/process-food-order.step.ts-features.json.txt} +0 -0
- /package/dist/cjs/create/templates/nodejs/steps/{state-audit-cron.step.ts-features.json.txt → petstore/state-audit-cron.step.ts-features.json.txt} +0 -0
- /package/dist/cjs/create/templates/nodejs/steps/{state-audit-cron.step.ts.txt → petstore/state-audit-cron.step.ts.txt} +0 -0
- /package/dist/esm/create/templates/nodejs/{services → src/services/pet-store}/types.ts.txt +0 -0
- /package/dist/esm/create/templates/nodejs/steps/{notification.step.ts.txt → petstore/notification.step.ts.txt} +0 -0
- /package/dist/esm/create/templates/nodejs/steps/{process-food-order.step.ts-features.json.txt → petstore/process-food-order.step.ts-features.json.txt} +0 -0
- /package/dist/esm/create/templates/nodejs/steps/{state-audit-cron.step.ts-features.json.txt → petstore/state-audit-cron.step.ts-features.json.txt} +0 -0
- /package/dist/esm/create/templates/nodejs/steps/{state-audit-cron.step.ts.txt → petstore/state-audit-cron.step.ts.txt} +0 -0
|
@@ -6,7 +6,6 @@ export declare class PythonBuilder implements StepBuilder {
|
|
|
6
6
|
private readonly listener;
|
|
7
7
|
private packager;
|
|
8
8
|
constructor(builder: Builder, listener: BuildListener);
|
|
9
|
-
private getRequirements;
|
|
10
9
|
buildApiSteps(steps: Step<ApiRouteConfig>[]): Promise<RouterBuildResult>;
|
|
11
10
|
build(step: Step): Promise<void>;
|
|
12
11
|
private generatePackage;
|
|
@@ -12,7 +12,7 @@ const archiver_1 = require("../archiver");
|
|
|
12
12
|
const include_static_files_1 = require("../include-static-files");
|
|
13
13
|
const extract_python_data_1 = require("./python-data/extract-python-data");
|
|
14
14
|
const read_requirements_1 = require("./python-data/read-requirements");
|
|
15
|
-
const
|
|
15
|
+
const resolve_dep_names_1 = require("./python-data/resolve-dep-names");
|
|
16
16
|
const uv_packager_1 = require("./uv-packager");
|
|
17
17
|
class PythonBuilder {
|
|
18
18
|
constructor(builder, listener) {
|
|
@@ -21,17 +21,6 @@ class PythonBuilder {
|
|
|
21
21
|
(0, activate_python_env_1.activatePythonVenv)({ baseDir: this.builder.projectDir });
|
|
22
22
|
this.packager = new uv_packager_1.UvPackager();
|
|
23
23
|
}
|
|
24
|
-
getRequirements() {
|
|
25
|
-
const requirementsFile = path_1.default.join(this.builder.projectDir, 'requirements.txt');
|
|
26
|
-
const depNames = Object.keys((0, read_requirements_1.readRequirements)(requirementsFile, (name) => ({ name, importName: name })));
|
|
27
|
-
const sitePackagesPath = (0, activate_python_env_1.getSitePackagesPath)({ baseDir: this.builder.projectDir });
|
|
28
|
-
const mapper = (0, resolve_dep_name_1.resolveDepNames)(depNames, sitePackagesPath);
|
|
29
|
-
const describer = (name) => {
|
|
30
|
-
const [, to] = mapper.find(([from]) => from === name) ?? [];
|
|
31
|
-
return { name, importName: to ?? name };
|
|
32
|
-
};
|
|
33
|
-
return (0, read_requirements_1.readRequirements)(requirementsFile, describer);
|
|
34
|
-
}
|
|
35
24
|
async buildApiSteps(steps) {
|
|
36
25
|
const zipName = 'router-python.zip';
|
|
37
26
|
const archive = new archiver_1.Archiver(path_1.default.join(constants_1.distDir, zipName));
|
|
@@ -79,8 +68,11 @@ class PythonBuilder {
|
|
|
79
68
|
}
|
|
80
69
|
}
|
|
81
70
|
async generatePackage(bundleDir, entrypointPath, archive, fileContent) {
|
|
82
|
-
const
|
|
83
|
-
const
|
|
71
|
+
const requirementsFile = path_1.default.join(this.builder.projectDir, 'requirements.txt');
|
|
72
|
+
const requirements = (0, read_requirements_1.readRequirements)(requirementsFile);
|
|
73
|
+
const sitePackagesPath = (0, activate_python_env_1.getSitePackagesPath)({ baseDir: this.builder.projectDir });
|
|
74
|
+
const dependenciesMap = (0, resolve_dep_names_1.resolveDepNames)(Object.keys(requirements), sitePackagesPath);
|
|
75
|
+
const { externalDependencies, files } = (0, extract_python_data_1.extractPythonData)(this.builder.projectDir, entrypointPath, dependenciesMap, fileContent);
|
|
84
76
|
// move files
|
|
85
77
|
for (const file of files) {
|
|
86
78
|
fs_1.default.mkdirSync(path_1.default.dirname(path_1.default.join(bundleDir, file)), { recursive: true });
|
|
@@ -94,7 +86,10 @@ class PythonBuilder {
|
|
|
94
86
|
const dependencies = Object.values(externalDependencies);
|
|
95
87
|
if (dependencies.length > 0) {
|
|
96
88
|
// create requirements.txt
|
|
97
|
-
|
|
89
|
+
const requirementsContent = Object.values(externalDependencies)
|
|
90
|
+
.map((dependency) => requirements[dependency])
|
|
91
|
+
.join('\n');
|
|
92
|
+
fs_1.default.writeFileSync(path_1.default.join(bundleDir, 'requirements.txt'), requirementsContent);
|
|
98
93
|
await this.packager.packageDependencies(bundleDir);
|
|
99
94
|
}
|
|
100
95
|
// zip entire folder
|
package/dist/cjs/cloud/build/builders/python/python-data/__tests__/extract-python-data.test.js
CHANGED
|
@@ -8,11 +8,10 @@ const glob_1 = require("glob");
|
|
|
8
8
|
const read_requirements_1 = require("../read-requirements");
|
|
9
9
|
const extract_python_data_1 = require("../extract-python-data");
|
|
10
10
|
const python_errors_1 = require("../python-errors");
|
|
11
|
-
const mockPackageDescriber = (name) => ({ name, importName: name });
|
|
12
11
|
describe('extractPythonData', () => {
|
|
13
12
|
test('extracts python data correctly', () => {
|
|
14
13
|
const rootDir = path_1.default.join(__dirname, './examples/example-1');
|
|
15
|
-
const requirements = (0, read_requirements_1.readRequirements)(path_1.default.join(rootDir, 'requirements.txt')
|
|
14
|
+
const requirements = (0, read_requirements_1.readRequirements)(path_1.default.join(rootDir, 'requirements.txt'));
|
|
16
15
|
const steps = (0, glob_1.globSync)('**/*_step.py', { absolute: false, cwd: path_1.default.join(rootDir, 'steps') });
|
|
17
16
|
for (const file of steps) {
|
|
18
17
|
const result = (0, extract_python_data_1.extractPythonData)(rootDir, `/steps/${file}`, requirements);
|
|
@@ -25,17 +24,17 @@ describe('extractPythonData', () => {
|
|
|
25
24
|
});
|
|
26
25
|
test('extracts python data correctly with invalid dependency', () => {
|
|
27
26
|
const rootDir = path_1.default.join(__dirname, './examples/invalid-dependency');
|
|
28
|
-
const requirements = (0, read_requirements_1.readRequirements)(path_1.default.join(rootDir, 'requirements.txt')
|
|
27
|
+
const requirements = (0, read_requirements_1.readRequirements)(path_1.default.join(rootDir, 'requirements.txt'));
|
|
29
28
|
expect(() => (0, extract_python_data_1.extractPythonData)(rootDir, `/steps/api_step.py`, requirements)).toThrow(python_errors_1.PythonImportNotFoundError);
|
|
30
29
|
});
|
|
31
30
|
test('extracts python data correctly with compilation error', () => {
|
|
32
31
|
const rootDir = path_1.default.join(__dirname, './examples/compilation-error');
|
|
33
|
-
const requirements = (0, read_requirements_1.readRequirements)(path_1.default.join(rootDir, 'requirements.txt')
|
|
32
|
+
const requirements = (0, read_requirements_1.readRequirements)(path_1.default.join(rootDir, 'requirements.txt'));
|
|
34
33
|
expect(() => (0, extract_python_data_1.extractPythonData)(rootDir, `/steps/api_step.py`, requirements)).toThrow(new python_errors_1.PythonError("Compilation error: no viable alternative at input ':' at line 3:10 in /steps/api_step.py", '/steps/api_step.py'));
|
|
35
34
|
});
|
|
36
35
|
test('extracts python data with nested import from requirements', () => {
|
|
37
36
|
const rootDir = path_1.default.join(__dirname, './examples/chessarena');
|
|
38
|
-
const requirements = (0, read_requirements_1.readRequirements)(path_1.default.join(rootDir, 'requirements.txt')
|
|
37
|
+
const requirements = (0, read_requirements_1.readRequirements)(path_1.default.join(rootDir, 'requirements.txt'));
|
|
39
38
|
const result = (0, extract_python_data_1.extractPythonData)(rootDir, `/steps/evaluate_player_move_step.py`, requirements);
|
|
40
39
|
expect(result.externalDependencies).toEqual({ chess: 'chess>=1.0.0', pydantic: 'pydantic>=2.6.1' });
|
|
41
40
|
});
|
|
@@ -11,9 +11,7 @@ import requests
|
|
|
11
11
|
from .local_module import something
|
|
12
12
|
from ..parent_module import other
|
|
13
13
|
`;
|
|
14
|
-
const requirements = {
|
|
15
|
-
requests: 'requests==2.25.1',
|
|
16
|
-
};
|
|
14
|
+
const requirements = { requests: 'requests' };
|
|
17
15
|
const deps = (0, get_dependencies_from_file_1.getDependenciesFromFile)(pythonCode, 'test.py', requirements);
|
|
18
16
|
expect(Array.from(deps.standardLibDependencies)).toEqual(['os', 'sys', 'collections']);
|
|
19
17
|
expect(Array.from(deps.externalDependencies)).toEqual(['requests']);
|
|
@@ -31,9 +29,7 @@ import json
|
|
|
31
29
|
import numpy
|
|
32
30
|
import mypackage.submodule
|
|
33
31
|
`;
|
|
34
|
-
const requirements = {
|
|
35
|
-
numpy: 'numpy==1.21.0',
|
|
36
|
-
};
|
|
32
|
+
const requirements = { numpy: 'numpy' };
|
|
37
33
|
const deps = (0, get_dependencies_from_file_1.getDependenciesFromFile)(pythonCode, 'test.py', requirements);
|
|
38
34
|
expect(Array.from(deps.standardLibDependencies)).toEqual(['json']);
|
|
39
35
|
expect(Array.from(deps.externalDependencies)).toEqual(['numpy']);
|
|
@@ -45,9 +41,7 @@ import json
|
|
|
45
41
|
import numpy as np
|
|
46
42
|
import mypackage.submodule
|
|
47
43
|
`;
|
|
48
|
-
const requirements = {
|
|
49
|
-
numpy: 'numpy==1.21.0',
|
|
50
|
-
};
|
|
44
|
+
const requirements = { numpy: 'numpy' };
|
|
51
45
|
const deps = (0, get_dependencies_from_file_1.getDependenciesFromFile)(pythonCode, 'test.py', requirements);
|
|
52
46
|
expect(Array.from(deps.standardLibDependencies)).toEqual(['json']);
|
|
53
47
|
expect(Array.from(deps.externalDependencies)).toEqual(['numpy']);
|
package/dist/cjs/cloud/build/builders/python/python-data/__tests__/read-requirements.test.js
CHANGED
|
@@ -9,7 +9,6 @@ const path_1 = __importDefault(require("path"));
|
|
|
9
9
|
const os_1 = require("os");
|
|
10
10
|
describe('readRequirements', () => {
|
|
11
11
|
let tempFilePath;
|
|
12
|
-
const mockPackageDescriber = jest.fn((name) => ({ name, importName: name }));
|
|
13
12
|
beforeEach(() => {
|
|
14
13
|
// Create a temporary file path
|
|
15
14
|
tempFilePath = path_1.default.join((0, os_1.tmpdir)(), `requirements-${Date.now()}.txt`);
|
|
@@ -25,7 +24,7 @@ describe('readRequirements', () => {
|
|
|
25
24
|
numpy>=1.20.0
|
|
26
25
|
flask~=2.0`;
|
|
27
26
|
fs_1.default.writeFileSync(tempFilePath, content);
|
|
28
|
-
const requirements = (0, read_requirements_1.readRequirements)(tempFilePath
|
|
27
|
+
const requirements = (0, read_requirements_1.readRequirements)(tempFilePath);
|
|
29
28
|
expect(Object.keys(requirements)).toHaveLength(3);
|
|
30
29
|
expect(requirements.requests).toBe('requests==2.25.1');
|
|
31
30
|
expect(requirements.numpy).toBe('numpy>=1.20.0');
|
|
@@ -40,38 +39,17 @@ numpy>=1.20.0
|
|
|
40
39
|
|
|
41
40
|
flask~=2.0`;
|
|
42
41
|
fs_1.default.writeFileSync(tempFilePath, content);
|
|
43
|
-
const requirements = (0, read_requirements_1.readRequirements)(tempFilePath
|
|
42
|
+
const requirements = (0, read_requirements_1.readRequirements)(tempFilePath);
|
|
44
43
|
expect(Object.keys(requirements)).toHaveLength(3);
|
|
45
44
|
expect(requirements.requests).toBe('requests==2.25.1');
|
|
46
45
|
expect(requirements.numpy).toBe('numpy>=1.20.0');
|
|
47
46
|
expect(requirements.flask).toBe('flask~=2.0');
|
|
48
47
|
});
|
|
49
|
-
test('handles complex package names and version specifiers', () => {
|
|
50
|
-
const content = `scikit-learn==1.0.2
|
|
51
|
-
python-dateutil==1.4
|
|
52
|
-
Django<4.0.0,>=3.2.0`;
|
|
53
|
-
fs_1.default.writeFileSync(tempFilePath, content);
|
|
54
|
-
const describer = jest.fn((name) => {
|
|
55
|
-
// mocking a describer resolution for these packages
|
|
56
|
-
// we're going to implement it separately
|
|
57
|
-
const map = {
|
|
58
|
-
'scikit-learn': 'sklearn',
|
|
59
|
-
'python-dateutil': 'dateutil',
|
|
60
|
-
Django: 'django',
|
|
61
|
-
};
|
|
62
|
-
return map[name] ? { name, importName: map[name] } : { name, importName: name };
|
|
63
|
-
});
|
|
64
|
-
const requirements = (0, read_requirements_1.readRequirements)(tempFilePath, describer);
|
|
65
|
-
expect(Object.keys(requirements)).toEqual(['sklearn', 'dateutil', 'django']);
|
|
66
|
-
expect(requirements['sklearn']).toBe('scikit-learn==1.0.2');
|
|
67
|
-
expect(requirements['dateutil']).toBe('python-dateutil==1.4');
|
|
68
|
-
expect(requirements['django']).toBe('Django<4.0.0,>=3.2.0');
|
|
69
|
-
});
|
|
70
48
|
test('handles requirements with extra dependencies', () => {
|
|
71
49
|
const content = `requests[security]==2.25.1
|
|
72
50
|
flask[async]==2.0.1`;
|
|
73
51
|
fs_1.default.writeFileSync(tempFilePath, content);
|
|
74
|
-
const requirements = (0, read_requirements_1.readRequirements)(tempFilePath
|
|
52
|
+
const requirements = (0, read_requirements_1.readRequirements)(tempFilePath);
|
|
75
53
|
expect(Object.keys(requirements)).toHaveLength(2);
|
|
76
54
|
expect(requirements['requests']).toBe('requests[security]==2.25.1');
|
|
77
55
|
expect(requirements['flask']).toBe('flask[async]==2.0.1');
|
|
@@ -81,7 +59,7 @@ flask[async]==2.0.1`;
|
|
|
81
59
|
|
|
82
60
|
# And empty lines`;
|
|
83
61
|
fs_1.default.writeFileSync(tempFilePath, content);
|
|
84
|
-
const requirements = (0, read_requirements_1.readRequirements)(tempFilePath
|
|
62
|
+
const requirements = (0, read_requirements_1.readRequirements)(tempFilePath);
|
|
85
63
|
expect(Object.keys(requirements)).toHaveLength(0);
|
|
86
64
|
});
|
|
87
65
|
test('handles malformed lines gracefully', () => {
|
|
@@ -90,7 +68,7 @@ flask[async]==2.0.1`;
|
|
|
90
68
|
numpy>=1.20.0
|
|
91
69
|
==invalid-version-only`;
|
|
92
70
|
fs_1.default.writeFileSync(tempFilePath, content);
|
|
93
|
-
const requirements = (0, read_requirements_1.readRequirements)(tempFilePath
|
|
71
|
+
const requirements = (0, read_requirements_1.readRequirements)(tempFilePath);
|
|
94
72
|
expect(Object.keys(requirements)).toHaveLength(2);
|
|
95
73
|
expect(requirements.requests).toBe('requests==2.25.1');
|
|
96
74
|
expect(requirements.numpy).toBe('numpy>=1.20.0');
|
|
@@ -98,7 +76,7 @@ numpy>=1.20.0
|
|
|
98
76
|
test('handles mixed line endings', () => {
|
|
99
77
|
const content = 'requests==2.25.1\r\nnumpy>=1.20.0\nflask~=2.0';
|
|
100
78
|
fs_1.default.writeFileSync(tempFilePath, content);
|
|
101
|
-
const requirements = (0, read_requirements_1.readRequirements)(tempFilePath
|
|
79
|
+
const requirements = (0, read_requirements_1.readRequirements)(tempFilePath);
|
|
102
80
|
expect(Object.keys(requirements)).toHaveLength(3);
|
|
103
81
|
expect(requirements.requests).toBe('requests==2.25.1');
|
|
104
82
|
expect(requirements.numpy).toBe('numpy>=1.20.0');
|
|
@@ -107,7 +85,7 @@ numpy>=1.20.0
|
|
|
107
85
|
test('handles requirements with no versions', () => {
|
|
108
86
|
const content = ['requests', 'numpy', 'flask'].join('\n');
|
|
109
87
|
fs_1.default.writeFileSync(tempFilePath, content);
|
|
110
|
-
const requirements = (0, read_requirements_1.readRequirements)(tempFilePath
|
|
88
|
+
const requirements = (0, read_requirements_1.readRequirements)(tempFilePath);
|
|
111
89
|
expect(Object.keys(requirements)).toHaveLength(3);
|
|
112
90
|
expect(requirements.requests).toBe('requests');
|
|
113
91
|
expect(requirements.numpy).toBe('numpy');
|
|
@@ -4,26 +4,35 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const path_1 = __importDefault(require("path"));
|
|
7
|
-
const
|
|
7
|
+
const resolve_dep_names_1 = require("../resolve-dep-names");
|
|
8
8
|
const python_errors_1 = require("../python-errors");
|
|
9
9
|
const sitePackagesDir = path_1.default.join(__dirname, 'site-packages');
|
|
10
10
|
describe('resolveDepName', () => {
|
|
11
11
|
test('resolves dependency names correctly', () => {
|
|
12
12
|
const depNames = ['httpx'];
|
|
13
|
-
const result = (0,
|
|
14
|
-
expect(result).toEqual(
|
|
13
|
+
const result = (0, resolve_dep_names_1.resolveDepNames)(depNames, sitePackagesDir);
|
|
14
|
+
expect(result).toEqual({ httpx: 'httpx' });
|
|
15
15
|
});
|
|
16
16
|
test('resolves multiple dependency names correctly', () => {
|
|
17
17
|
const depNames = ['httpx', 'scikit-learn', 'opencv-python'];
|
|
18
|
-
const result = (0,
|
|
19
|
-
expect(result).toEqual(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
const result = (0, resolve_dep_names_1.resolveDepNames)(depNames, sitePackagesDir);
|
|
19
|
+
expect(result).toEqual({
|
|
20
|
+
httpx: 'httpx',
|
|
21
|
+
sklearn: 'scikit-learn',
|
|
22
|
+
cv2: 'opencv-python',
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
test('resolves pymongo correctly', () => {
|
|
26
|
+
const depNames = ['pymongo'];
|
|
27
|
+
const result = (0, resolve_dep_names_1.resolveDepNames)(depNames, sitePackagesDir);
|
|
28
|
+
expect(result).toEqual({
|
|
29
|
+
pymongo: 'pymongo',
|
|
30
|
+
bson: 'pymongo',
|
|
31
|
+
gridfs: 'pymongo',
|
|
32
|
+
});
|
|
24
33
|
});
|
|
25
34
|
test('should throw an error if the dependency is not found', () => {
|
|
26
35
|
const depNames = ['httpx', 'scikit-learn', 'opencv-python', 'pydantic'];
|
|
27
|
-
expect(() => (0,
|
|
36
|
+
expect(() => (0, resolve_dep_names_1.resolveDepNames)(depNames, sitePackagesDir)).toThrow(new python_errors_1.PythonError('Could not find dependency name in site-packages: pydantic', 'pydantic'));
|
|
28
37
|
});
|
|
29
38
|
});
|
|
@@ -4,4 +4,4 @@ export type PythonResult = {
|
|
|
4
4
|
externalDependencies: Requirements;
|
|
5
5
|
files: string[];
|
|
6
6
|
};
|
|
7
|
-
export declare const extractPythonData: (rootDir: string, filePath: string,
|
|
7
|
+
export declare const extractPythonData: (rootDir: string, filePath: string, dependenciesMap: Record<string, string>, fileContent?: string) => PythonResult;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.extractPythonData = void 0;
|
|
4
4
|
const traverse_tree_1 = require("./traverse-tree");
|
|
5
|
-
const extractPythonData = (rootDir, filePath,
|
|
5
|
+
const extractPythonData = (rootDir, filePath, dependenciesMap,
|
|
6
6
|
// optional
|
|
7
7
|
fileContent) => {
|
|
8
8
|
const result = {
|
|
@@ -10,10 +10,10 @@ fileContent) => {
|
|
|
10
10
|
externalDependencies: new Set(),
|
|
11
11
|
files: new Set(),
|
|
12
12
|
};
|
|
13
|
-
(0, traverse_tree_1.traverseTree)(rootDir, filePath, result,
|
|
13
|
+
(0, traverse_tree_1.traverseTree)(rootDir, filePath, result, dependenciesMap, fileContent);
|
|
14
14
|
const resultDependencies = {};
|
|
15
15
|
result.externalDependencies.forEach((dependency) => {
|
|
16
|
-
resultDependencies[dependency] =
|
|
16
|
+
resultDependencies[dependency] = dependenciesMap[dependency];
|
|
17
17
|
});
|
|
18
18
|
return {
|
|
19
19
|
standardLibDependencies: Array.from(result.standardLibDependencies),
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { Requirements } from './read-requirements';
|
|
2
1
|
export type Dependencies = {
|
|
3
2
|
standardLibDependencies: Set<string>;
|
|
4
3
|
externalDependencies: Set<string>;
|
|
5
4
|
projectDependencies: Set<string>;
|
|
6
5
|
};
|
|
7
|
-
export declare const getDependenciesFromFile: (content: string, path: string,
|
|
6
|
+
export declare const getDependenciesFromFile: (content: string, path: string, externalDependenciesMap: Record<string, string>) => Dependencies;
|
|
@@ -23,7 +23,7 @@ function parse(source, sourceName) {
|
|
|
23
23
|
parser.addErrorListener(listener);
|
|
24
24
|
return parser.file_input();
|
|
25
25
|
}
|
|
26
|
-
const getDependenciesFromFile = (content, path,
|
|
26
|
+
const getDependenciesFromFile = (content, path, externalDependenciesMap) => {
|
|
27
27
|
const result = parse(content + '\n', path);
|
|
28
28
|
const modulesSet = new Set();
|
|
29
29
|
(0, python_ast_1.createVisitor)({
|
|
@@ -60,7 +60,7 @@ const getDependenciesFromFile = (content, path, requirements) => {
|
|
|
60
60
|
else if (constants_1.STANDARD_LIB_MODULES.has(module)) {
|
|
61
61
|
dependencies.standardLibDependencies.add(module);
|
|
62
62
|
}
|
|
63
|
-
else if (
|
|
63
|
+
else if (externalDependenciesMap[module] || externalDependenciesMap[moduleName]) {
|
|
64
64
|
dependencies.externalDependencies.add(module);
|
|
65
65
|
}
|
|
66
66
|
else {
|
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
type PackageDescriber = (packageName: string) => PackageInfo;
|
|
1
|
+
/**
|
|
2
|
+
* { libraryName: lineFromRequirementsFile }
|
|
3
|
+
*
|
|
4
|
+
* Example:
|
|
5
|
+
* { scikit-learn: 'scikit-learn==1.0.2' }
|
|
6
|
+
*/
|
|
7
|
+
export type Requirements = Record<string, string>;
|
|
9
8
|
/**
|
|
10
9
|
* Read the requirements.txt file and return a set of dependencies
|
|
11
10
|
* @param filePath
|
|
12
11
|
* @returns set of all dependencies names
|
|
13
12
|
*/
|
|
14
|
-
export declare const readRequirements: (filePath: string
|
|
15
|
-
export {};
|
|
13
|
+
export declare const readRequirements: (filePath: string) => Requirements;
|
|
@@ -10,7 +10,7 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
10
10
|
* @param filePath
|
|
11
11
|
* @returns set of all dependencies names
|
|
12
12
|
*/
|
|
13
|
-
const readRequirements = (filePath
|
|
13
|
+
const readRequirements = (filePath) => {
|
|
14
14
|
const content = fs_1.default.readFileSync(filePath, 'utf8');
|
|
15
15
|
const lines = content.split('\n');
|
|
16
16
|
const requirements = {};
|
|
@@ -23,8 +23,8 @@ const readRequirements = (filePath, describer) => {
|
|
|
23
23
|
// Extract package name (everything before version specifiers)
|
|
24
24
|
const packageMatch = trimmedLine.match(/^([a-zA-Z0-9_-]+)/);
|
|
25
25
|
if (packageMatch) {
|
|
26
|
-
const
|
|
27
|
-
requirements[
|
|
26
|
+
const packageName = packageMatch[1];
|
|
27
|
+
requirements[packageName] = trimmedLine;
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
return requirements;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Resolve the name of the import from the name of the package
|
|
3
3
|
* @param depName the package name
|
|
4
|
-
* @returns the import name
|
|
4
|
+
* @returns a map of the import name to the package name
|
|
5
5
|
*/
|
|
6
|
-
export declare const resolveDepNames: (depNames: string[], sitePackagesDir: string) =>
|
|
6
|
+
export declare const resolveDepNames: (depNames: string[], sitePackagesDir: string) => Record<string, string>;
|
|
@@ -10,13 +10,13 @@ const python_errors_1 = require("./python-errors");
|
|
|
10
10
|
/**
|
|
11
11
|
* Resolve the name of the import from the name of the package
|
|
12
12
|
* @param depName the package name
|
|
13
|
-
* @returns the import name
|
|
13
|
+
* @returns a map of the import name to the package name
|
|
14
14
|
*/
|
|
15
15
|
const resolveDepNames = (depNames, sitePackagesDir) => {
|
|
16
16
|
const folders = fs_1.default
|
|
17
17
|
.readdirSync(sitePackagesDir)
|
|
18
18
|
.filter((folder) => fs_1.default.statSync(path_1.default.join(sitePackagesDir, folder)).isDirectory());
|
|
19
|
-
const result =
|
|
19
|
+
const result = {};
|
|
20
20
|
for (const depName of depNames) {
|
|
21
21
|
const regex = new RegExp(`^${depName.replace(/-/g, '[-_]')}-.*\\.dist-info$`);
|
|
22
22
|
const folder = folders.find((folder) => regex.test(folder));
|
|
@@ -25,7 +25,7 @@ const resolveDepNames = (depNames, sitePackagesDir) => {
|
|
|
25
25
|
const recordFile = fs_1.default.existsSync(path_1.default.join(sitePackagesDir, folder, 'RECORD'));
|
|
26
26
|
if (topLevelFile) {
|
|
27
27
|
const topLevel = fs_1.default.readFileSync(path_1.default.join(sitePackagesDir, folder, 'top_level.txt'), 'utf8').trim();
|
|
28
|
-
result
|
|
28
|
+
result[topLevel] = depName;
|
|
29
29
|
}
|
|
30
30
|
else if (recordFile) {
|
|
31
31
|
const record = fs_1.default.readFileSync(path_1.default.join(sitePackagesDir, folder, 'RECORD'), 'utf8').trim();
|
|
@@ -35,8 +35,7 @@ const resolveDepNames = (depNames, sitePackagesDir) => {
|
|
|
35
35
|
// RECORD format: path/__init__.py,sha256=hash,size
|
|
36
36
|
const match = /^([^/]+)\/__init__\.py,/.exec(line);
|
|
37
37
|
if (match) {
|
|
38
|
-
result
|
|
39
|
-
break;
|
|
38
|
+
result[match[1]] = depName;
|
|
40
39
|
}
|
|
41
40
|
}
|
|
42
41
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { Requirements } from './read-requirements';
|
|
2
1
|
export type TraverseTreeResult = {
|
|
3
2
|
standardLibDependencies: Set<string>;
|
|
4
3
|
externalDependencies: Set<string>;
|
|
5
4
|
files: Set<string>;
|
|
6
5
|
};
|
|
7
|
-
export declare const traverseTree: (rootDir: string, filePath: string, result: TraverseTreeResult,
|
|
6
|
+
export declare const traverseTree: (rootDir: string, filePath: string, result: TraverseTreeResult, dependenciesMap: Record<string, string>, fileContent?: string) => void;
|
|
@@ -9,7 +9,7 @@ const path_1 = __importDefault(require("path"));
|
|
|
9
9
|
const convert_import_path_1 = require("./convert-import-path");
|
|
10
10
|
const get_dependencies_from_file_1 = require("./get-dependencies-from-file");
|
|
11
11
|
const python_errors_1 = require("./python-errors");
|
|
12
|
-
const traverseTree = (rootDir, filePath, result,
|
|
12
|
+
const traverseTree = (rootDir, filePath, result, dependenciesMap,
|
|
13
13
|
// optional
|
|
14
14
|
fileContent) => {
|
|
15
15
|
const fileAbsolutePath = path_1.default.join(rootDir, filePath);
|
|
@@ -21,7 +21,7 @@ fileContent) => {
|
|
|
21
21
|
result.files.add(initPath.replace(rootDir, ''));
|
|
22
22
|
}
|
|
23
23
|
const content = fileContent || fs_1.default.readFileSync(fileAbsolutePath, 'utf8');
|
|
24
|
-
const dependencies = (0, get_dependencies_from_file_1.getDependenciesFromFile)(content, filePath,
|
|
24
|
+
const dependencies = (0, get_dependencies_from_file_1.getDependenciesFromFile)(content, filePath, dependenciesMap);
|
|
25
25
|
result.files.add(filePath);
|
|
26
26
|
dependencies.externalDependencies.forEach((dependency) => {
|
|
27
27
|
result.externalDependencies.add(dependency);
|
|
@@ -36,7 +36,7 @@ fileContent) => {
|
|
|
36
36
|
const dependencyPath = dependencyFilePath.replace(rootDir, '');
|
|
37
37
|
if (!result.files.has(dependencyPath)) {
|
|
38
38
|
try {
|
|
39
|
-
(0, exports.traverseTree)(rootDir, dependencyPath, result,
|
|
39
|
+
(0, exports.traverseTree)(rootDir, dependencyPath, result, dependenciesMap);
|
|
40
40
|
}
|
|
41
41
|
catch (error) {
|
|
42
42
|
if (error instanceof python_errors_1.PythonFileNotFoundError) {
|
|
@@ -44,7 +44,7 @@ fileContent) => {
|
|
|
44
44
|
// try root folder
|
|
45
45
|
try {
|
|
46
46
|
const rootDependencyFilePath = path_1.default.resolve(rootDir, `${pythonPath}.py`).replace(rootDir, '');
|
|
47
|
-
return (0, exports.traverseTree)(rootDir, rootDependencyFilePath, result,
|
|
47
|
+
return (0, exports.traverseTree)(rootDir, rootDependencyFilePath, result, dependenciesMap);
|
|
48
48
|
}
|
|
49
49
|
catch (_error) {
|
|
50
50
|
// let it throw
|
|
@@ -40,7 +40,7 @@ const glob_1 = require("glob");
|
|
|
40
40
|
const generateTemplateSteps = (templateFolder) => {
|
|
41
41
|
return async (rootDir, context) => {
|
|
42
42
|
const templatePath = path.join(__dirname, templateFolder);
|
|
43
|
-
const files = (0, glob_1.globSync)('**/*', { absolute: false, cwd: templatePath });
|
|
43
|
+
const files = (0, glob_1.globSync)('**/*', { absolute: false, cwd: templatePath, dot: true });
|
|
44
44
|
try {
|
|
45
45
|
for (const fileName of files) {
|
|
46
46
|
const filePath = path.join(templatePath, fileName);
|
|
@@ -54,7 +54,7 @@ const generateTemplateSteps = (templateFolder) => {
|
|
|
54
54
|
(0, fs_1.mkdirSync)(targetDir, { recursive: true });
|
|
55
55
|
}
|
|
56
56
|
if ((0, fs_1.statSync)(filePath).isDirectory()) {
|
|
57
|
-
const folderPath =
|
|
57
|
+
const folderPath = filePath.replace(templatePath, '');
|
|
58
58
|
(0, fs_1.mkdirSync)(path.join(rootDir, folderPath), { recursive: true });
|
|
59
59
|
continue;
|
|
60
60
|
}
|
|
@@ -8,7 +8,7 @@ export type Generator = (rootDir: string, context: CliContext) => Promise<void>
|
|
|
8
8
|
export const generateTemplateSteps = (templateFolder: string): Generator => {
|
|
9
9
|
return async (rootDir: string, context: CliContext): Promise<void> => {
|
|
10
10
|
const templatePath = path.join(__dirname, templateFolder)
|
|
11
|
-
const files = globSync('**/*', { absolute: false, cwd: templatePath })
|
|
11
|
+
const files = globSync('**/*', { absolute: false, cwd: templatePath, dot: true })
|
|
12
12
|
|
|
13
13
|
try {
|
|
14
14
|
for (const fileName of files) {
|
|
@@ -24,7 +24,7 @@ export const generateTemplateSteps = (templateFolder: string): Generator => {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
if (statSync(filePath).isDirectory()) {
|
|
27
|
-
const folderPath =
|
|
27
|
+
const folderPath = filePath.replace(templatePath, '')
|
|
28
28
|
mkdirSync(path.join(rootDir, folderPath), { recursive: true })
|
|
29
29
|
continue
|
|
30
30
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: How to configure database migrations in the project
|
|
3
|
+
globs:
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
# Configuring database migrations
|
|
7
|
+
|
|
8
|
+
When configuring database in the project, create a `knexfile.ts` file in the root of the project.
|
|
9
|
+
|
|
10
|
+
```typescript
|
|
11
|
+
import type { Knex } from 'knex'
|
|
12
|
+
import * as dotenv from 'dotenv'
|
|
13
|
+
|
|
14
|
+
dotenv.config({ path: '.env' })
|
|
15
|
+
|
|
16
|
+
const config: Knex.Config = {
|
|
17
|
+
client: 'postgresql',
|
|
18
|
+
connection: {
|
|
19
|
+
host: process.env.DB_HOST,
|
|
20
|
+
port: process.env.DB_PORT,
|
|
21
|
+
database: process.env.DB_NAME,
|
|
22
|
+
user: process.env.DB_USER,
|
|
23
|
+
password: process.env.DB_PASS,
|
|
24
|
+
},
|
|
25
|
+
pool: {
|
|
26
|
+
min: 2,
|
|
27
|
+
max: 10,
|
|
28
|
+
},
|
|
29
|
+
migrations: {
|
|
30
|
+
tableName: 'knex_migrations',
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default config
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Creating a new migration
|
|
38
|
+
|
|
39
|
+
Prefix should be timestamp in milliseconds.
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm run migrate:make 1727115600000_create_users_table
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Running migrations
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm run migrate:latest
|
|
49
|
+
```
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Database connections and queries
|
|
3
|
+
globs: src/repositories/**/*.ts
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
# Database Guide
|
|
7
|
+
|
|
8
|
+
- Prefer knex to interact with the database
|
|
9
|
+
- http://npmjs.com/package/knex
|
|
10
|
+
- Use knex migrations to manage database schema changes
|
|
11
|
+
- Do NOT create DB calls directly in steps or services, ALWAYS create a repository file to handle the database calls. Follow DDD principles.
|
|
12
|
+
|
|
13
|
+
## Add commands to package.json
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"scripts": {
|
|
18
|
+
"migrate:up": "knex migrate:latest",
|
|
19
|
+
"migrate:down": "knex migrate:rollback",
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Creating base database connection
|
|
25
|
+
|
|
26
|
+
- When SQL database is used, create a database connection file in the `src/repositories/database.ts` file.
|
|
27
|
+
- All columns in code are cammelCase, however, in the database and in the migration, we use snake_case.
|
|
28
|
+
- Avoid numeric incremental IDs, use UUIDs instead. Make sure to add foreign key with cascade delete when applicable.
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import knex, { Knex } from 'knex'
|
|
32
|
+
/**
|
|
33
|
+
* Create these functions to convert between camelCase and snake_case.
|
|
34
|
+
* This is important to keep the consistency of the data.
|
|
35
|
+
*/
|
|
36
|
+
import { camelToSnake, snakeToCamelObject } from '../utils/case-conversion'
|
|
37
|
+
|
|
38
|
+
const isProduction = process.env.NODE_ENV === 'production'
|
|
39
|
+
const isDevelopment = process.env.NODE_ENV === 'development'
|
|
40
|
+
|
|
41
|
+
// Knex configuration
|
|
42
|
+
const knexConfig: Knex.Config = {
|
|
43
|
+
client: 'pg',
|
|
44
|
+
connection: {
|
|
45
|
+
host: process.env.DB_HOST,
|
|
46
|
+
port: process.env.DB_PORT,
|
|
47
|
+
user: process.env.DB_USER,
|
|
48
|
+
password: process.env.DB_PASSWORD,
|
|
49
|
+
database: process.env.DB_NAME,
|
|
50
|
+
ssl: process.env.DB_SSL ? {
|
|
51
|
+
/** In development, we might use self-signed certs */
|
|
52
|
+
rejectUnauthorized: isProduction,
|
|
53
|
+
/** Add CA certificate if needed */
|
|
54
|
+
ca: undefined,
|
|
55
|
+
} : false,
|
|
56
|
+
},
|
|
57
|
+
pool: {
|
|
58
|
+
min: 2,
|
|
59
|
+
max: 10,
|
|
60
|
+
idleTimeoutMillis: 30000,
|
|
61
|
+
},
|
|
62
|
+
debug: isDevelopment,
|
|
63
|
+
wrapIdentifier: (value, origImpl) => origImpl(camelToSnake(value)),
|
|
64
|
+
postProcessResponse: result =>
|
|
65
|
+
Array.isArray(result)
|
|
66
|
+
? result.map(row => snakeToCamelObject(row))
|
|
67
|
+
: snakeToCamelObject(result),
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Create a singleton instance
|
|
71
|
+
let db: Knex | null = null
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Get the database instance
|
|
75
|
+
* @returns Knex instance
|
|
76
|
+
*/
|
|
77
|
+
export const getDb = (): Knex => {
|
|
78
|
+
if (!db) {
|
|
79
|
+
db = knex(knexConfig)
|
|
80
|
+
}
|
|
81
|
+
return db
|
|
82
|
+
}
|
|
83
|
+
```
|