@vryzel/file-next 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,9 +1,9 @@
1
- import { b as FileSystemConfig, C as CreateFileSystemOptions, a as FileSystem, S as S3CompatibleAdapter, c as S3Key, R as Result, M as MetadataStore } from './filesystem-BbZJLy4A.cjs';
2
- export { d as CopyInput, e as CopyOutput, f as CreateNodeInput, g as Credentials, D as DeleteInput, h as DeleteNodeInput, i as DeleteOutput, E as ExistsInput, j as ExistsOutput, F as FileNode, G as GetMetadataInput, k as GetMetadataOutput, l as GetNodeInput, m as GetPathInput, n as GetPathOutput, o as GetPublicUrlInput, p as GetPublicUrlOutput, L as ListChildrenInput, q as ListChildrenOutput, r as ListInput, s as ListOutput, t as MoveInput, u as MoveNodeInput, v as MoveOutput, N as NodeKind, P as Path, w as Prefix, x as PresignedDownloadInput, y as PresignedDownloadOutput, z as PresignedUploadInput, A as PresignedUploadOutput, B as R2Config, H as ReadInput, I as ReadOutput, J as ReconcileResult, K as S3Config, O as SearchInput, Q as SetMetadataInput, V as SetMetadataOutput, W as StatInput, X as StatOutput, T as TenantId, Y as UpdateMetadataInput, U as UserId, Z as WriteInput, _ as WriteOutput, $ as andThen, a0 as asPath, a1 as asPrefix, a2 as asS3Key, a3 as asTenantId, a4 as asUserId, a5 as assertPath, a6 as assertPrefix, a7 as assertS3Key, a8 as assertTenantId, a9 as assertUserId, aa as err, ab as map, ac as mapErr, ad as ok, ae as parseFileSystemConfig, af as unwrap, ag as unwrapOr } from './filesystem-BbZJLy4A.cjs';
1
+ import { b as FileSystemConfig, C as CreateFileSystemOptions, a as FileSystem, S as S3CompatibleAdapter, c as S3Key, R as Result, M as MetadataStore } from './filesystem-CewcaWEl.cjs';
2
+ export { d as CopyInput, e as CopyOutput, f as CreateNodeInput, g as Credentials, D as DeleteInput, h as DeleteNodeInput, i as DeleteOutput, E as ExistsInput, j as ExistsOutput, F as FileNode, G as GetMetadataInput, k as GetMetadataOutput, l as GetNodeInput, m as GetPathInput, n as GetPathOutput, o as GetPublicUrlInput, p as GetPublicUrlOutput, L as ListChildrenInput, q as ListChildrenOutput, r as ListInput, s as ListOutput, t as MoveInput, u as MoveNodeInput, v as MoveOutput, N as NodeKind, P as Path, w as Prefix, x as PresignedDownloadInput, y as PresignedDownloadOutput, z as PresignedUploadInput, A as PresignedUploadOutput, B as R2Config, H as ReadInput, I as ReadOutput, J as ReconcileResult, K as S3Config, O as SearchInput, Q as SetMetadataInput, V as SetMetadataOutput, W as StatInput, X as StatOutput, T as TenantId, Y as UpdateMetadataInput, U as UserId, Z as WriteInput, _ as WriteOutput, $ as andThen, a0 as asPath, a1 as asPrefix, a2 as asS3Key, a3 as asTenantId, a4 as asUserId, a5 as assertPath, a6 as assertPrefix, a7 as assertS3Key, a8 as assertTenantId, a9 as assertUserId, aa as err, ab as map, ac as mapErr, ad as ok, ae as parseFileSystemConfig, af as unwrap, ag as unwrapOr } from './filesystem-CewcaWEl.cjs';
3
3
  import { FileSystemError } from './errors/index.cjs';
4
4
  export { FILE_SYSTEM_ERROR_CODES, FileSystemErrorCode, FileSystemErrorJson, FileSystemErrorOptions, RETRYABLE_BY_CODE, fromAws, fromPg, fromSqlite } from './errors/index.cjs';
5
5
  import { ClassValue } from 'clsx';
6
- export { A as AuthContext, w as withAuth } from './with-auth-BueIpNZ7.cjs';
6
+ export { A as AuthContext, w as withAuth } from './with-auth-DDTngJoQ.cjs';
7
7
  import 'zod';
8
8
 
9
9
  /**
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { b as FileSystemConfig, C as CreateFileSystemOptions, a as FileSystem, S as S3CompatibleAdapter, c as S3Key, R as Result, M as MetadataStore } from './filesystem-D1Jjx3md.js';
2
- export { d as CopyInput, e as CopyOutput, f as CreateNodeInput, g as Credentials, D as DeleteInput, h as DeleteNodeInput, i as DeleteOutput, E as ExistsInput, j as ExistsOutput, F as FileNode, G as GetMetadataInput, k as GetMetadataOutput, l as GetNodeInput, m as GetPathInput, n as GetPathOutput, o as GetPublicUrlInput, p as GetPublicUrlOutput, L as ListChildrenInput, q as ListChildrenOutput, r as ListInput, s as ListOutput, t as MoveInput, u as MoveNodeInput, v as MoveOutput, N as NodeKind, P as Path, w as Prefix, x as PresignedDownloadInput, y as PresignedDownloadOutput, z as PresignedUploadInput, A as PresignedUploadOutput, B as R2Config, H as ReadInput, I as ReadOutput, J as ReconcileResult, K as S3Config, O as SearchInput, Q as SetMetadataInput, V as SetMetadataOutput, W as StatInput, X as StatOutput, T as TenantId, Y as UpdateMetadataInput, U as UserId, Z as WriteInput, _ as WriteOutput, $ as andThen, a0 as asPath, a1 as asPrefix, a2 as asS3Key, a3 as asTenantId, a4 as asUserId, a5 as assertPath, a6 as assertPrefix, a7 as assertS3Key, a8 as assertTenantId, a9 as assertUserId, aa as err, ab as map, ac as mapErr, ad as ok, ae as parseFileSystemConfig, af as unwrap, ag as unwrapOr } from './filesystem-D1Jjx3md.js';
1
+ import { b as FileSystemConfig, C as CreateFileSystemOptions, a as FileSystem, S as S3CompatibleAdapter, c as S3Key, R as Result, M as MetadataStore } from './filesystem-B0bJh8bW.js';
2
+ export { d as CopyInput, e as CopyOutput, f as CreateNodeInput, g as Credentials, D as DeleteInput, h as DeleteNodeInput, i as DeleteOutput, E as ExistsInput, j as ExistsOutput, F as FileNode, G as GetMetadataInput, k as GetMetadataOutput, l as GetNodeInput, m as GetPathInput, n as GetPathOutput, o as GetPublicUrlInput, p as GetPublicUrlOutput, L as ListChildrenInput, q as ListChildrenOutput, r as ListInput, s as ListOutput, t as MoveInput, u as MoveNodeInput, v as MoveOutput, N as NodeKind, P as Path, w as Prefix, x as PresignedDownloadInput, y as PresignedDownloadOutput, z as PresignedUploadInput, A as PresignedUploadOutput, B as R2Config, H as ReadInput, I as ReadOutput, J as ReconcileResult, K as S3Config, O as SearchInput, Q as SetMetadataInput, V as SetMetadataOutput, W as StatInput, X as StatOutput, T as TenantId, Y as UpdateMetadataInput, U as UserId, Z as WriteInput, _ as WriteOutput, $ as andThen, a0 as asPath, a1 as asPrefix, a2 as asS3Key, a3 as asTenantId, a4 as asUserId, a5 as assertPath, a6 as assertPrefix, a7 as assertS3Key, a8 as assertTenantId, a9 as assertUserId, aa as err, ab as map, ac as mapErr, ad as ok, ae as parseFileSystemConfig, af as unwrap, ag as unwrapOr } from './filesystem-B0bJh8bW.js';
3
3
  import { FileSystemError } from './errors/index.js';
4
4
  export { FILE_SYSTEM_ERROR_CODES, FileSystemErrorCode, FileSystemErrorJson, FileSystemErrorOptions, RETRYABLE_BY_CODE, fromAws, fromPg, fromSqlite } from './errors/index.js';
5
5
  import { ClassValue } from 'clsx';
6
- export { A as AuthContext, w as withAuth } from './with-auth-yfezt7YS.js';
6
+ export { A as AuthContext, w as withAuth } from './with-auth-f82V2WB6.js';
7
7
  import 'zod';
8
8
 
9
9
  /**
package/dist/index.js CHANGED
@@ -3973,6 +3973,36 @@ var createMemoryStore = () => {
3973
3973
  }
3974
3974
  return ok(void 0);
3975
3975
  },
3976
+ async purgeNode(input) {
3977
+ const n = nodes.get(input.id);
3978
+ if (!n || n.tenantId !== input.tenantId || n.deletedAt === null) {
3979
+ return err(
3980
+ new FileSystemError({
3981
+ code: "NotFound",
3982
+ message: `Trashed node ${input.id} not found`,
3983
+ retryable: false
3984
+ })
3985
+ );
3986
+ }
3987
+ const prefix = `${n.path}/`;
3988
+ const s3Keys = [];
3989
+ const ids = [];
3990
+ for (const node of nodes.values()) {
3991
+ if (node.tenantId !== input.tenantId || node.deletedAt === null) continue;
3992
+ if (node.id !== n.id && !node.path.startsWith(prefix)) continue;
3993
+ ids.push(node.id);
3994
+ if (node.kind === "file" && node.s3Key) s3Keys.push(node.s3Key);
3995
+ }
3996
+ for (const id of ids) {
3997
+ const node = nodes.get(id);
3998
+ if (node) removeFromChildrenIndex(node);
3999
+ nodes.delete(id);
4000
+ }
4001
+ for (const [token, share] of shares) {
4002
+ if (ids.includes(share.nodeId)) shares.delete(token);
4003
+ }
4004
+ return ok({ s3Keys });
4005
+ },
3976
4006
  async updateMetadata(input) {
3977
4007
  const n = nodes.get(input.id);
3978
4008
  if (!n || n.tenantId !== input.tenantId || n.deletedAt !== null) {
@@ -4203,7 +4233,7 @@ var rowToFileNode = (row) => ({
4203
4233
  updatedAt: new Date(row.updated_at),
4204
4234
  deletedAt: row.deleted_at === null ? null : new Date(row.deleted_at)
4205
4235
  });
4206
- var SCHEMA_VERSION = 3;
4236
+ var SCHEMA_VERSION = 4;
4207
4237
  var MIGRATION_SQL = `
4208
4238
  CREATE TABLE IF NOT EXISTS schema_meta (
4209
4239
  key TEXT PRIMARY KEY,
@@ -4287,7 +4317,8 @@ WHEN new.deleted_at IS NULL BEGIN
4287
4317
  INSERT INTO nodes_fts(rowid, name) VALUES (new.rowid, new.name);
4288
4318
  END;
4289
4319
 
4290
- CREATE TRIGGER IF NOT EXISTS nodes_fts_ad AFTER DELETE ON nodes BEGIN
4320
+ CREATE TRIGGER IF NOT EXISTS nodes_fts_ad AFTER DELETE ON nodes
4321
+ WHEN old.deleted_at IS NULL BEGIN
4291
4322
  INSERT INTO nodes_fts(nodes_fts, rowid, name) VALUES('delete', old.rowid, old.name);
4292
4323
  END;
4293
4324
 
@@ -4297,8 +4328,39 @@ CREATE TRIGGER IF NOT EXISTS nodes_fts_au AFTER UPDATE ON nodes BEGIN
4297
4328
  SELECT new.rowid, new.name WHERE new.deleted_at IS NULL;
4298
4329
  END;
4299
4330
  `;
4331
+ var FTS_REBUILD_SQL = `
4332
+ DROP TRIGGER IF EXISTS nodes_fts_ai;
4333
+ DROP TRIGGER IF EXISTS nodes_fts_ad;
4334
+ DROP TRIGGER IF EXISTS nodes_fts_au;
4335
+ DROP TABLE IF EXISTS nodes_fts;
4336
+ CREATE VIRTUAL TABLE nodes_fts USING fts5(
4337
+ name,
4338
+ content='nodes',
4339
+ content_rowid='rowid',
4340
+ tokenize='unicode61 remove_diacritics 2'
4341
+ );
4342
+ CREATE TRIGGER nodes_fts_ai AFTER INSERT ON nodes
4343
+ WHEN new.deleted_at IS NULL BEGIN
4344
+ INSERT INTO nodes_fts(rowid, name) VALUES (new.rowid, new.name);
4345
+ END;
4346
+ CREATE TRIGGER nodes_fts_ad AFTER DELETE ON nodes
4347
+ WHEN old.deleted_at IS NULL BEGIN
4348
+ INSERT INTO nodes_fts(nodes_fts, rowid, name) VALUES('delete', old.rowid, old.name);
4349
+ END;
4350
+ CREATE TRIGGER nodes_fts_au AFTER UPDATE ON nodes BEGIN
4351
+ INSERT INTO nodes_fts(nodes_fts, rowid, name) VALUES('delete', old.rowid, old.name);
4352
+ INSERT INTO nodes_fts(rowid, name)
4353
+ SELECT new.rowid, new.name WHERE new.deleted_at IS NULL;
4354
+ END;
4355
+ INSERT INTO nodes_fts(rowid, name) SELECT rowid, name FROM nodes WHERE deleted_at IS NULL;
4356
+ `;
4300
4357
  var runMigrations = (db) => {
4301
4358
  db.exec(MIGRATION_SQL);
4359
+ const row = db.prepare("SELECT value FROM schema_meta WHERE key = 'version'").get();
4360
+ const version = row ? Number(row.value) : 0;
4361
+ if (!Number.isFinite(version) || version < 4) {
4362
+ db.exec(FTS_REBUILD_SQL);
4363
+ }
4302
4364
  db.prepare(
4303
4365
  "INSERT OR REPLACE INTO schema_meta (key, value) VALUES ('version', ?)"
4304
4366
  ).run(String(SCHEMA_VERSION));
@@ -4343,6 +4405,7 @@ var createSqliteStore = (options) => {
4343
4405
  listChildren: wrap((s, i) => s.listChildren(i)),
4344
4406
  moveNode: wrap((s, i) => s.moveNode(i)),
4345
4407
  deleteNode: wrap((s, i) => s.deleteNode(i)),
4408
+ purgeNode: wrap((s, i) => s.purgeNode(i)),
4346
4409
  updateMetadata: wrap((s, i) => s.updateMetadata(i)),
4347
4410
  search: wrap((s, i) => s.search(i)),
4348
4411
  getPath: wrap((s, i) => s.getPath(i)),
@@ -4682,6 +4745,35 @@ var buildInner = (Database, options) => {
4682
4745
  }
4683
4746
  return ok(void 0);
4684
4747
  },
4748
+ async purgeNode(input) {
4749
+ const node = db.prepare(
4750
+ `SELECT id, path FROM nodes WHERE id = ? AND tenant_id = ? AND deleted_at IS NOT NULL`
4751
+ ).get(input.id, input.tenantId);
4752
+ if (!node) {
4753
+ return err(
4754
+ new FileSystemError({
4755
+ code: "NotFound",
4756
+ message: `Trashed node ${input.id} not found`,
4757
+ retryable: false
4758
+ })
4759
+ );
4760
+ }
4761
+ const like = `${node.path}/%`;
4762
+ const files = db.prepare(
4763
+ `SELECT s3_key FROM nodes
4764
+ WHERE tenant_id = ? AND deleted_at IS NOT NULL AND kind = 'file' AND s3_key != ''
4765
+ AND (id = ? OR path LIKE ?)`
4766
+ ).all(input.tenantId, input.id, like);
4767
+ db.prepare(
4768
+ `DELETE FROM shares WHERE tenant_id = ? AND node_id IN (
4769
+ SELECT id FROM nodes WHERE tenant_id = ? AND deleted_at IS NOT NULL AND (id = ? OR path LIKE ?)
4770
+ )`
4771
+ ).run(input.tenantId, input.tenantId, input.id, like);
4772
+ db.prepare(
4773
+ `DELETE FROM nodes WHERE tenant_id = ? AND deleted_at IS NOT NULL AND (id = ? OR path LIKE ?)`
4774
+ ).run(input.tenantId, input.id, like);
4775
+ return ok({ s3Keys: files.map((row) => row.s3_key) });
4776
+ },
4685
4777
  async updateMetadata(input) {
4686
4778
  const node = stmtGetById.get(input.id, input.tenantId);
4687
4779
  if (!node) return notFound(input.id);
@@ -5062,6 +5154,7 @@ var createPostgresStore = (options) => {
5062
5154
  listChildren: wrap((s, i) => s.listChildren(i)),
5063
5155
  moveNode: wrap((s, i) => s.moveNode(i)),
5064
5156
  deleteNode: wrap((s, i) => s.deleteNode(i)),
5157
+ purgeNode: wrap((s, i) => s.purgeNode(i)),
5065
5158
  updateMetadata: wrap((s, i) => s.updateMetadata(i)),
5066
5159
  search: wrap((s, i) => s.search(i)),
5067
5160
  getPath: wrap((s, i) => s.getPath(i)),
@@ -5402,6 +5495,48 @@ var buildInner2 = (pg, options) => {
5402
5495
  }
5403
5496
  return ok(void 0);
5404
5497
  },
5498
+ async purgeNode(input) {
5499
+ await ensureInitialized();
5500
+ const nodeRes = await q(
5501
+ input.tenantId,
5502
+ `SELECT id, path FROM "${schema}".nodes
5503
+ WHERE id = $1 AND tenant_id = $2 AND deleted_at IS NOT NULL`,
5504
+ [input.id, input.tenantId]
5505
+ );
5506
+ const node = nodeRes.rows[0];
5507
+ if (!node) {
5508
+ return err(
5509
+ new FileSystemError({
5510
+ code: "NotFound",
5511
+ message: `Trashed node ${input.id} not found`,
5512
+ retryable: false
5513
+ })
5514
+ );
5515
+ }
5516
+ const like = `${node.path}/%`;
5517
+ const files = await q(
5518
+ input.tenantId,
5519
+ `SELECT s3_key FROM "${schema}".nodes
5520
+ WHERE tenant_id = $1 AND deleted_at IS NOT NULL AND kind = 'file' AND s3_key <> ''
5521
+ AND (id = $2 OR path LIKE $3)`,
5522
+ [input.tenantId, input.id, like]
5523
+ );
5524
+ await q(
5525
+ input.tenantId,
5526
+ `DELETE FROM "${schema}".shares WHERE tenant_id = $1 AND node_id IN (
5527
+ SELECT id FROM "${schema}".nodes
5528
+ WHERE tenant_id = $1 AND deleted_at IS NOT NULL AND (id = $2 OR path LIKE $3)
5529
+ )`,
5530
+ [input.tenantId, input.id, like]
5531
+ );
5532
+ await q(
5533
+ input.tenantId,
5534
+ `DELETE FROM "${schema}".nodes
5535
+ WHERE tenant_id = $1 AND deleted_at IS NOT NULL AND (id = $2 OR path LIKE $3)`,
5536
+ [input.tenantId, input.id, like]
5537
+ );
5538
+ return ok({ s3Keys: files.rows.map((row) => row.s3_key) });
5539
+ },
5405
5540
  async updateMetadata(input) {
5406
5541
  await ensureInitialized();
5407
5542
  const exists = await q(