Foundation 6

Classes

cs.fnd.date

Created by: Wayne Stewart (Claude Opus 5) (2026-08-14) The Fnd_Date module as a class, so a host can reach it through the class store instead of the method names.

In a host:         cs.fnd.date.new().toISO(Current date; Current time)
Inside Foundation: cs.date.new().toISO(Current date; Current time)

The namespace is the "Component namespace in the class store" setting, which is "fnd" here. It governs how the host sees these classes; inside the component they are plain cs.<name>.

Design decisions and assumptions:

  • Every function delegates to the Fnd_Date_ method of the same behaviour. The methods remain the implementation, so the class cannot drift from them and adds no behavioural risk.
  • Stateless, so new() is cheap and instances are interchangeable. What little module state there is lives in Storage.Fnd.Date and Fnd.Date.
  • Named for what they do rather than transcribing the method names, so Fnd_Date_DateAndTimeToISO becomes toISO and Fnd_Date_ISOtoDate becomes dateFromISO.
  • Fnd_Date_Calendar and Fnd_Date_EntryFilter are not here. Both take a pointer to a form object and only mean anything inside a running form, which is not what a class store instance is for.

info

info($infoRequested_t : Text)->$result_t : Text

The module's own labels — "name" and "version".

toISO

toISO($date_d : Date; $time_h : Time)->$result_t : Text

A date alone gives YYYY-MM-DD, a date and time the joined form. A null date with a time gives the time alone; a null date alone gives "".

dateFromISO

dateFromISO($isoDate_t : Text)->$result_d : Date

Reads YYYY-MM-DD and YYYY-MM-DDThh:mm:ss alike. 4D's own Date() will not take the first of those, which is why this is not a wrapper over it.

timeFromISO

timeFromISO($isoDateTime_t : Text)->$result_h : Time

Reads the time out of a stamp, including one carrying milliseconds or a zone suffix. The suffix is dropped rather than applied, so no silent conversion from UTC happens.

localTimestamp

localTimestamp()->$result_t : Text

Local wall-clock time, YYYY-MM-DDThh:mm:ss.mmm, with no zone suffix. Comparable with other stamps from here, not with a UTC one.

fromParts

fromParts($year_i : Integer; $month_i : Integer; $day_i : Integer)->$result_d : Date

Out of range parts roll over rather than being refused: month 13 is January of the next year, day 0 the last day of the previous month.

fromString

fromString($theDate_t : Text; $dateFormat_t : Text)->$result_d : Date

Unlike fromParts, this refuses a month above 12 or a day above 31, and gives the null date instead. Pass a format such as "D/M/Y" to read the string as something other than the machine's own setting.

toString

toString($theDate_t : Date; $relativeTo_d : Date; $dateFormat_t : Text)->$result_t : Text

"Today", "Tomorrow" or "Yesterday" where they apply, localized; the null date gives "". Everything else is formatted to the given format.

endOfMonth

endOfMonth($theDate_d : Date)->$result_d : Date

The last day of the month the date falls in.

monthName

monthName($monthNumber_i : Integer)->$result_t : Text

Localized. Anything outside 1 to 12 gives "Error".

systemDateFormat

systemDateFormat()->$result_t : Text

"M/D/Y" or "D/M/Y" and so on, for the machine this is running on.

roundTime

roundTime($theTime_h : Time; $option_h : Time)->$result_h : Time

No option, or 1, rounds to the nearest quarter hour; 2 rounds down.

roundTimeDown

roundTimeDown($theTime_h : Time)->$result_h : Time

Down to the quarter hour, however close the next one is.

roundTimeNear

roundTimeNear($theTime_h : Time)->$result_h : Time

The quarter is held for ten minutes past it before the next is reached, and the last five minutes of the day give 23:59 rather than midnight.

cs.fnd.fnd

info

info($infoRequested_t : Text)->$result_t : Text

The component's own labels — "name" and "version". Anything else answers "Component Did Not Recognize Request".

getCurrentTable

getCurrentTable->$result_ptr : Pointer

The table this instance was told to work on, or Null if it was never set.

setCurrentTable

setCurrentTable($table_ptr : Pointer)->$result_ptr : Pointer

Records the table to work on, and returns it.

getCurrentFormType

getCurrentFormType->$result_i : Integer

The form type this instance was told to work on. Fnd_Gen_NoForm when none.

setComponentInfo

setComponentInfo($key_t : Text; $value_t : Text)->$result_t : Text

Publishes one label for another component to read. The store lives on the Form object, so this only works while a form is loaded.

getComponentInfo

getComponentInfo($key_t : Text)->$result_t : Text

Reads back a label another component published. Empty when there is none, or when no form is loaded.

componentCheck

componentCheck($calling_t : Text; $required_t : Text)->$result_b : Boolean

True when the required component answers. False alerts the developer first, and does not stop the caller — test the result and decide.

cs.fnd.Fnd_PrefEntity

Created by: Wayne Stewart, Created: 2026-04-28 Entity extension for the [Fnd_Pref] dataclass.

Adds typed value access on top of the (Type, Value) column pair. Value is stored as text; Type records the original 4D type so it can be decoded on read. Supported types: Is text, Is longint, Is real, Is boolean, Is object.

typedValue

typedValue() : Variant

setTypedValue

setTypedValue($value : Variant)

Encodes $value into (Type, Value) on this entity. Caller saves. Numerics stored as plain text. Booleans stored as "true" / "false". Objects stored as pretty-printed JSON.

cs.fnd.log

Created by WBS, 2026-09-12 (FND-26) Logging access for hosts: cs.fnd.log.new(). No shared singleton syntax. Delegates to methods; enabled/selection remain in the calling process. A future 21 singleton can use the same functions without sharing process state.

enable

enable($enabled_b : Boolean)->$result_b : Boolean

Read or set the current process enable flag.

config

config($options_o : Object)->$result_o : Object

Read or update application defaults; declared logs keep their settings.

declareLog

declareLog($label_t : Text; $file_t : Text; $folder_t : Text; $options_o : Object; $dedicated_b : Boolean)

Declare once; optional dedicated writer defaults to False.

useLog

useLog($label_t : Text)

Empty/omitted selects default; does not alter enable state.

label

label()->$result_t : Text

Current process log label.

overrideLevel

overrideLevel($level_i : Integer; $application_b : Boolean)->$result_i : Integer

No arguments reads effective threshold. Optional True sets application scope.

addEntry

addEntry($message_v : Variant; $options_o : Object)

Text or a collection of text columns, plus optional entry metadata.

flush

flush($label_t : Text)

Queue a flush; no completion acknowledgement.

closeLog

closeLog($label_t : Text)

Flush and close a label, or all logs when omitted.

createTable

createTable()->$result_o : Object

Explicit only; interpreted host required. Inspect restartRequired.

shutdown

shutdown()

Call after producers finish, outside a logger worker.

extension

extension($value_t : Text)->$result_t : Text

Omit to read; pass text to update through Fnd_Log_Extension.

fileName

fileName($value_t : Text)->$result_t : Text

Omit to read; pass text to update through Fnd_Log_FileName.

path

path($value_t : Text)->$result_t : Text

Omit to read; pass text to update through Fnd_Log_Path.

maximumSize

maximumSize($bytes_i : Integer)->$result_i : Integer

Get/set rollover size; zero disables rollover.

info

info($request_t : Text)->$result_t : Text

Existing module name/version/logging query API.

cs.fnd.pref

Created by: Wayne Stewart (Claude Opus 5) (2026-08-14) The Fnd_Pref module as a class, so a host can reach it through the class store instead of the method names.

In a host:         cs.fnd.pref.new().getText("Report: Last Folder"; "")
Inside Foundation: cs.pref.new().getText("Report: Last Folder"; "")

The namespace is the "Component namespace in the class store" setting, which is "fnd" here. It governs how the host sees these classes; inside the component they are plain cs.<name>.

Not to be confused with cs.Fnd_Pref, which is the DataClass extension for the [Fnd_Pref] table and belongs to the host that owns the table. This one is the module's API and belongs to the component.

Design decisions and assumptions:

  • Every function delegates to the Fnd_Pref_ method of the same behaviour. The methods remain the implementation, so the class cannot drift from them and adds no behavioural risk.
  • Stateless, so new() is cheap and instances are interchangeable. Module state lives in Storage.Fnd.Pref, shared by both routes.
  • getWindow is the one place the shape changes rather than passing through. The method writes through four pointers, which is not something to publish on a modern API, so this returns {left; top; right; bottom} - or Null when nothing is stored, which the pointer form signals by leaving the caller's variables alone.
  • The scope argument is a constant or a label, the same Variant the methods take. On a getter it only says where to store a default it has to create; on remove it says where to delete from. See the method headers.
  • 4D 20 LTS has no singletons, so a host instantiates: cs.fnd.pref.new(). From 21 a shared singleton would allow cs.fnd.pref.me, and the functions below would not change.

info

info($infoRequested_t : Text)->$result_t : Text

The module's own labels — "name" and "version".

path

path()->$result_t : Text

Where the local preferences file is, or would be.

userName

userName($name_t : Text)->$result_t : Text

The name the server preferences are owned by. Setting it reloads.

save

save()

Writes the local file and the user's server preferences. Called on quit.

getText

getText($name_t : Text; $default_t : Text; $scope_v : Variant)->$result_t : Text

The stored text, or the default. Passing a default stores it when the preference does not exist yet; the scope says where.

getBoolean

getBoolean($name_t : Text; $default_b : Boolean; $scope_v : Variant)->$result_b : Boolean

As getText, for a Boolean.

getLongInt

getLongInt($name_t : Text; $default_i : Integer; $scope_v : Variant)->$result_i : Integer

As getText, for an Integer.

getReal

getReal($name_t : Text; $default_r : Real; $scope_v : Variant)->$result_r : Real

As getText, for a Real.

getObject

getObject($name_t : Text; $default_o : Object; $scope_v : Variant)->$result_o : Object

As getText, for an Object.

getWindow

getWindow($name_t : Text)->$result_o : Object

The stored rectangle as {left; top; right; bottom}, or Null when there is none. Fnd_Pref_GetWindow signals that by leaving the caller's variables untouched, so the four are seeded with something no window could hold and the result is Null if the seed survived.

setText

setText($name_t : Text; $value_t : Text; $scope_v : Variant)

Stores the value. The scope decides local or server; the default is the module's, see the method header.

setBoolean

setBoolean($name_t : Text; $value_b : Boolean; $scope_v : Variant)

As setText, for a Boolean.

setLongInt

setLongInt($name_t : Text; $value_i : Integer; $scope_v : Variant)

As setText, for an Integer.

setReal

setReal($name_t : Text; $value_r : Real; $scope_v : Variant)

As setText, for a Real.

setObject

setObject($name_t : Text; $value_o : Object; $scope_v : Variant)

As setText, for an Object.

setWindow

setWindow($name_t : Text; $rect_o : Object)

Pass {left; top; right; bottom}, or nothing for the frontmost window of the current process.

remove

remove($name_t : Text; $scope_v : Variant)->$result_b : Boolean

True if there was one to delete. The scope says where to delete from.

cs.fnd.pswd

Created by: Wayne Stewart (Claude Opus 5) (2026-08-14) The Fnd_Pswd module as a class, so a host can reach it through the class store instead of the method names.

In a host:         cs.fnd.pswd.new().generate({length: 16})
Inside Foundation: cs.pswd.new().generate({length: 16})

The namespace is the "Component namespace in the class store" setting, which is "fnd" here. It governs how the host sees these classes; inside the component they are plain cs.<name>.

Design decisions and assumptions:

  • Every function delegates to the Fnd_Pswd_ method of the same behaviour. The methods remain the implementation, so the class cannot drift from them and adds no behavioural risk.
  • Stateless, so new() is cheap and instances are interchangeable. Module state lives in Storage.Fnd.Pswd, shared by both routes.
  • generate() taking an options object is the one to reach for: it touches no shared state, so it is safe from a worker and from two processes at once. The setters below change the stored defaults and are not.
  • 4D 20 LTS has no singletons, so a host instantiates: cs.fnd.pswd.new(). From 21 a shared singleton would allow cs.fnd.pswd.me, and the functions below would not change.

info

info($infoRequested_t : Text)->$result_t : Text

The module's own labels — "name" and "version".

generate

generate($options_o : Object)->$result_t : Text

Pass nothing for the stored settings, or an object to override them for this call only: {type; length; minLength; maxLength; useUppercase; useLowercase; useNumbers; useSymbols; customCharacters; excludedCharacters; requireEachClass}

validCharacters

validCharacters($options_o : Object)->$result_t : Text

The alphabet a generation would draw from, under the same options.

strength

strength($password_t : Text; $options_o : Object)->$result_o : Object

{ length ; poolSize ; bits ; rating }. Pass {type} when it is known, or a pronounceable password is weighed on its characters and overstated.

dialog

dialog()->$result_t : Text

Shows the generator dialog. Returns "" if it was cancelled.

useUppercase

useUppercase($use_b : Boolean)->$result_b : Boolean

Reads the stored default, or sets it when passed a value.

useLowercase

useLowercase($use_b : Boolean)->$result_b : Boolean

Reads the stored default, or sets it when passed a value.

useNumbers

useNumbers($use_b : Boolean)->$result_b : Boolean

Reads the stored default, or sets it when passed a value.

useSymbols

useSymbols($use_b : Boolean)->$result_b : Boolean

Reads the stored default, or sets it when passed a value.

customCharacters

customCharacters($characters_t : Text)->$result_t : Text

Setting characters turns the custom set on; setting none turns it off.

excludeCharacters

excludeCharacters($characters_t : Text)->$result_t : Text

Matched exactly, so excluding "o" leaves "O" alone.

minLength

minLength($characters_i : Integer; $limit_i : Integer)->$result_i : Integer

Carries the maximum up with it rather than leaving the pair inverted.

maxLength

maxLength($characters_i : Integer; $limit_i : Integer)->$result_i : Integer

Carries the minimum down with it, the mirror of minLength.

cs.fnd.text

Created by: Wayne Stewart (Claude Opus 5) (2026-08-13) WBS, 2026-09-12 - Expose existing whitespace trim through the class. The Fnd_Text module as a class, so a host can reach it through the class store instead of the method names.

In a host:        cs.fnd.text.new().capitalize("hello world")
Inside Foundation: cs.text.new().capitalize("hello world")

The namespace is the "Component namespace in the class store" setting, which is "fnd" here. It governs how the host sees these classes; inside the component they are plain cs.<name>.

Design decisions and assumptions:

  • Every function delegates to the Fnd_Text_ method of the same behaviour. The methods remain the implementation, so the class cannot drift from them and adds no behavioural risk. The direction can invert later, one function at a time, without either API changing.
  • Stateless, so new() is cheap and instances are interchangeable. Module state lives in Storage.Fnd.Text, shared by both routes.
  • 4D 20 LTS has no singletons, so a host instantiates: cs.fnd.text.new(). From 21 a shared singleton would allow cs.fnd.text.me, and the functions below would not change.
  • Named for what they do rather than transcribing the method names, so Fnd_Text_TextToMD5 becomes toMD5 and Fnd_Text_Base64ToText becomes fromBase64.

info

info($infoRequested_t : Text)->$result_t : Text

The module's own labels — "name" and "version".

capitalize

capitalize($theText_t : Text; $options_i : Integer)->$result_t : Text

Book title capitalisation. Option 4 skips the exclude word list.

capitalizeExclude

capitalizeExclude($words_c : Collection)->$result_c : Collection

Pass a collection to replace the exclude word list, or nothing to read it.

padSpaces

padSpaces($theText_t : Text; $length_i : Integer)->$result_t : Text

Pads with spaces, or truncates, to exactly $length_i characters.

stripSpaces

stripSpaces($theText_t : Text; $options_i : Integer; $altSpaces_t : Text)->$result_t : Text

1 leading, 2 trailing, 4 doubles, added together. Default is 1+2.

trim

trim($theText_t : Text)->$result_t : Text

Trim both ends using Fnd_Text_Trim's whitespace set; preserve NBSP.

wrap

wrap($theText_t : Text; $lineLength_i : Integer)->$result_t : Text

Wraps at the last space before the limit, joined by carriage returns.

equalStrings

equalStrings($stringOne_t : Text; $stringTwo_t : Text)->$result_b : Boolean

Case and diacritic sensitive, unlike 4D's = operator.

formatNumber

formatNumber($theNumber_t : Text; $theFormat_t : Text)->$result_t : Text

Strips punctuation from the number, then applies the 4D number format.

toMD5

toMD5($theText_t : Text; $charset_t : Text)->$result_t : Text

Defaults to ISO-8859-1, which is what Foundation has always hashed.

md5Encoding

md5Encoding($charset_t : Text)->$result_t : Text

Sets the charset every later toMD5 uses, or reads it when passed nothing.

toBase64

toBase64($theText_t : Text)->$result_t : Text

Base64 on one line: BASE64 ENCODE does not wrap at 76 characters.

fromBase64

fromBase64($theText_t : Text)->$result_t : Text

The reverse of toBase64.

encodeBase64

encodeBase64($theBlob_x : Blob)->$result_x : Blob

Takes and returns a blob, rather than the pointer the method wants.

decodeBase64

decodeBase64($theBlob_x : Blob)->$result_x : Blob

Takes and returns a blob, rather than the pointer the method wants.