@objectstack/cli 9.7.0 → 9.9.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.
@@ -1,6 +1,18 @@
1
1
  // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
2
  import { describe, it, expect } from 'vitest';
3
- import { lintFlowPatterns, FLOW_TIME_RELATIVE_ANTIPATTERN, FLOW_DOUBLE_BRACE_INTERP, FLOW_BARE_DOLLAR_REF, } from './lint-flow-patterns.js';
3
+ import { lintFlowPatterns, FLOW_TIME_RELATIVE_ANTIPATTERN, FLOW_DATE_EQUALITY_FILTER, FLOW_PHANTOM_AGGREGATION, FLOW_DOUBLE_BRACE_INTERP, FLOW_BARE_DOLLAR_REF, } from './lint-flow-patterns.js';
4
+ const CEL = (source) => ({ dialect: 'cel', source });
5
+ /** A scheduled flow with a get_record node carrying `filter`. */
6
+ const filterFlow = (filter) => ({
7
+ flows: [{
8
+ name: 'expiry_alert',
9
+ nodes: [
10
+ { id: 'start', type: 'start', config: { triggerType: 'schedule', schedule: 'cron:0 9 * * *' } },
11
+ { id: 'query', type: 'get_record', config: { objectName: 'contract', filter } },
12
+ ],
13
+ edges: [],
14
+ }],
15
+ });
4
16
  const flow = (condition, triggerType = 'record-after-update') => ({
5
17
  flows: [{
6
18
  name: 'renewal_alert',
@@ -38,6 +50,74 @@ describe('lintFlowPatterns — time-relative anti-pattern (#1874)', () => {
38
50
  });
39
51
  });
40
52
  });
53
+ describe('lintFlowPatterns — date-equality in query filter (#1874)', () => {
54
+ it('flags a field bound directly to a time value (implicit equality)', () => {
55
+ const fnds = lintFlowPatterns(filterFlow({ expires_at: CEL('daysFromNow(30)') }));
56
+ expect(fnds).toHaveLength(1);
57
+ expect(fnds[0].rule).toBe(FLOW_DATE_EQUALITY_FILTER);
58
+ expect(fnds[0].hint).toMatch(/\$gte.*daysFromNow\(N\).*\$lt/);
59
+ });
60
+ it('flags `$in` against time values (the original renewal_alert bug)', () => {
61
+ const fnds = lintFlowPatterns(filterFlow({
62
+ status: 'active',
63
+ end_date: { $in: [CEL('daysFromNow(60)'), CEL('daysFromNow(30)'), CEL('daysFromNow(7)')] },
64
+ }));
65
+ expect(fnds).toHaveLength(1);
66
+ expect(fnds[0].rule).toBe(FLOW_DATE_EQUALITY_FILTER);
67
+ });
68
+ it('flags `$eq` against a time value', () => {
69
+ expect(lintFlowPatterns(filterFlow({ d: { $eq: CEL('today()') } }))).toHaveLength(1);
70
+ });
71
+ describe('does NOT flag (false-positive guards)', () => {
72
+ it('a one-day window (the correct fix)', () => {
73
+ expect(lintFlowPatterns(filterFlow({
74
+ end_date: { $gte: CEL('daysFromNow(7)'), $lt: CEL('daysFromNow(8)') },
75
+ }))).toHaveLength(0);
76
+ });
77
+ it('multi-tier windows wrapped in $or', () => {
78
+ expect(lintFlowPatterns(filterFlow({
79
+ status: 'active',
80
+ $or: [
81
+ { end_date: { $gte: CEL('daysFromNow(7)'), $lt: CEL('daysFromNow(8)') } },
82
+ { end_date: { $gte: CEL('daysFromNow(30)'), $lt: CEL('daysFromNow(31)') } },
83
+ ],
84
+ }))).toHaveLength(0);
85
+ });
86
+ it('a plain range like `due_date < today()` (overdue query)', () => {
87
+ expect(lintFlowPatterns(filterFlow({ status: 'open', due_date: { $lt: CEL('today()') } }))).toHaveLength(0);
88
+ });
89
+ it('equality against a non-time value (status, interpolated id)', () => {
90
+ expect(lintFlowPatterns(filterFlow({ status: 'active', id: '{record.id}' }))).toHaveLength(0);
91
+ expect(lintFlowPatterns(filterFlow({ amount: { $eq: CEL('record.threshold') } }))).toHaveLength(0);
92
+ });
93
+ });
94
+ });
95
+ describe('lintFlowPatterns — phantom aggregation capability (#1870)', () => {
96
+ const scriptNode = (config) => ({
97
+ flows: [{
98
+ name: 'rollup',
99
+ nodes: [
100
+ { id: 'start', type: 'start', config: {} },
101
+ { id: 'sum', type: 'script', config },
102
+ ],
103
+ edges: [],
104
+ }],
105
+ });
106
+ it('flags `aggregations` on a script node (publication_rollup bug)', () => {
107
+ const fnds = lintFlowPatterns(scriptNode({ aggregations: { total: { sum: 'amount' } } }));
108
+ expect(fnds).toHaveLength(1);
109
+ expect(fnds[0].rule).toBe(FLOW_PHANTOM_AGGREGATION);
110
+ expect(fnds[0].hint).toMatch(/Field\.summary/);
111
+ });
112
+ it('flags groupBy / rollup / aggregate / having too', () => {
113
+ for (const key of ['groupBy', 'rollup', 'aggregate', 'having']) {
114
+ expect(lintFlowPatterns(scriptNode({ [key]: {} })).map((f) => f.rule)).toContain(FLOW_PHANTOM_AGGREGATION);
115
+ }
116
+ });
117
+ it('does NOT flag an ordinary script/function node', () => {
118
+ expect(lintFlowPatterns(scriptNode({ function: 'helpdesk.triage', inputs: { x: 1 } }))).toHaveLength(0);
119
+ });
120
+ });
41
121
  /** A flow with a create_record node carrying `config`. */
42
122
  const nodeFlow = (config) => ({
43
123
  flows: [{
@@ -1 +1 @@
1
- {"version":3,"file":"lint-flow-patterns.test.js","sourceRoot":"","sources":["../../src/utils/lint-flow-patterns.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lint-flow-patterns.test.js","sourceRoot":"","sources":["../../src/utils/lint-flow-patterns.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export interface LivenessLintFinding {
2
+ where: string;
3
+ message: string;
4
+ hint: string;
5
+ rule: string;
6
+ }
7
+ export declare const LIVENESS_DEAD_PROPERTY = "liveness-dead-property";
8
+ export declare const LIVENESS_EXPERIMENTAL_PROPERTY = "liveness-experimental-property";
9
+ type AnyRec = Record<string, unknown>;
10
+ /**
11
+ * Lint the compiled stack for authored properties the liveness ledger flags as
12
+ * misleading. Advisory only — returns findings, never throws. v1 covers the two
13
+ * highest-signal surfaces (objects incl. their `enable.*` flags, and their
14
+ * fields); the mechanism is ledger-driven, so coverage grows by marking more
15
+ * entries `authorWarn` rather than touching this code.
16
+ */
17
+ export declare function lintLivenessProperties(stack: AnyRec): LivenessLintFinding[];
18
+ export {};
19
+ //# sourceMappingURL=lint-liveness-properties.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint-liveness-properties.d.ts","sourceRoot":"","sources":["../../src/utils/lint-liveness-properties.ts"],"names":[],"mappings":"AA0BA,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,sBAAsB,2BAA2B,CAAC;AAC/D,eAAO,MAAM,8BAA8B,mCAAmC,CAAC;AAE/E,KAAK,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AA8GtC;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,mBAAmB,EAAE,CAmB3E"}
@@ -0,0 +1,150 @@
1
+ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
+ /**
3
+ * Build-time lint that closes the spec-liveness loop on the AUTHOR side.
4
+ *
5
+ * The liveness ledgers (`@objectstack/spec/liveness/<type>.json`) classify every
6
+ * authorable metadata property as live / experimental / dead with evidence. The
7
+ * CI gate enforces that classification is *complete*, but the ledger's knowledge
8
+ * never reached the person (very often an AI) writing the metadata. This lint
9
+ * surfaces it: when an authored object/field sets a property the ledger marks as
10
+ * dead-and-misleading (or experimental), it emits an advisory WARNING — "you set
11
+ * this expecting it to do something; at runtime it does nothing" — with a hint
12
+ * toward the supported alternative. It NEVER fails the build.
13
+ *
14
+ * Signal over noise is the whole point, so the ledger opts in per entry via
15
+ * `"authorWarn": true` (+ an optional `"authorHint"`). A property being merely
16
+ * `dead` is NOT enough — plenty of dead props are benign display/doc metadata.
17
+ * Only entries an author would be *misled* by are marked. Booleans warn only when
18
+ * set truthy (so schema defaults like `enable.trash` never trip it); object/
19
+ * string/array props warn when present at all.
20
+ */
21
+ import { createRequire } from 'node:module';
22
+ import { dirname, join } from 'node:path';
23
+ import { existsSync, readFileSync } from 'node:fs';
24
+ export const LIVENESS_DEAD_PROPERTY = 'liveness-dead-property';
25
+ export const LIVENESS_EXPERIMENTAL_PROPERTY = 'liveness-experimental-property';
26
+ function asArray(v) {
27
+ if (Array.isArray(v))
28
+ return v;
29
+ if (v && typeof v === 'object')
30
+ return Object.entries(v).map(([name, def]) => ({ name, ...def }));
31
+ return [];
32
+ }
33
+ /** Locate `@objectstack/spec`'s shipped `liveness/` dir (workspace src or published files). */
34
+ function resolveLivenessDir() {
35
+ try {
36
+ const require = createRequire(import.meta.url);
37
+ const pkgJson = require.resolve('@objectstack/spec/package.json');
38
+ const dir = join(dirname(pkgJson), 'liveness');
39
+ return existsSync(dir) ? dir : null;
40
+ }
41
+ catch {
42
+ return null;
43
+ }
44
+ }
45
+ /** Build the warn-only lookup for one type, flattening one level of `children`. */
46
+ function loadWarnMap(dir, type) {
47
+ const map = new Map();
48
+ const file = join(dir, `${type}.json`);
49
+ if (!existsSync(file))
50
+ return map;
51
+ let ledger;
52
+ try {
53
+ ledger = JSON.parse(readFileSync(file, 'utf8'));
54
+ }
55
+ catch {
56
+ return map;
57
+ }
58
+ const props = ledger.props || {};
59
+ for (const [key, entry] of Object.entries(props)) {
60
+ if (entry?.children) {
61
+ for (const [ck, centry] of Object.entries(entry.children)) {
62
+ if (shouldWarn(centry))
63
+ map.set(`${key}.${ck}`, centry);
64
+ }
65
+ }
66
+ if (shouldWarn(entry))
67
+ map.set(key, entry);
68
+ }
69
+ return map;
70
+ }
71
+ /** An entry warns when explicitly opted in, OR when it's experimental (a declared-but-unenforced guarantee). */
72
+ function shouldWarn(entry) {
73
+ if (!entry)
74
+ return false;
75
+ return entry.authorWarn === true || entry.status === 'experimental';
76
+ }
77
+ /** A value that signals authoring intent: booleans only when truthy; everything else when present. */
78
+ function isAuthored(value) {
79
+ if (value === undefined || value === null)
80
+ return false;
81
+ if (typeof value === 'boolean')
82
+ return value === true;
83
+ return true;
84
+ }
85
+ function describe(entry) {
86
+ if (entry.status === 'experimental') {
87
+ return { kind: 'is experimental — declared but NOT enforced at runtime', rule: LIVENESS_EXPERIMENTAL_PROPERTY };
88
+ }
89
+ return { kind: 'has no runtime effect (liveness: dead)', rule: LIVENESS_DEAD_PROPERTY };
90
+ }
91
+ /** Check one metadata item's set properties against its type's warn-map. */
92
+ function checkItem(type, item, whereBase, warnMap, findings) {
93
+ for (const [path, entry] of warnMap) {
94
+ const value = path.includes('.')
95
+ ? getNested(item, path)
96
+ : item[path];
97
+ if (!isAuthored(value))
98
+ continue;
99
+ const { kind, rule } = describe(entry);
100
+ const hint = entry.authorHint
101
+ ?? entry.note
102
+ ?? 'Remove it — it is declared in the spec but not consumed at runtime.';
103
+ findings.push({
104
+ where: whereBase,
105
+ message: `sets \`${path}\` but this ${type} property ${kind}.`,
106
+ hint,
107
+ rule,
108
+ });
109
+ }
110
+ }
111
+ /** Resolve a dotted path one or more levels, treating a missing parent as absent. */
112
+ function getNested(obj, path) {
113
+ let cur = obj;
114
+ for (const seg of path.split('.')) {
115
+ if (cur === null || typeof cur !== 'object')
116
+ return undefined;
117
+ cur = cur[seg];
118
+ }
119
+ return cur;
120
+ }
121
+ /**
122
+ * Lint the compiled stack for authored properties the liveness ledger flags as
123
+ * misleading. Advisory only — returns findings, never throws. v1 covers the two
124
+ * highest-signal surfaces (objects incl. their `enable.*` flags, and their
125
+ * fields); the mechanism is ledger-driven, so coverage grows by marking more
126
+ * entries `authorWarn` rather than touching this code.
127
+ */
128
+ export function lintLivenessProperties(stack) {
129
+ const dir = resolveLivenessDir();
130
+ if (!dir)
131
+ return [];
132
+ const objectWarn = loadWarnMap(dir, 'object');
133
+ const fieldWarn = loadWarnMap(dir, 'field');
134
+ if (objectWarn.size === 0 && fieldWarn.size === 0)
135
+ return [];
136
+ const findings = [];
137
+ for (const obj of asArray(stack.objects)) {
138
+ const objName = typeof obj.name === 'string' ? obj.name : '(unnamed object)';
139
+ if (objectWarn.size > 0)
140
+ checkItem('object', obj, `object '${objName}'`, objectWarn, findings);
141
+ if (fieldWarn.size > 0) {
142
+ for (const field of asArray(obj.fields)) {
143
+ const fieldName = typeof field.name === 'string' ? field.name : '(unnamed field)';
144
+ checkItem('field', field, `object '${objName}' · field '${fieldName}'`, fieldWarn, findings);
145
+ }
146
+ }
147
+ }
148
+ return findings;
149
+ }
150
+ //# sourceMappingURL=lint-liveness-properties.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint-liveness-properties.js","sourceRoot":"","sources":["../../src/utils/lint-liveness-properties.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=lint-liveness-properties.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint-liveness-properties.test.d.ts","sourceRoot":"","sources":["../../src/utils/lint-liveness-properties.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,66 @@
1
+ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
+ import { describe, it, expect } from 'vitest';
3
+ import { lintLivenessProperties, LIVENESS_DEAD_PROPERTY, } from './lint-liveness-properties.js';
4
+ /**
5
+ * These run against the REAL ledgers shipped by `@objectstack/spec` (the same
6
+ * files the gate enforces), so they double as a contract test: if an
7
+ * `authorWarn` annotation is removed from `enable.feeds` / `columnName` / etc.,
8
+ * the matching assertion fails.
9
+ */
10
+ const objStack = (obj) => ({ objects: [{ name: 'widget', ...obj }] });
11
+ const rules = (findings) => findings.map((f) => f.rule);
12
+ const paths = (findings) => findings.map((f) => f.message);
13
+ describe('lintLivenessProperties', () => {
14
+ it('warns on an authored dead capability flag (enable.feeds: true)', () => {
15
+ const findings = lintLivenessProperties(objStack({ enable: { feeds: true } }));
16
+ expect(findings.length).toBeGreaterThan(0);
17
+ const feeds = findings.find((f) => f.message.includes('enable.feeds'));
18
+ expect(feeds).toBeDefined();
19
+ expect(feeds.rule).toBe(LIVENESS_DEAD_PROPERTY);
20
+ expect(feeds.where).toBe("object 'widget'");
21
+ expect(feeds.hint.length).toBeGreaterThan(0);
22
+ });
23
+ it('does NOT warn on a default-on flag the author left alone (enable.trash: true)', () => {
24
+ const findings = lintLivenessProperties(objStack({ enable: { trash: true } }));
25
+ expect(paths(findings).some((m) => m.includes('enable.trash'))).toBe(false);
26
+ });
27
+ it('does NOT warn when a dead boolean flag is explicitly false (enable.files: false)', () => {
28
+ const findings = lintLivenessProperties(objStack({ enable: { files: false } }));
29
+ expect(paths(findings).some((m) => m.includes('enable.files'))).toBe(false);
30
+ });
31
+ it('warns on a present dead object block (versioning)', () => {
32
+ const findings = lintLivenessProperties(objStack({ versioning: { enabled: true } }));
33
+ expect(paths(findings).some((m) => m.includes('versioning'))).toBe(true);
34
+ });
35
+ it('warns on a misleading dead field prop (columnName)', () => {
36
+ const findings = lintLivenessProperties(objStack({ fields: [{ name: 'code', type: 'text', columnName: 'legacy_code' }] }));
37
+ const f = findings.find((x) => x.message.includes('columnName'));
38
+ expect(f).toBeDefined();
39
+ expect(f.where).toBe("object 'widget' · field 'code'");
40
+ });
41
+ it('warns on a field-level index flag set true, but not when false', () => {
42
+ const on = lintLivenessProperties(objStack({ fields: [{ name: 'code', type: 'text', index: true }] }));
43
+ expect(paths(on).some((m) => m.includes('`index`'))).toBe(true);
44
+ const off = lintLivenessProperties(objStack({ fields: [{ name: 'code', type: 'text', index: false }] }));
45
+ expect(paths(off).some((m) => m.includes('`index`'))).toBe(false);
46
+ });
47
+ it('is silent for a clean object with only live properties', () => {
48
+ const findings = lintLivenessProperties(objStack({
49
+ label: 'Widget',
50
+ enable: { apiEnabled: true },
51
+ fields: [{ name: 'name', type: 'text', label: 'Name' }],
52
+ }));
53
+ expect(findings).toEqual([]);
54
+ });
55
+ it('handles objects as a keyed record (not just arrays)', () => {
56
+ const findings = lintLivenessProperties({
57
+ objects: { widget: { name: 'widget', enable: { feeds: true } } },
58
+ });
59
+ expect(rules(findings)).toContain(LIVENESS_DEAD_PROPERTY);
60
+ });
61
+ it('returns [] on an empty / shapeless stack', () => {
62
+ expect(lintLivenessProperties({})).toEqual([]);
63
+ expect(lintLivenessProperties({ objects: [] })).toEqual([]);
64
+ });
65
+ });
66
+ //# sourceMappingURL=lint-liveness-properties.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint-liveness-properties.test.js","sourceRoot":"","sources":["../../src/utils/lint-liveness-properties.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@objectstack/cli",
3
- "version": "9.7.0",
3
+ "version": "9.9.0",
4
4
  "description": "Command Line Interface for ObjectStack Protocol",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -47,51 +47,51 @@
47
47
  "tsx": "^4.22.4",
48
48
  "yaml": "^2.9.0",
49
49
  "zod": "^4.4.3",
50
- "@objectstack/account": "9.7.0",
51
- "@objectstack/client": "9.7.0",
52
- "@objectstack/console": "9.7.0",
53
- "@objectstack/core": "^9.7.0",
54
- "@objectstack/driver-memory": "^9.7.0",
55
- "@objectstack/driver-mongodb": "^9.7.0",
56
- "@objectstack/driver-sql": "^9.7.0",
57
- "@objectstack/driver-sqlite-wasm": "^9.7.0",
58
- "@objectstack/formula": "9.7.0",
59
- "@objectstack/objectql": "^9.7.0",
60
- "@objectstack/observability": "^9.7.0",
61
- "@objectstack/platform-objects": "9.7.0",
62
- "@objectstack/plugin-approvals": "9.7.0",
63
- "@objectstack/plugin-audit": "9.7.0",
64
- "@objectstack/plugin-auth": "9.7.0",
65
- "@objectstack/plugin-email": "9.7.0",
66
- "@objectstack/setup": "9.7.0",
67
- "@objectstack/studio": "9.7.0",
68
- "@objectstack/plugin-hono-server": "9.7.0",
69
- "@objectstack/mcp": "9.7.0",
70
- "@objectstack/plugin-org-scoping": "9.7.0",
71
- "@objectstack/plugin-reports": "9.7.0",
72
- "@objectstack/plugin-security": "9.7.0",
73
- "@objectstack/plugin-sharing": "9.7.0",
74
- "@objectstack/trigger-record-change": "9.7.0",
75
- "@objectstack/trigger-api": "9.7.0",
76
- "@objectstack/trigger-schedule": "9.7.0",
77
- "@objectstack/plugin-webhooks": "9.7.0",
78
- "@objectstack/rest": "9.7.0",
79
- "@objectstack/runtime": "^9.7.0",
80
- "@objectstack/service-ai": "9.7.0",
81
- "@objectstack/service-analytics": "9.7.0",
82
- "@objectstack/service-automation": "9.7.0",
83
- "@objectstack/service-cache": "9.7.0",
84
- "@objectstack/service-datasource": "9.7.0",
85
- "@objectstack/service-feed": "9.7.0",
86
- "@objectstack/service-job": "9.7.0",
87
- "@objectstack/service-messaging": "9.7.0",
88
- "@objectstack/service-package": "9.7.0",
89
- "@objectstack/service-queue": "9.7.0",
90
- "@objectstack/service-realtime": "9.7.0",
91
- "@objectstack/service-settings": "9.7.0",
92
- "@objectstack/service-storage": "9.7.0",
93
- "@objectstack/spec": "9.7.0",
94
- "@objectstack/types": "9.7.0"
50
+ "@objectstack/account": "9.9.0",
51
+ "@objectstack/client": "9.9.0",
52
+ "@objectstack/cloud-connection": "9.9.0",
53
+ "@objectstack/console": "9.9.0",
54
+ "@objectstack/core": "^9.9.0",
55
+ "@objectstack/driver-memory": "^9.9.0",
56
+ "@objectstack/driver-mongodb": "^9.9.0",
57
+ "@objectstack/driver-sql": "^9.9.0",
58
+ "@objectstack/driver-sqlite-wasm": "^9.9.0",
59
+ "@objectstack/formula": "9.9.0",
60
+ "@objectstack/objectql": "^9.9.0",
61
+ "@objectstack/observability": "^9.9.0",
62
+ "@objectstack/platform-objects": "9.9.0",
63
+ "@objectstack/plugin-approvals": "9.9.0",
64
+ "@objectstack/plugin-audit": "9.9.0",
65
+ "@objectstack/plugin-auth": "9.9.0",
66
+ "@objectstack/plugin-email": "9.9.0",
67
+ "@objectstack/setup": "9.9.0",
68
+ "@objectstack/studio": "9.9.0",
69
+ "@objectstack/plugin-hono-server": "9.9.0",
70
+ "@objectstack/mcp": "9.9.0",
71
+ "@objectstack/plugin-org-scoping": "9.9.0",
72
+ "@objectstack/plugin-reports": "9.9.0",
73
+ "@objectstack/plugin-security": "9.9.0",
74
+ "@objectstack/plugin-sharing": "9.9.0",
75
+ "@objectstack/trigger-record-change": "9.9.0",
76
+ "@objectstack/trigger-api": "9.9.0",
77
+ "@objectstack/trigger-schedule": "9.9.0",
78
+ "@objectstack/plugin-webhooks": "9.9.0",
79
+ "@objectstack/rest": "9.9.0",
80
+ "@objectstack/runtime": "^9.9.0",
81
+ "@objectstack/service-ai": "9.9.0",
82
+ "@objectstack/service-analytics": "9.9.0",
83
+ "@objectstack/service-automation": "9.9.0",
84
+ "@objectstack/service-cache": "9.9.0",
85
+ "@objectstack/service-datasource": "9.9.0",
86
+ "@objectstack/service-job": "9.9.0",
87
+ "@objectstack/service-messaging": "9.9.0",
88
+ "@objectstack/service-package": "9.9.0",
89
+ "@objectstack/service-queue": "9.9.0",
90
+ "@objectstack/service-realtime": "9.9.0",
91
+ "@objectstack/service-settings": "9.9.0",
92
+ "@objectstack/service-storage": "9.9.0",
93
+ "@objectstack/spec": "9.9.0",
94
+ "@objectstack/types": "9.9.0"
95
95
  },
96
96
  "devDependencies": {
97
97
  "@oclif/plugin-help": "^6.2.50",