From c54aa6999f36746f40a5d11a41911a13e2bdb14f Mon Sep 17 00:00:00 2001 From: "Shahid N. Shah" Date: Wed, 21 Aug 2024 21:35:25 -0400 Subject: [PATCH] refactor: sqlpage aide moved to RSC --- lib/sqlpage/README.md | 199 ---------- lib/sqlpage/component.ts | 729 ------------------------------------ lib/sqlpage/mod.ts | 3 - lib/sqlpage/mod_test.ts | 145 ------- lib/sqlpage/render.ts | 120 ------ lib/sqlpage/sqlpage-aide.ts | 649 -------------------------------- 6 files changed, 1845 deletions(-) delete mode 100644 lib/sqlpage/README.md delete mode 100644 lib/sqlpage/component.ts delete mode 100644 lib/sqlpage/mod.ts delete mode 100644 lib/sqlpage/mod_test.ts delete mode 100644 lib/sqlpage/render.ts delete mode 100644 lib/sqlpage/sqlpage-aide.ts diff --git a/lib/sqlpage/README.md b/lib/sqlpage/README.md deleted file mode 100644 index 73279496..00000000 --- a/lib/sqlpage/README.md +++ /dev/null @@ -1,199 +0,0 @@ -# SQLPageAide - -## Introduction to SQLPage - -SQLPage is an open-source web server written in Rust, designed to build web -applications entirely using SQL. It allows users to write SQL queries that are -executed on a database, and the results are rendered as web pages. This utility -is particularly useful for those who are proficient in SQL but may not have -extensive experience with traditional web programming languages like HTML, CSS, -or JavaScript. - -SQLPage operates by mapping the results of SQL queries to pre-defined web -components, such as tables, charts, forms, and more. These components can be -customized using HTML templates, providing flexibility in how the data is -presented. The tool supports multiple databases, including SQLite, PostgreSQL, -MySQL, and Microsoft SQL Server. - -The primary appeal of SQLPage is its simplicity and ease of use. Developers can -get started quickly by downloading a single executable file, writing SQL -queries, and immediately seeing the results as a functional website. It's -particularly well-suited for data analysts, business intelligence teams, and -others who need to build data-centric applications without getting into the -complexities of full-stack web development. - -SQLPage also supports advanced features like user authentication, file uploads, -and HTTPS. It can be deployed on various platforms, including local servers and -cloud environments, and supports integration with Docker for easy deployment. - -For more detailed information and examples, you can explore the documentation -and discussions available on -[SQLPage's GitHub](https://github.com/lovasoa/SQLpage) and related resources. - -## Structure of `sqlpage_files` Table - -The `sqlpage_files` table in SQLPage serves as a storage mechanism within the -database to host files used by the application. The structure of this table -includes the following columns: - -- **path**: A text or string field that stores the file path or identifier. This - path is used to reference the file within the SQLPage application, allowing it - to be served or accessed as needed. - -- **contents**: A BLOB (Binary Large Object) field that contains the actual file - data. This could be anything from images, JSON files, configuration files, or - other binary content. Storing the file data in BLOB format ensures that binary - data can be stored and retrieved accurately. - -- **last_modified**: A timestamp field that records the last time the file was - modified. This is useful for caching, version control, and ensuring that the - most up-to-date version of the file is served. - -This structure allows SQLPage to serve files dynamically from the database, -enabling features like localization, theming, and dynamic content management -directly within SQLPage applications. - -## SQLPageAide class - -`SQLPageAide` is a utility class designed to facilitate the creation of upsert -statements for inserting records into `sqlpage_files` table. `SQLPageAide` does -not operate on a database, it just generates SQL. - -## Key Features - -- **No Dependencies**: Does not depend on SQLa or any other library but can use - all of SQLa if desired. -- **Structured Definitions**: Define SQL page paths and contents using classes - or objects. -- **Convenience Functions**: - - `sources()`: Specify the classes or objects containing SQL definitions. - - `includeUpserts()`: Include specific patterns to match method names that - will generate Upsert content (defaults to /*.sql$/). - - `excludeUpserts()`: Exclude specific patterns from matching method names - that will generate Upsert content. - - `includeSql()`: Include specific patterns to match method names that will - generate general SQL statements to incorporate before upserts. - - `excludeSql()`: Exclude specific patterns from matching method names that - will generate general SQL statements to incorporate before upserts. - - `withContentsArgs()`: Inject additional context or arguments into SQL - methods for dynamic content. - - `pathContents()`: Customize the method selection process for upserting into - `sqlpage_files`. -- **Automatic Upsert Generation**: - - `upsertValues()`: Collects and prepares SQL statements for insertion or - update. - - `SQL()`: Generates SQL statements to manage entries in the `sqlpage_files` - table. - -## Usage Examples - -### Basic Example - -Define a class with SQL methods and use SQLPageAide to generate SQL upsert -statements. - -```typescript -// Define a class with SQL methods -class MySqlPages { - "index.sql"() { - return "SELECT * FROM users;"; - } - - "page1.sql"() { - return "INSERT INTO users (name, email) VALUES ('John Doe', 'john@example.com');"; - } -} - -// Generate SQL statements -const sqlAide = new SQLPageAide(MySqlPages); -const sqlStatements = sqlAide.SQL(); -console.log(sqlStatements); -// Output: -// INSERT INTO sqlpage_files (path, contents, last_modified) VALUES ('index.sql', 'SELECT * FROM users;', CURRENT_TIMESTAMP) ON CONFLICT(path) DO UPDATE SET contents=excluded.contents, last_modified=CURRENT_TIMESTAMP); -// INSERT INTO sqlpage_files (path, contents, last_modified) VALUES ('page1.sql', 'INSERT INTO users (name, email) VALUES (''John Doe'', ''john@example.com'');', CURRENT_TIMESTAMP) ON CONFLICT(path) DO UPDATE SET contents=excluded.contents, last_modified=CURRENT_TIMESTAMP); -``` - -### Using Contents Args Supplier - -Inject additional arguments into SQL methods for dynamic content generation. - -```typescript -class MySqlPages { - "index.sql"(user: string) { - return `SELECT * FROM users WHERE name = '${user}';`; - } -} - -const sqlPageAide = new SQLPageAide(MySqlPages) - .withContentsArgs((_source, _path, user: string) => [user]); - -const sqlStatements = sqlPageAide.SQL("John Doe"); -console.log(sqlStatements); -// Output: -// INSERT INTO sqlpage_files (path, contents, last_modified) VALUES ('index.sql', 'SELECT * FROM users WHERE name = ''John Doe'';', CURRENT_TIMESTAMP) ON CONFLICT(path) DO UPDATE SET contents=excluded.contents, last_modified=CURRENT_TIMESTAMP); -``` - -### Including and Excluding Methods - -Include or exclude specific methods based on patterns. - -```typescript -class MySqlPages { - "index.sql"() { - return "SELECT * FROM users;"; - } - - "page1.sql"() { - return "INSERT INTO users (name, email) VALUES ('John Doe', 'john@example.com');"; - } - - "admin.sql"() { - return "SELECT * FROM admins;"; - } -} - -const sqlAide = new SQLPageAide(MySqlPages) - .include(/index\.sql/, /page1\.sql/) - .exclude(/admin\.sql/); - -const sqlStatements = sqlAide.SQL(); -console.log(sqlStatements); -// Output includes only statements for index.sql and page1.sql, excluding admin.sql. -``` - -### Custom Path Contents Supplier - -Customize the method selection process. - -```typescript -class MySqlPages { - "index.sql"() { - return "SELECT * FROM users;"; - } - - "page1.sql"() { - return "INSERT INTO users (name, email) VALUES ('John Doe', 'john@example.com');"; - } - - "admin.sql"() { - return "SELECT * FROM admins;"; - } -} - -const customPathContentsSupplier = ( - sp: SourcePaths, - includePatterns: PathPattern[], - excludePatterns: PathPattern[], -) => { - return sp.paths.filter((path) => - path.startsWith("index") || path.startsWith("page") - ); -}; - -const sqlAide = new SQLPageAide(MySqlPages) - .pathContents(customPathContentsSupplier); - -const sqlStatements = sqlAide.SQL(); -console.log(sqlStatements); -// Output includes statements for index.sql and page1.sql, based on custom supplier logic. -``` diff --git a/lib/sqlpage/component.ts b/lib/sqlpage/component.ts deleted file mode 100644 index 72418001..00000000 --- a/lib/sqlpage/component.ts +++ /dev/null @@ -1,729 +0,0 @@ -export interface Component { - readonly component: Identity; - readonly title?: string; -} - -export interface RenderedComponent> { - readonly component: T; - readonly SQL: (() => string) | string | string[]; -} - -export interface Alert extends Component<"alert"> { - readonly message: string; - readonly type?: "info" | "warning" | "error"; -} - -export interface Authentication extends Component<"authentication"> { - readonly link: string; - readonly token?: string; -} - -export interface Breadcrumb extends Component<"breadcrumb"> { - readonly items: readonly BreadcrumbItem[]; -} - -export interface BreadcrumbItem { - readonly label: string; - readonly link: string; -} - -export interface Button extends Component<"button"> { - readonly buttons: readonly ButtonItem[]; -} - -export interface ButtonItem { - readonly label: string; - readonly link: string; - readonly style?: "primary" | "secondary" | "danger"; -} - -export interface Card extends Component<"card"> { - readonly items: readonly CardItem[]; -} - -export interface CardItem { - readonly title: string; - readonly content: string; - readonly image?: string; - readonly link?: string; -} - -export interface Carousel extends Component<"carousel"> { - readonly images: readonly CarouselImage[]; -} - -export interface CarouselImage { - readonly src: string; - readonly alt?: string; -} - -export interface Chart extends Component<"chart"> { - readonly type: "line" | "bar" | "pie" | "area"; - readonly data: readonly ChartDataPoint[]; -} - -export interface ChartDataPoint { - readonly x: string | number; - readonly y: number; -} - -export interface Code extends Component<"code"> { - readonly language: string; - readonly code: string; -} - -export interface Cookie extends Component<"cookie"> { - readonly name: string; - readonly value: string; - readonly path?: string; - readonly expires?: string; -} - -export interface Csv extends Component<"csv"> { - readonly filename: string; - readonly columns: readonly string[]; -} - -export interface DataGrid extends Component<"datagrid"> { - readonly items: readonly DataGridItem[]; -} - -export interface DataGridItem { - readonly name: string; - readonly value: string; -} - -export interface Debug extends Component<"debug"> { - readonly data: unknown; -} - -export interface Divider extends Component<"divider"> { - readonly style?: string; -} - -export interface Dynamic extends Component<"dynamic"> { - readonly content: string; -} - -export interface Form extends Component<"form"> { - readonly fields: readonly FormField[]; - readonly action: string; -} - -export interface FormField { - readonly name: string; - readonly type: - | "text" - | "password" - | "email" - | "number" - | "date" - | "textarea" - | "select" - | "checkbox" - | "radio"; - readonly placeholder?: string; - readonly required?: boolean; - readonly options?: readonly string[]; // for select fields - readonly label?: string; - readonly min?: number; - readonly max?: number; - readonly step?: number; - readonly minlength?: number; - readonly maxlength?: number; - readonly pattern?: string; - readonly autocomplete?: "on" | "off" | string; - readonly autofocus?: boolean; - readonly description?: string; - readonly checked?: boolean; -} - -export interface Hero extends Component<"hero"> { - readonly description?: string; - readonly image?: string; - readonly link?: string; - readonly linkText?: string; -} - -export interface Html extends Component<"html"> { - readonly content: string; -} - -export interface HttpHeader extends Component<"http_header"> { - readonly headers: Record; -} - -export interface Json extends Component<"json"> { - readonly data: unknown; -} - -export interface List extends Component<"list"> { - readonly items: readonly ListItem[]; -} - -export interface ListItem { - readonly title: string; - readonly link?: string; - readonly description?: string; - readonly icon?: string; - readonly active?: boolean; - readonly color?: string; - readonly delete_link?: string; - readonly edit_link?: string; - readonly image_url?: string; - readonly view_link?: string; -} - -export interface Map extends Component<"map"> { - readonly markers: readonly MapMarker[]; -} - -export interface MapMarker { - readonly latitude: number; - readonly longitude: number; - readonly label?: string; -} - -export interface Redirect extends Component<"redirect"> { - readonly url: string; -} - -export interface Rss extends Component<"rss"> { - readonly url: string; - readonly title: string; - readonly description?: string; -} - -export interface Shell extends Component<"shell"> { - readonly layout?: "boxed" | "horizontal" | "fluid"; - readonly css?: string; - readonly favicon?: string; - readonly javascript?: string; - readonly language?: string; - readonly theme?: "dark" | "light"; - readonly title: string; - readonly description?: string; - readonly image?: string; - readonly manifest?: string; - readonly menu_item?: string | { title: string; submenu: readonly MenuItem[] }; - readonly norobot?: boolean; - readonly refresh?: number; - readonly rss?: string; - readonly search_target?: string; - readonly search_value?: string; - readonly social_image?: string; -} - -export interface MenuItem { - readonly title: string; - readonly link: string; -} - -export interface Steps extends Component<"steps"> { - readonly steps: readonly StepItem[]; -} - -export interface StepItem { - readonly label: string; - readonly link: string; -} - -export interface Tab extends Component<"tab"> { - readonly tabs: readonly TabItem[]; -} - -export interface TabItem { - readonly label: string; - readonly link: string; - readonly active?: boolean; -} - -export interface Table extends Component<"table"> { - readonly columns: readonly TableColumn[]; - readonly sort?: boolean; - readonly search?: boolean; -} - -export interface TableColumn { - readonly name: string; - readonly label?: "markdown" | string; -} - -export interface Text extends Component<"text"> { - readonly content: string; -} - -export interface Timeline extends Component<"timeline"> { - readonly events: readonly TimelineEvent[]; -} - -export interface TimelineEvent { - readonly timestamp: string; - readonly description: string; -} - -export interface Title extends Component<"title"> { - readonly level?: 1 | 2 | 3 | 4 | 5 | 6; - readonly contents: string; -} - -export interface Tracking extends Component<"tracking"> { - readonly logs: readonly TrackingLog[]; -} - -export interface TrackingLog { - readonly timestamp: string; - readonly action: string; - readonly user?: string; -} - -export function alertSQL(component: Alert): RenderedComponent { - return { - component, - SQL: [ - `SELECT '${component.component}' AS component, '${component.message}' AS message${ - component.type ? `, '${component.type}' AS type` : "" - };`, - ], - }; -} - -export function authenticationSQL( - component: Authentication, -): RenderedComponent { - return { - component, - SQL: [ - `SELECT '${component.component}' AS component, '${component.link}' AS link${ - component.token ? `, '${component.token}' AS token` : "" - };`, - ], - }; -} - -export function breadcrumbSQL( - component: Breadcrumb, -): RenderedComponent { - return { - component, - SQL: [ - `SELECT '${component.component}' AS component;`, - ...component.items.map((item) => - `SELECT '${item.label}' AS label, '${item.link}' AS link;` - ), - ], - }; -} - -export function buttonSQL(component: Button): RenderedComponent