@stonyx/orm 0.2.1-alpha.35 → 0.2.1-alpha.37

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 (151) hide show
  1. package/dist/aggregates.d.ts +21 -0
  2. package/dist/aggregates.js +90 -0
  3. package/dist/attr.d.ts +2 -0
  4. package/dist/attr.js +22 -0
  5. package/dist/belongs-to.d.ts +11 -0
  6. package/dist/belongs-to.js +59 -0
  7. package/dist/cli.d.ts +22 -0
  8. package/dist/cli.js +148 -0
  9. package/dist/commands.d.ts +7 -0
  10. package/dist/commands.js +146 -0
  11. package/dist/db.d.ts +21 -0
  12. package/dist/db.js +174 -0
  13. package/dist/exports/db.d.ts +7 -0
  14. package/{src → dist}/exports/db.js +2 -4
  15. package/dist/has-many.d.ts +11 -0
  16. package/dist/has-many.js +58 -0
  17. package/dist/hooks.d.ts +47 -0
  18. package/dist/hooks.js +106 -0
  19. package/dist/index.d.ts +14 -0
  20. package/dist/index.js +34 -0
  21. package/dist/main.d.ts +46 -0
  22. package/dist/main.js +179 -0
  23. package/dist/manage-record.d.ts +13 -0
  24. package/dist/manage-record.js +117 -0
  25. package/dist/meta-request.d.ts +6 -0
  26. package/dist/meta-request.js +52 -0
  27. package/dist/migrate.d.ts +2 -0
  28. package/dist/migrate.js +57 -0
  29. package/dist/model-property.d.ts +9 -0
  30. package/dist/model-property.js +29 -0
  31. package/dist/model.d.ts +15 -0
  32. package/dist/model.js +18 -0
  33. package/dist/mysql/connection.d.ts +14 -0
  34. package/dist/mysql/connection.js +24 -0
  35. package/dist/mysql/migration-generator.d.ts +45 -0
  36. package/dist/mysql/migration-generator.js +245 -0
  37. package/dist/mysql/migration-runner.d.ts +12 -0
  38. package/dist/mysql/migration-runner.js +83 -0
  39. package/dist/mysql/mysql-db.d.ts +100 -0
  40. package/dist/mysql/mysql-db.js +415 -0
  41. package/dist/mysql/query-builder.d.ts +10 -0
  42. package/dist/mysql/query-builder.js +44 -0
  43. package/dist/mysql/schema-introspector.d.ts +19 -0
  44. package/dist/mysql/schema-introspector.js +286 -0
  45. package/dist/mysql/type-map.d.ts +21 -0
  46. package/dist/mysql/type-map.js +36 -0
  47. package/dist/orm-request.d.ts +38 -0
  48. package/dist/orm-request.js +455 -0
  49. package/dist/plural-registry.d.ts +4 -0
  50. package/{src → dist}/plural-registry.js +3 -6
  51. package/dist/postgres/connection.d.ts +15 -0
  52. package/dist/postgres/connection.js +30 -0
  53. package/dist/postgres/migration-generator.d.ts +45 -0
  54. package/dist/postgres/migration-generator.js +257 -0
  55. package/dist/postgres/migration-runner.d.ts +10 -0
  56. package/dist/postgres/migration-runner.js +82 -0
  57. package/dist/postgres/postgres-db.d.ts +119 -0
  58. package/dist/postgres/postgres-db.js +476 -0
  59. package/dist/postgres/query-builder.d.ts +27 -0
  60. package/dist/postgres/query-builder.js +98 -0
  61. package/dist/postgres/schema-introspector.d.ts +29 -0
  62. package/dist/postgres/schema-introspector.js +309 -0
  63. package/dist/postgres/type-map.d.ts +23 -0
  64. package/dist/postgres/type-map.js +53 -0
  65. package/dist/record.d.ts +75 -0
  66. package/dist/record.js +129 -0
  67. package/dist/relationships.d.ts +10 -0
  68. package/dist/relationships.js +39 -0
  69. package/dist/serializer.d.ts +17 -0
  70. package/dist/serializer.js +136 -0
  71. package/dist/setup-rest-server.d.ts +1 -0
  72. package/dist/setup-rest-server.js +54 -0
  73. package/dist/standalone-db.d.ts +58 -0
  74. package/dist/standalone-db.js +142 -0
  75. package/dist/store.d.ts +62 -0
  76. package/dist/store.js +271 -0
  77. package/dist/timescale/query-builder.d.ts +41 -0
  78. package/dist/timescale/query-builder.js +87 -0
  79. package/dist/timescale/timescale-db.d.ts +45 -0
  80. package/dist/timescale/timescale-db.js +84 -0
  81. package/dist/transforms.d.ts +2 -0
  82. package/dist/transforms.js +17 -0
  83. package/dist/types/orm-types.d.ts +142 -0
  84. package/dist/types/orm-types.js +1 -0
  85. package/dist/utils.d.ts +5 -0
  86. package/dist/utils.js +13 -0
  87. package/dist/view-resolver.d.ts +8 -0
  88. package/dist/view-resolver.js +169 -0
  89. package/dist/view.d.ts +11 -0
  90. package/dist/view.js +18 -0
  91. package/package.json +34 -11
  92. package/src/{aggregates.js → aggregates.ts} +27 -13
  93. package/src/{attr.js → attr.ts} +2 -2
  94. package/src/belongs-to.ts +90 -0
  95. package/src/{cli.js → cli.ts} +17 -11
  96. package/src/{commands.js → commands.ts} +179 -170
  97. package/src/{db.js → db.ts} +35 -26
  98. package/src/exports/db.ts +7 -0
  99. package/src/has-many.ts +92 -0
  100. package/src/{hooks.js → hooks.ts} +23 -27
  101. package/src/{index.js → index.ts} +4 -4
  102. package/src/{main.js → main.ts} +60 -34
  103. package/src/{manage-record.js → manage-record.ts} +47 -22
  104. package/src/{meta-request.js → meta-request.ts} +17 -14
  105. package/src/{migrate.js → migrate.ts} +9 -9
  106. package/src/{model-property.js → model-property.ts} +12 -6
  107. package/src/{model.js → model.ts} +5 -4
  108. package/src/mysql/{connection.js → connection.ts} +43 -28
  109. package/src/mysql/{migration-generator.js → migration-generator.ts} +332 -286
  110. package/src/mysql/{migration-runner.js → migration-runner.ts} +116 -110
  111. package/src/mysql/{mysql-db.js → mysql-db.ts} +537 -473
  112. package/src/mysql/{query-builder.js → query-builder.ts} +69 -64
  113. package/src/mysql/{schema-introspector.js → schema-introspector.ts} +355 -325
  114. package/src/mysql/{type-map.js → type-map.ts} +42 -37
  115. package/src/{orm-request.js → orm-request.ts} +169 -97
  116. package/src/plural-registry.ts +12 -0
  117. package/src/postgres/{connection.js → connection.ts} +14 -5
  118. package/src/postgres/{migration-generator.js → migration-generator.ts} +82 -38
  119. package/src/postgres/{migration-runner.js → migration-runner.ts} +11 -10
  120. package/src/postgres/{postgres-db.js → postgres-db.ts} +198 -114
  121. package/src/postgres/{query-builder.js → query-builder.ts} +27 -28
  122. package/src/postgres/{schema-introspector.js → schema-introspector.ts} +87 -58
  123. package/src/postgres/{type-map.js → type-map.ts} +10 -6
  124. package/src/record.ts +186 -0
  125. package/src/relationships.ts +53 -0
  126. package/src/{serializer.js → serializer.ts} +52 -36
  127. package/src/{setup-rest-server.js → setup-rest-server.ts} +18 -13
  128. package/src/{standalone-db.js → standalone-db.ts} +33 -24
  129. package/src/{store.js → store.ts} +90 -68
  130. package/src/timescale/{query-builder.js → query-builder.ts} +33 -38
  131. package/src/timescale/timescale-db.ts +119 -0
  132. package/src/transforms.ts +20 -0
  133. package/src/types/mysql2.d.ts +30 -0
  134. package/src/types/orm-types.ts +146 -0
  135. package/src/types/pg.d.ts +28 -0
  136. package/src/types/stonyx-cron.d.ts +5 -0
  137. package/src/types/stonyx-events.d.ts +4 -0
  138. package/src/types/stonyx-rest-server.d.ts +11 -0
  139. package/src/types/stonyx-utils.d.ts +33 -0
  140. package/src/types/stonyx.d.ts +21 -0
  141. package/src/utils.ts +16 -0
  142. package/src/{view-resolver.js → view-resolver.ts} +51 -24
  143. package/src/view.ts +22 -0
  144. package/src/belongs-to.js +0 -70
  145. package/src/has-many.js +0 -68
  146. package/src/record.js +0 -132
  147. package/src/relationships.js +0 -43
  148. package/src/timescale/timescale-db.js +0 -111
  149. package/src/transforms.js +0 -20
  150. package/src/utils.js +0 -12
  151. package/src/view.js +0 -21
package/src/record.js DELETED
@@ -1,132 +0,0 @@
1
- import { store } from './index.js';
2
- import { getComputedProperties } from "./serializer.js";
3
- import { camelCaseToKebabCase } from '@stonyx/utils/string';
4
- import { getPluralName } from './plural-registry.js';
5
- export default class Record {
6
- /** @private */
7
- __data = {};
8
- /** @private */
9
- __relationships = {};
10
- /** @private */
11
- __serialized = false;
12
-
13
- constructor(model, serializer) {
14
- /** @private */
15
- this.__model = model;
16
- /** @private */
17
- this.__serializer = serializer;
18
-
19
- }
20
-
21
- serialize(rawData, options={}) {
22
- const { __data:data } = this;
23
-
24
- if (this.__serialized && !options.update) {
25
- const relatedIds = {};
26
-
27
- for (const [ key, childRecord ] of Object.entries(this.__relationships)) {
28
- relatedIds[key] = Array.isArray(childRecord)
29
- ? childRecord.map(r => r.id)
30
- : childRecord?.id ?? null;
31
- }
32
-
33
- return { ...data, ...relatedIds };
34
- }
35
-
36
- const normalizedData = this.__serializer.normalize(rawData);
37
- this.__serializer.setProperties(normalizedData, this, options);
38
-
39
- return data;
40
- }
41
-
42
- // Similar to serialize, but preserves top level relationship records
43
- format() {
44
- if (!this.__serialized) throw new Error('Record must be serialized before being converted to JSON');
45
-
46
- const { __data:data } = this;
47
- const records = {};
48
-
49
- for (const [ key, childRecord ] of Object.entries(this.__relationships)) {
50
- records[key] = Array.isArray(childRecord)
51
- ? childRecord.map(r => r.serialize())
52
- : childRecord?.serialize() ?? null;
53
- }
54
-
55
- return { ...data, ...records };
56
- }
57
-
58
- // Formats record for JSON API output
59
- toJSON(options = {}) {
60
- if (!this.__serialized) throw new Error('Record must be serialized before being converted to JSON');
61
-
62
- const { fields, baseUrl } = options;
63
- const { __data:data } = this;
64
- const modelName = this.__model.__name;
65
- const pluralizedModelName = getPluralName(modelName);
66
- const recordId = data.id;
67
- const relationships = {};
68
- const attributes = {};
69
-
70
- for (const [key, value] of Object.entries(data)) {
71
- if (key === 'id') continue;
72
- if (fields && !fields.has(key)) continue;
73
- attributes[key] = value;
74
- }
75
-
76
- for (const [key, getter] of getComputedProperties(this.__model)) {
77
- if (fields && !fields.has(key)) continue;
78
- attributes[key] = getter.call(this);
79
- }
80
-
81
- for (const [key, childRecord] of Object.entries(this.__relationships)) {
82
- if (fields && !fields.has(key)) continue;
83
-
84
- const relationshipData = Array.isArray(childRecord)
85
- ? childRecord.map(r => ({ type: r.__model.__name, id: r.id }))
86
- : childRecord ? { type: childRecord.__model.__name, id: childRecord.id } : null;
87
-
88
- // Dasherize the key for URL paths (e.g., accessLinks -> access-links)
89
- const dasherizedKey = camelCaseToKebabCase(key);
90
-
91
- relationships[dasherizedKey] = { data: relationshipData };
92
-
93
- // Add links to relationship if baseUrl provided
94
- if (baseUrl) {
95
- relationships[dasherizedKey].links = {
96
- self: `${baseUrl}/${pluralizedModelName}/${recordId}/relationships/${dasherizedKey}`,
97
- related: `${baseUrl}/${pluralizedModelName}/${recordId}/${dasherizedKey}`
98
- };
99
- }
100
- }
101
-
102
- const result = {
103
- attributes,
104
- relationships,
105
- id: recordId,
106
- type: modelName,
107
- };
108
-
109
- // Add resource links if baseUrl provided
110
- if (baseUrl) {
111
- result.links = {
112
- self: `${baseUrl}/${pluralizedModelName}/${recordId}`
113
- };
114
- }
115
-
116
- return result;
117
- }
118
-
119
- unload(options={}) {
120
- store.unloadRecord(this.__model.__name, this.id, options);
121
- }
122
-
123
- clean() {
124
- try {
125
- for (const key of Object.keys(this)) {
126
- delete this[key];
127
- }
128
- } catch {
129
- // Ignore errors during cleanup, as some keys may not be deletable
130
- }
131
- }
132
- }
@@ -1,43 +0,0 @@
1
- import { relationships } from "@stonyx/orm";
2
-
3
- export default class Relationships {
4
- constructor() {
5
- if (Relationships.instance) return Relationships.instance;
6
- Relationships.instance = this;
7
-
8
- this.data = new Map();
9
- }
10
-
11
- get(key) {
12
- return this.data.get(key);
13
- }
14
-
15
- set(key, value) {
16
- this.data.set(key, value);
17
- }
18
- }
19
-
20
- // TODO: Refactor mapping to remove a level of iteration
21
- export function getRelationships(type, sourceModel, targetModel, relationshipId) {
22
- const allRelationships = relationships.get(type);
23
-
24
- // create relationship map for this type of it doesn't already exist
25
- if (!allRelationships.has(sourceModel)) allRelationships.set(sourceModel, new Map());
26
-
27
- const modelRelationship = allRelationships.get(sourceModel);
28
-
29
- if (!modelRelationship.has(targetModel)) modelRelationship.set(targetModel, new Map());
30
-
31
- const relationship = modelRelationship.get(targetModel);
32
-
33
- // TODO: Determine whether already having id should be handled differently
34
- //if (relationship.has(relationshipId)) return;
35
-
36
- return relationship;
37
- }
38
-
39
- export function getHasManyRelationships(sourceModel, targetModel) {
40
- return relationships.get('hasMany').get(sourceModel)?.get(targetModel);
41
- }
42
-
43
- export const TYPES = ['global', 'hasMany', 'belongsTo', 'pending'];
@@ -1,111 +0,0 @@
1
- import PostgresDB from '../postgres/postgres-db.js';
2
- import { buildCreateHypertable, buildTimeBucket, buildContinuousAggregate, buildCompressionPolicy, buildEnableCompression } from './query-builder.js';
3
-
4
- export default class TimescaleDB extends PostgresDB {
5
- static extensions = ['timescaledb'];
6
- static configKey = 'timescale';
7
-
8
- constructor(deps = {}) {
9
- super({
10
- ...deps,
11
- buildCreateHypertable,
12
- buildTimeBucket,
13
- buildContinuousAggregate,
14
- buildCompressionPolicy,
15
- buildEnableCompression,
16
- });
17
- }
18
-
19
- /**
20
- * Convert a table to a TimescaleDB hypertable.
21
- * Should be called after the table is created (e.g. after initial migration).
22
- * @param {string} modelName
23
- * @param {string} timeColumn - The time-partitioning column
24
- * @param {Object} [options]
25
- * @param {string} [options.chunkInterval='7 days']
26
- */
27
- async createHypertable(modelName, timeColumn, options = {}) {
28
- const schemas = this.deps.introspectModels();
29
- const schema = schemas[modelName];
30
- if (!schema) throw new Error(`Model '${modelName}' not found`);
31
-
32
- const { sql } = this.deps.buildCreateHypertable(schema.table, timeColumn, options);
33
- await this.pool.query(sql);
34
- }
35
-
36
- /**
37
- * Query time-bucketed aggregations on a hypertable.
38
- * @param {string} modelName
39
- * @param {string} timeColumn - Timestamp column to bucket
40
- * @param {string} bucketSize - Bucket interval (e.g. '1 hour', '5 minutes')
41
- * @param {Object} [options]
42
- * @param {string[]} [options.aggregates] - Aggregate expressions
43
- * @param {Object} [options.where] - WHERE conditions
44
- * @param {number} [options.limit]
45
- * @returns {Promise<Object[]>} Rows with bucket + aggregate columns
46
- */
47
- async timeBucket(modelName, timeColumn, bucketSize, options = {}) {
48
- const schemas = this.deps.introspectModels();
49
- const schema = schemas[modelName];
50
- if (!schema) return [];
51
-
52
- const { sql, values } = this.deps.buildTimeBucket(schema.table, timeColumn, bucketSize, options);
53
-
54
- try {
55
- const result = await this.pool.query(sql, values);
56
- return result.rows;
57
- } catch (error) {
58
- if (error.code === '42P01') return [];
59
- throw error;
60
- }
61
- }
62
-
63
- /**
64
- * Create a continuous aggregate view on a hypertable.
65
- * @param {string} viewName - Name for the materialized view
66
- * @param {string} modelName - Source hypertable model
67
- * @param {string} timeColumn - Timestamp column
68
- * @param {string} bucketSize - Bucket interval
69
- * @param {string[]} aggregates - Aggregate expressions
70
- * @param {Object} [options]
71
- * @param {boolean} [options.withNoData=false]
72
- */
73
- async createContinuousAggregate(viewName, modelName, timeColumn, bucketSize, aggregates, options = {}) {
74
- const schemas = this.deps.introspectModels();
75
- const schema = schemas[modelName];
76
- if (!schema) throw new Error(`Model '${modelName}' not found`);
77
-
78
- const { sql } = this.deps.buildContinuousAggregate(viewName, schema.table, timeColumn, bucketSize, aggregates, options);
79
- await this.pool.query(sql);
80
- }
81
-
82
- /**
83
- * Enable compression on a hypertable.
84
- * @param {string} modelName
85
- * @param {Object} [options]
86
- * @param {string} [options.segmentBy] - Column to segment by
87
- * @param {string} [options.orderBy] - Column to order by
88
- */
89
- async enableCompression(modelName, options = {}) {
90
- const schemas = this.deps.introspectModels();
91
- const schema = schemas[modelName];
92
- if (!schema) throw new Error(`Model '${modelName}' not found`);
93
-
94
- const { sql } = this.deps.buildEnableCompression(schema.table, options.segmentBy, options.orderBy);
95
- await this.pool.query(sql);
96
- }
97
-
98
- /**
99
- * Add a compression policy to a hypertable.
100
- * @param {string} modelName
101
- * @param {string} compressAfter - Interval after which to compress (e.g. '7 days')
102
- */
103
- async addCompressionPolicy(modelName, compressAfter) {
104
- const schemas = this.deps.introspectModels();
105
- const schema = schemas[modelName];
106
- if (!schema) throw new Error(`Model '${modelName}' not found`);
107
-
108
- const { sql } = this.deps.buildCompressionPolicy(schema.table, compressAfter);
109
- await this.pool.query(sql);
110
- }
111
- }
package/src/transforms.js DELETED
@@ -1,20 +0,0 @@
1
- import { getTimestamp } from "@stonyx/utils/date";
2
-
3
- const transforms = {
4
- boolean: value => typeof value === 'string' ? value.trim().toLowerCase() === 'true' : !!value,
5
- date: value => value ? new Date(value) : null,
6
- float: value => parseFloat(value),
7
- number: value => parseInt(value),
8
- passthrough: value => value,
9
- string: value => String(value),
10
- timestamp: value => getTimestamp(value),
11
- trim: value => value?.trim(),
12
- uppercase: value => value?.toUpperCase(),
13
- };
14
-
15
- // Math Proxies
16
- ['ceil', 'floor', 'round'].forEach(method => {
17
- transforms[method] = value => Math[method](value);
18
- });
19
-
20
- export default transforms;
package/src/utils.js DELETED
@@ -1,12 +0,0 @@
1
- import { pluralize as basePluralize } from '@stonyx/utils/string';
2
-
3
- // Wrapper to handle dasherized model names (e.g., "access-link" → "access-links")
4
- export function pluralize(word) {
5
- if (word.includes('-')) {
6
- const parts = word.split('-');
7
- const pluralizedLast = basePluralize(parts.pop());
8
- return [...parts, pluralizedLast].join('-');
9
- }
10
-
11
- return basePluralize(word);
12
- }
package/src/view.js DELETED
@@ -1,21 +0,0 @@
1
- import { attr } from '@stonyx/orm';
2
-
3
- export default class View {
4
- static memory = false;
5
- static readOnly = true;
6
- static pluralName = undefined;
7
- static source = undefined;
8
- static groupBy = undefined;
9
- static resolve = undefined;
10
-
11
- id = attr('number');
12
-
13
- constructor(name) {
14
- this.__name = name;
15
-
16
- // Enforce readOnly — cannot be overridden to false
17
- if (this.constructor.readOnly !== true) {
18
- throw new Error(`View '${name}' cannot override readOnly to false`);
19
- }
20
- }
21
- }