@deessejs/collections 0.0.41 → 0.0.45

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 (59) hide show
  1. package/dist/esm/collections/define.d.ts +43 -0
  2. package/dist/esm/collections/define.js +9 -0
  3. package/dist/esm/collections/extend-fields.d.ts +3 -0
  4. package/dist/esm/collections/extend-fields.js +9 -0
  5. package/dist/esm/collections/index.d.ts +1 -0
  6. package/dist/esm/collections/index.js +1 -0
  7. package/dist/esm/collections/types.d.ts +29 -0
  8. package/dist/esm/collections/types.js +1 -0
  9. package/dist/esm/config/index.d.ts +5 -0
  10. package/dist/esm/config/index.js +13 -0
  11. package/dist/esm/config/orchestrator.d.ts +8 -0
  12. package/dist/esm/config/orchestrator.js +66 -0
  13. package/dist/esm/config/types.d.ts +14 -0
  14. package/dist/esm/config/types.js +1 -0
  15. package/dist/esm/database/types.d.ts +10 -0
  16. package/dist/esm/database/types.js +1 -0
  17. package/dist/esm/drizzle/generate.d.ts +2 -0
  18. package/dist/esm/drizzle/generate.js +30 -0
  19. package/dist/esm/drizzle/index.d.ts +31 -0
  20. package/dist/esm/drizzle/index.js +20 -0
  21. package/dist/esm/drizzle/types.d.ts +0 -0
  22. package/dist/esm/drizzle/types.js +1 -0
  23. package/dist/esm/dsl/collections.d.ts +13 -0
  24. package/dist/esm/dsl/collections.js +10 -0
  25. package/dist/esm/dsl/index.d.ts +1 -0
  26. package/dist/esm/dsl/index.js +1 -0
  27. package/dist/esm/fields/constraints.d.ts +6 -0
  28. package/dist/esm/fields/constraints.js +59 -0
  29. package/dist/esm/fields/core.d.ts +71 -0
  30. package/dist/esm/fields/core.js +27 -0
  31. package/dist/esm/fields/field.d.ts +24 -0
  32. package/dist/esm/fields/field.js +33 -0
  33. package/dist/esm/fields/index.d.ts +4 -0
  34. package/dist/esm/fields/index.js +4 -0
  35. package/dist/esm/fields/types.d.ts +48 -0
  36. package/dist/esm/fields/types.js +1 -0
  37. package/dist/esm/index.d.ts +8 -0
  38. package/dist/esm/index.js +8 -0
  39. package/dist/esm/next/index.d.ts +5 -0
  40. package/dist/esm/next/index.js +17 -0
  41. package/dist/esm/plugins/index.d.ts +2 -0
  42. package/dist/esm/plugins/index.js +3 -0
  43. package/dist/esm/plugins/types.d.ts +1 -0
  44. package/dist/esm/plugins/types.js +1 -0
  45. package/dist/esm/providers/index.d.ts +2 -0
  46. package/dist/esm/providers/index.js +53 -0
  47. package/dist/esm/providers/types.d.ts +8 -0
  48. package/dist/esm/providers/types.js +1 -0
  49. package/dist/esm/utils/deep-partial.d.ts +3 -0
  50. package/dist/esm/utils/deep-partial.js +1 -0
  51. package/dist/esm/utils/exact.d.ts +1 -0
  52. package/dist/esm/utils/exact.js +1 -0
  53. package/dist/esm/utils/union-intersection.d.ts +1 -0
  54. package/dist/esm/utils/union-intersection.js +1 -0
  55. package/dist/esm/worker/index.d.ts +2 -0
  56. package/dist/esm/worker/index.js +32 -0
  57. package/dist/worker/index.d.ts +1 -2
  58. package/dist/worker/index.js +1 -62
  59. package/package.json +1 -1
@@ -0,0 +1,43 @@
1
+ import { Field } from "../fields";
2
+ import { Collection } from "./types";
3
+ export declare const collection: <const Slug extends string, const Fields extends Record<string, Field>>(config: Collection<Slug, Fields>) => Collection<Slug, Fields & {
4
+ readonly id: Field<{
5
+ kind: import("../fields").FieldKind;
6
+ params: unknown;
7
+ dsl: {
8
+ kind: import("../fields").FieldKind;
9
+ isPrimary: boolean;
10
+ isUnique: boolean;
11
+ canBeNull: boolean;
12
+ };
13
+ admin: {
14
+ component: any;
15
+ };
16
+ }>;
17
+ readonly createdAt: import("../fields").FieldChain<{
18
+ kind: import("../fields").FieldKind;
19
+ params: unknown;
20
+ dsl: {
21
+ kind: import("../fields").FieldKind;
22
+ isPrimary: boolean;
23
+ isUnique: boolean;
24
+ canBeNull: boolean;
25
+ };
26
+ admin: {
27
+ component: any;
28
+ };
29
+ }>;
30
+ readonly updatedAt: import("../fields").FieldChain<{
31
+ kind: import("../fields").FieldKind;
32
+ params: unknown;
33
+ dsl: {
34
+ kind: import("../fields").FieldKind;
35
+ isPrimary: boolean;
36
+ isUnique: boolean;
37
+ canBeNull: boolean;
38
+ };
39
+ admin: {
40
+ component: any;
41
+ };
42
+ }>;
43
+ }>;
@@ -0,0 +1,9 @@
1
+ import { field, primary, serial, timestamp } from "../fields";
2
+ import { extendFields } from "./extend-fields";
3
+ export const collection = (config) => {
4
+ return extendFields(config, {
5
+ id: primary(field({ type: serial() })),
6
+ createdAt: field({ type: timestamp() }),
7
+ updatedAt: field({ type: timestamp() }),
8
+ });
9
+ };
@@ -0,0 +1,3 @@
1
+ import { Field } from "../fields";
2
+ import { Collection } from "./types";
3
+ export declare const extendFields: <const Slug extends string, const Fields extends Record<string, Field>, const NewFields extends Record<string, Field>>(base: Collection<Slug, Fields>, newFields: NewFields) => Collection<Slug, Fields & NewFields>;
@@ -0,0 +1,9 @@
1
+ export const extendFields = (base, newFields) => {
2
+ return {
3
+ ...base,
4
+ fields: {
5
+ ...base.fields,
6
+ ...newFields,
7
+ },
8
+ };
9
+ };
@@ -0,0 +1 @@
1
+ export * from './define';
@@ -0,0 +1 @@
1
+ export * from './define';
@@ -0,0 +1,29 @@
1
+ import { Field } from "../fields";
2
+ export type CollectionHooks = {
3
+ beforeCreate?: (data: any) => Promise<any>;
4
+ afterCreate?: (data: any) => Promise<any>;
5
+ beforeUpdate?: (data: any) => Promise<any>;
6
+ afterUpdate?: (data: any) => Promise<any>;
7
+ beforeDelete?: (data: any) => Promise<any>;
8
+ afterDelete?: (data: any) => Promise<any>;
9
+ beforeOperation?: (data: any) => Promise<any>;
10
+ afterOperation?: (data: any) => Promise<any>;
11
+ afterError?: (error: Error) => Promise<any>;
12
+ afterSuccess?: (data: any) => Promise<any>;
13
+ };
14
+ export type Collection<Slug extends string = string, Fields extends Record<string, Field> = Record<string, Field>> = {
15
+ slug: Slug;
16
+ name?: string;
17
+ admin?: {
18
+ title?: string;
19
+ group?: string;
20
+ };
21
+ fields: Fields;
22
+ hooks?: CollectionHooks;
23
+ permissions?: {
24
+ create?: (ctx: any) => Promise<boolean>;
25
+ read?: (ctx: any) => Promise<boolean>;
26
+ update?: (ctx: any) => Promise<boolean>;
27
+ delete?: (ctx: any) => Promise<boolean>;
28
+ };
29
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ import { Config } from "./types";
2
+ export declare const defineConfig: (config: Config) => import("drizzle-orm/node-postgres").NodePgDatabase<Record<string, never>> & {
3
+ $client: import("pg").Pool;
4
+ };
5
+ export declare const waitConfig: () => Promise<Config>;
@@ -0,0 +1,13 @@
1
+ import { drizzle } from "drizzle-orm/node-postgres";
2
+ let _config;
3
+ export const defineConfig = (config) => {
4
+ _config = config;
5
+ const db = drizzle(config.databaseUrl);
6
+ return db;
7
+ };
8
+ export const waitConfig = async () => {
9
+ while (!_config) {
10
+ await new Promise((r) => setTimeout(r, 50));
11
+ }
12
+ return _config;
13
+ };
@@ -0,0 +1,8 @@
1
+ import { Collection } from "../collections/types";
2
+ import { Provider } from "../providers/types";
3
+ type Action = 'create' | 'read' | 'update' | 'delete';
4
+ export declare const runOperation: (action: Action, collection: Collection, provider: Provider, payload: {
5
+ id?: string;
6
+ data?: any;
7
+ }) => Promise<any>;
8
+ export {};
@@ -0,0 +1,66 @@
1
+ export const runOperation = async (action, collection, provider, payload) => {
2
+ const { hooks } = collection;
3
+ let currentData = payload.data;
4
+ const id = payload.id;
5
+ try {
6
+ // 1. Hook Global: beforeOperation
7
+ if (hooks?.beforeOperation) {
8
+ await hooks.beforeOperation({ action, collection: collection.slug, data: currentData, id });
9
+ }
10
+ // 2. Hook Spécifique: before[Action]
11
+ // Note: TypeScript peut être strict ici, on simplifie pour la demo
12
+ if (action === 'create' && hooks?.beforeCreate)
13
+ currentData = await hooks.beforeCreate(currentData);
14
+ if (action === 'update' && hooks?.beforeUpdate)
15
+ currentData = await hooks.beforeUpdate(currentData);
16
+ if (action === 'delete' && hooks?.beforeDelete)
17
+ await hooks.beforeDelete({ id });
18
+ // 3. APPEL AU PROVIDER (Le vrai travail DB)
19
+ let result;
20
+ switch (action) {
21
+ case 'create':
22
+ result = await provider.create(collection.slug, currentData);
23
+ break;
24
+ case 'read':
25
+ if (!id)
26
+ throw new Error("ID required for read");
27
+ result = await provider.read(collection.slug, id);
28
+ break;
29
+ case 'update':
30
+ if (!id)
31
+ throw new Error("ID required for update");
32
+ result = await provider.update(collection.slug, id, currentData);
33
+ break;
34
+ case 'delete':
35
+ if (!id)
36
+ throw new Error("ID required for delete");
37
+ await provider.delete(collection.slug, id);
38
+ result = { success: true, id };
39
+ break;
40
+ }
41
+ // 4. Hook Spécifique: after[Action]
42
+ if (action === 'create' && hooks?.afterCreate)
43
+ result = await hooks.afterCreate(result);
44
+ if (action === 'update' && hooks?.afterUpdate)
45
+ result = await hooks.afterUpdate(result);
46
+ if (action === 'delete' && hooks?.afterDelete)
47
+ result = await hooks.afterDelete(result);
48
+ // 5. Hook Global: afterOperation
49
+ if (hooks?.afterOperation) {
50
+ await hooks.afterOperation({ action, result });
51
+ }
52
+ // 6. Hook Global: afterSuccess (spécifique à ta liste)
53
+ if (hooks?.afterSuccess) {
54
+ await hooks.afterSuccess(result);
55
+ }
56
+ return result;
57
+ }
58
+ catch (error) {
59
+ // Gestion des erreurs via les hooks
60
+ if (hooks?.afterError) {
61
+ // Le hook peut transformer l'erreur ou la logger
62
+ await hooks.afterError(error);
63
+ }
64
+ throw error; // On relance l'erreur pour que l'appelant sache que ça a échoué
65
+ }
66
+ };
@@ -0,0 +1,14 @@
1
+ import { Collection } from "../collections/types";
2
+ import { CollectionsCrud } from "../database/types";
3
+ import { Field, FieldTypeFinal } from "../fields";
4
+ import { Plugin } from "../plugins/types";
5
+ import { UnionToIntersection } from "../utils/union-intersection";
6
+ export type Config = {
7
+ databaseUrl: string;
8
+ readonly collections: Collection[];
9
+ plugins?: Plugin[];
10
+ };
11
+ export type DbFromConfig<C extends Config> = UnionToIntersection<CollectionsCrud<C["collections"][number]>>;
12
+ export type InferSchema<F extends Record<string, Field>> = {
13
+ [K in keyof F]: F[K] extends Field<infer FT> ? FT extends FieldTypeFinal<any, infer TVal> ? TVal : never : never;
14
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,10 @@
1
+ import { Collection } from "../collections/types";
2
+ import { InferSchema } from "../fields/types";
3
+ export type CollectionsCrud<C extends Collection> = {
4
+ [K in C["slug"]]: {
5
+ create: (data: InferSchema<C["fields"]>) => Promise<any>;
6
+ read: (id: string) => Promise<any>;
7
+ update: (id: string, data: Partial<InferSchema<C["fields"]>>) => Promise<any>;
8
+ delete: (id: string) => Promise<void>;
9
+ };
10
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import { Collection } from "../collections/types";
2
+ export declare const generateShadowSchema: (collections: Collection[]) => void;
@@ -0,0 +1,30 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { DrizzleTypes } from ".";
4
+ const SHADOW_DIR = path.join(process.cwd(), ".deesse", "shadow");
5
+ const SCHEMA_PATH = path.join(SHADOW_DIR, "schema.ts");
6
+ export const generateShadowSchema = (collections) => {
7
+ fs.mkdirSync(SHADOW_DIR, { recursive: true });
8
+ const tablesCode = collections.map((col) => {
9
+ const columns = Object.entries(col.fields)
10
+ .map(([name, field]) => {
11
+ const kind = field.type.dsl.kind;
12
+ const drizzleType = Object.keys(DrizzleTypes).includes(kind)
13
+ ? `p.${kind}()`
14
+ : `p.text()`;
15
+ return ` ${name}: ${drizzleType},`;
16
+ })
17
+ .join("\n");
18
+ return `
19
+ export const ${col.slug} = p.pgTable("${col.slug}", {
20
+ ${columns}
21
+ });`;
22
+ });
23
+ const schemaFileContent = `
24
+ import * as p from "drizzle-orm/pg-core";
25
+
26
+ ${tablesCode.join("\n")}
27
+ `;
28
+ fs.writeFileSync(SCHEMA_PATH, schemaFileContent);
29
+ console.log("[Deesse] Shadow schema generated at", SCHEMA_PATH);
30
+ };
@@ -0,0 +1,31 @@
1
+ import { Collection } from "../collections/types";
2
+ import { FieldKind } from "../fields";
3
+ export declare const DrizzleTypes: Record<FieldKind, () => any>;
4
+ export declare const toDrizzle: (collection: Collection) => import("drizzle-orm/pg-core").PgTableWithColumns<{
5
+ name: string;
6
+ schema: undefined;
7
+ columns: {
8
+ [x: string]: import("drizzle-orm/pg-core").PgColumn<{
9
+ name: any;
10
+ tableName: string;
11
+ dataType: any;
12
+ columnType: any;
13
+ data: any;
14
+ driverParam: any;
15
+ notNull: false;
16
+ hasDefault: false;
17
+ isPrimaryKey: false;
18
+ isAutoincrement: false;
19
+ hasRuntimeDefault: false;
20
+ enumValues: any;
21
+ baseColumn: never;
22
+ identity: undefined;
23
+ generated: undefined;
24
+ }, {}, {
25
+ [x: string]: any;
26
+ [x: number]: any;
27
+ [x: symbol]: any;
28
+ }>;
29
+ };
30
+ dialect: "pg";
31
+ }>;
@@ -0,0 +1,20 @@
1
+ import { boolean, integer, serial, text, varchar, char, numeric, decimal, json, uuid, timestamp, pgTable, } from "drizzle-orm/pg-core";
2
+ export const DrizzleTypes = {
3
+ boolean: () => boolean(),
4
+ integer: () => integer(),
5
+ serial: () => serial(),
6
+ text: () => text(),
7
+ varchar: () => varchar(),
8
+ char: () => char(),
9
+ numeric: () => numeric(),
10
+ decimal: () => decimal(),
11
+ json: () => json(),
12
+ uuid: () => uuid(),
13
+ timestamp: () => timestamp(),
14
+ };
15
+ export const toDrizzle = (collection) => {
16
+ return pgTable(collection.slug, Object.fromEntries(Object.entries(collection.fields).map(([name, field]) => {
17
+ const kind = field.type.dsl.kind;
18
+ return [name, DrizzleTypes[kind]()];
19
+ })));
20
+ };
File without changes
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1,13 @@
1
+ import { Collection } from "../collections/types";
2
+ export declare const dsl: (collection: Collection) => {
3
+ slug: string;
4
+ fields: {
5
+ name: string;
6
+ dsl: {
7
+ kind: string;
8
+ isPrimary: boolean;
9
+ isUnique: boolean;
10
+ canBeNull: boolean;
11
+ };
12
+ }[];
13
+ };
@@ -0,0 +1,10 @@
1
+ export const dsl = (collection) => {
2
+ const { slug, fields } = collection;
3
+ return {
4
+ slug,
5
+ fields: Object.entries(fields).map(([name, field]) => ({
6
+ name,
7
+ dsl: field.type.dsl,
8
+ })),
9
+ };
10
+ };
@@ -0,0 +1 @@
1
+ export * from './collections';
@@ -0,0 +1 @@
1
+ export * from './collections';
@@ -0,0 +1,6 @@
1
+ import { Field, FieldChain, FieldTypeFinal } from "./types";
2
+ export declare const unique: <TType extends FieldTypeFinal>(field: Field<TType>) => Field<TType>;
3
+ export declare const required: <TType extends FieldTypeFinal>(field: Field<TType>) => Field<TType>;
4
+ export declare const optional: <TType extends FieldTypeFinal>(field: Field<TType>) => Field<TType>;
5
+ export declare const primary: <TType extends FieldTypeFinal>(field: Field<TType>) => Field<TType>;
6
+ export declare const attachChain: <TType extends FieldTypeFinal>(f: Field<TType>) => FieldChain<TType>;
@@ -0,0 +1,59 @@
1
+ export const unique = (field) => {
2
+ return {
3
+ ...field,
4
+ type: {
5
+ ...field.type,
6
+ dsl: {
7
+ ...field.type.dsl,
8
+ isUnique: true,
9
+ },
10
+ },
11
+ };
12
+ };
13
+ export const required = (field) => ({
14
+ ...field,
15
+ type: {
16
+ ...field.type,
17
+ dsl: {
18
+ ...field.type.dsl,
19
+ canBeNull: false,
20
+ },
21
+ },
22
+ });
23
+ export const optional = (field) => ({
24
+ ...field,
25
+ type: {
26
+ ...field.type,
27
+ dsl: {
28
+ ...field.type.dsl,
29
+ canBeNull: true,
30
+ },
31
+ },
32
+ });
33
+ export const primary = (field) => ({
34
+ ...field,
35
+ type: {
36
+ ...field.type,
37
+ dsl: {
38
+ ...field.type.dsl,
39
+ isPrimary: true,
40
+ },
41
+ },
42
+ });
43
+ export const attachChain = (f) => {
44
+ return {
45
+ ...f,
46
+ unique() {
47
+ return attachChain(unique(f));
48
+ },
49
+ required() {
50
+ return attachChain(required(f));
51
+ },
52
+ optional() {
53
+ return attachChain(optional(f));
54
+ },
55
+ primary() {
56
+ return attachChain(primary(f));
57
+ },
58
+ };
59
+ };
@@ -0,0 +1,71 @@
1
+ export declare const number: (params?: {
2
+ min?: number | undefined;
3
+ max?: number | undefined;
4
+ } | undefined) => {
5
+ kind: import("./types").FieldKind;
6
+ params: unknown;
7
+ dsl: {
8
+ kind: import("./types").FieldKind;
9
+ isPrimary: boolean;
10
+ isUnique: boolean;
11
+ canBeNull: boolean;
12
+ };
13
+ admin: {
14
+ component: any;
15
+ };
16
+ };
17
+ export declare const text: (params?: {
18
+ min?: number | undefined;
19
+ max?: number | undefined;
20
+ } | undefined) => {
21
+ kind: import("./types").FieldKind;
22
+ params: unknown;
23
+ dsl: {
24
+ kind: import("./types").FieldKind;
25
+ isPrimary: boolean;
26
+ isUnique: boolean;
27
+ canBeNull: boolean;
28
+ };
29
+ admin: {
30
+ component: any;
31
+ };
32
+ };
33
+ export declare const uuid: (params?: void | undefined) => {
34
+ kind: import("./types").FieldKind;
35
+ params: unknown;
36
+ dsl: {
37
+ kind: import("./types").FieldKind;
38
+ isPrimary: boolean;
39
+ isUnique: boolean;
40
+ canBeNull: boolean;
41
+ };
42
+ admin: {
43
+ component: any;
44
+ };
45
+ };
46
+ export declare const timestamp: (params?: void | undefined) => {
47
+ kind: import("./types").FieldKind;
48
+ params: unknown;
49
+ dsl: {
50
+ kind: import("./types").FieldKind;
51
+ isPrimary: boolean;
52
+ isUnique: boolean;
53
+ canBeNull: boolean;
54
+ };
55
+ admin: {
56
+ component: any;
57
+ };
58
+ };
59
+ export declare const serial: (params?: void | undefined) => {
60
+ kind: import("./types").FieldKind;
61
+ params: unknown;
62
+ dsl: {
63
+ kind: import("./types").FieldKind;
64
+ isPrimary: boolean;
65
+ isUnique: boolean;
66
+ canBeNull: boolean;
67
+ };
68
+ admin: {
69
+ component: any;
70
+ };
71
+ };
@@ -0,0 +1,27 @@
1
+ import z from "zod";
2
+ import { fieldType } from "./field";
3
+ export const number = fieldType({
4
+ schema: z.object({ min: z.number().optional(), max: z.number().optional() }),
5
+ dsl: { kind: "numeric" },
6
+ admin: { component: undefined },
7
+ });
8
+ export const text = fieldType({
9
+ schema: z.object({ min: z.number().optional(), max: z.number().optional() }),
10
+ dsl: { kind: "text" },
11
+ admin: { component: undefined },
12
+ });
13
+ export const uuid = fieldType({
14
+ schema: z.void(),
15
+ dsl: { kind: "uuid" },
16
+ admin: { component: undefined },
17
+ });
18
+ export const timestamp = fieldType({
19
+ schema: z.void(),
20
+ dsl: { kind: "timestamp" },
21
+ admin: { component: undefined },
22
+ });
23
+ export const serial = fieldType({
24
+ schema: z.void(),
25
+ dsl: { kind: "serial" },
26
+ admin: { component: undefined },
27
+ });
@@ -0,0 +1,24 @@
1
+ import z from "zod";
2
+ import { FieldChain, FieldConfig, FieldKind, FieldTypeFinal } from "./types";
3
+ export declare const fieldType: <TOutput, TParams extends z.ZodType | undefined>(config: {
4
+ schema?: TParams;
5
+ dsl: {
6
+ kind: FieldKind;
7
+ };
8
+ admin: {
9
+ component: any;
10
+ };
11
+ }) => (params?: TParams extends z.ZodType ? z.infer<TParams> : undefined) => {
12
+ kind: FieldKind;
13
+ params: unknown;
14
+ dsl: {
15
+ kind: FieldKind;
16
+ isPrimary: boolean;
17
+ isUnique: boolean;
18
+ canBeNull: boolean;
19
+ };
20
+ admin: {
21
+ component: any;
22
+ };
23
+ };
24
+ export declare const field: <TType extends FieldTypeFinal>(config: FieldConfig<TType>) => FieldChain<TType>;
@@ -0,0 +1,33 @@
1
+ import { attachChain } from "./constraints";
2
+ export const fieldType = (config) => (params) => {
3
+ const validated = config.schema && params !== undefined
4
+ ? config.schema.parse(params)
5
+ : params;
6
+ return {
7
+ kind: config.dsl.kind,
8
+ params: validated,
9
+ dsl: {
10
+ kind: config.dsl.kind,
11
+ isPrimary: false,
12
+ isUnique: false,
13
+ canBeNull: true,
14
+ },
15
+ admin: config.admin,
16
+ };
17
+ };
18
+ const defaultPermissions = {
19
+ create: async () => true,
20
+ read: async () => true,
21
+ update: async () => true,
22
+ delete: async () => true,
23
+ };
24
+ export const field = (config) => {
25
+ const base = {
26
+ type: config.type,
27
+ permissions: {
28
+ ...defaultPermissions,
29
+ ...config.permissions,
30
+ },
31
+ };
32
+ return attachChain(base);
33
+ };
@@ -0,0 +1,4 @@
1
+ export * from './field';
2
+ export * from './types';
3
+ export * from './core';
4
+ export * from './constraints';
@@ -0,0 +1,4 @@
1
+ export * from './field';
2
+ export * from './types';
3
+ export * from './core';
4
+ export * from './constraints';
@@ -0,0 +1,48 @@
1
+ import { z } from "zod";
2
+ export type FieldKind = "integer" | "serial" | "boolean" | "text" | "varchar" | "char" | "numeric" | "decimal" | "json" | "uuid" | "timestamp";
3
+ export type FieldTypeConfig<TParams extends z.ZodType = z.ZodType> = {
4
+ schema?: TParams;
5
+ dsl: {
6
+ kind: FieldKind;
7
+ };
8
+ admin: {
9
+ component: any;
10
+ };
11
+ };
12
+ export type FieldTypeFinal<TParams extends z.ZodType = z.ZodType, TOutput = any> = {
13
+ kind: string;
14
+ params: z.infer<TParams>;
15
+ dsl: {
16
+ kind: string;
17
+ isPrimary: boolean;
18
+ isUnique: boolean;
19
+ canBeNull: boolean;
20
+ };
21
+ admin: {
22
+ component: any;
23
+ };
24
+ _output?: TOutput;
25
+ };
26
+ export type FieldPermissions = {
27
+ create: (ctx: any) => Promise<boolean>;
28
+ read: (ctx: any) => Promise<boolean>;
29
+ update: (ctx: any) => Promise<boolean>;
30
+ delete: (ctx: any) => Promise<boolean>;
31
+ };
32
+ export type FieldConfig<TType extends FieldTypeFinal> = {
33
+ type: TType;
34
+ permissions?: Partial<FieldPermissions>;
35
+ };
36
+ export type Field<TType extends FieldTypeFinal = FieldTypeFinal> = {
37
+ type: TType;
38
+ permissions: FieldPermissions;
39
+ };
40
+ export type InferSchema<F extends Record<string, Field>> = {
41
+ [K in keyof F]: F[K] extends Field<infer FT> ? FT extends FieldTypeFinal<any, infer TVal> ? TVal : never : never;
42
+ };
43
+ export type FieldChain<TType extends FieldTypeFinal> = Field<TType> & {
44
+ unique(): FieldChain<TType>;
45
+ required(): FieldChain<TType>;
46
+ optional(): FieldChain<TType>;
47
+ primary(): FieldChain<TType>;
48
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ export * from "./collections";
2
+ export * from "./config";
3
+ export * from "./drizzle";
4
+ export * from "./dsl";
5
+ export * from "./fields";
6
+ export * from "./next";
7
+ export * from "./plugins";
8
+ export * from "./providers";
@@ -0,0 +1,8 @@
1
+ export * from "./collections";
2
+ export * from "./config";
3
+ export * from "./drizzle";
4
+ export * from "./dsl";
5
+ export * from "./fields";
6
+ export * from "./next";
7
+ export * from "./plugins";
8
+ export * from "./providers";
@@ -0,0 +1,5 @@
1
+ import type { NextConfig } from "next";
2
+ declare global {
3
+ var __collections_worker_started: boolean | undefined;
4
+ }
5
+ export declare const withCollections: (phase: string, config: NextConfig) => NextConfig;
@@ -0,0 +1,17 @@
1
+ import { spawn } from "child_process";
2
+ import { PHASE_DEVELOPMENT_SERVER } from "next/constants";
3
+ import path from "path";
4
+ export const withCollections = (phase, config) => {
5
+ const isDev = phase === PHASE_DEVELOPMENT_SERVER;
6
+ if (isDev && !global.__collections_worker_started) {
7
+ global.__collections_worker_started = true;
8
+ const workerPath = path.join(__dirname, "../worker/index.js");
9
+ console.log("[withCollections] Spawning background worker:", workerPath);
10
+ spawn("node", [workerPath], {
11
+ stdio: "inherit",
12
+ });
13
+ }
14
+ return {
15
+ ...config,
16
+ };
17
+ };
@@ -0,0 +1,2 @@
1
+ import { Plugin } from "./types";
2
+ export declare const plugin: () => Plugin;
@@ -0,0 +1,3 @@
1
+ export const plugin = () => {
2
+ return {};
3
+ };
@@ -0,0 +1 @@
1
+ export type Plugin = {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import { Provider } from "./types";
2
+ export declare const inAppProvider: () => Provider;
@@ -0,0 +1,53 @@
1
+ export const inAppProvider = () => {
2
+ // Stockage en mémoire : { "posts": { "id_1": { ...data }, "id_2": { ...data } } }
3
+ const storage = {};
4
+ return {
5
+ // L'init reçoit maintenant la liste des collections pour préparer le "schéma"
6
+ init: (collections) => {
7
+ console.log("Initializing in-app provider");
8
+ for (const col of collections) {
9
+ // On initialise un "bucket" vide pour chaque collection si pas déjà fait
10
+ if (!storage[col.slug]) {
11
+ storage[col.slug] = {};
12
+ }
13
+ }
14
+ },
15
+ create: async (collectionSlug, data) => {
16
+ // Simulation d'un ID (dans une vraie DB, c'est géré par le moteur ou UUID)
17
+ const id = Math.random().toString(36).substring(2, 15);
18
+ const record = { ...data, id };
19
+ // Sécurité au cas où on écrit dans une collection non initialisée
20
+ if (!storage[collectionSlug])
21
+ storage[collectionSlug] = {};
22
+ storage[collectionSlug][id] = record;
23
+ return record;
24
+ },
25
+ read: async (collectionSlug, id) => {
26
+ const record = storage[collectionSlug]?.[id];
27
+ if (!record) {
28
+ throw new Error(`Record with ID "${id}" not found in "${collectionSlug}".`);
29
+ }
30
+ return record;
31
+ },
32
+ update: async (collectionSlug, id, data) => {
33
+ const existing = storage[collectionSlug]?.[id];
34
+ if (!existing) {
35
+ throw new Error(`Cannot update: Record with ID "${id}" not found in "${collectionSlug}".`);
36
+ }
37
+ // Fusion des données (Partial update)
38
+ const updated = { ...existing, ...data };
39
+ storage[collectionSlug][id] = updated;
40
+ return updated;
41
+ },
42
+ delete: async (collectionSlug, id) => {
43
+ if (storage[collectionSlug] && storage[collectionSlug][id]) {
44
+ delete storage[collectionSlug][id];
45
+ }
46
+ else {
47
+ // Optionnel : Throw une erreur si l'item n'existe pas,
48
+ // ou juste ignorer comme le ferait une requête SQL "DELETE WHERE ID=..."
49
+ console.warn(`Attempted to delete non-existent record "${id}" in "${collectionSlug}"`);
50
+ }
51
+ }
52
+ };
53
+ };
@@ -0,0 +1,8 @@
1
+ import { Collection } from "../collections/types";
2
+ export type Provider = {
3
+ init: (collections: readonly Collection[]) => Promise<void> | void;
4
+ create: (collectionSlug: string, data: any) => Promise<any>;
5
+ read: (collectionSlug: string, id: string) => Promise<any>;
6
+ update: (collectionSlug: string, id: string, data: any) => Promise<any>;
7
+ delete: (collectionSlug: string, id: string) => Promise<void>;
8
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ export type DeepPartial<T> = T extends (infer U)[] ? DeepPartial<U>[] : T extends object ? {
2
+ [K in keyof T]?: DeepPartial<T[K]>;
3
+ } : T;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ type Exact<A, B> = A extends B ? Exclude<keyof A, keyof B> extends never ? A : never : never;
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1 @@
1
+ export type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import { Collection } from "../collections/types";
2
+ export declare const loadCollections: () => Promise<Collection[]>;
@@ -0,0 +1,32 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { generateShadowSchema } from "../drizzle/generate";
4
+ // Dossier des collections
5
+ const collectionsDir = path.join(process.cwd(), "src", "collections");
6
+ console.log(`[worker] Loading collections from ${collectionsDir}`);
7
+ // Fonction pour importer toutes les collections
8
+ export const loadCollections = async () => {
9
+ const files = fs
10
+ .readdirSync(collectionsDir)
11
+ .filter((f) => f.endsWith(".ts") || f.endsWith(".js"));
12
+ const collections = [];
13
+ for (const file of files) {
14
+ const fullPath = path.join(collectionsDir, file);
15
+ // Utilisation de import dynamique
16
+ const module = await import(fullPath);
17
+ // On suppose que la collection exporte toujours une const (ex: Posts)
18
+ for (const exported of Object.values(module)) {
19
+ const col = exported;
20
+ if (col?.slug && col?.fields) {
21
+ collections.push(col);
22
+ }
23
+ }
24
+ }
25
+ return collections;
26
+ };
27
+ // Exemple d'utilisation
28
+ (async () => {
29
+ const collections = await loadCollections();
30
+ generateShadowSchema(collections);
31
+ console.log(`[worker] Shadow schema generated for ${collections.length} collections.`);
32
+ })();
@@ -1,2 +1 @@
1
- import { Collection } from "../collections/types";
2
- export declare const loadCollections: () => Promise<Collection[]>;
1
+ export {};
@@ -1,72 +1,11 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
36
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
4
  };
38
5
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.loadCollections = void 0;
40
- const fs_1 = __importDefault(require("fs"));
41
6
  const path_1 = __importDefault(require("path"));
42
- const generate_1 = require("../drizzle/generate");
43
- // Dossier des collections
44
7
  const collectionsDir = path_1.default.join(process.cwd(), "src", "collections");
45
8
  console.log(`[worker] Loading collections from ${collectionsDir}`);
46
- // Fonction pour importer toutes les collections
47
- const loadCollections = async () => {
48
- const files = fs_1.default
49
- .readdirSync(collectionsDir)
50
- .filter((f) => f.endsWith(".ts") || f.endsWith(".js"));
51
- const collections = [];
52
- for (const file of files) {
53
- const fullPath = path_1.default.join(collectionsDir, file);
54
- // Utilisation de import dynamique
55
- const module = await Promise.resolve(`${fullPath}`).then(s => __importStar(require(s)));
56
- // On suppose que la collection exporte toujours une const (ex: Posts)
57
- for (const exported of Object.values(module)) {
58
- const col = exported;
59
- if (col?.slug && col?.fields) {
60
- collections.push(col);
61
- }
62
- }
63
- }
64
- return collections;
65
- };
66
- exports.loadCollections = loadCollections;
67
- // Exemple d'utilisation
68
9
  (async () => {
69
- const collections = await (0, exports.loadCollections)();
70
- (0, generate_1.generateShadowSchema)(collections);
71
- console.log(`[worker] Shadow schema generated for ${collections.length} collections.`);
10
+ console.log(`[worker] Shadow schema generated for collections.`);
72
11
  })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deessejs/collections",
3
- "version": "0.0.41",
3
+ "version": "0.0.45",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",