streamby-core 0.39.0 → 0.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +84 -0
- package/LICENSE +661 -661
- package/README.md +785 -573
- package/dist/adapters/database/connectionManager.js +182 -124
- package/dist/adapters/database/sql.js +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +9 -1
- package/dist/mcp/audit.d.ts +5 -2
- package/dist/mcp/audit.js +8 -0
- package/dist/mcp/server.js +3 -3
- package/dist/mcp/tools.js +41 -0
- package/dist/middleware/createRouter.js +14 -1
- package/dist/middleware/routes/ai.js +3 -3
- package/dist/middleware/routes/deliverable.d.ts +4 -2
- package/dist/middleware/routes/deliverable.js +16 -7
- package/dist/middleware/routes/mcp.js +11 -4
- package/dist/middleware/routes/media.js +7 -6
- package/dist/middleware/routes/{apiConnection.d.ts → oauthResource.d.ts} +1 -1
- package/dist/middleware/routes/oauthResource.js +18 -0
- package/dist/middleware/routes/project.js +5 -1
- package/dist/middleware/routes/renderFarm.js +4 -77
- package/dist/middleware/routes/storage.js +13 -27
- package/dist/middleware/routes/worker.d.ts +7 -0
- package/dist/middleware/routes/worker.js +125 -0
- package/dist/middleware/routes/workerCallback.d.ts +5 -0
- package/dist/middleware/routes/workerCallback.js +31 -0
- package/dist/models/Model.js +9 -9
- package/dist/services/aiProcessor.js +11 -11
- package/dist/services/apiTokenPermissions.js +6 -5
- package/dist/services/auth.d.ts +2 -0
- package/dist/services/auth.js +36 -10
- package/dist/services/executor.js +10 -10
- package/dist/services/jobQueue.d.ts +6 -4
- package/dist/services/jobQueue.js +28 -16
- package/dist/services/jobStore.d.ts +27 -0
- package/dist/services/jobStore.js +177 -0
- package/dist/services/mediaProcessor.js +16 -16
- package/dist/services/oauthTokens.d.ts +60 -0
- package/dist/services/oauthTokens.js +164 -0
- package/dist/services/vfxProcessor.js +12 -12
- package/dist/services/workerJobs.d.ts +73 -0
- package/dist/services/workerJobs.js +459 -0
- package/dist/services/workers.d.ts +78 -0
- package/dist/services/workers.js +179 -0
- package/dist/types/index.d.ts +64 -2
- package/dist/utils/assetCategories.d.ts +4 -0
- package/dist/utils/assetCategories.js +21 -0
- package/dist/utils/builtinAccess.d.ts +1 -1
- package/dist/utils/builtinAccess.js +4 -3
- package/dist/utils/privateAddress.d.ts +10 -0
- package/dist/utils/privateAddress.js +85 -0
- package/package.json +1 -1
- package/dist/middleware/routes/apiConnection.js +0 -100
- package/dist/middleware/routes/credential.d.ts +0 -3
- package/dist/middleware/routes/credential.js +0 -80
- package/dist/services/apiConnection.d.ts +0 -18
- package/dist/services/apiConnection.js +0 -65
- package/dist/services/credential.d.ts +0 -8
- package/dist/services/credential.js +0 -70
- package/dist/services/pipeline.d.ts +0 -2
- package/dist/services/pipeline.js +0 -292
- package/dist/utils/crypto.d.ts +0 -3
- package/dist/utils/crypto.js +0 -32
|
@@ -41,159 +41,217 @@ const getConnection = (id) => {
|
|
|
41
41
|
return clientEntry;
|
|
42
42
|
};
|
|
43
43
|
exports.getConnection = getConnection;
|
|
44
|
+
// StreamBy's tables, made (or brought up to date) at startup. Several instances starting at once
|
|
45
|
+
// against the same database would deadlock on these statements, so one runs them at a time:
|
|
46
|
+
// in a transaction holding a transaction-level advisory lock, which ends with it. (A session
|
|
47
|
+
// lock could outlive its unlock behind a pooler in transaction mode, such as Supabase's, which
|
|
48
|
+
// may run the unlock on another connection, and block every later startup.)
|
|
44
49
|
const ensureTablesExist = async (pool) => {
|
|
50
|
+
const client = await pool.connect();
|
|
45
51
|
try {
|
|
46
|
-
await
|
|
47
|
-
|
|
48
|
-
|
|
52
|
+
await client.query('BEGIN');
|
|
53
|
+
await client.query(`SELECT pg_advisory_xact_lock(hashtext('streamby:ensure-tables'))`);
|
|
54
|
+
await createTables(client);
|
|
55
|
+
await client.query('COMMIT');
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
await client.query('ROLLBACK').catch(() => { });
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
client.release();
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
const createTables = async (pool) => {
|
|
66
|
+
try {
|
|
67
|
+
await pool.query(`
|
|
68
|
+
CREATE SCHEMA IF NOT EXISTS streamby;
|
|
69
|
+
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
|
49
70
|
`);
|
|
50
71
|
// Migrate id column from UUID to TEXT if it was created with the old schema
|
|
51
|
-
await pool.query(`
|
|
52
|
-
DO $$ BEGIN
|
|
53
|
-
ALTER TABLE streamby.projects ALTER COLUMN id TYPE TEXT USING id::text;
|
|
54
|
-
ALTER TABLE streamby.projects ALTER COLUMN id SET DEFAULT uuid_generate_v4()::text;
|
|
55
|
-
EXCEPTION WHEN OTHERS THEN NULL; END $$;
|
|
72
|
+
await pool.query(`
|
|
73
|
+
DO $$ BEGIN
|
|
74
|
+
ALTER TABLE streamby.projects ALTER COLUMN id TYPE TEXT USING id::text;
|
|
75
|
+
ALTER TABLE streamby.projects ALTER COLUMN id SET DEFAULT uuid_generate_v4()::text;
|
|
76
|
+
EXCEPTION WHEN OTHERS THEN NULL; END $$;
|
|
56
77
|
`);
|
|
57
|
-
await pool.query(`
|
|
58
|
-
CREATE TABLE IF NOT EXISTS streamby.projects (
|
|
59
|
-
id TEXT PRIMARY KEY DEFAULT uuid_generate_v4()::text,
|
|
60
|
-
name VARCHAR(255) NOT NULL,
|
|
61
|
-
description TEXT,
|
|
62
|
-
image TEXT,
|
|
63
|
-
"allowedOrigin" JSONB DEFAULT '[]',
|
|
64
|
-
exports JSONB DEFAULT '[]',
|
|
65
|
-
connections JSONB DEFAULT '[]',
|
|
66
|
-
"dbConnections" JSONB DEFAULT '[]',
|
|
67
|
-
"dbType" VARCHAR(50) NOT NULL DEFAULT 'sql',
|
|
68
|
-
"createdAt" TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
69
|
-
"updatedAt" TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
70
|
-
);
|
|
78
|
+
await pool.query(`
|
|
79
|
+
CREATE TABLE IF NOT EXISTS streamby.projects (
|
|
80
|
+
id TEXT PRIMARY KEY DEFAULT uuid_generate_v4()::text,
|
|
81
|
+
name VARCHAR(255) NOT NULL,
|
|
82
|
+
description TEXT,
|
|
83
|
+
image TEXT,
|
|
84
|
+
"allowedOrigin" JSONB DEFAULT '[]',
|
|
85
|
+
exports JSONB DEFAULT '[]',
|
|
86
|
+
connections JSONB DEFAULT '[]',
|
|
87
|
+
"dbConnections" JSONB DEFAULT '[]',
|
|
88
|
+
"dbType" VARCHAR(50) NOT NULL DEFAULT 'sql',
|
|
89
|
+
"createdAt" TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
90
|
+
"updatedAt" TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
91
|
+
);
|
|
71
92
|
`);
|
|
72
93
|
console.log('✅ "projects" table ensured to exist.');
|
|
73
94
|
// Add JSONB columns to existing tables that predate this schema version
|
|
74
|
-
await pool.query(`
|
|
75
|
-
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS "allowedOrigin" JSONB DEFAULT '[]';
|
|
76
|
-
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS exports JSONB DEFAULT '[]';
|
|
77
|
-
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS connections JSONB DEFAULT '[]';
|
|
78
|
-
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS "dbConnections" JSONB DEFAULT '[]';
|
|
79
|
-
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS "storageConnections" JSONB DEFAULT '[]';
|
|
80
|
-
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS workflow JSONB;
|
|
81
|
-
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS pipelines JSONB DEFAULT '[]';
|
|
82
|
-
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS "builtinBackfilledAt" TIMESTAMP WITH TIME ZONE;
|
|
83
|
-
-- Written when a project is made (routes/project) and by its connection routes.
|
|
84
|
-
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS public BOOLEAN DEFAULT TRUE;
|
|
85
|
-
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS category TEXT;
|
|
86
|
-
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS "integrationConnections" JSONB DEFAULT '[]';
|
|
87
|
-
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS "distributionConnections" JSONB DEFAULT '[]';
|
|
88
|
-
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS "renderFarmConnections" JSONB DEFAULT '[]';
|
|
95
|
+
await pool.query(`
|
|
96
|
+
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS "allowedOrigin" JSONB DEFAULT '[]';
|
|
97
|
+
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS exports JSONB DEFAULT '[]';
|
|
98
|
+
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS connections JSONB DEFAULT '[]';
|
|
99
|
+
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS "dbConnections" JSONB DEFAULT '[]';
|
|
100
|
+
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS "storageConnections" JSONB DEFAULT '[]';
|
|
101
|
+
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS workflow JSONB;
|
|
102
|
+
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS pipelines JSONB DEFAULT '[]';
|
|
103
|
+
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS "builtinBackfilledAt" TIMESTAMP WITH TIME ZONE;
|
|
104
|
+
-- Written when a project is made (routes/project) and by its connection routes.
|
|
105
|
+
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS public BOOLEAN DEFAULT TRUE;
|
|
106
|
+
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS category TEXT;
|
|
107
|
+
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS "integrationConnections" JSONB DEFAULT '[]';
|
|
108
|
+
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS "distributionConnections" JSONB DEFAULT '[]';
|
|
109
|
+
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS "renderFarmConnections" JSONB DEFAULT '[]';
|
|
89
110
|
`);
|
|
90
111
|
// Ensure dbType exists with a non-null default
|
|
91
|
-
await pool.query(`
|
|
92
|
-
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS "dbType" VARCHAR(50) NOT NULL DEFAULT 'sql';
|
|
112
|
+
await pool.query(`
|
|
113
|
+
ALTER TABLE streamby.projects ADD COLUMN IF NOT EXISTS "dbType" VARCHAR(50) NOT NULL DEFAULT 'sql';
|
|
93
114
|
`);
|
|
94
|
-
await pool.query(`
|
|
95
|
-
CREATE TABLE IF NOT EXISTS streamby.project_members (
|
|
96
|
-
id TEXT PRIMARY KEY DEFAULT uuid_generate_v4()::text,
|
|
97
|
-
"projectId" TEXT NOT NULL REFERENCES streamby.projects(id) ON DELETE CASCADE,
|
|
98
|
-
"userId" VARCHAR(255) NOT NULL,
|
|
99
|
-
role VARCHAR(255) NOT NULL DEFAULT 'member',
|
|
100
|
-
status VARCHAR(50) NOT NULL DEFAULT 'active',
|
|
101
|
-
archived BOOLEAN NOT NULL DEFAULT FALSE,
|
|
102
|
-
"archivedBy" VARCHAR(255),
|
|
103
|
-
"archivedAt" TIMESTAMP WITH TIME ZONE,
|
|
104
|
-
"createdAt" TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
105
|
-
"updatedAt" TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
106
|
-
UNIQUE ("projectId", "userId")
|
|
107
|
-
);
|
|
115
|
+
await pool.query(`
|
|
116
|
+
CREATE TABLE IF NOT EXISTS streamby.project_members (
|
|
117
|
+
id TEXT PRIMARY KEY DEFAULT uuid_generate_v4()::text,
|
|
118
|
+
"projectId" TEXT NOT NULL REFERENCES streamby.projects(id) ON DELETE CASCADE,
|
|
119
|
+
"userId" VARCHAR(255) NOT NULL,
|
|
120
|
+
role VARCHAR(255) NOT NULL DEFAULT 'member',
|
|
121
|
+
status VARCHAR(50) NOT NULL DEFAULT 'active',
|
|
122
|
+
archived BOOLEAN NOT NULL DEFAULT FALSE,
|
|
123
|
+
"archivedBy" VARCHAR(255),
|
|
124
|
+
"archivedAt" TIMESTAMP WITH TIME ZONE,
|
|
125
|
+
"createdAt" TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
126
|
+
"updatedAt" TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
127
|
+
UNIQUE ("projectId", "userId")
|
|
128
|
+
);
|
|
108
129
|
`);
|
|
109
|
-
await pool.query(`
|
|
110
|
-
ALTER TABLE streamby.project_members ADD COLUMN IF NOT EXISTS status VARCHAR(50) NOT NULL DEFAULT 'active';
|
|
130
|
+
await pool.query(`
|
|
131
|
+
ALTER TABLE streamby.project_members ADD COLUMN IF NOT EXISTS status VARCHAR(50) NOT NULL DEFAULT 'active';
|
|
111
132
|
`);
|
|
112
133
|
console.log('✅ "project_members" table ensured to exist.');
|
|
113
134
|
// Migrate projectId FK column from UUID to TEXT if table predates this schema version
|
|
114
|
-
await pool.query(`
|
|
115
|
-
DO $$ BEGIN
|
|
116
|
-
ALTER TABLE streamby.project_members DROP CONSTRAINT IF EXISTS project_members_projectId_fkey;
|
|
117
|
-
ALTER TABLE streamby.project_members ALTER COLUMN "projectId" TYPE TEXT;
|
|
118
|
-
ALTER TABLE streamby.project_members ADD CONSTRAINT project_members_projectid_fkey
|
|
119
|
-
FOREIGN KEY ("projectId") REFERENCES streamby.projects(id) ON DELETE CASCADE;
|
|
120
|
-
EXCEPTION WHEN OTHERS THEN NULL; END $$;
|
|
135
|
+
await pool.query(`
|
|
136
|
+
DO $$ BEGIN
|
|
137
|
+
ALTER TABLE streamby.project_members DROP CONSTRAINT IF EXISTS project_members_projectId_fkey;
|
|
138
|
+
ALTER TABLE streamby.project_members ALTER COLUMN "projectId" TYPE TEXT;
|
|
139
|
+
ALTER TABLE streamby.project_members ADD CONSTRAINT project_members_projectid_fkey
|
|
140
|
+
FOREIGN KEY ("projectId") REFERENCES streamby.projects(id) ON DELETE CASCADE;
|
|
141
|
+
EXCEPTION WHEN OTHERS THEN NULL; END $$;
|
|
121
142
|
`);
|
|
122
|
-
await pool.query(`
|
|
123
|
-
CREATE TABLE IF NOT EXISTS streamby.exports (
|
|
124
|
-
id TEXT PRIMARY KEY DEFAULT uuid_generate_v4()::text,
|
|
125
|
-
"projectId" TEXT NOT NULL REFERENCES streamby.projects(id) ON DELETE CASCADE,
|
|
126
|
-
status VARCHAR(50) NOT NULL DEFAULT 'pending',
|
|
127
|
-
"filePath" TEXT,
|
|
128
|
-
"createdAt" TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
129
|
-
"updatedAt" TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
130
|
-
);
|
|
143
|
+
await pool.query(`
|
|
144
|
+
CREATE TABLE IF NOT EXISTS streamby.exports (
|
|
145
|
+
id TEXT PRIMARY KEY DEFAULT uuid_generate_v4()::text,
|
|
146
|
+
"projectId" TEXT NOT NULL REFERENCES streamby.projects(id) ON DELETE CASCADE,
|
|
147
|
+
status VARCHAR(50) NOT NULL DEFAULT 'pending',
|
|
148
|
+
"filePath" TEXT,
|
|
149
|
+
"createdAt" TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
150
|
+
"updatedAt" TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
151
|
+
);
|
|
131
152
|
`);
|
|
132
153
|
console.log('✅ "exports" table ensured to exist.');
|
|
133
154
|
// user_integrations is registered against the main db only (see createRouter.ts), but
|
|
134
155
|
// this function runs per-SQL-connection like projects/exports above — harmless on
|
|
135
156
|
// non-main connections since the model never queries them there.
|
|
136
|
-
await pool.query(`
|
|
137
|
-
CREATE TABLE IF NOT EXISTS streamby.user_integrations (
|
|
138
|
-
id TEXT PRIMARY KEY DEFAULT uuid_generate_v4()::text,
|
|
139
|
-
"userId" VARCHAR(255) NOT NULL,
|
|
140
|
-
kind VARCHAR(20) NOT NULL,
|
|
141
|
-
provider VARCHAR(20) NOT NULL,
|
|
142
|
-
name VARCHAR(255) NOT NULL,
|
|
143
|
-
description TEXT,
|
|
144
|
-
"encryptedCredential" TEXT NOT NULL,
|
|
145
|
-
"createdAt" TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
146
|
-
"updatedAt" TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
147
|
-
);
|
|
148
|
-
CREATE INDEX IF NOT EXISTS user_integrations_userid_idx ON streamby.user_integrations ("userId");
|
|
157
|
+
await pool.query(`
|
|
158
|
+
CREATE TABLE IF NOT EXISTS streamby.user_integrations (
|
|
159
|
+
id TEXT PRIMARY KEY DEFAULT uuid_generate_v4()::text,
|
|
160
|
+
"userId" VARCHAR(255) NOT NULL,
|
|
161
|
+
kind VARCHAR(20) NOT NULL,
|
|
162
|
+
provider VARCHAR(20) NOT NULL,
|
|
163
|
+
name VARCHAR(255) NOT NULL,
|
|
164
|
+
description TEXT,
|
|
165
|
+
"encryptedCredential" TEXT NOT NULL,
|
|
166
|
+
"createdAt" TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
167
|
+
"updatedAt" TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
168
|
+
);
|
|
169
|
+
CREATE INDEX IF NOT EXISTS user_integrations_userid_idx ON streamby.user_integrations ("userId");
|
|
149
170
|
`);
|
|
150
171
|
console.log('✅ "user_integrations" table ensured to exist.');
|
|
151
172
|
// API tokens: only their hash is kept (see services/apiTokens). Main db only, like
|
|
152
173
|
// user_integrations above. A table from before tokens had a kind and permissions gets the
|
|
153
174
|
// new columns; its old tokens no longer work (they have no kind) and aren't listed.
|
|
154
|
-
await pool.query(`
|
|
155
|
-
CREATE TABLE IF NOT EXISTS streamby.api_tokens (
|
|
156
|
-
id TEXT PRIMARY KEY DEFAULT uuid_generate_v4()::text,
|
|
157
|
-
kind VARCHAR(10),
|
|
158
|
-
"userId" VARCHAR(255) NOT NULL,
|
|
159
|
-
"createdByName" VARCHAR(255),
|
|
160
|
-
name VARCHAR(255) NOT NULL,
|
|
161
|
-
prefix VARCHAR(32) NOT NULL,
|
|
162
|
-
hash CHAR(64) NOT NULL UNIQUE,
|
|
163
|
-
permissions JSONB NOT NULL DEFAULT '[]',
|
|
164
|
-
"projectIds" JSONB NOT NULL,
|
|
165
|
-
"createdAt" TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
166
|
-
"expiresAt" TIMESTAMP WITH TIME ZONE,
|
|
167
|
-
"lastUsedAt" TIMESTAMP WITH TIME ZONE
|
|
168
|
-
);
|
|
169
|
-
ALTER TABLE streamby.api_tokens ADD COLUMN IF NOT EXISTS kind VARCHAR(10);
|
|
170
|
-
ALTER TABLE streamby.api_tokens ADD COLUMN IF NOT EXISTS "createdByName" VARCHAR(255);
|
|
171
|
-
ALTER TABLE streamby.api_tokens ADD COLUMN IF NOT EXISTS permissions JSONB NOT NULL DEFAULT '[]';
|
|
172
|
-
DO $$ BEGIN
|
|
173
|
-
IF EXISTS (SELECT 1 FROM information_schema.columns
|
|
174
|
-
WHERE table_schema = 'streamby' AND table_name = 'api_tokens' AND column_name = 'access') THEN
|
|
175
|
-
ALTER TABLE streamby.api_tokens ALTER COLUMN access DROP NOT NULL;
|
|
176
|
-
END IF;
|
|
177
|
-
END $$;
|
|
178
|
-
CREATE INDEX IF NOT EXISTS api_tokens_userid_idx ON streamby.api_tokens ("userId");
|
|
179
|
-
CREATE INDEX IF NOT EXISTS api_tokens_kind_idx ON streamby.api_tokens (kind);
|
|
175
|
+
await pool.query(`
|
|
176
|
+
CREATE TABLE IF NOT EXISTS streamby.api_tokens (
|
|
177
|
+
id TEXT PRIMARY KEY DEFAULT uuid_generate_v4()::text,
|
|
178
|
+
kind VARCHAR(10),
|
|
179
|
+
"userId" VARCHAR(255) NOT NULL,
|
|
180
|
+
"createdByName" VARCHAR(255),
|
|
181
|
+
name VARCHAR(255) NOT NULL,
|
|
182
|
+
prefix VARCHAR(32) NOT NULL,
|
|
183
|
+
hash CHAR(64) NOT NULL UNIQUE,
|
|
184
|
+
permissions JSONB NOT NULL DEFAULT '[]',
|
|
185
|
+
"projectIds" JSONB NOT NULL,
|
|
186
|
+
"createdAt" TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
187
|
+
"expiresAt" TIMESTAMP WITH TIME ZONE,
|
|
188
|
+
"lastUsedAt" TIMESTAMP WITH TIME ZONE
|
|
189
|
+
);
|
|
190
|
+
ALTER TABLE streamby.api_tokens ADD COLUMN IF NOT EXISTS kind VARCHAR(10);
|
|
191
|
+
ALTER TABLE streamby.api_tokens ADD COLUMN IF NOT EXISTS "createdByName" VARCHAR(255);
|
|
192
|
+
ALTER TABLE streamby.api_tokens ADD COLUMN IF NOT EXISTS permissions JSONB NOT NULL DEFAULT '[]';
|
|
193
|
+
DO $$ BEGIN
|
|
194
|
+
IF EXISTS (SELECT 1 FROM information_schema.columns
|
|
195
|
+
WHERE table_schema = 'streamby' AND table_name = 'api_tokens' AND column_name = 'access') THEN
|
|
196
|
+
ALTER TABLE streamby.api_tokens ALTER COLUMN access DROP NOT NULL;
|
|
197
|
+
END IF;
|
|
198
|
+
END $$;
|
|
199
|
+
CREATE INDEX IF NOT EXISTS api_tokens_userid_idx ON streamby.api_tokens ("userId");
|
|
200
|
+
CREATE INDEX IF NOT EXISTS api_tokens_kind_idx ON streamby.api_tokens (kind);
|
|
180
201
|
`);
|
|
181
202
|
console.log('✅ "api_tokens" table ensured to exist.');
|
|
203
|
+
// Jobs (see services/jobStore): kept here so they survive restarts and every instance sees
|
|
204
|
+
// them. Main db only, like the tables above.
|
|
205
|
+
await pool.query(`
|
|
206
|
+
CREATE TABLE IF NOT EXISTS streamby.jobs (
|
|
207
|
+
id TEXT PRIMARY KEY,
|
|
208
|
+
"jobType" VARCHAR(40) NOT NULL,
|
|
209
|
+
"userId" VARCHAR(255) NOT NULL,
|
|
210
|
+
"projectId" VARCHAR(255) NOT NULL,
|
|
211
|
+
"assetId" VARCHAR(255),
|
|
212
|
+
status VARCHAR(20) NOT NULL,
|
|
213
|
+
stage VARCHAR(60) NOT NULL,
|
|
214
|
+
progress INTEGER NOT NULL DEFAULT 0,
|
|
215
|
+
payload JSONB NOT NULL DEFAULT '{}',
|
|
216
|
+
error TEXT,
|
|
217
|
+
worker JSONB,
|
|
218
|
+
kind VARCHAR(100),
|
|
219
|
+
profile JSONB,
|
|
220
|
+
"versionId" VARCHAR(255),
|
|
221
|
+
"resultMode" VARCHAR(20),
|
|
222
|
+
attempts INTEGER NOT NULL DEFAULT 0,
|
|
223
|
+
"maxAttempts" INTEGER NOT NULL DEFAULT 1,
|
|
224
|
+
"nextAttemptAt" TIMESTAMP WITH TIME ZONE,
|
|
225
|
+
"leaseUntil" TIMESTAMP WITH TIME ZONE,
|
|
226
|
+
"callbackHash" CHAR(64),
|
|
227
|
+
upload JSONB,
|
|
228
|
+
report JSONB,
|
|
229
|
+
result JSONB,
|
|
230
|
+
"createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
|
|
231
|
+
"updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
|
|
232
|
+
);
|
|
233
|
+
CREATE INDEX IF NOT EXISTS jobs_project_idx ON streamby.jobs ("projectId", "createdAt");
|
|
234
|
+
CREATE INDEX IF NOT EXISTS jobs_due_idx ON streamby.jobs (status, "nextAttemptAt") WHERE worker IS NOT NULL;
|
|
235
|
+
`);
|
|
236
|
+
console.log('✅ "jobs" table ensured to exist.');
|
|
182
237
|
// The MCP server's audit log: every tool call (see mcp/audit). Main db only.
|
|
183
|
-
await pool.query(`
|
|
184
|
-
CREATE TABLE IF NOT EXISTS streamby.mcp_audit (
|
|
185
|
-
id TEXT PRIMARY KEY DEFAULT uuid_generate_v4()::text,
|
|
186
|
-
"userId" VARCHAR(255) NOT NULL,
|
|
187
|
-
"tokenId" VARCHAR(255) NOT NULL,
|
|
188
|
-
"projectId" VARCHAR(255),
|
|
189
|
-
tool VARCHAR(100) NOT NULL,
|
|
190
|
-
ok BOOLEAN NOT NULL,
|
|
191
|
-
status INTEGER,
|
|
192
|
-
error TEXT,
|
|
193
|
-
"durationMs" INTEGER NOT NULL,
|
|
194
|
-
"createdAt" TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
195
|
-
);
|
|
196
|
-
CREATE INDEX IF NOT EXISTS mcp_audit_token_idx ON streamby.mcp_audit ("tokenId", "createdAt");
|
|
238
|
+
await pool.query(`
|
|
239
|
+
CREATE TABLE IF NOT EXISTS streamby.mcp_audit (
|
|
240
|
+
id TEXT PRIMARY KEY DEFAULT uuid_generate_v4()::text,
|
|
241
|
+
"userId" VARCHAR(255) NOT NULL,
|
|
242
|
+
"tokenId" VARCHAR(255) NOT NULL,
|
|
243
|
+
"projectId" VARCHAR(255),
|
|
244
|
+
tool VARCHAR(100) NOT NULL,
|
|
245
|
+
ok BOOLEAN NOT NULL,
|
|
246
|
+
status INTEGER,
|
|
247
|
+
error TEXT,
|
|
248
|
+
"durationMs" INTEGER NOT NULL,
|
|
249
|
+
"createdAt" TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
250
|
+
);
|
|
251
|
+
CREATE INDEX IF NOT EXISTS mcp_audit_token_idx ON streamby.mcp_audit ("tokenId", "createdAt");
|
|
252
|
+
-- An app's calls (an OAuth access token) are recorded by its client, with no token.
|
|
253
|
+
ALTER TABLE streamby.mcp_audit ADD COLUMN IF NOT EXISTS "oauthClientId" VARCHAR(255);
|
|
254
|
+
ALTER TABLE streamby.mcp_audit ALTER COLUMN "tokenId" DROP NOT NULL;
|
|
197
255
|
`);
|
|
198
256
|
console.log('✅ "mcp_audit" table ensured to exist.');
|
|
199
257
|
}
|
|
@@ -10,7 +10,7 @@ function serializeForPg(v) {
|
|
|
10
10
|
}
|
|
11
11
|
const createSQLExportTable = async (connection, projectId, exportName, nodeSchema) => {
|
|
12
12
|
const exportId = (0, crypto_1.randomUUID)();
|
|
13
|
-
await connection.query(`INSERT INTO "exports" (id, "projectId", node_schema, name, method, created_at, updated_at)
|
|
13
|
+
await connection.query(`INSERT INTO "exports" (id, "projectId", node_schema, name, method, created_at, updated_at)
|
|
14
14
|
VALUES ($1, $2, $3, $4, 'GET', NOW(), NOW())`, [exportId, projectId, nodeSchema ? JSON.stringify(nodeSchema) : null, exportName]);
|
|
15
15
|
return { exportId };
|
|
16
16
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export { createStreamByRouter } from './middleware/createRouter';
|
|
2
2
|
export { emitToUser } from './services/wsHub';
|
|
3
3
|
export { createNotification } from './services/notification';
|
|
4
|
-
export type { UserPlan, UserSubscription, Auth, ApiTokenScope, ApiTokenKind, ApiTokenPermission, ProjectPermission, AccountPermission } from './types';
|
|
4
|
+
export type { UserPlan, UserSubscription, Auth, ApiTokenScope, ApiTokenKind, ApiTokenPermission, ProjectPermission, AccountPermission, OAuthClientInfo, OAuthResourceConfig } from './types';
|
|
5
5
|
export { resolveApiToken, API_TOKEN_PREFIX } from './services/apiTokens';
|
|
6
6
|
export { PROJECT_PERMISSIONS, ACCOUNT_PERMISSIONS } from './services/apiTokenPermissions';
|
|
7
7
|
export type { ResolvedApiToken } from './services/apiTokens';
|
|
8
|
+
export { createOAuthTokenVerifier, looksLikeOAuthAccessToken, protectedResourceMetadata, defaultResourceMetadataUrl, permissionsForOAuthScopes, OAUTH_SCOPES, OAUTH_SCOPE_PERMISSIONS, } from './services/oauthTokens';
|
|
9
|
+
export type { VerifiedOAuthToken, OAuthTokenVerifierOptions, Jwks, Jwk, OAuthScope } from './services/oauthTokens';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ACCOUNT_PERMISSIONS = exports.PROJECT_PERMISSIONS = exports.API_TOKEN_PREFIX = exports.resolveApiToken = exports.createNotification = exports.emitToUser = exports.createStreamByRouter = void 0;
|
|
3
|
+
exports.OAUTH_SCOPE_PERMISSIONS = exports.OAUTH_SCOPES = exports.permissionsForOAuthScopes = exports.defaultResourceMetadataUrl = exports.protectedResourceMetadata = exports.looksLikeOAuthAccessToken = exports.createOAuthTokenVerifier = exports.ACCOUNT_PERMISSIONS = exports.PROJECT_PERMISSIONS = exports.API_TOKEN_PREFIX = exports.resolveApiToken = exports.createNotification = exports.emitToUser = exports.createStreamByRouter = void 0;
|
|
4
4
|
var createRouter_1 = require("./middleware/createRouter");
|
|
5
5
|
Object.defineProperty(exports, "createStreamByRouter", { enumerable: true, get: function () { return createRouter_1.createStreamByRouter; } });
|
|
6
6
|
var wsHub_1 = require("./services/wsHub");
|
|
@@ -13,3 +13,11 @@ Object.defineProperty(exports, "API_TOKEN_PREFIX", { enumerable: true, get: func
|
|
|
13
13
|
var apiTokenPermissions_1 = require("./services/apiTokenPermissions");
|
|
14
14
|
Object.defineProperty(exports, "PROJECT_PERMISSIONS", { enumerable: true, get: function () { return apiTokenPermissions_1.PROJECT_PERMISSIONS; } });
|
|
15
15
|
Object.defineProperty(exports, "ACCOUNT_PERMISSIONS", { enumerable: true, get: function () { return apiTokenPermissions_1.ACCOUNT_PERMISSIONS; } });
|
|
16
|
+
var oauthTokens_1 = require("./services/oauthTokens");
|
|
17
|
+
Object.defineProperty(exports, "createOAuthTokenVerifier", { enumerable: true, get: function () { return oauthTokens_1.createOAuthTokenVerifier; } });
|
|
18
|
+
Object.defineProperty(exports, "looksLikeOAuthAccessToken", { enumerable: true, get: function () { return oauthTokens_1.looksLikeOAuthAccessToken; } });
|
|
19
|
+
Object.defineProperty(exports, "protectedResourceMetadata", { enumerable: true, get: function () { return oauthTokens_1.protectedResourceMetadata; } });
|
|
20
|
+
Object.defineProperty(exports, "defaultResourceMetadataUrl", { enumerable: true, get: function () { return oauthTokens_1.defaultResourceMetadataUrl; } });
|
|
21
|
+
Object.defineProperty(exports, "permissionsForOAuthScopes", { enumerable: true, get: function () { return oauthTokens_1.permissionsForOAuthScopes; } });
|
|
22
|
+
Object.defineProperty(exports, "OAUTH_SCOPES", { enumerable: true, get: function () { return oauthTokens_1.OAUTH_SCOPES; } });
|
|
23
|
+
Object.defineProperty(exports, "OAUTH_SCOPE_PERMISSIONS", { enumerable: true, get: function () { return oauthTokens_1.OAUTH_SCOPE_PERMISSIONS; } });
|
package/dist/mcp/audit.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { StreamByConfig } from '../types';
|
|
1
|
+
import { Auth, StreamByConfig } from '../types';
|
|
2
2
|
export interface McpAuditEntry {
|
|
3
3
|
userId: string;
|
|
4
|
-
tokenId: string;
|
|
4
|
+
tokenId: string | null;
|
|
5
|
+
oauthClientId: string | null;
|
|
5
6
|
projectId: string | null;
|
|
6
7
|
tool: string;
|
|
7
8
|
ok: boolean;
|
|
@@ -9,4 +10,6 @@ export interface McpAuditEntry {
|
|
|
9
10
|
error: string | null;
|
|
10
11
|
durationMs: number;
|
|
11
12
|
}
|
|
13
|
+
/** Who made an MCP request, as the audit log keeps it. */
|
|
14
|
+
export declare const auditCallerOf: (auth: Auth) => Pick<McpAuditEntry, "userId" | "tokenId" | "oauthClientId">;
|
|
12
15
|
export declare function recordMcpCall(entry: McpAuditEntry, config: StreamByConfig): Promise<void>;
|
package/dist/mcp/audit.js
CHANGED
|
@@ -3,9 +3,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.auditCallerOf = void 0;
|
|
6
7
|
exports.recordMcpCall = recordMcpCall;
|
|
7
8
|
const crypto_1 = __importDefault(require("crypto"));
|
|
8
9
|
const manager_1 = require("../models/manager");
|
|
10
|
+
/** Who made an MCP request, as the audit log keeps it. */
|
|
11
|
+
const auditCallerOf = (auth) => ({
|
|
12
|
+
userId: auth.userId,
|
|
13
|
+
tokenId: auth.oauth ? null : auth.apiToken?.tokenId ?? null,
|
|
14
|
+
oauthClientId: auth.oauth?.clientId ?? null,
|
|
15
|
+
});
|
|
16
|
+
exports.auditCallerOf = auditCallerOf;
|
|
9
17
|
async function recordMcpCall(entry, config) {
|
|
10
18
|
try {
|
|
11
19
|
const dbType = config.databases?.find(db => db.main)?.type ?? 'nosql';
|
package/dist/mcp/server.js
CHANGED
|
@@ -40,7 +40,7 @@ function createMcpServer(auth, api, config, version) {
|
|
|
40
40
|
const refused = await (0, workflowNodes_1.ensureWorkflowNode)(tool.workflowNode, tool.projectOf?.(args), auth, api);
|
|
41
41
|
if (refused) {
|
|
42
42
|
await (0, audit_1.recordMcpCall)({
|
|
43
|
-
|
|
43
|
+
...(0, audit_1.auditCallerOf)(auth), projectId, tool: tool.name,
|
|
44
44
|
ok: false, status: null, error: refused, durationMs: Date.now() - started,
|
|
45
45
|
}, config);
|
|
46
46
|
return { isError: true, content: [{ type: 'text', text: refused }] };
|
|
@@ -50,7 +50,7 @@ function createMcpServer(auth, api, config, version) {
|
|
|
50
50
|
status = answer.status;
|
|
51
51
|
const ok = status >= 200 && status < 300;
|
|
52
52
|
await (0, audit_1.recordMcpCall)({
|
|
53
|
-
|
|
53
|
+
...(0, audit_1.auditCallerOf)(auth), projectId, tool: tool.name,
|
|
54
54
|
ok, status, error: ok ? null : errorText(answer.body, status), durationMs: Date.now() - started,
|
|
55
55
|
}, config);
|
|
56
56
|
if (!ok)
|
|
@@ -61,7 +61,7 @@ function createMcpServer(auth, api, config, version) {
|
|
|
61
61
|
catch (err) {
|
|
62
62
|
const message = err instanceof Error ? err.message : String(err);
|
|
63
63
|
await (0, audit_1.recordMcpCall)({
|
|
64
|
-
|
|
64
|
+
...(0, audit_1.auditCallerOf)(auth), projectId, tool: tool.name,
|
|
65
65
|
ok: false, status, error: message, durationMs: Date.now() - started,
|
|
66
66
|
}, config);
|
|
67
67
|
return { isError: true, content: [{ type: 'text', text: `The call failed: ${message}` }] };
|
package/dist/mcp/tools.js
CHANGED
|
@@ -317,6 +317,47 @@ exports.TOOLS = [
|
|
|
317
317
|
projectOf: byProject,
|
|
318
318
|
call: ({ projectId, deliverableId }) => ({ method: 'DELETE', path: `/projects/${enc(projectId)}/deliverables/${enc(deliverableId)}` }),
|
|
319
319
|
}),
|
|
320
|
+
// ── Processing (workers) ──
|
|
321
|
+
tool({
|
|
322
|
+
name: 'list_workers', title: 'List workers', permissions: ['project:read'],
|
|
323
|
+
description: "The processing workers a project can use: the host's and the project's own (each one's id, source, what it does — its kinds — and the asset categories it takes). They show in the project's Workers settings.",
|
|
324
|
+
input: { projectId },
|
|
325
|
+
projectOf: byProject,
|
|
326
|
+
call: ({ projectId }) => ({ method: 'GET', path: `/projects/${enc(projectId)}/workers` }),
|
|
327
|
+
pick: (data) => data?.data ?? [],
|
|
328
|
+
}),
|
|
329
|
+
tool({
|
|
330
|
+
name: 'process_asset', title: 'Process an asset', permissions: ['jobs:run'], write: true,
|
|
331
|
+
description: "Asks a worker to process an asset (or one of its versions), e.g. optimize a glTF. The result is kept as a new asset derived from it (resultMode 'derived', the default: the original is untouched) or as the asset's new version ('version': its URL then serves the result). It runs in the background: follow it with get_job or list_jobs; it shows in the file's Jobs tab, in Storage.",
|
|
332
|
+
input: {
|
|
333
|
+
projectId,
|
|
334
|
+
assetId: id('asset'),
|
|
335
|
+
versionId: zod_1.z.string().optional().describe('A version (list_asset_versions); the latest if not given'),
|
|
336
|
+
worker: zod_1.z.object({ source: zod_1.z.enum(['builtin', 'project']), id: zod_1.z.string().min(1) }).describe('A worker, from list_workers'),
|
|
337
|
+
kind: zod_1.z.string().min(1).describe("What it should do: one of the worker's kinds"),
|
|
338
|
+
profile: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).optional().describe("Options for the worker (e.g. { \"textureFormat\": \"ktx2\" })"),
|
|
339
|
+
resultMode: zod_1.z.enum(['derived', 'version']).optional(),
|
|
340
|
+
},
|
|
341
|
+
projectOf: byProject,
|
|
342
|
+
call: ({ projectId, ...fields }) => ({ method: 'POST', path: `/projects/${enc(projectId)}/jobs/process`, body: defined(fields) }),
|
|
343
|
+
pick: (data) => data?.job,
|
|
344
|
+
}),
|
|
345
|
+
tool({
|
|
346
|
+
name: 'list_jobs', title: 'List jobs', permissions: ['jobs:read'],
|
|
347
|
+
description: "A project's jobs, newest first (of one asset if given): their status, stage, progress, error and, when done, their worker's report and result.",
|
|
348
|
+
input: { projectId, assetId: zod_1.z.string().optional() },
|
|
349
|
+
projectOf: byProject,
|
|
350
|
+
call: ({ projectId, assetId }) => ({ method: 'GET', path: `/projects/${enc(projectId)}/jobs${assetId ? `?${new URLSearchParams({ assetId })}` : ''}` }),
|
|
351
|
+
pick: (data) => data?.data ?? [],
|
|
352
|
+
}),
|
|
353
|
+
tool({
|
|
354
|
+
name: 'retry_job', title: 'Retry a job', permissions: ['jobs:run'], write: true,
|
|
355
|
+
description: "Sends a failed worker job to its worker again.",
|
|
356
|
+
input: { projectId, jobId: id('job') },
|
|
357
|
+
projectOf: byProject,
|
|
358
|
+
call: ({ projectId, jobId }) => ({ method: 'POST', path: `/projects/${enc(projectId)}/jobs/${enc(jobId)}/retry` }),
|
|
359
|
+
pick: (data) => data?.job,
|
|
360
|
+
}),
|
|
320
361
|
// ── Projects ──
|
|
321
362
|
tool({
|
|
322
363
|
name: 'create_project', title: 'Create a project', permissions: ['projects:create'], write: true,
|
|
@@ -15,6 +15,7 @@ const auth_1 = require("../services/auth");
|
|
|
15
15
|
const apiToken_1 = require("./routes/apiToken");
|
|
16
16
|
const mcp_1 = require("./routes/mcp");
|
|
17
17
|
const encryption_1 = require("../utils/encryption");
|
|
18
|
+
const jobStore_1 = require("../services/jobStore");
|
|
18
19
|
const auth_2 = require("./routes/auth");
|
|
19
20
|
const user_1 = require("./routes/user");
|
|
20
21
|
const export_1 = require("./routes/export");
|
|
@@ -27,6 +28,7 @@ const dbConnection_1 = require("./routes/dbConnection");
|
|
|
27
28
|
const storageConnection_1 = require("./routes/storageConnection");
|
|
28
29
|
const userIntegration_1 = require("./routes/userIntegration");
|
|
29
30
|
const oauth_1 = require("./routes/oauth");
|
|
31
|
+
const oauthResource_1 = require("./routes/oauthResource");
|
|
30
32
|
const notification_1 = require("./routes/notification");
|
|
31
33
|
const subscription_1 = require("./routes/subscription");
|
|
32
34
|
const media_1 = require("./routes/media");
|
|
@@ -38,11 +40,15 @@ const production_1 = require("./routes/production");
|
|
|
38
40
|
const rights_1 = require("./routes/rights");
|
|
39
41
|
const workflow_1 = require("./routes/workflow");
|
|
40
42
|
const pipeline_1 = require("./routes/pipeline");
|
|
43
|
+
const worker_1 = require("./routes/worker");
|
|
44
|
+
const workerCallback_1 = require("./routes/workerCallback");
|
|
45
|
+
const workerJobs_1 = require("../services/workerJobs");
|
|
41
46
|
const deliverable_1 = require("./routes/deliverable");
|
|
42
47
|
function createStreamByRouter(config) {
|
|
43
48
|
const router = express_1.default.Router();
|
|
44
49
|
if (config.encrypt)
|
|
45
50
|
(0, encryption_1.setEncryptionKey)(config.encrypt, config.encryptPreviousKeys);
|
|
51
|
+
(0, jobStore_1.setJobStoreDatabase)(config);
|
|
46
52
|
// Establish DB connections asynchronously (Postgres/Mongo + schema migrations).
|
|
47
53
|
// Until they're ready, HOLD incoming requests instead of letting them through —
|
|
48
54
|
// route handlers resolve projects/exports (e.g. the /menu-list export) against a
|
|
@@ -69,6 +75,8 @@ function createStreamByRouter(config) {
|
|
|
69
75
|
})
|
|
70
76
|
.finally(() => {
|
|
71
77
|
ready = true;
|
|
78
|
+
// Jobs left pending (or with their worker's time up) by a restart are sent again.
|
|
79
|
+
(0, workerJobs_1.startWorkerSweeper)({ ...config, adapter });
|
|
72
80
|
});
|
|
73
81
|
router.use((_req, _res, next) => {
|
|
74
82
|
if (ready)
|
|
@@ -105,9 +113,13 @@ function createStreamByRouter(config) {
|
|
|
105
113
|
if (config.websocket?.server) {
|
|
106
114
|
(0, wsHub_1.initWsHub)(config.websocket.server, config);
|
|
107
115
|
}
|
|
116
|
+
// Where to sign in for a token (RFC 9728): open, before anything asks for one.
|
|
117
|
+
router.use((0, oauthResource_1.oauthResourceRouter)(config));
|
|
108
118
|
// /auth answers whether there's a session (it reads it itself); everything after needs one,
|
|
109
119
|
// but for the public export route (see authenticate).
|
|
110
120
|
router.use((0, auth_2.authRouter)(config));
|
|
121
|
+
// Workers call back with their job's token, not a session (see routes/workerCallback).
|
|
122
|
+
router.use((0, workerCallback_1.workerCallbackRouter)({ ...config, adapter }));
|
|
111
123
|
router.use((0, auth_1.authenticate)(config));
|
|
112
124
|
router.use(auth_1.enforceApiTokenScope);
|
|
113
125
|
router.use(subscription_1.ensureSubscription);
|
|
@@ -135,6 +147,7 @@ function createStreamByRouter(config) {
|
|
|
135
147
|
router.use((0, rights_1.rightsRouter)(config));
|
|
136
148
|
router.use((0, workflow_1.workflowRouter)(config));
|
|
137
149
|
router.use((0, pipeline_1.pipelineRouter)(config));
|
|
138
|
-
router.use((0,
|
|
150
|
+
router.use((0, worker_1.workerRouter)({ ...config, adapter }));
|
|
151
|
+
router.use((0, deliverable_1.deliverableRouter)({ ...config, adapter }));
|
|
139
152
|
return router;
|
|
140
153
|
}
|
|
@@ -31,7 +31,7 @@ function aiRouter(_config) {
|
|
|
31
31
|
return res.status(404).json({ message: 'Project not found' });
|
|
32
32
|
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
33
33
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
34
|
-
const job = (0, jobQueue_1.createJob)('transcription', auth.userId, projectId, { fileId, model, sourceLanguage, outputFormats, provider, credentialId });
|
|
34
|
+
const job = await (0, jobQueue_1.createJob)('transcription', auth.userId, projectId, { fileId, model, sourceLanguage, outputFormats, provider, credentialId });
|
|
35
35
|
setImmediate(() => (0, aiProcessor_1.runTranscriptionJob)(job.jobId, fileId, projectId, { model, sourceLanguage, outputFormats, provider, credentialId }));
|
|
36
36
|
res.status(202).json({ jobId: job.jobId, status: job.status });
|
|
37
37
|
}
|
|
@@ -52,7 +52,7 @@ function aiRouter(_config) {
|
|
|
52
52
|
return res.status(404).json({ message: 'Project not found' });
|
|
53
53
|
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
54
54
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
55
|
-
const job = (0, jobQueue_1.createJob)('upscale', auth.userId, projectId, { fileId, scale, model, mode, credentialId });
|
|
55
|
+
const job = await (0, jobQueue_1.createJob)('upscale', auth.userId, projectId, { fileId, scale, model, mode, credentialId });
|
|
56
56
|
setImmediate(() => (0, aiProcessor_1.runUpscaleJob)(job.jobId, fileId, projectId, { scale, model, mode, credentialId }));
|
|
57
57
|
res.status(202).json({ jobId: job.jobId, status: job.status });
|
|
58
58
|
}
|
|
@@ -73,7 +73,7 @@ function aiRouter(_config) {
|
|
|
73
73
|
return res.status(404).json({ message: 'Project not found' });
|
|
74
74
|
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
75
75
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
76
|
-
const job = (0, jobQueue_1.createJob)('generate-asset', auth.userId, projectId, { assetType, provider, prompt, seed, credentialId });
|
|
76
|
+
const job = await (0, jobQueue_1.createJob)('generate-asset', auth.userId, projectId, { assetType, provider, prompt, seed, credentialId });
|
|
77
77
|
setImmediate(() => (0, aiProcessor_1.runGenerateAssetJob)(job.jobId, projectId, { assetType, provider, prompt, seed, credentialId }));
|
|
78
78
|
res.status(202).json({ jobId: job.jobId, status: job.status });
|
|
79
79
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
|
-
import { StreamByConfig } from '../../types';
|
|
3
|
-
export declare function deliverableRouter(
|
|
2
|
+
import { StorageAdapter, StreamByConfig } from '../../types';
|
|
3
|
+
export declare function deliverableRouter(config: StreamByConfig & {
|
|
4
|
+
adapter?: StorageAdapter;
|
|
5
|
+
}): Router;
|