ormbridge 0.0.0-stage → 0.2.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 (84) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +408 -2
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.js +20 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/cliRunner.d.ts +20 -0
  7. package/dist/cliRunner.js +343 -0
  8. package/dist/cliRunner.js.map +1 -0
  9. package/dist/config.d.ts +40 -0
  10. package/dist/config.js +204 -0
  11. package/dist/config.js.map +1 -0
  12. package/dist/convert.d.ts +20 -0
  13. package/dist/convert.js +61 -0
  14. package/dist/convert.js.map +1 -0
  15. package/dist/emitters/django.d.ts +4 -0
  16. package/dist/emitters/django.js +501 -0
  17. package/dist/emitters/django.js.map +1 -0
  18. package/dist/emitters/doctrine.d.ts +20 -0
  19. package/dist/emitters/doctrine.js +1134 -0
  20. package/dist/emitters/doctrine.js.map +1 -0
  21. package/dist/emitters/graphene.d.ts +4 -0
  22. package/dist/emitters/graphene.js +431 -0
  23. package/dist/emitters/graphene.js.map +1 -0
  24. package/dist/emitters/laravel.d.ts +33 -0
  25. package/dist/emitters/laravel.js +1695 -0
  26. package/dist/emitters/laravel.js.map +1 -0
  27. package/dist/emitters/prisma.d.ts +21 -0
  28. package/dist/emitters/prisma.js +1058 -0
  29. package/dist/emitters/prisma.js.map +1 -0
  30. package/dist/emitters/typeorm.d.ts +9 -0
  31. package/dist/emitters/typeorm.js +833 -0
  32. package/dist/emitters/typeorm.js.map +1 -0
  33. package/dist/emitters/typescriptInterfaces.d.ts +15 -0
  34. package/dist/emitters/typescriptInterfaces.js +350 -0
  35. package/dist/emitters/typescriptInterfaces.js.map +1 -0
  36. package/dist/formats.d.ts +80 -0
  37. package/dist/formats.js +212 -0
  38. package/dist/formats.js.map +1 -0
  39. package/dist/index.d.ts +33 -0
  40. package/dist/index.js +18 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/io.d.ts +48 -0
  43. package/dist/io.js +328 -0
  44. package/dist/io.js.map +1 -0
  45. package/dist/ir.d.ts +197 -0
  46. package/dist/ir.js +10 -0
  47. package/dist/ir.js.map +1 -0
  48. package/dist/naming.d.ts +11 -0
  49. package/dist/naming.js +88 -0
  50. package/dist/naming.js.map +1 -0
  51. package/dist/parsers/django.d.ts +14 -0
  52. package/dist/parsers/django.js +1161 -0
  53. package/dist/parsers/django.js.map +1 -0
  54. package/dist/parsers/doctrine.d.ts +12 -0
  55. package/dist/parsers/doctrine.js +1782 -0
  56. package/dist/parsers/doctrine.js.map +1 -0
  57. package/dist/parsers/laravel.d.ts +17 -0
  58. package/dist/parsers/laravel.js +2824 -0
  59. package/dist/parsers/laravel.js.map +1 -0
  60. package/dist/parsers/phpSyntax.d.ts +124 -0
  61. package/dist/parsers/phpSyntax.js +429 -0
  62. package/dist/parsers/phpSyntax.js.map +1 -0
  63. package/dist/parsers/prisma.d.ts +12 -0
  64. package/dist/parsers/prisma.js +964 -0
  65. package/dist/parsers/prisma.js.map +1 -0
  66. package/dist/parsers/pythonSyntax.d.ts +38 -0
  67. package/dist/parsers/pythonSyntax.js +120 -0
  68. package/dist/parsers/pythonSyntax.js.map +1 -0
  69. package/dist/parsers/typeorm.d.ts +12 -0
  70. package/dist/parsers/typeorm.js +1614 -0
  71. package/dist/parsers/typeorm.js.map +1 -0
  72. package/dist/parsers/typescriptSyntax.d.ts +57 -0
  73. package/dist/parsers/typescriptSyntax.js +200 -0
  74. package/dist/parsers/typescriptSyntax.js.map +1 -0
  75. package/dist/prismaOnlyConstructs.d.ts +7 -0
  76. package/dist/prismaOnlyConstructs.js +76 -0
  77. package/dist/prismaOnlyConstructs.js.map +1 -0
  78. package/dist/result.d.ts +20 -0
  79. package/dist/result.js +18 -0
  80. package/dist/result.js.map +1 -0
  81. package/dist/transforms.d.ts +13 -0
  82. package/dist/transforms.js +142 -0
  83. package/dist/transforms.js.map +1 -0
  84. package/package.json +83 -4
@@ -0,0 +1,142 @@
1
+ import { singularize, toPascalCase, toSnakeCase } from './naming.js';
2
+ const CREATED_FIELD_NAMES = new Set([
3
+ 'created_at',
4
+ 'created',
5
+ 'createdat',
6
+ 'date_created',
7
+ ]);
8
+ const UPDATED_FIELD_NAMES = new Set([
9
+ 'updated_at',
10
+ 'updated',
11
+ 'updatedat',
12
+ 'modified',
13
+ 'modified_at',
14
+ 'date_updated',
15
+ ]);
16
+ /**
17
+ * Replaces every many-to-many relation with an explicit join model that mirrors the
18
+ * table Django creates (app_post_tags with id, post_id, tag_id and a unique pair).
19
+ * Keeps converted schemas compatible with existing Django databases.
20
+ */
21
+ export function expandManyToMany(schema) {
22
+ const joinModels = [];
23
+ const models = schema.models.map((model) => {
24
+ const keptRelations = [];
25
+ for (const relation of model.relations) {
26
+ if (relation.kind !== 'manyToMany') {
27
+ keptRelations.push(relation);
28
+ continue;
29
+ }
30
+ joinModels.push(buildJoinModel(model, relation));
31
+ }
32
+ return { ...model, relations: keptRelations };
33
+ });
34
+ return { ...schema, models: [...models, ...joinModels] };
35
+ }
36
+ function buildJoinModel(owner, relation) {
37
+ const ownerSnake = toSnakeCase(owner.name);
38
+ const targetSnake = toSnakeCase(relation.targetModel);
39
+ const isSelfReference = owner.name === relation.targetModel;
40
+ const fromName = isSelfReference ? `from_${ownerSnake}` : ownerSnake;
41
+ const toName = isSelfReference ? `to_${targetSnake}` : targetSnake;
42
+ return {
43
+ name: `${owner.name}${toPascalCase(relation.name)}`,
44
+ tableName: `${owner.tableName}_${relation.name}`,
45
+ appLabel: owner.appLabel,
46
+ isJoinTable: true,
47
+ fields: [
48
+ {
49
+ name: 'id',
50
+ columnName: 'id',
51
+ type: 'int',
52
+ isPrimaryKey: true,
53
+ isUnique: false,
54
+ isNullable: false,
55
+ isAutoUpdated: false,
56
+ default: { kind: 'autoIncrement' },
57
+ },
58
+ ],
59
+ relations: [
60
+ {
61
+ name: fromName,
62
+ kind: 'foreignKey',
63
+ targetModel: owner.name,
64
+ columnName: `${fromName}_id`,
65
+ isNullable: false,
66
+ onDelete: 'cascade',
67
+ relatedName: relation.name,
68
+ },
69
+ {
70
+ name: toName,
71
+ kind: 'foreignKey',
72
+ targetModel: relation.targetModel,
73
+ columnName: `${toName}_id`,
74
+ isNullable: false,
75
+ onDelete: 'cascade',
76
+ relatedName: relation.relatedName ?? `${ownerSnake}_${relation.name}`,
77
+ },
78
+ ],
79
+ indexes: [{ fields: [fromName, toName], isUnique: true }],
80
+ };
81
+ }
82
+ /**
83
+ * Applies a fresh-schema style: singular snake_case table names, UUID primary keys in place of
84
+ * auto-increment ids, snake_case columns, and created_at / updated_at timestamps where missing.
85
+ */
86
+ export function normalizeSchema(schema) {
87
+ return { ...schema, models: schema.models.map(normalizeModel) };
88
+ }
89
+ function normalizeModel(model) {
90
+ const fields = model.fields.map(normalizeField);
91
+ if (model.isJoinTable !== true) {
92
+ const hasCreated = fields.some((field) => CREATED_FIELD_NAMES.has(field.name.toLowerCase()));
93
+ const hasUpdated = fields.some((field) => field.isAutoUpdated || UPDATED_FIELD_NAMES.has(field.name.toLowerCase()));
94
+ if (!hasCreated) {
95
+ fields.push({
96
+ name: 'created_at',
97
+ columnName: 'created_at',
98
+ type: 'dateTime',
99
+ isPrimaryKey: false,
100
+ isUnique: false,
101
+ isNullable: false,
102
+ isAutoUpdated: false,
103
+ default: { kind: 'now' },
104
+ });
105
+ }
106
+ if (!hasUpdated) {
107
+ fields.push({
108
+ name: 'updated_at',
109
+ columnName: 'updated_at',
110
+ type: 'dateTime',
111
+ isPrimaryKey: false,
112
+ isUnique: false,
113
+ isNullable: false,
114
+ isAutoUpdated: true,
115
+ });
116
+ }
117
+ }
118
+ return {
119
+ ...model,
120
+ tableName: singularize(toSnakeCase(model.name)),
121
+ fields,
122
+ relations: model.relations.map((relation) => ({
123
+ ...relation,
124
+ columnName: toSnakeCase(relation.columnName),
125
+ })),
126
+ };
127
+ }
128
+ function normalizeField(field) {
129
+ const normalized = {
130
+ ...field,
131
+ columnName: toSnakeCase(field.columnName),
132
+ };
133
+ const isAutoIncrementKey = field.isPrimaryKey &&
134
+ field.default !== undefined &&
135
+ field.default.kind === 'autoIncrement' &&
136
+ (field.type === 'int' || field.type === 'bigInt');
137
+ if (isAutoIncrementKey) {
138
+ return { ...normalized, type: 'uuid', default: { kind: 'uuid' } };
139
+ }
140
+ return normalized;
141
+ }
142
+ //# sourceMappingURL=transforms.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transforms.js","sourceRoot":"","sources":["../src/transforms.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAIrE,MAAM,mBAAmB,GAAwB,IAAI,GAAG,CAAC;IACvD,YAAY;IACZ,SAAS;IACT,WAAW;IACX,cAAc;CACf,CAAC,CAAC;AACH,MAAM,mBAAmB,GAAwB,IAAI,GAAG,CAAC;IACvD,YAAY;IACZ,SAAS;IACT,WAAW;IACX,UAAU;IACV,aAAa;IACb,cAAc;CACf,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAgB;IAC/C,MAAM,UAAU,GAAc,EAAE,CAAC;IACjC,MAAM,MAAM,GAAc,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAc,EAAW,EAAE;QACtE,MAAM,aAAa,GAAiB,EAAE,CAAC;QACvC,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YACvC,IAAI,QAAQ,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBACnC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC7B,SAAS;YACX,CAAC;YACD,UAAU,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;QACnD,CAAC;QACD,OAAO,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;IAChD,CAAC,CAAC,CAAC;IACH,OAAO,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,GAAG,UAAU,CAAC,EAAE,CAAC;AAC3D,CAAC;AAED,SAAS,cAAc,CAAC,KAAc,EAAE,QAAoB;IAC1D,MAAM,UAAU,GAAW,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnD,MAAM,WAAW,GAAW,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC9D,MAAM,eAAe,GAAY,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,WAAW,CAAC;IACrE,MAAM,QAAQ,GAAW,eAAe,CAAC,CAAC,CAAC,QAAQ,UAAU,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC;IAC7E,MAAM,MAAM,GAAW,eAAe,CAAC,CAAC,CAAC,MAAM,WAAW,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;IAE3E,OAAO;QACL,IAAI,EAAE,GAAG,KAAK,CAAC,IAAI,GAAG,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;QACnD,SAAS,EAAE,GAAG,KAAK,CAAC,SAAS,IAAI,QAAQ,CAAC,IAAI,EAAE;QAChD,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,WAAW,EAAE,IAAI;QACjB,MAAM,EAAE;YACN;gBACE,IAAI,EAAE,IAAI;gBACV,UAAU,EAAE,IAAI;gBAChB,IAAI,EAAE,KAAK;gBACX,YAAY,EAAE,IAAI;gBAClB,QAAQ,EAAE,KAAK;gBACf,UAAU,EAAE,KAAK;gBACjB,aAAa,EAAE,KAAK;gBACpB,OAAO,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE;aACnC;SACF;QACD,SAAS,EAAE;YACT;gBACE,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,YAAY;gBAClB,WAAW,EAAE,KAAK,CAAC,IAAI;gBACvB,UAAU,EAAE,GAAG,QAAQ,KAAK;gBAC5B,UAAU,EAAE,KAAK;gBACjB,QAAQ,EAAE,SAAS;gBACnB,WAAW,EAAE,QAAQ,CAAC,IAAI;aAC3B;YACD;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,YAAY;gBAClB,WAAW,EAAE,QAAQ,CAAC,WAAW;gBACjC,UAAU,EAAE,GAAG,MAAM,KAAK;gBAC1B,UAAU,EAAE,KAAK;gBACjB,QAAQ,EAAE,SAAS;gBACnB,WAAW,EAAE,QAAQ,CAAC,WAAW,IAAI,GAAG,UAAU,IAAI,QAAQ,CAAC,IAAI,EAAE;aACtE;SACF;QACD,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;KAC1D,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,MAAgB;IAC9C,OAAO,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC;AAClE,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACpC,MAAM,MAAM,GAAc,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAE3D,IAAI,KAAK,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;QAC/B,MAAM,UAAU,GAAY,MAAM,CAAC,IAAI,CAAC,CAAC,KAAc,EAAE,EAAE,CACzD,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAClD,CAAC;QACF,MAAM,UAAU,GAAY,MAAM,CAAC,IAAI,CACrC,CAAC,KAAc,EAAE,EAAE,CACjB,KAAK,CAAC,aAAa,IAAI,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAC3E,CAAC;QACF,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,YAAY;gBAClB,UAAU,EAAE,YAAY;gBACxB,IAAI,EAAE,UAAU;gBAChB,YAAY,EAAE,KAAK;gBACnB,QAAQ,EAAE,KAAK;gBACf,UAAU,EAAE,KAAK;gBACjB,aAAa,EAAE,KAAK;gBACpB,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;aACzB,CAAC,CAAC;QACL,CAAC;QACD,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,YAAY;gBAClB,UAAU,EAAE,YAAY;gBACxB,IAAI,EAAE,UAAU;gBAChB,YAAY,EAAE,KAAK;gBACnB,QAAQ,EAAE,KAAK;gBACf,UAAU,EAAE,KAAK;gBACjB,aAAa,EAAE,IAAI;aACpB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO;QACL,GAAG,KAAK;QACR,SAAS,EAAE,WAAW,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/C,MAAM;QACN,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAoB,EAAE,EAAE,CAAC,CAAC;YACxD,GAAG,QAAQ;YACX,UAAU,EAAE,WAAW,CAAC,QAAQ,CAAC,UAAU,CAAC;SAC7C,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACpC,MAAM,UAAU,GAAY;QAC1B,GAAG,KAAK;QACR,UAAU,EAAE,WAAW,CAAC,KAAK,CAAC,UAAU,CAAC;KAC1C,CAAC;IACF,MAAM,kBAAkB,GACtB,KAAK,CAAC,YAAY;QAClB,KAAK,CAAC,OAAO,KAAK,SAAS;QAC3B,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,eAAe;QACtC,CAAC,KAAK,CAAC,IAAI,KAAK,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;IACpD,IAAI,kBAAkB,EAAE,CAAC;QACvB,OAAO,EAAE,GAAG,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC;IACpE,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,85 @@
1
1
  {
2
2
  "name": "ormbridge",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.2.0",
4
+ "description": "Convert ORM models between frameworks and languages (Django, Prisma, TypeORM, Doctrine, Laravel). Define your data model once and share typed schemas across your stack.",
5
+ "author": {
6
+ "name": "Richard McQuiston",
7
+ "email": "richard.mcquiston01@gmail.com"
8
+ },
9
+ "type": "module",
10
+ "main": "./dist/index.js",
11
+ "types": "./dist/index.d.ts",
12
+ "bin": {
13
+ "ormbridge": "./dist/cli.js"
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md"
18
+ ],
19
+ "engines": {
20
+ "node": ">=20"
21
+ },
22
+ "scripts": {
23
+ "build": "tsc -p tsconfig.json",
24
+ "dev": "tsc -p tsconfig.json --watch",
25
+ "test": "vitest run",
26
+ "prepublishOnly": "npm run build && npm test",
27
+ "lint": "eslint .",
28
+ "lint:fix": "eslint . --fix",
29
+ "format": "prettier --write .",
30
+ "format:check": "prettier --check .",
31
+ "docs:matrix": "tsx scripts/generate-conversion-matrix.ts"
32
+ },
33
+ "keywords": [
34
+ "django",
35
+ "prisma",
36
+ "orm",
37
+ "schema",
38
+ "schema-converter",
39
+ "django-to-prisma",
40
+ "prisma-to-django",
41
+ "django-models",
42
+ "prisma-schema",
43
+ "models.py",
44
+ "migration",
45
+ "database",
46
+ "code-generation",
47
+ "codegen",
48
+ "cli",
49
+ "tree-sitter",
50
+ "typescript",
51
+ "python",
52
+ "typeorm",
53
+ "graphene",
54
+ "doctrine",
55
+ "laravel",
56
+ "eloquent",
57
+ "php",
58
+ "graphql"
59
+ ],
60
+ "license": "MIT",
61
+ "dependencies": {
62
+ "commander": "^15.0.0",
63
+ "tree-sitter-wasms": "^0.1.13",
64
+ "web-tree-sitter": "0.22.6"
65
+ },
66
+ "devDependencies": {
67
+ "@eslint/js": "^10.0.1",
68
+ "@types/node": "^26.6.4",
69
+ "eslint": "^10.12.0",
70
+ "eslint-config-prettier": "^10.1.8",
71
+ "prettier": "^3.9.9",
72
+ "tsx": "^4.23.15",
73
+ "typescript": "^6.0.3",
74
+ "typescript-eslint": "^8.71.1",
75
+ "vitest": "^5.0.3"
76
+ },
77
+ "repository": {
78
+ "type": "git",
79
+ "url": "git+https://github.com/RichardMcQuiston01/ormbridge.git"
80
+ },
81
+ "homepage": "https://github.com/RichardMcQuiston01/ormbridge#readme",
82
+ "bugs": {
83
+ "url": "https://github.com/RichardMcQuiston01/ormbridge/issues"
84
+ }
85
+ }